summaryrefslogtreecommitdiff
path: root/libjack/metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'libjack/metadata.c')
-rw-r--r--libjack/metadata.c1172
1 files changed, 607 insertions, 565 deletions
diff --git a/libjack/metadata.c b/libjack/metadata.c
index a12778f..226ac1d 100644
--- a/libjack/metadata.c
+++ b/libjack/metadata.c
@@ -1,20 +1,20 @@
/*
- Copyright (C) 2013 Paul Davis
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
+ Copyright (C) 2013 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
#include <string.h>
#include <db.h>
@@ -39,519 +39,551 @@ static DB_ENV* db_env = NULL;
static int
jack_property_init (const char* server_name)
{
- int ret;
- char dbpath[PATH_MAX+1];
- char server_dir[PATH_MAX+1];
-
- /* idempotent */
-
- if (db_env) {
- return 0;
- }
-
- if ((ret = db_env_create(&db_env, 0)) != 0) {
- jack_error ("cannot initialize DB environment: %s\n", db_strerror(ret));
- return -1;
- }
-
- if ((ret = db_env->open(db_env, jack_server_dir (server_name, server_dir), DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_THREAD, 0)) != 0) {
- jack_error ("cannot open DB environment: %s", db_strerror (ret));
- return -1;
- }
-
- if ((ret = db_create (&db, db_env, 0)) != 0) {
- jack_error ("Cannot initialize metadata DB (%s)", db_strerror (ret));
- return -1;
- }
-
- snprintf (dbpath, sizeof (dbpath), "%s/%s", jack_server_dir (server_name, server_dir), "metadata.db");
-
- if ((ret = db->open (db, NULL, dbpath, NULL, DB_HASH, DB_CREATE|DB_THREAD, 0666)) != 0) {
- jack_error ("Cannot open metadata DB at %s: %s", dbpath, db_strerror (ret));
- db->close (db, 0);
- db = NULL;
- return -1;
- }
-
- return 0;
+ int ret;
+ char dbpath[PATH_MAX + 1];
+ char server_dir[PATH_MAX + 1];
+
+ /* idempotent */
+
+ if (db_env) {
+ return 0;
+ }
+
+ if ((ret = db_env_create (&db_env, 0)) != 0) {
+ jack_error ("cannot initialize DB environment: %s\n", db_strerror (ret));
+ return -1;
+ }
+
+ if ((ret = db_env->open (db_env, jack_server_dir (server_name, server_dir), DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL | DB_THREAD, 0)) != 0) {
+ jack_error ("cannot open DB environment: %s", db_strerror (ret));
+ return -1;
+ }
+
+ if ((ret = db_create (&db, db_env, 0)) != 0) {
+ jack_error ("Cannot initialize metadata DB (%s)", db_strerror (ret));
+ return -1;
+ }
+
+ snprintf (dbpath, sizeof(dbpath), "%s/%s", jack_server_dir (server_name, server_dir), "metadata.db");
+
+ if ((ret = db->open (db, NULL, dbpath, NULL, DB_HASH, DB_CREATE | DB_THREAD, 0666)) != 0) {
+ jack_error ("Cannot open metadata DB at %s: %s", dbpath, db_strerror (ret));
+ db->close (db, 0);
+ db = NULL;
+ return -1;
+ }
+
+ return 0;
}
-static void jack_properties_uninit () __attribute__ ((destructor));
+static void jack_properties_uninit() __attribute__ ((destructor));
void
jack_properties_uninit ()
{
- if (db) {
- db->close (db, 0);
- db = NULL;
- }
- if (db_env) {
- db_env->close (db_env, 0);
- db_env = 0;
- }
+ if (db) {
+ db->close (db, 0);
+ db = NULL;
+ }
+ if (db_env) {
+ db_env->close (db_env, 0);
+ db_env = 0;
+ }
}
void
-jack_free_description(jack_description_t* desc, int free_actual_description_too)
+jack_free_description (jack_description_t* desc, int free_actual_description_too)
{
- uint32_t n;
-
- for (n = 0; n < desc->property_cnt; ++n) {
- free ((char*) desc->properties[n].key);
- free ((char*) desc->properties[n].data);
- if (desc->properties[n].type) {
- free ((char*) desc->properties[n].type);
- }
- }
+ uint32_t n;
+
+ for (n = 0; n < desc->property_cnt; ++n) {
+ free ((char*)desc->properties[n].key);
+ free ((char*)desc->properties[n].data);
+ if (desc->properties[n].type) {
+ free ((char*)desc->properties[n].type);
+ }
+ }
- free (desc->properties);
+ free (desc->properties);
- if (free_actual_description_too) {
- free (desc);
- }
+ if (free_actual_description_too) {
+ free (desc);
+ }
}
static int
jack_property_change_notify (jack_client_t* client, jack_uuid_t uuid, const char* key, jack_property_change_t change)
{
- jack_request_t req;
+ jack_request_t req;
- /* the engine passes in a NULL client when it removes metadata during port or client removal
- */
+ /* the engine passes in a NULL client when it removes metadata during port or client removal
+ */
- if (client == NULL) {
- return 0;
- }
+ if (client == NULL) {
+ return 0;
+ }
- req.type = PropertyChangeNotify;
- req.x.property.change = change;
- jack_uuid_copy (&req.x.property.uuid, uuid);
- req.x.property.keylen = key ? strlen (key) + 1 : 0;
- req.x.property.key = key;
- return jack_client_deliver_request (client, &req);
+ req.type = PropertyChangeNotify;
+ req.x.property.change = change;
+ jack_uuid_copy (&req.x.property.uuid, uuid);
+ req.x.property.keylen = key ? strlen (key) + 1 : 0;
+ req.x.property.key = key;
+ return jack_client_deliver_request (client, &req);
}
static void
make_key_dbt (DBT* dbt, jack_uuid_t subject, const char* key)
{
- char ustr[JACK_UUID_STRING_SIZE];
- size_t len1, len2;
-
- memset(dbt, 0, sizeof(DBT));
- memset(ustr, 0, JACK_UUID_STRING_SIZE);
- jack_uuid_unparse (subject, ustr);
- len1 = JACK_UUID_STRING_SIZE;
- len2 = strlen (key) + 1;
- dbt->size = len1 + len2;
- dbt->data = malloc (dbt->size);
- memcpy (dbt->data, ustr, len1); // copy subject+null
- memcpy (dbt->data + len1, key, len2); // copy key+null
+ char ustr[JACK_UUID_STRING_SIZE];
+ size_t len1, len2;
+
+ memset (dbt, 0, sizeof(DBT));
+ memset (ustr, 0, JACK_UUID_STRING_SIZE);
+ jack_uuid_unparse (subject, ustr);
+ len1 = JACK_UUID_STRING_SIZE;
+ len2 = strlen (key) + 1;
+ dbt->size = len1 + len2;
+ dbt->data = malloc (dbt->size);
+ memcpy (dbt->data, ustr, len1); // copy subject+null
+ memcpy (dbt->data + len1, key, len2); // copy key+null
}
int
jack_set_property (jack_client_t* client,
- jack_uuid_t subject,
- const char* key,
- const char* value,
- const char* type)
+ jack_uuid_t subject,
+ const char* key,
+ const char* value,
+ const char* type)
{
- DBT d_key;
- DBT data;
- int ret;
- size_t len1, len2;
- jack_property_change_t change;
-
- if (!key || key[0] == '\0') {
- jack_error ("empty key string for metadata not allowed");
- return -1;
- }
-
- if (!value || value[0] == '\0') {
- jack_error ("empty value string for metadata not allowed");
- return -1;
- }
-
- if (jack_property_init (NULL)) {
- return -1;
- }
-
- /* build a key */
-
- make_key_dbt (&d_key, subject, key);
-
- /* build data */
-
- memset(&data, 0, sizeof(data));
-
- len1 = strlen(value) + 1;
- if (type && type[0] != '\0') {
- len2 = strlen(type) + 1;
- } else {
- len2 = 0;
- }
-
- data.size = len1 + len2;
- data.data = malloc (data.size);
- memcpy (data.data, value, len1);
-
- if (len2) {
- memcpy (data.data + len1, type, len2);
- }
-
- if (db->exists (db, NULL, &d_key, 0) == DB_NOTFOUND) {
- change = PropertyCreated;
- } else {
- change = PropertyChanged;
- }
-
- if ((ret = db->put (db, NULL, &d_key, &data, 0)) != 0) {
- char ustr[JACK_UUID_STRING_SIZE];
- jack_uuid_unparse (subject, ustr);
- jack_error ("Cannot store metadata for %s/%s (%s)", ustr, key, db_strerror (ret));
- if (d_key.size > 0) free(d_key.data);
- if (data.size > 0) free(data.data);
- return -1;
- }
-
- jack_property_change_notify (client, subject, key, change);
-
- if (d_key.size > 0) free(d_key.data);
- if (data.size > 0) free(data.data);
-
- return 0;
+ DBT d_key;
+ DBT data;
+ int ret;
+ size_t len1, len2;
+ jack_property_change_t change;
+
+ if (!key || key[0] == '\0') {
+ jack_error ("empty key string for metadata not allowed");
+ return -1;
+ }
+
+ if (!value || value[0] == '\0') {
+ jack_error ("empty value string for metadata not allowed");
+ return -1;
+ }
+
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
+
+ /* build a key */
+
+ make_key_dbt (&d_key, subject, key);
+
+ /* build data */
+
+ memset (&data, 0, sizeof(data));
+
+ len1 = strlen (value) + 1;
+ if (type && type[0] != '\0') {
+ len2 = strlen (type) + 1;
+ } else {
+ len2 = 0;
+ }
+
+ data.size = len1 + len2;
+ data.data = malloc (data.size);
+ memcpy (data.data, value, len1);
+
+ if (len2) {
+ memcpy (data.data + len1, type, len2);
+ }
+
+ if (db->exists (db, NULL, &d_key, 0) == DB_NOTFOUND) {
+ change = PropertyCreated;
+ } else {
+ change = PropertyChanged;
+ }
+
+ if ((ret = db->put (db, NULL, &d_key, &data, 0)) != 0) {
+ char ustr[JACK_UUID_STRING_SIZE];
+ jack_uuid_unparse (subject, ustr);
+ jack_error ("Cannot store metadata for %s/%s (%s)", ustr, key, db_strerror (ret));
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ if (data.size > 0) {
+ free (data.data);
+ }
+ return -1;
+ }
+
+ jack_property_change_notify (client, subject, key, change);
+
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ if (data.size > 0) {
+ free (data.data);
+ }
+
+ return 0;
}
int
jack_get_property (jack_uuid_t subject,
- const char* key,
- char** value,
- char** type)
+ const char* key,
+ char** value,
+ char** type)
{
- DBT d_key;
- DBT data;
- int ret;
- size_t len1, len2;
-
- if (key == NULL || key[0] == '\0') {
- return -1;
- }
-
- if (jack_property_init (NULL)) {
- return -1;
- }
-
- /* build a key */
-
- make_key_dbt (&d_key, subject, key);
-
- /* setup data DBT */
-
- memset(&data, 0, sizeof(data));
- data.flags = DB_DBT_MALLOC;
-
- if ((ret = db->get (db, NULL, &d_key, &data, 0)) != 0) {
- if (ret != DB_NOTFOUND) {
- char ustr[JACK_UUID_STRING_SIZE];
- jack_uuid_unparse (subject, ustr);
- jack_error ("Cannot metadata for %s/%s (%s)", ustr, key, db_strerror (ret));
- }
- if (d_key.size > 0) free(d_key.data);
- if (data.size > 0) free(data.data);
- return -1;
- }
-
- /* result must have at least 2 chars plus 2 nulls to be valid
- */
-
- if (data.size < 4) {
- if (d_key.size > 0) free(d_key.data);
- if (data.size > 0) free(data.data);
- return -1;
- }
-
- len1 = strlen (data.data) + 1;
- (*value) = (char *) malloc (len1);
- memcpy (*value, data.data, len1);
-
- if (len1 < data.size) {
- len2 = strlen (data.data+len1) + 1;
-
- (*type) = (char *) malloc (len2);
- memcpy (*type, data.data+len1, len2);
- } else {
- /* no type specified, assume default */
- *type = NULL;
- }
-
- if (d_key.size > 0) free(d_key.data);
- if (data.size > 0) free(data.data);
-
- return 0;
+ DBT d_key;
+ DBT data;
+ int ret;
+ size_t len1, len2;
+
+ if (key == NULL || key[0] == '\0') {
+ return -1;
+ }
+
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
+
+ /* build a key */
+
+ make_key_dbt (&d_key, subject, key);
+
+ /* setup data DBT */
+
+ memset (&data, 0, sizeof(data));
+ data.flags = DB_DBT_MALLOC;
+
+ if ((ret = db->get (db, NULL, &d_key, &data, 0)) != 0) {
+ if (ret != DB_NOTFOUND) {
+ char ustr[JACK_UUID_STRING_SIZE];
+ jack_uuid_unparse (subject, ustr);
+ jack_error ("Cannot metadata for %s/%s (%s)", ustr, key, db_strerror (ret));
+ }
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ if (data.size > 0) {
+ free (data.data);
+ }
+ return -1;
+ }
+
+ /* result must have at least 2 chars plus 2 nulls to be valid
+ */
+
+ if (data.size < 4) {
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ if (data.size > 0) {
+ free (data.data);
+ }
+ return -1;
+ }
+
+ len1 = strlen (data.data) + 1;
+ (*value) = (char*)malloc (len1);
+ memcpy (*value, data.data, len1);
+
+ if (len1 < data.size) {
+ len2 = strlen (data.data + len1) + 1;
+
+ (*type) = (char*)malloc (len2);
+ memcpy (*type, data.data + len1, len2);
+ } else {
+ /* no type specified, assume default */
+ *type = NULL;
+ }
+
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ if (data.size > 0) {
+ free (data.data);
+ }
+
+ return 0;
}
int
jack_get_properties (jack_uuid_t subject,
- jack_description_t* desc)
+ jack_description_t* desc)
{
- DBT key;
- DBT data;
- DBC* cursor;
- int ret;
- size_t len1, len2;
- size_t cnt = 0;
- char ustr[JACK_UUID_STRING_SIZE];
- size_t props_size = 0;
- jack_property_t* prop;
-
- desc->properties = NULL;
- desc->property_cnt = 0;
-
- memset(ustr, 0, JACK_UUID_STRING_SIZE);
- jack_uuid_unparse (subject, ustr);
-
- if (jack_property_init (NULL)) {
- return -1;
- }
-
-
- if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
- jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
- return -1;
- }
-
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- data.flags = DB_DBT_MALLOC;
-
- while ((ret = cursor->get(cursor, &key, &data, DB_NEXT)) == 0) {
-
- /* require 2 extra chars (data+null) for key,
- which is composed of UUID str plus a key name
- */
-
- if (key.size < JACK_UUID_STRING_SIZE + 2) {
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- if (memcmp (ustr, key.data, JACK_UUID_STRING_SIZE) != 0) {
- /* not relevant */
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- /* result must have at least 2 chars plus 2 nulls to be valid
- */
-
- if (data.size < 4) {
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- /* realloc array if necessary */
-
- if (cnt == props_size) {
- if (props_size == 0) {
- props_size = 8; /* a rough guess at a likely upper bound for the number of properties */
- } else {
- props_size *= 2;
- }
-
- desc->properties = (jack_property_t*) realloc (desc->properties, sizeof (jack_property_t) * props_size);
- }
-
- prop = &desc->properties[cnt];
-
- /* store UUID/subject */
-
- jack_uuid_copy (&desc->subject, subject);
-
- /* copy key (without leading UUID as subject */
-
- len1 = key.size - JACK_UUID_STRING_SIZE;
- prop->key = malloc (len1);
- memcpy ((char*) prop->key, key.data + JACK_UUID_STRING_SIZE, len1);
-
- /* copy data (which contains 1 or 2 null terminated strings, the value
- and optionally a MIME type.
- */
-
- len1 = strlen (data.data) + 1;
- prop->data = (char *) malloc (len1);
- memcpy ((char*) prop->data, data.data, len1);
-
- if (len1 < data.size) {
- len2 = strlen (data.data+len1) + 1;
-
- prop->type= (char *) malloc (len2);
- memcpy ((char*) prop->type, data.data+len1, len2);
- } else {
- /* no type specified, assume default */
- prop->type = NULL;
- }
-
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
-
- ++cnt;
- }
-
- cursor->close (cursor);
- desc->property_cnt = cnt;
-
- return cnt;
+ DBT key;
+ DBT data;
+ DBC* cursor;
+ int ret;
+ size_t len1, len2;
+ size_t cnt = 0;
+ char ustr[JACK_UUID_STRING_SIZE];
+ size_t props_size = 0;
+ jack_property_t* prop;
+
+ desc->properties = NULL;
+ desc->property_cnt = 0;
+
+ memset (ustr, 0, JACK_UUID_STRING_SIZE);
+ jack_uuid_unparse (subject, ustr);
+
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
+
+
+ if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
+ jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
+ return -1;
+ }
+
+ memset (&key, 0, sizeof(key));
+ memset (&data, 0, sizeof(data));
+ data.flags = DB_DBT_MALLOC;
+
+ while ((ret = cursor->get (cursor, &key, &data, DB_NEXT)) == 0) {
+
+ /* require 2 extra chars (data+null) for key,
+ which is composed of UUID str plus a key name
+ */
+
+ if (key.size < JACK_UUID_STRING_SIZE + 2) {
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ if (memcmp (ustr, key.data, JACK_UUID_STRING_SIZE) != 0) {
+ /* not relevant */
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ /* result must have at least 2 chars plus 2 nulls to be valid
+ */
+
+ if (data.size < 4) {
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ /* realloc array if necessary */
+
+ if (cnt == props_size) {
+ if (props_size == 0) {
+ props_size = 8; /* a rough guess at a likely upper bound for the number of properties */
+ } else {
+ props_size *= 2;
+ }
+
+ desc->properties = (jack_property_t*)realloc (desc->properties, sizeof(jack_property_t) * props_size);
+ }
+
+ prop = &desc->properties[cnt];
+
+ /* store UUID/subject */
+
+ jack_uuid_copy (&desc->subject, subject);
+
+ /* copy key (without leading UUID as subject */
+
+ len1 = key.size - JACK_UUID_STRING_SIZE;
+ prop->key = malloc (len1);
+ memcpy ((char*)prop->key, key.data + JACK_UUID_STRING_SIZE, len1);
+
+ /* copy data (which contains 1 or 2 null terminated strings, the value
+ and optionally a MIME type.
+ */
+
+ len1 = strlen (data.data) + 1;
+ prop->data = (char*)malloc (len1);
+ memcpy ((char*)prop->data, data.data, len1);
+
+ if (len1 < data.size) {
+ len2 = strlen (data.data + len1) + 1;
+
+ prop->type = (char*)malloc (len2);
+ memcpy ((char*)prop->type, data.data + len1, len2);
+ } else {
+ /* no type specified, assume default */
+ prop->type = NULL;
+ }
+
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+
+ ++cnt;
+ }
+
+ cursor->close (cursor);
+ desc->property_cnt = cnt;
+
+ return cnt;
}
int
jack_get_all_properties (jack_description_t** descriptions)
{
- DBT key;
- DBT data;
- DBC* cursor;
- int ret;
- size_t dcnt = 0;
- size_t dsize = 0;
- size_t n = 0;
- jack_description_t* desc = NULL;
- jack_uuid_t uuid = JACK_UUID_EMPTY_INITIALIZER;
- jack_description_t* current_desc = NULL;
- jack_property_t* current_prop = NULL;
- size_t len1, len2;
-
- if (jack_property_init (NULL)) {
- return -1;
- }
-
- if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
- jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
- return -1;
- }
-
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- data.flags = DB_DBT_MALLOC;
-
- dsize = 8; /* initial guess at number of descriptions we need */
- dcnt = 0;
- desc = (jack_description_t*) malloc (dsize * sizeof (jack_description_t));
-
- while ((ret = cursor->get(cursor, &key, &data, DB_NEXT)) == 0) {
-
- /* require 2 extra chars (data+null) for key,
- which is composed of UUID str plus a key name
- */
-
- if (key.size < JACK_UUID_STRING_SIZE + 2) {
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- if (jack_uuid_parse (key.data, &uuid) != 0) {
- continue;
- }
-
- /* do we have an existing description for this UUID */
-
- for (n = 0; n < dcnt ; ++n) {
- if (jack_uuid_compare (uuid, desc[n].subject) == 0) {
- break;
- }
- }
-
- if (n == dcnt) {
- /* we do not have an existing description, so grow the array */
-
- if (dcnt == dsize) {
- dsize *= 2;
- desc = (jack_description_t*) realloc (desc, sizeof (jack_description_t) * dsize);
- }
-
- /* initialize */
-
- desc[n].property_size = 0;
- desc[n].property_cnt = 0;
- desc[n].properties = NULL;
-
- /* set up UUID */
-
- jack_uuid_copy (&desc[n].subject, uuid);
- dcnt++;
- }
-
- current_desc = &desc[n];
-
- /* see if there is room for the new property or if we need to realloc
- */
-
- if (current_desc->property_cnt == current_desc->property_size) {
- if (current_desc->property_size == 0) {
- current_desc->property_size = 8;
- } else {
- current_desc->property_size *= 2;
- }
-
- current_desc->properties = (jack_property_t*) realloc (current_desc->properties, sizeof (jack_property_t) * current_desc->property_size);
- }
-
- current_prop = &current_desc->properties[current_desc->property_cnt++];
-
- /* copy key (without leading UUID) */
-
- len1 = key.size - JACK_UUID_STRING_SIZE;
- current_prop->key = malloc (len1);
- memcpy ((char*) current_prop->key, key.data + JACK_UUID_STRING_SIZE, len1);
-
- /* copy data (which contains 1 or 2 null terminated strings, the value
- and optionally a MIME type.
- */
-
- len1 = strlen (data.data) + 1;
- current_prop->data = (char *) malloc (len1);
- memcpy ((char*) current_prop->data, data.data, len1);
-
- if (len1 < data.size) {
- len2 = strlen (data.data+len1) + 1;
-
- current_prop->type= (char *) malloc (len2);
- memcpy ((char*) current_prop->type, data.data+len1, len2);
- } else {
- /* no type specified, assume default */
- current_prop->type = NULL;
- }
-
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- }
-
- cursor->close (cursor);
-
- (*descriptions) = desc;
-
- return dcnt;
+ DBT key;
+ DBT data;
+ DBC* cursor;
+ int ret;
+ size_t dcnt = 0;
+ size_t dsize = 0;
+ size_t n = 0;
+ jack_description_t* desc = NULL;
+ jack_uuid_t uuid = JACK_UUID_EMPTY_INITIALIZER;
+ jack_description_t* current_desc = NULL;
+ jack_property_t* current_prop = NULL;
+ size_t len1, len2;
+
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
+
+ if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
+ jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
+ return -1;
+ }
+
+ memset (&key, 0, sizeof(key));
+ memset (&data, 0, sizeof(data));
+ data.flags = DB_DBT_MALLOC;
+
+ dsize = 8; /* initial guess at number of descriptions we need */
+ dcnt = 0;
+ desc = (jack_description_t*)malloc (dsize * sizeof(jack_description_t));
+
+ while ((ret = cursor->get (cursor, &key, &data, DB_NEXT)) == 0) {
+
+ /* require 2 extra chars (data+null) for key,
+ which is composed of UUID str plus a key name
+ */
+
+ if (key.size < JACK_UUID_STRING_SIZE + 2) {
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ if (jack_uuid_parse (key.data, &uuid) != 0) {
+ continue;
+ }
+
+ /* do we have an existing description for this UUID */
+
+ for (n = 0; n < dcnt; ++n) {
+ if (jack_uuid_compare (uuid, desc[n].subject) == 0) {
+ break;
+ }
+ }
+
+ if (n == dcnt) {
+ /* we do not have an existing description, so grow the array */
+
+ if (dcnt == dsize) {
+ dsize *= 2;
+ desc = (jack_description_t*)realloc (desc, sizeof(jack_description_t) * dsize);
+ }
+
+ /* initialize */
+
+ desc[n].property_size = 0;
+ desc[n].property_cnt = 0;
+ desc[n].properties = NULL;
+
+ /* set up UUID */
+
+ jack_uuid_copy (&desc[n].subject, uuid);
+ dcnt++;
+ }
+
+ current_desc = &desc[n];
+
+ /* see if there is room for the new property or if we need to realloc
+ */
+
+ if (current_desc->property_cnt == current_desc->property_size) {
+ if (current_desc->property_size == 0) {
+ current_desc->property_size = 8;
+ } else {
+ current_desc->property_size *= 2;
+ }
+
+ current_desc->properties = (jack_property_t*)realloc (current_desc->properties, sizeof(jack_property_t) * current_desc->property_size);
+ }
+
+ current_prop = &current_desc->properties[current_desc->property_cnt++];
+
+ /* copy key (without leading UUID) */
+
+ len1 = key.size - JACK_UUID_STRING_SIZE;
+ current_prop->key = malloc (len1);
+ memcpy ((char*)current_prop->key, key.data + JACK_UUID_STRING_SIZE, len1);
+
+ /* copy data (which contains 1 or 2 null terminated strings, the value
+ and optionally a MIME type.
+ */
+
+ len1 = strlen (data.data) + 1;
+ current_prop->data = (char*)malloc (len1);
+ memcpy ((char*)current_prop->data, data.data, len1);
+
+ if (len1 < data.size) {
+ len2 = strlen (data.data + len1) + 1;
+
+ current_prop->type = (char*)malloc (len2);
+ memcpy ((char*)current_prop->type, data.data + len1, len2);
+ } else {
+ /* no type specified, assume default */
+ current_prop->type = NULL;
+ }
+
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ }
+
+ cursor->close (cursor);
+
+ (*descriptions) = desc;
+
+ return dcnt;
}
int
-jack_get_description (jack_uuid_t subject,
- jack_description_t* desc)
+jack_get_description (jack_uuid_t subject,
+ jack_description_t* desc)
{
- return 0;
+ return 0;
}
int
jack_get_all_descriptions (jack_description_t** descs)
{
- return 0;
+ return 0;
}
-int
+int
jack_set_property_change_callback (jack_client_t *client,
- JackPropertyChangeCallback callback, void *arg)
+ JackPropertyChangeCallback callback, void *arg)
{
if (client->control->active) {
jack_error ("You cannot set callbacks on an active client.");
@@ -563,118 +595,128 @@ jack_set_property_change_callback (jack_client_t *client,
return 0;
}
-int
+int
jack_remove_property (jack_client_t* client, jack_uuid_t subject, const char* key)
{
- DBT d_key;
- int ret;
+ DBT d_key;
+ int ret;
- if (jack_property_init (NULL)) {
- return -1;
- }
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
- make_key_dbt (&d_key, subject, key);
- if ((ret = db->del (db, NULL, &d_key, 0)) != 0) {
- jack_error ("Cannot delete key %s (%s)", key, db_strerror (ret));
- if (d_key.size > 0) free(d_key.data);
- return -1;
- }
+ make_key_dbt (&d_key, subject, key);
+ if ((ret = db->del (db, NULL, &d_key, 0)) != 0) {
+ jack_error ("Cannot delete key %s (%s)", key, db_strerror (ret));
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
+ return -1;
+ }
- jack_property_change_notify (client, subject, key, PropertyDeleted);
+ jack_property_change_notify (client, subject, key, PropertyDeleted);
- if (d_key.size > 0) free(d_key.data);
+ if (d_key.size > 0) {
+ free (d_key.data);
+ }
- return 0;
+ return 0;
}
-int
+int
jack_remove_properties (jack_client_t* client, jack_uuid_t subject)
{
- DBT key;
- DBT data;
- DBC* cursor;
- int ret;
- char ustr[JACK_UUID_STRING_SIZE];
- int retval = 0;
- uint32_t cnt = 0;
-
- memset(ustr, 0, JACK_UUID_STRING_SIZE);
- jack_uuid_unparse (subject, ustr);
-
- if (jack_property_init (NULL)) {
- return -1;
- }
-
- if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
- jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
- return -1;
- }
-
- memset(&key, 0, sizeof(key));
- memset(&data, 0, sizeof(data));
- data.flags = DB_DBT_MALLOC;
-
- while ((ret = cursor->get(cursor, &key, &data, DB_NEXT)) == 0) {
-
- /* require 2 extra chars (data+null) for key,
- which is composed of UUID str plus a key name
- */
-
- if (key.size < JACK_UUID_STRING_SIZE + 2) {
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- if (memcmp (ustr, key.data, JACK_UUID_STRING_SIZE) != 0) {
- /* not relevant */
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- continue;
- }
-
- if ((ret = cursor->del (cursor, 0)) != 0) {
- jack_error ("cannot delete property (%s)", db_strerror (ret));
- /* don't return -1 here since this would leave things
- even more inconsistent. wait till the cursor is finished
- */
- retval = -1;
- }
- cnt++;
-
- /* if (key.size > 0) free(key.data); */
- if (data.size > 0) free(data.data);
- }
-
- cursor->close (cursor);
-
- if (cnt) {
- jack_property_change_notify (client, subject, NULL, PropertyDeleted);
- }
-
- if (retval) {
- return -1;
- }
-
- return cnt;
+ DBT key;
+ DBT data;
+ DBC* cursor;
+ int ret;
+ char ustr[JACK_UUID_STRING_SIZE];
+ int retval = 0;
+ uint32_t cnt = 0;
+
+ memset (ustr, 0, JACK_UUID_STRING_SIZE);
+ jack_uuid_unparse (subject, ustr);
+
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
+
+ if ((ret = db->cursor (db, NULL, &cursor, 0)) != 0) {
+ jack_error ("Cannot create cursor for metadata search (%s)", db_strerror (ret));
+ return -1;
+ }
+
+ memset (&key, 0, sizeof(key));
+ memset (&data, 0, sizeof(data));
+ data.flags = DB_DBT_MALLOC;
+
+ while ((ret = cursor->get (cursor, &key, &data, DB_NEXT)) == 0) {
+
+ /* require 2 extra chars (data+null) for key,
+ which is composed of UUID str plus a key name
+ */
+
+ if (key.size < JACK_UUID_STRING_SIZE + 2) {
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ if (memcmp (ustr, key.data, JACK_UUID_STRING_SIZE) != 0) {
+ /* not relevant */
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ continue;
+ }
+
+ if ((ret = cursor->del (cursor, 0)) != 0) {
+ jack_error ("cannot delete property (%s)", db_strerror (ret));
+ /* don't return -1 here since this would leave things
+ even more inconsistent. wait till the cursor is finished
+ */
+ retval = -1;
+ }
+ cnt++;
+
+ /* if (key.size > 0) free(key.data); */
+ if (data.size > 0) {
+ free (data.data);
+ }
+ }
+
+ cursor->close (cursor);
+
+ if (cnt) {
+ jack_property_change_notify (client, subject, NULL, PropertyDeleted);
+ }
+
+ if (retval) {
+ return -1;
+ }
+
+ return cnt;
}
-int
+int
jack_remove_all_properties (jack_client_t* client)
{
- int ret;
- jack_uuid_t empty_uuid = JACK_UUID_EMPTY_INITIALIZER;
+ int ret;
+ jack_uuid_t empty_uuid = JACK_UUID_EMPTY_INITIALIZER;
- if (jack_property_init (NULL)) {
- return -1;
- }
+ if (jack_property_init (NULL)) {
+ return -1;
+ }
- if ((ret = db->truncate (db, NULL, NULL, 0)) != 0) {
- jack_error ("Cannot clear properties (%s)", db_strerror (ret));
- return -1;
- }
+ if ((ret = db->truncate (db, NULL, NULL, 0)) != 0) {
+ jack_error ("Cannot clear properties (%s)", db_strerror (ret));
+ return -1;
+ }
- jack_property_change_notify (client, empty_uuid, NULL, PropertyDeleted);
+ jack_property_change_notify (client, empty_uuid, NULL, PropertyDeleted);
- return 0;
+ return 0;
}