Signed-off-by: Giuseppe Scrivano <gscrivan@xxxxxxxxxx> --- osinfo/osinfo_loader.c | 159 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 48 deletions(-) diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c index a767bb8..6b1d3e1 100644 --- a/osinfo/osinfo_loader.c +++ b/osinfo/osinfo_loader.c @@ -55,6 +55,7 @@ G_DEFINE_TYPE (OsinfoLoader, osinfo_loader, G_TYPE_OBJECT); struct _OsinfoLoaderPrivate { OsinfoDb *db; + GHashTable *xpath_cache; }; struct _OsinfoEntityKey @@ -70,6 +71,7 @@ osinfo_loader_finalize (GObject *object) OsinfoLoader *loader = OSINFO_LOADER (object); g_object_unref(loader->priv->db); + g_hash_table_destroy(loader->priv->xpath_cache); /* Chain up to the parent class */ G_OBJECT_CLASS (osinfo_loader_parent_class)->finalize (object); @@ -89,11 +91,21 @@ osinfo_loader_class_init (OsinfoLoaderClass *klass) g_type_class_add_private (klass, sizeof (OsinfoLoaderPrivate)); } + +static void xpath_cache_value_free(gpointer values) +{ + xmlXPathFreeCompExpr(values); +} + static void osinfo_loader_init (OsinfoLoader *loader) { loader->priv = OSINFO_LOADER_GET_PRIVATE(loader); loader->priv->db = osinfo_db_new(); + loader->priv->xpath_cache = g_hash_table_new_full(g_str_hash, + g_str_equal, + g_free, + xpath_cache_value_free); } /** PUBLIC METHODS */ @@ -118,8 +130,20 @@ static gboolean error_is_set(GError **error) return ((error != NULL) && (*error != NULL)); } +static xmlXPathCompExprPtr osinfo_loader_get_comp_xpath(OsinfoLoader *loader, + const char *xpath) +{ + xmlXPathCompExprPtr comp = g_hash_table_lookup(loader->priv->xpath_cache, + xpath); + if (comp == NULL) { + comp = xmlXPathCompile(BAD_CAST xpath); + g_hash_table_insert(loader->priv->xpath_cache, g_strdup(xpath), comp); + } + return comp; +} + static int -osinfo_loader_nodeset(const char *xpath, +osinfo_loader_nodeset(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt, xmlNodePtr **list, GError **err) @@ -129,19 +153,19 @@ osinfo_loader_nodeset(const char *xpath, int ret; g_return_val_if_fail(ctxt != NULL, -1); - g_return_val_if_fail(xpath != NULL, -1); + g_return_val_if_fail(comp != NULL, -1); if (list != NULL) *list = NULL; relnode = ctxt->node; - obj = xmlXPathEval(BAD_CAST xpath, ctxt); + obj = xmlXPathCompiledEval(comp, ctxt); ctxt->node = relnode; if (obj == NULL) return(0); if (obj->type != XPATH_NODESET) { g_set_error(err, g_quark_from_static_string("libosinfo"), 0, - _("Expected a nodeset in XPath query %s"), xpath); + _("Expected a nodeset in XPath query")); xmlXPathFreeObject(obj); return (-1); } @@ -161,7 +185,7 @@ osinfo_loader_nodeset(const char *xpath, } static gchar * -osinfo_loader_string(const char *xpath, +osinfo_loader_string(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt, GError **err) { @@ -169,11 +193,9 @@ osinfo_loader_string(const char *xpath, xmlNodePtr relnode; gchar *ret; - g_return_val_if_fail(ctxt != NULL, NULL); - g_return_val_if_fail(xpath != NULL, NULL); - relnode = ctxt->node; - obj = xmlXPathEval(BAD_CAST xpath, ctxt); + obj = xmlXPathCompiledEval(comp, ctxt); + ctxt->node = relnode; if ((obj == NULL) || (obj->type != XPATH_STRING) || (obj->stringval == NULL) || (obj->stringval[0] == 0)) { @@ -187,7 +209,7 @@ osinfo_loader_string(const char *xpath, } static gboolean -osinfo_loader_boolean(const char *xpath, +osinfo_loader_boolean(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt, GError **err) { @@ -198,9 +220,9 @@ osinfo_loader_boolean(const char *xpath, gboolean ret = FALSE; g_return_val_if_fail(ctxt != NULL, FALSE); - g_return_val_if_fail(xpath != NULL, FALSE); + g_return_val_if_fail(comp != NULL, FALSE); - count = osinfo_loader_nodeset(xpath, ctxt, &nodes, err); + count = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (count < 0) { return FALSE; @@ -229,7 +251,7 @@ cleanup: } static gchar * -osinfo_loader_doc(const char *xpath, +osinfo_loader_doc(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt, GError **err) { @@ -239,10 +261,10 @@ osinfo_loader_doc(const char *xpath, xmlBufferPtr buf; g_return_val_if_fail(ctxt != NULL, NULL); - g_return_val_if_fail(xpath != NULL, NULL); + g_return_val_if_fail(comp != NULL, NULL); relnode = ctxt->node; - obj = xmlXPathEval(BAD_CAST xpath, ctxt); + obj = xmlXPathCompiledEval(comp, ctxt); ctxt->node = relnode; if ((obj == NULL) || (obj->type != XPATH_NODESET)) { xmlXPathFreeObject(obj); @@ -283,6 +305,7 @@ static void osinfo_loader_entity(OsinfoLoader *loader, gboolean value_bool = FALSE; gchar *xpath = NULL; int j; + xmlXPathCompExprPtr comp; /* We are guaranteed to have at least the default "C" locale and we * want to ignore that, hence the NULL check on index 'j + 1'. @@ -291,7 +314,8 @@ static void osinfo_loader_entity(OsinfoLoader *loader, for (j = 0; langs[j + 1] != NULL; j++) { xpath = g_strdup_printf("string(./%s[lang('%s')])", keys[i].name, langs[j]); - value_str = osinfo_loader_string(xpath, ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, xpath); + value_str = osinfo_loader_string(comp, ctxt, err); g_free(xpath); xpath = NULL; if (error_is_set(err)) @@ -304,20 +328,23 @@ static void osinfo_loader_entity(OsinfoLoader *loader, switch (keys[i].type) { case G_TYPE_STRING: - xpath = g_strdup_printf("string(./%s)", keys[i].name); if (value_str == NULL) { - value_str = osinfo_loader_string(xpath, ctxt, err); + xpath = g_strdup_printf("string(./%s)", keys[i].name); + comp = osinfo_loader_get_comp_xpath(loader, xpath); + value_str = osinfo_loader_string(comp, ctxt, err); + g_free(xpath); } break; case G_TYPE_BOOLEAN: xpath = g_strdup_printf("./%s", keys[i].name); - value_bool = osinfo_loader_boolean(xpath, ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, xpath); + value_bool = osinfo_loader_boolean(comp, ctxt, err); + g_free(xpath); break; default: g_warn_if_reached(); break; } - g_free(xpath); switch (keys[i].type) { case G_TYPE_STRING: @@ -339,7 +366,10 @@ static void osinfo_loader_entity(OsinfoLoader *loader, /* Then any site specific custom keys. x-... Can be repeated */ xmlNodePtr *custom = NULL; - int ncustom = osinfo_loader_nodeset("./*[substring(name(),1,2)='x-']", ctxt, &custom, err); + xmlXPathCompExprPtr comp; + comp = osinfo_loader_get_comp_xpath(loader, + "./*[substring(name(),1,2)='x-']"); + int ncustom = osinfo_loader_nodeset(comp, ctxt, &custom, err); if (error_is_set(err)) return; @@ -457,7 +487,8 @@ static void osinfo_loader_device_link(OsinfoLoader *loader, GError **err) { xmlNodePtr *related = NULL; - int nrelated = osinfo_loader_nodeset(xpath, ctxt, &related, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, xpath); + int nrelated = osinfo_loader_nodeset(comp, ctxt, &related, err); int i; if (error_is_set(err)) return; @@ -505,7 +536,8 @@ static void osinfo_loader_product_relshp(OsinfoLoader *loader, GError **err) { xmlNodePtr *related = NULL; - int nrelated = osinfo_loader_nodeset(xpath, ctxt, &related, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, xpath); + int nrelated = osinfo_loader_nodeset(comp, ctxt, &related, err); int i; if (error_is_set(err)) return; @@ -611,13 +643,15 @@ static void osinfo_loader_deployment(OsinfoLoader *loader, xmlNodePtr root, GError **err) { + xmlXPathCompExprPtr comp; gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id"); if (!id) { OSINFO_ERROR(err, _("Missing deployment id property")); return; } - gchar *osid = osinfo_loader_string("string(./os/@id)", ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, "string(./os/@id)"); + gchar *osid = osinfo_loader_string(comp, ctxt, err); if (!osid && 0) { OSINFO_ERROR(err, _("Missing deployment os id property")); xmlFree(id); @@ -626,7 +660,8 @@ static void osinfo_loader_deployment(OsinfoLoader *loader, OsinfoOs *os = osinfo_loader_get_os(loader, osid); g_free(osid); - gchar *platformid = osinfo_loader_string("string(./platform/@id)", ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, "string(./platform/@id)"); + gchar *platformid = osinfo_loader_string(comp, ctxt, err); if (!platformid) { OSINFO_ERROR(err, _("Missing deployment platform id property")); xmlFree(id); @@ -672,7 +707,8 @@ static void osinfo_loader_datamap(OsinfoLoader *loader, OsinfoDatamap *map = osinfo_loader_get_datamap(loader, id); - nnodes = osinfo_loader_nodeset("./entry", ctxt, &nodes, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, "./entry"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -702,7 +738,8 @@ static void osinfo_loader_install_config_params(OsinfoLoader *loader, GError **err) { xmlNodePtr *nodes = NULL; - int nnodes = osinfo_loader_nodeset(xpath, ctxt, &nodes, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, xpath); + int nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); int i; if (error_is_set(err)) return; @@ -786,6 +823,7 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, return; } + xmlXPathCompExprPtr comp; OsinfoInstallScript *installScript = osinfo_loader_get_install_script(loader, id); xmlFree(id); @@ -794,7 +832,8 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, if (error_is_set(err)) goto error; - value = osinfo_loader_doc("./template/*[1]", ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, "./template/*[1]"); + value = osinfo_loader_doc(comp, ctxt, err); if (error_is_set(err)) goto error; if (value) @@ -803,7 +842,8 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, value); g_free(value); - value = osinfo_loader_string("./template/@uri", ctxt, err); + comp = osinfo_loader_get_comp_xpath(loader, "./template/@uri"); + value = osinfo_loader_string(comp, ctxt, err); if (error_is_set(err)) goto error; if (value) @@ -819,7 +859,8 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, root, err); - nnodes = osinfo_loader_nodeset("./avatar-format", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./avatar-format"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto error; @@ -837,7 +878,8 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, } g_free(nodes); - nnodes = osinfo_loader_nodeset("./injection-method", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./injection-method"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto error; @@ -872,6 +914,7 @@ static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader, { xmlNodePtr *nodes = NULL; guint i; + xmlXPathCompExprPtr comp; gchar *arch = (gchar *)xmlGetProp(root, BAD_CAST "arch"); xmlChar *live = xmlGetProp(root, BAD_CAST OSINFO_MEDIA_PROP_LIVE); @@ -910,7 +953,8 @@ static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader, xmlFree(installer_reboots); } - gint nnodes = osinfo_loader_nodeset("./variant", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./variant"); + gint nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) { g_object_unref(media); return NULL; @@ -925,7 +969,8 @@ static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader, } g_free(nodes); - nnodes = osinfo_loader_nodeset("./iso/*", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./iso/*"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) { g_object_unref(media); return NULL; @@ -986,6 +1031,7 @@ static OsinfoTree *osinfo_loader_tree (OsinfoLoader *loader, { xmlNodePtr *nodes = NULL; guint i; + xmlXPathCompExprPtr comp; gchar *arch = (gchar *)xmlGetProp(root, BAD_CAST "arch"); const OsinfoEntityKey keys[] = { @@ -1001,7 +1047,8 @@ static OsinfoTree *osinfo_loader_tree (OsinfoLoader *loader, osinfo_loader_entity(loader, OSINFO_ENTITY(tree), keys, ctxt, root, err); - gint nnodes = osinfo_loader_nodeset("./treeinfo/*", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./treeinfo/*"); + gint nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) { g_object_unref(G_OBJECT(tree)); return NULL; @@ -1071,7 +1118,8 @@ static OsinfoResources *osinfo_loader_resources(OsinfoLoader *loader, gchar *arch = (gchar *)xmlGetProp(root, BAD_CAST "arch"); gchar *node_path = g_strjoin("/", ".", name, "*", NULL); - gint nnodes = osinfo_loader_nodeset(node_path, ctxt, &nodes, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, node_path); + gint nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); g_free(node_path); if (error_is_set(err) || nnodes < 1) goto EXIT; @@ -1175,7 +1223,8 @@ static OsinfoDeviceDriver *osinfo_loader_driver(OsinfoLoader *loader, xmlFree(is_signed); } - gint nnodes = osinfo_loader_nodeset("./*", ctxt, &nodes, err); + xmlXPathCompExprPtr comp = osinfo_loader_get_comp_xpath(loader, "./*"); + gint nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) { g_object_unref(G_OBJECT(driver)); return NULL; @@ -1214,6 +1263,7 @@ static void osinfo_loader_os(OsinfoLoader *loader, xmlNodePtr *nodes = NULL; guint i; int nnodes; + xmlXPathCompExprPtr comp; gchar *id = (gchar *)xmlGetProp(root, BAD_CAST "id"); const OsinfoEntityKey keys[] = { @@ -1243,7 +1293,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, if (error_is_set(err)) goto cleanup; - nnodes = osinfo_loader_nodeset("./media", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./media"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1263,7 +1314,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); - nnodes = osinfo_loader_nodeset("./tree", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./tree"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1283,7 +1335,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); - nnodes = osinfo_loader_nodeset("./variant", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./variant"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1304,7 +1357,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); - nnodes = osinfo_loader_nodeset("./resources", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./resources"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1326,7 +1380,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); - nnodes = osinfo_loader_nodeset("./installer/script", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./installer/script"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1345,7 +1400,8 @@ static void osinfo_loader_os(OsinfoLoader *loader, g_free(nodes); - nnodes = osinfo_loader_nodeset("./driver", ctxt, &nodes, err); + comp = osinfo_loader_get_comp_xpath(loader, "./driver"); + nnodes = osinfo_loader_nodeset(comp, ctxt, &nodes, err); if (error_is_set(err)) goto cleanup; @@ -1406,13 +1462,15 @@ static void osinfo_loader_root(OsinfoLoader *loader, int nplatform; int ninstallScript; int ndataMaps; + xmlXPathCompExprPtr comp; if (!xmlStrEqual(root->name, BAD_CAST "libosinfo")) { OSINFO_ERROR(err, _("Incorrect root element")); return; } - ndevice = osinfo_loader_nodeset("./device", ctxt, &devices, err); + comp = osinfo_loader_get_comp_xpath(loader, "./device"); + ndevice = osinfo_loader_nodeset(comp, ctxt, &devices, err); if (error_is_set(err)) goto cleanup; @@ -1425,7 +1483,8 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } - nplatform = osinfo_loader_nodeset("./platform", ctxt, &platforms, err); + comp = osinfo_loader_get_comp_xpath(loader, "./platform"); + nplatform = osinfo_loader_nodeset(comp, ctxt, &platforms, err); if (error_is_set(err)) goto cleanup; @@ -1438,7 +1497,8 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } - nos = osinfo_loader_nodeset("./os", ctxt, &oss, err); + comp = osinfo_loader_get_comp_xpath(loader, "./os"); + nos = osinfo_loader_nodeset(comp, ctxt, &oss, err); if (error_is_set(err)) goto cleanup; @@ -1451,7 +1511,8 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } - ndeployment = osinfo_loader_nodeset("./deployment", ctxt, &deployments, err); + comp = osinfo_loader_get_comp_xpath(loader, "./deployment"); + ndeployment = osinfo_loader_nodeset(comp, ctxt, &deployments, err); if (error_is_set(err)) goto cleanup; @@ -1464,7 +1525,8 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } - ninstallScript = osinfo_loader_nodeset("./install-script", ctxt, &installScripts, err); + comp = osinfo_loader_get_comp_xpath(loader, "./install-script"); + ninstallScript = osinfo_loader_nodeset(comp, ctxt, &installScripts, err); if (error_is_set(err)) goto cleanup; @@ -1477,7 +1539,8 @@ static void osinfo_loader_root(OsinfoLoader *loader, goto cleanup; } - ndataMaps = osinfo_loader_nodeset("./datamap", ctxt, &dataMaps, err); + comp = osinfo_loader_get_comp_xpath(loader, "./datamap"); + ndataMaps = osinfo_loader_nodeset(comp, ctxt, &dataMaps, err); if (error_is_set(err)) goto cleanup; -- 1.9.3 _______________________________________________ Libosinfo mailing list Libosinfo@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libosinfo