diff options
author | David Robillard <d@drobilla.net> | 2016-07-11 20:26:39 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2016-07-11 20:26:39 -0400 |
commit | 2f745fae447200b666c9f5810796d13a20fdf559 (patch) | |
tree | 37f5dde7f63fe36c70cf92a44f4b5835ea95aeac | |
parent | 05f9e858a5dd4b3a1ba5047aa703e55da70dcfdf (diff) | |
download | lilv-2f745fae447200b666c9f5810796d13a20fdf559.tar.gz lilv-2f745fae447200b666c9f5810796d13a20fdf559.tar.bz2 lilv-2f745fae447200b666c9f5810796d13a20fdf559.zip |
Fully reset plugin struct when plugin is reloaded
This fixes a bug where, for example, after re-loading a plugin from a
different bundle, the LilvPlugin would still report the old bundle.
Also never replace a newer version with an older version when a bundle
is loaded. Ignores the entire bundle if an older plugin than one loaded
is found. This is tricky because the unit of loading/unloading is a
bundle, and the unit of versioning is a plugin, but since having data
from an old bundle still loaded seems like a bad idea, this seems like
the most correct behaviour.
-rw-r--r-- | COPYING | 2 | ||||
-rw-r--r-- | src/lilv_internal.h | 7 | ||||
-rw-r--r-- | src/plugin.c | 31 | ||||
-rw-r--r-- | src/world.c | 45 | ||||
-rw-r--r-- | test/lilv_test.c | 41 |
5 files changed, 95 insertions, 31 deletions
@@ -1,4 +1,4 @@ -Copyright 2011-2014 David Robillard <http://drobilla.net> +Copyright 2011-2016 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/src/lilv_internal.h b/src/lilv_internal.h index ea96418..5abfcd4 100644 --- a/src/lilv_internal.h +++ b/src/lilv_internal.h @@ -1,5 +1,5 @@ /* - Copyright 2007-2015 David Robillard <http://drobilla.net> + Copyright 2007-2016 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -257,6 +257,7 @@ void lilv_port_free(const LilvPlugin* plugin, LilvPort* port); LilvPlugin* lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri); +void lilv_plugin_clear(LilvPlugin* plugin, LilvNode* bundle_uri); void lilv_plugin_load_if_necessary(const LilvPlugin* p); void lilv_plugin_free(LilvPlugin* plugin); LilvNode* lilv_plugin_get_unique(const LilvPlugin* p, @@ -428,6 +429,10 @@ static const LV2_Feature* const dman_features = { NULL }; __func__) #define LILV_WARNF(fmt, ...) fprintf(stderr, "%s(): warning: " fmt, \ __func__, __VA_ARGS__) +#define LILV_NOTE(str) fprintf(stderr, "%s(): note: " str, \ + __func__) +#define LILV_NOTEF(fmt, ...) fprintf(stderr, "%s(): note: " fmt, \ + __func__, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/plugin.c b/src/plugin.c index 837fd62..58cee88 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -1,5 +1,5 @@ /* - Copyright 2007-2014 David Robillard <http://drobilla.net> + Copyright 2007-2016 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -32,14 +32,9 @@ #define NS_DOAP (const uint8_t*)"http://usefulinc.com/ns/doap#" #define NS_FOAF (const uint8_t*)"http://xmlns.com/foaf/0.1/" -/** Ownership of `uri` is taken */ -LilvPlugin* -lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) +static void +lilv_plugin_init(LilvPlugin* plugin, LilvNode* bundle_uri) { - assert(bundle_uri); - LilvPlugin* plugin = (LilvPlugin*)malloc(sizeof(LilvPlugin)); - plugin->world = world; - plugin->plugin_uri = uri; plugin->bundle_uri = bundle_uri; plugin->binary_uri = NULL; #ifdef LILV_DYN_MANIFEST @@ -52,10 +47,30 @@ lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) plugin->loaded = false; plugin->parse_errors = false; plugin->replaced = false; +} +/** Ownership of `uri` and `bundle` is taken */ +LilvPlugin* +lilv_plugin_new(LilvWorld* world, LilvNode* uri, LilvNode* bundle_uri) +{ + LilvPlugin* plugin = (LilvPlugin*)malloc(sizeof(LilvPlugin)); + + plugin->world = world; + plugin->plugin_uri = uri; + + lilv_plugin_init(plugin, bundle_uri); return plugin; } +void +lilv_plugin_clear(LilvPlugin* plugin, LilvNode* bundle_uri) +{ + lilv_node_free(plugin->bundle_uri); + lilv_node_free(plugin->binary_uri); + lilv_nodes_free(plugin->data_uris); + lilv_plugin_init(plugin, bundle_uri); +} + static void lilv_plugin_free_ports(LilvPlugin* p) { diff --git a/src/world.c b/src/world.c index d08e32d..e1f40c8 100644 --- a/src/world.c +++ b/src/world.c @@ -1,5 +1,5 @@ /* - Copyright 2007-2015 David Robillard <http://drobilla.net> + Copyright 2007-2016 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -23,6 +23,9 @@ #include "lilv_internal.h" +static int +lilv_world_drop_graph(LilvWorld* world, const SordNode* graph); + LILV_API LilvWorld* lilv_world_new(void) { @@ -415,7 +418,7 @@ lilv_world_add_plugin(LilvWorld* world, zix_tree_remove(world->zombies, z); zix_tree_insert((ZixTree*)world->plugins, plugin, NULL); lilv_node_free(plugin_uri); - plugin->loaded = false; + lilv_plugin_clear(plugin, lilv_node_new_from_node(world, bundle)); } else { // Add new plugin to the world plugin = lilv_plugin_new( @@ -720,16 +723,30 @@ lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri) LilvVersion last_version = get_version(world, last_model, plugin_uri); sord_free(this_model); sord_free(last_model); - if (lilv_version_cmp(&this_version, &last_version) > 0) { + const int cmp = lilv_version_cmp(&this_version, &last_version); + if (cmp > 0) { zix_tree_insert((ZixTree*)unload_uris, lilv_node_duplicate(plugin_uri), NULL); - LILV_WARNF("Version %d.%d of <%s> in <%s> replaces %d.%d in <%s>\n", + LILV_WARNF("Replacing version %d.%d of <%s> from <%s>\n", + last_version.minor, last_version.micro, + sord_node_get_string(plug), + sord_node_get_string(last_bundle->node)); + LILV_NOTEF("New version %d.%d found in <%s>\n", this_version.minor, this_version.micro, + sord_node_get_string(bundle_node)); + } else if (cmp < 0) { + LILV_WARNF("Ignoring bundle <%s>\n", + sord_node_get_string(bundle_node)); + LILV_NOTEF("Newer version of <%s> loaded from <%s>\n", sord_node_get_string(plug), - sord_node_get_string(bundle_node), - last_version.minor, last_version.micro, sord_node_get_string(last_bundle->node)); + lilv_node_free(plugin_uri); + sord_iter_free(plug_results); + lilv_world_drop_graph(world, bundle_node); + lilv_node_free(manifest); + lilv_nodes_free(unload_uris); + return; } lilv_node_free(plugin_uri); } @@ -749,12 +766,6 @@ lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri) lilv_node_duplicate(bundle), NULL); - // Remove plugin from zombies list - ZixTreeIter* z; - if ((z = lilv_collection_find_by_uri(world->zombies, uri))) { - lilv_plugin_free((LilvPlugin*)zix_tree_get(z)); - zix_tree_remove(world->zombies, z); - } } lilv_nodes_free(unload_uris); @@ -799,14 +810,14 @@ lilv_world_load_bundle(LilvWorld* world, const LilvNode* bundle_uri) } static int -lilv_world_drop_graph(LilvWorld* world, const LilvNode* graph) +lilv_world_drop_graph(LilvWorld* world, const SordNode* graph) { - SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph->node); + SordIter* i = sord_search(world->model, NULL, NULL, NULL, graph); while (!sord_iter_end(i)) { const SerdStatus st = sord_erase(world->model, i); if (st) { LILV_ERRORF("Error removing statement from <%s> (%s)\n", - lilv_node_as_uri(graph), serd_strerror(st)); + sord_node_get_string(graph), serd_strerror(st)); return st; } } @@ -875,7 +886,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri) } // Drop everything in bundle graph - return lilv_world_drop_graph(world, bundle_uri); + return lilv_world_drop_graph(world, bundle_uri->node); } static void @@ -1108,7 +1119,7 @@ lilv_world_unload_resource(LilvWorld* world, if (sord_node_get_type(file) != SORD_URI) { LILV_ERRORF("rdfs:seeAlso node `%s' is not a URI\n", sord_node_get_string(file)); - } else if (!lilv_world_drop_graph(world, file_node)) { + } else if (!lilv_world_drop_graph(world, file_node->node)) { lilv_world_unload_file(world, file_node); ++n_dropped; } diff --git a/test/lilv_test.c b/test/lilv_test.c index 4215d97..69f58c7 100644 --- a/test/lilv_test.c +++ b/test/lilv_test.c @@ -2039,6 +2039,8 @@ test_replace_version(void) LilvNode* plug_uri = lilv_new_uri(world, "http://example.org/versioned"); LilvNode* lv2_minorVersion = lilv_new_uri(world, LV2_CORE__minorVersion); LilvNode* lv2_microVersion = lilv_new_uri(world, LV2_CORE__microVersion); + LilvNode* minor = NULL; + LilvNode* micro = NULL; char* old_bundle_path = malloc(strlen(LILV_TEST_DIR) + 32); strcpy(old_bundle_path, LILV_TEST_DIR); @@ -2053,8 +2055,12 @@ test_replace_version(void) const LilvPlugins* plugins = lilv_world_get_all_plugins(world); const LilvPlugin* old_plug = lilv_plugins_get_by_uri(plugins, plug_uri); TEST_ASSERT(old_plug); - TEST_ASSERT(!strcmp(lilv_node_as_string(lilv_world_get(world, plug_uri, lv2_minorVersion, 0)), "1")); - TEST_ASSERT(!strcmp(lilv_node_as_string(lilv_world_get(world, plug_uri, lv2_microVersion, 0)), "0")); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + TEST_ASSERT(!strcmp(lilv_node_as_string(minor), "1")); + TEST_ASSERT(!strcmp(lilv_node_as_string(micro), "0")); + lilv_node_free(micro); + lilv_node_free(minor); char* new_bundle_path = malloc(strlen(LILV_TEST_DIR) + 32); strcpy(new_bundle_path, LILV_TEST_DIR); @@ -2069,9 +2075,36 @@ test_replace_version(void) plugins = lilv_world_get_all_plugins(world); const LilvPlugin* new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); TEST_ASSERT(new_plug); - TEST_ASSERT(!strcmp(lilv_node_as_string(lilv_world_get(world, plug_uri, lv2_minorVersion, 0)), "2")); - TEST_ASSERT(!strcmp(lilv_node_as_string(lilv_world_get(world, plug_uri, lv2_microVersion, 0)), "1")); + TEST_ASSERT(lilv_node_equals(lilv_plugin_get_bundle_uri(new_plug), new_bundle)); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + TEST_ASSERT(!strcmp(lilv_node_as_string(minor), "2")); + TEST_ASSERT(!strcmp(lilv_node_as_string(micro), "1")); + lilv_node_free(micro); + lilv_node_free(minor); + + // Try to load the old version again + lilv_world_load_bundle(world, old_bundle); + lilv_world_load_resource(world, plug_uri); + // Check that version in the world model has not changed + plugins = lilv_world_get_all_plugins(world); + new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); + TEST_ASSERT(new_plug); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + TEST_ASSERT(!strcmp(lilv_node_as_string(minor), "2")); + TEST_ASSERT(!strcmp(lilv_node_as_string(micro), "1")); + lilv_node_free(micro); + lilv_node_free(minor); + + lilv_node_free(new_bundle); + lilv_node_free(old_bundle); + free(new_bundle_path); + free(old_bundle_path); + lilv_node_free(plug_uri); + lilv_node_free(lv2_minorVersion); + lilv_node_free(lv2_microVersion); return 1; } |