summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lilv_internal.h1
-rw-r--r--src/world.c64
-rw-r--r--test/lilv_test.c8
3 files changed, 58 insertions, 15 deletions
diff --git a/src/lilv_internal.h b/src/lilv_internal.h
index 89ae629..bdb88ed 100644
--- a/src/lilv_internal.h
+++ b/src/lilv_internal.h
@@ -156,6 +156,7 @@ struct LilvWorldImpl {
LilvPluginClasses* plugin_classes;
LilvSpec* specs;
LilvPlugins* plugins;
+ LilvPlugins* zombies;
LilvNodes* loaded_files;
ZixTree* libs;
struct {
diff --git a/src/world.c b/src/world.c
index 70a79d6..0710899 100644
--- a/src/world.c
+++ b/src/world.c
@@ -39,6 +39,7 @@ lilv_world_new(void)
world->specs = NULL;
world->plugin_classes = lilv_plugin_classes_new();
world->plugins = lilv_plugins_new();
+ world->zombies = lilv_plugins_new();
world->loaded_files = zix_tree_new(
false, lilv_resource_node_cmp, NULL, (ZixDestroyFunc)lilv_node_free);
@@ -133,6 +134,13 @@ lilv_world_free(LilvWorld* world)
zix_tree_free((ZixTree*)world->plugins);
world->plugins = NULL;
+ LILV_FOREACH(plugins, i, world->zombies) {
+ const LilvPlugin* p = lilv_plugins_get(world->zombies, i);
+ lilv_plugin_free((LilvPlugin*)p);
+ }
+ zix_tree_free((ZixTree*)world->zombies);
+ world->zombies = NULL;
+
zix_tree_free((ZixTree*)world->loaded_files);
world->loaded_files = NULL;
@@ -322,23 +330,27 @@ lilv_lib_compare(const void* a, const void* b, void* user_data)
}
/** Get an element of a collection of any object with an LilvHeader by URI. */
-struct LilvHeader*
-lilv_collection_get_by_uri(const ZixTree* const_seq,
- const LilvNode* uri)
+static ZixTreeIter*
+lilv_collection_find_by_uri(const ZixTree* seq, const LilvNode* uri)
{
if (!lilv_node_is_uri(uri)) {
return NULL;
}
- ZixTree* seq = (ZixTree*)const_seq;
struct LilvHeader key = { NULL, (LilvNode*)uri };
ZixTreeIter* i = NULL;
- ZixStatus st = zix_tree_find(seq, &key, &i);
- if (!st) {
- return (struct LilvHeader*)zix_tree_get(i);
- }
+ const ZixStatus st = zix_tree_find(seq, &key, &i);
- return NULL;
+ return st ? NULL : i;
+}
+
+/** Get an element of a collection of any object with an LilvHeader by URI. */
+struct LilvHeader*
+lilv_collection_get_by_uri(const ZixTree* seq, const LilvNode* uri)
+{
+ ZixTreeIter* const i = lilv_collection_find_by_uri(seq, uri);
+
+ return i ? (struct LilvHeader*)zix_tree_get(i) : NULL;
}
static void
@@ -377,8 +389,9 @@ lilv_world_add_plugin(LilvWorld* world,
void* dynmanifest,
const SordNode* bundle)
{
- LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node);
- LilvPlugin* plugin = (LilvPlugin*)lilv_plugins_get_by_uri(
+ LilvNode* plugin_uri = lilv_node_new_from_node(world, plugin_node);
+ ZixTreeIter* z = NULL;
+ LilvPlugin* plugin = (LilvPlugin*)lilv_plugins_get_by_uri(
world->plugins, plugin_uri);
if (plugin) {
@@ -397,6 +410,13 @@ lilv_world_add_plugin(LilvWorld* world,
lilv_node_free(plugin_uri);
return;
}
+ } else if ((z = lilv_collection_find_by_uri(world->zombies, plugin_uri))) {
+ // Plugin bundle has been re-loaded, move from zombies to plugins
+ plugin = zix_tree_get(z);
+ zix_tree_remove(world->zombies, z);
+ zix_tree_insert((ZixTree*)world->plugins, plugin, NULL);
+ lilv_node_free(plugin_uri);
+ plugin->loaded = false;
} else {
// Add new plugin to the world
plugin = lilv_plugin_new(
@@ -682,7 +702,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri)
return 0;
}
- // Unload any files, including manifest.ttl
+ // Find all loaded files that are inside the bundle
LilvNodes* files = lilv_nodes_new();
LILV_FOREACH(nodes, i, world->loaded_files) {
const LilvNode* file = lilv_nodes_get(world->loaded_files, i);
@@ -695,6 +715,7 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri)
}
}
+ // Unload all loaded files in the bundle
LILV_FOREACH(nodes, i, files) {
const LilvNode* file = lilv_nodes_get(world->plugins, i);
lilv_world_unload_file(world, file);
@@ -702,6 +723,25 @@ lilv_world_unload_bundle(LilvWorld* world, const LilvNode* bundle_uri)
lilv_nodes_free(files);
+ /* Remove any plugins in the bundle from the plugin list. Since the
+ application may still have a pointer to the LilvPlugin, it can not be
+ destroyed here. Instead, we move it to the zombie plugin list, so it
+ will not be in the list returned by lilv_world_get_all_plugins() but can
+ still be used.
+ */
+ ZixTreeIter* i = zix_tree_begin(world->plugins);
+ while (i != zix_tree_end(world->plugins)) {
+ LilvPlugin* p = (LilvPlugin*)zix_tree_get(i);
+ ZixTreeIter* next = zix_tree_iter_next(i);
+
+ if (lilv_node_equals(lilv_plugin_get_bundle_uri(p), bundle_uri)) {
+ zix_tree_remove(world->plugins, i);
+ zix_tree_insert(world->zombies, p, NULL);
+ }
+
+ i = next;
+ }
+
// Drop everything in bundle graph
return lilv_world_drop_graph(world, bundle_uri);
}
diff --git a/test/lilv_test.c b/test/lilv_test.c
index 7b6d14a..64021f8 100644
--- a/test/lilv_test.c
+++ b/test/lilv_test.c
@@ -1982,14 +1982,16 @@ test_reload_bundle(void)
":plug a lv2:Plugin ; "
PLUGIN_NAME("Second name") " .");
+ // Check that plugin is no longer in the world's plugin list
+ TEST_ASSERT(lilv_plugins_size(plugins) == 0);
+
// Load new bundle
lilv_world_load_bundle(world, bundle_uri);
- // TODO: Mechanism to actually remove plugin from world list
-
- // Check that plugin is present again
+ // Check that plugin is present again and is the same LilvPlugin
const LilvPlugin* plug2 = lilv_plugins_get_by_uri(plugins, plugin_uri_value);
TEST_ASSERT(plug2);
+ TEST_ASSERT(plug2 == plug);
// Check that plugin now has new name
LilvNode* name2 = lilv_plugin_get_name(plug2);