[Libosinfo] [PATCH 2/5] loader: identify referenced but not defined entities
Christophe Fergeau
cfergeau at redhat.com
Wed Oct 7 08:26:04 UTC 2015
On Tue, Oct 06, 2015 at 05:41:00PM +0100, Daniel P. Berrange wrote:
> When loading the database we often have to instantiate
> entities to represent relationships (upgrades, derives,
> etc) before the entity is actually defined. This makes
> the code liable to bugs as we might instantiate entities
> which are never defined.
>
> This extends the loader so that it tracks all entities
> that are created via references, and once loading is
> complete it prints out a warning if any referenced
> entities were not defined fully.
>
> This identifies a number of mistakes in our current
> database that the following patches will fix.
>
> Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
> ---
> osinfo/osinfo_loader.c | 94 ++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 75 insertions(+), 19 deletions(-)
>
> diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c
> index 0c7ddfb..4251a90 100644
> --- a/osinfo/osinfo_loader.c
> +++ b/osinfo/osinfo_loader.c
> @@ -56,6 +56,7 @@ struct _OsinfoLoaderPrivate
> {
> OsinfoDb *db;
> GHashTable *xpath_cache;
> + GHashTable *entityRefs;
"entity_refs"
> };
>
> struct _OsinfoEntityKey
> @@ -73,6 +74,8 @@ osinfo_loader_finalize(GObject *object)
> g_object_unref(loader->priv->db);
> g_hash_table_destroy(loader->priv->xpath_cache);
>
> + g_hash_table_destroy(loader->priv->entityRefs);
> +
> /* Chain up to the parent class */
> G_OBJECT_CLASS(osinfo_loader_parent_class)->finalize(object);
> }
> @@ -106,6 +109,10 @@ osinfo_loader_init(OsinfoLoader *loader)
> g_str_equal,
> g_free,
> xpath_cache_value_free);
> + loader->priv->entityRefs = g_hash_table_new_full(g_str_hash,
> + g_str_equal,
> + g_free,
> + NULL);
> }
>
> /** PUBLIC METHODS */
> @@ -409,61 +416,101 @@ static void osinfo_loader_entity(OsinfoLoader *loader,
> }
>
> static OsinfoDatamap *osinfo_loader_get_datamap(OsinfoLoader *loader,
> - const gchar *id)
> + const gchar *id,
> + gboolean reference)
> {
> OsinfoDatamap *datamap = osinfo_db_get_datamap(loader->priv->db, id);
> if (!datamap) {
> datamap = osinfo_datamap_new(id);
> osinfo_db_add_datamap(loader->priv->db, datamap);
> g_object_unref(datamap);
> + if (reference) {
> + g_hash_table_insert(loader->priv->entityRefs, g_strdup(id), datamap);
> + }
Given the way you use the hash table, you could use
g_hash_table_add/g_hash_table_contains, but this was only added in glib
2.32.
For what it's worth, I think the code would be a bit simpler without the
'reference' argument, ie you unconditionnally call g_hash_table_insert()
in the if (!datamap) block, and right after the (only)
osinfo_loader_get_datamap(loader, id, FALSE); call
you g_hash_table_remove(entity_refs, id);
Same for the other osinfo_loader_get_xxx changes.
ACK from me without or with changes.
Christophe
> + } else {
> + if (!reference) {
> + g_hash_table_remove(loader->priv->entityRefs, id);
> + }
> }
> return datamap;
> }
>
> static OsinfoDevice *osinfo_loader_get_device(OsinfoLoader *loader,
> - const gchar *id)
> + const gchar *id,
> + gboolean reference)
> {
> OsinfoDevice *dev = osinfo_db_get_device(loader->priv->db, id);
> if (!dev) {
> dev = osinfo_device_new(id);
> osinfo_db_add_device(loader->priv->db, dev);
> g_object_unref(dev);
> + if (reference) {
> + g_hash_table_insert(loader->priv->entityRefs, g_strdup(id), dev);
> + }
> + } else {
> + if (!reference) {
> + g_hash_table_remove(loader->priv->entityRefs, id);
> + }
> }
> return dev;
> }
>
> static OsinfoOs *osinfo_loader_get_os(OsinfoLoader *loader,
> - const gchar *id)
> + const gchar *id,
> + gboolean reference)
> {
> OsinfoOs *os = osinfo_db_get_os(loader->priv->db, id);
> if (!os) {
> os = osinfo_os_new(id);
> osinfo_db_add_os(loader->priv->db, os);
> g_object_unref(os);
> + if (reference) {
> + g_hash_table_insert(loader->priv->entityRefs, g_strdup(id), os);
> + }
> + } else {
> + if (!reference) {
> + g_hash_table_remove(loader->priv->entityRefs, id);
> + }
> }
> return os;
> }
>
> static OsinfoPlatform *osinfo_loader_get_platform(OsinfoLoader *loader,
> - const gchar *id)
> + const gchar *id,
> + gboolean reference)
> {
> OsinfoPlatform *platform = osinfo_db_get_platform(loader->priv->db, id);
> if (!platform) {
> platform = osinfo_platform_new(id);
> osinfo_db_add_platform(loader->priv->db, platform);
> g_object_unref(platform);
> + if (reference) {
> + g_hash_table_insert(loader->priv->entityRefs, g_strdup(id), platform);
> + }
> + } else {
> + if (!reference) {
> + g_hash_table_remove(loader->priv->entityRefs, id);
> + }
> }
> return platform;
> }
>
> static OsinfoInstallScript *osinfo_loader_get_install_script(OsinfoLoader *loader,
> - const gchar *id)
> + const gchar *id,
> + gboolean reference)
> {
> OsinfoInstallScript *script = osinfo_db_get_install_script(loader->priv->db, id);
> if (!script) {
> script = osinfo_install_script_new(id);
> osinfo_db_add_install_script(loader->priv->db, script);
> g_object_unref(script);
> + if (reference) {
> + g_hash_table_insert(loader->priv->entityRefs, g_strdup(id), script);
> + }
> + } else {
> + if (!reference) {
> + g_hash_table_remove(loader->priv->entityRefs, id);
> + }
> }
> return script;
> }
> @@ -490,7 +537,7 @@ static void osinfo_loader_device(OsinfoLoader *loader,
> return;
> }
>
> - OsinfoDevice *device = osinfo_loader_get_device(loader, id);
> + OsinfoDevice *device = osinfo_loader_get_device(loader, id, FALSE);
> xmlFree(id);
>
> osinfo_loader_entity(loader, OSINFO_ENTITY(device), keys, ctxt, root, err);
> @@ -519,7 +566,7 @@ static void osinfo_loader_device_link(OsinfoLoader *loader,
> OSINFO_ERROR(err, _("Missing device link id property"));
> goto cleanup;
> }
> - OsinfoDevice *dev = osinfo_loader_get_device(loader, id);
> + OsinfoDevice *dev = osinfo_loader_get_device(loader, id, TRUE);
> xmlFree(id);
>
> OsinfoDeviceLink *devlink = NULL;
> @@ -571,9 +618,9 @@ static void osinfo_loader_product_relshp(OsinfoLoader *loader,
> }
> OsinfoProduct *relproduct;
> if (OSINFO_IS_PLATFORM(product))
> - relproduct = OSINFO_PRODUCT(osinfo_loader_get_platform(loader, id));
> + relproduct = OSINFO_PRODUCT(osinfo_loader_get_platform(loader, id, TRUE));
> else
> - relproduct = OSINFO_PRODUCT(osinfo_loader_get_os(loader, id));
> + relproduct = OSINFO_PRODUCT(osinfo_loader_get_os(loader, id, TRUE));
> xmlFree(id);
>
> osinfo_product_add_related(product, relshp, relproduct);
> @@ -642,7 +689,7 @@ static void osinfo_loader_platform(OsinfoLoader *loader,
> return;
> }
>
> - OsinfoPlatform *platform = osinfo_loader_get_platform(loader, id);
> + OsinfoPlatform *platform = osinfo_loader_get_platform(loader, id, FALSE);
> xmlFree(id);
>
> osinfo_loader_entity(loader, OSINFO_ENTITY(platform), NULL, ctxt, root, err);
> @@ -676,7 +723,7 @@ static void osinfo_loader_deployment(OsinfoLoader *loader,
> xmlFree(id);
> return;
> }
> - OsinfoOs *os = osinfo_loader_get_os(loader, osid);
> + OsinfoOs *os = osinfo_loader_get_os(loader, osid, TRUE);
> g_free(osid);
>
> gchar *platformid = osinfo_loader_string("string(./platform/@id)", loader,
> @@ -686,7 +733,7 @@ static void osinfo_loader_deployment(OsinfoLoader *loader,
> xmlFree(id);
> return;
> }
> - OsinfoPlatform *platform = osinfo_loader_get_platform(loader, platformid);
> + OsinfoPlatform *platform = osinfo_loader_get_platform(loader, platformid, TRUE);
> g_free(platformid);
>
> OsinfoDeployment *deployment = osinfo_deployment_new(id, os, platform);
> @@ -724,7 +771,7 @@ static void osinfo_loader_datamap(OsinfoLoader *loader,
> return;
> }
>
> - OsinfoDatamap *map = osinfo_loader_get_datamap(loader, id);
> + OsinfoDatamap *map = osinfo_loader_get_datamap(loader, id, FALSE);
>
> nnodes = osinfo_loader_nodeset("./entry", loader, ctxt, &nodes, err);
> if (error_is_set(err))
> @@ -773,7 +820,7 @@ static void osinfo_loader_install_config_params(OsinfoLoader *loader,
> param);
> if (mapid != NULL) {
> OsinfoDatamap *map;
> - map = osinfo_loader_get_datamap(loader, mapid);
> + map = osinfo_loader_get_datamap(loader, mapid, TRUE);
> if (map != NULL)
> osinfo_install_config_param_set_value_map(param, map);
> }
> @@ -843,7 +890,8 @@ static void osinfo_loader_install_script(OsinfoLoader *loader,
> }
>
> OsinfoInstallScript *installScript = osinfo_loader_get_install_script(loader,
> - id);
> + id,
> + FALSE);
> xmlFree(id);
>
> osinfo_loader_entity(loader, OSINFO_ENTITY(installScript), keys, ctxt, root, err);
> @@ -1254,7 +1302,8 @@ static OsinfoDeviceDriver *osinfo_loader_driver(OsinfoLoader *loader,
> OSINFO_DEVICE_DRIVER_PROP_DEVICE) == 0) {
> xmlChar *device_id = xmlGetProp(nodes[i], BAD_CAST "id");
> OsinfoDevice *device = osinfo_loader_get_device(loader,
> - (gchar *)device_id);
> + (gchar *)device_id,
> + TRUE);
> xmlFree(device_id);
>
> osinfo_device_driver_add_device(driver, device);
> @@ -1289,7 +1338,7 @@ static void osinfo_loader_os(OsinfoLoader *loader,
> return;
> }
>
> - OsinfoOs *os = osinfo_loader_get_os(loader, id);
> + OsinfoOs *os = osinfo_loader_get_os(loader, id, FALSE);
>
> osinfo_loader_entity(loader, OSINFO_ENTITY(os), keys, ctxt, root, err);
> if (error_is_set(err))
> @@ -1399,7 +1448,7 @@ static void osinfo_loader_os(OsinfoLoader *loader,
> goto cleanup;
> }
> OsinfoInstallScript *script;
> - script = osinfo_loader_get_install_script(loader, scriptid);
> + script = osinfo_loader_get_install_script(loader, scriptid, TRUE);
> xmlFree(scriptid);
>
> osinfo_os_add_install_script(os, script);
> @@ -1651,7 +1700,7 @@ osinfo_loader_process_file_reg_ids(OsinfoLoader *loader,
> gchar *id = g_strdup_printf("%s/%s/%s",
> baseURI, vendor_id, device_id);
>
> - OsinfoDevice *dev = osinfo_loader_get_device(loader, id);
> + OsinfoDevice *dev = osinfo_loader_get_device(loader, id, FALSE);
> OsinfoEntity *entity = OSINFO_ENTITY(dev);
> osinfo_entity_set_param(entity,
> OSINFO_DEVICE_PROP_VENDOR_ID,
> @@ -1908,6 +1957,13 @@ void osinfo_loader_process_default_path(OsinfoLoader *loader, GError **err)
> if (error)
> goto error;
>
> + GHashTableIter iter;
> + gpointer key, value;
> + g_hash_table_iter_init(&iter, loader->priv->entityRefs);
> + while (g_hash_table_iter_next(&iter, &key, &value)) {
> + g_warning("Entity %s referenced but not defined", (const char *)key);
> + }
> + g_hash_table_remove_all(loader->priv->entityRefs);
> return;
>
> error:
> --
> 2.4.3
>
> _______________________________________________
> Libosinfo mailing list
> Libosinfo at redhat.com
> https://www.redhat.com/mailman/listinfo/libosinfo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libosinfo/attachments/20151007/e6979e46/attachment.sig>
More information about the Libosinfo
mailing list