summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-07-11 20:26:39 -0400
committerDavid Robillard <d@drobilla.net>2016-07-11 20:26:39 -0400
commit2f745fae447200b666c9f5810796d13a20fdf559 (patch)
tree37f5dde7f63fe36c70cf92a44f4b5835ea95aeac
parent05f9e858a5dd4b3a1ba5047aa703e55da70dcfdf (diff)
downloadlilv-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--COPYING2
-rw-r--r--src/lilv_internal.h7
-rw-r--r--src/plugin.c31
-rw-r--r--src/world.c45
-rw-r--r--test/lilv_test.c41
5 files changed, 95 insertions, 31 deletions
diff --git a/COPYING b/COPYING
index 3010008..7121a87 100644
--- a/COPYING
+++ b/COPYING
@@ -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;
}