changeset 599:c6debbac3216

End-to-end functioning SPARQL with audioDB storage module * AudioDB RDF storage module now works correctly with dimension and vectors * Apache module now returns a sparql version of the query results. * (including cleanup close/free calls).
author mas01mj
date Thu, 13 Aug 2009 11:20:56 +0000
parents b2a941a372fb
children 337e5962218a
files sparql/librdf/src/rdf_storage_audiodb.c sparql/mod_audiodb/Makefile.am sparql/mod_audiodb/mod_audiodb.c
diffstat 3 files changed, 235 insertions(+), 111 deletions(-) [+]
line wrap: on
line diff
--- a/sparql/librdf/src/rdf_storage_audiodb.c	Wed Aug 12 14:57:11 2009 +0000
+++ b/sparql/librdf/src/rdf_storage_audiodb.c	Thu Aug 13 11:20:56 2009 +0000
@@ -10,28 +10,25 @@
 #include <librdf.h>
 #include <audioDB_API.h>
 
+/**
+ * NB : This is pulled through from librdf internals. Not ideal, but
+ * otherwise we'd need to compile against their source tree!
+ **/
+
 #define LIBRDF_SIGN_KEY 0x04Ed1A7D
 
+
 typedef struct {
 	librdf_model* model;
 	librdf_storage* storage;
-	char *name;
+	char* name;
 	size_t name_len;
 	int is_new;
 
-	adb_t *adb;
+	adb_t* adb;
 
 } librdf_storage_audiodb_instance;
 
-typedef struct {
-	librdf_storage* storage;
-	librdf_storage_audiodb_instance* audiodb_context;
-	int finished;
-	librdf_statement* statement;
-	librdf_statement* query_statement;
-	librdf_node* context;
-
-} librdf_storage_audiodb_find_statements_stream_context;
 
 static int librdf_storage_audiodb_init(librdf_storage* storage, const char *name, librdf_hash* options);
 static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model);
@@ -55,6 +52,10 @@
 static void librdf_storage_audiodb_register_factory(librdf_storage_factory *factory);
 void librdf_storage_module_register_factory(librdf_world *world);
 
+/**
+ * These 3 are from librdf's rdf_internals - simplify the mallocing/freeing a bit.
+ */
+
 void librdf_sign_free(void *ptr)
 {
 	int *p;
@@ -138,7 +139,6 @@
 }
 
 static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model) {
-
 	librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);
 	int db_file_exists = 0;
 
@@ -214,8 +214,50 @@
 }
 
 static int librdf_storage_audiodb_contains_statement(librdf_storage* storage, librdf_statement* statement) {
-	librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
-		"Contains statement");
+
+	librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);	
+	librdf_world* world = librdf_storage_get_world(storage);
+	
+	librdf_node* subject = librdf_statement_get_subject(statement);
+	librdf_node* object = librdf_statement_get_object(statement);
+	librdf_node* predicate = librdf_statement_get_predicate(statement);
+
+
+	if(subject && object && predicate)
+	{
+		// audioDBs only contain Signals (tracks are held in a separate store).
+
+		librdf_uri* type_uri = librdf_new_uri(world, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
+		librdf_uri* signal_uri = librdf_new_uri(world, "http://purl.org/ontology/mo/Signal");
+		if(librdf_uri_equals(type_uri, librdf_node_get_uri(predicate)))
+		{
+			librdf_uri* object_uri = librdf_node_get_uri(object);
+			if(librdf_uri_equals(object_uri, signal_uri))
+			{
+				// Grab the track via audioDB
+				adb_datum_t datum = {0};
+				librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+					"Retrieve datum");
+				int result = audiodb_retrieve_datum(
+					context->adb, 
+					librdf_uri_as_string(librdf_node_get_uri(subject)),
+					&datum);
+				librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+					"Back...");
+				if(result == 0)
+				{
+					librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+						"Found datum");
+
+					// Found it! Free up the datum.
+					audiodb_free_datum(context->adb, &datum);
+					return 1;
+				}
+			}
+		}
+		librdf_free_uri(type_uri);
+		librdf_free_uri(signal_uri);
+	}
 	return 0;
 }
 
@@ -225,15 +267,86 @@
 	return NULL;
 }
 
+/**
+ * Linked list bits
+ */
+
+
+struct list_node_s
+{
+	struct list_node_s* next;
+	struct list_node_s* prev;
+	librdf_statement* statement;
+};
+
+typedef struct list_node_s list_node;
+
+struct list_s {
+	list_node* head;
+	list_node* tail;
+};
+
+typedef struct list_s result_list;
+
+result_list* result_data_new()
+{
+	result_list* list = (result_list*)calloc(1, sizeof(result_list));
+	if(!list)
+		return NULL;
+	return list;
+}
+
+int result_data_add(librdf_world* world, result_list* list) {
+
+	// First create the node
+	list_node* node = (list_node*)calloc(1, sizeof(list_node));
+
+	if(!node)
+		return 1;
+	
+	if(list->tail)
+	{
+		node->prev = list->tail;
+		list->tail->next = node;
+	}
+
+	list->tail = node;
+	if(!list->head)
+		list->head = node;
+	return 0;
+}
+
+/**
+ * Querying bits.
+ **/
+
+typedef struct {
+	librdf_storage* storage;
+	librdf_storage_audiodb_instance* audiodb_context;
+	int finished;
+	librdf_statement* statement;
+	librdf_statement* query_statement;
+	librdf_node* context;
+	result_list *results;
+
+} librdf_storage_audiodb_find_statements_stream_context;
+
+
+
+
 static librdf_stream* librdf_storage_audiodb_find_statements(librdf_storage* storage, librdf_statement* statement) {
 
 	librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);	
 	librdf_storage_audiodb_find_statements_stream_context* scontext;
 	librdf_stream* stream;
-	
+
+
+	librdf_world* world = librdf_storage_get_world(storage);
+
 	librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
-	"find statements %s", librdf_statement_to_string(statement));
+			"find statements %s", librdf_statement_to_string(statement));
 
+	// Create stream context 
 	scontext = (librdf_storage_audiodb_find_statements_stream_context*)librdf_sign_calloc(1, sizeof(librdf_storage_audiodb_find_statements_stream_context));
 
 	if(!scontext)
@@ -241,23 +354,88 @@
 
 	scontext->storage = storage;
 	librdf_storage_add_reference(scontext->storage);
-
+	
+	// Store a reference to the storage instance.
 	scontext->audiodb_context = context;
 
+	// Clone the query statement and store away.
 	scontext->query_statement = librdf_new_statement_from_statement(statement);
 	if(!scontext->query_statement) {
 		librdf_storage_audiodb_find_statements_finished((void*)scontext);
 		return NULL;
 	}
 
-	stream = librdf_new_stream(librdf_storage_get_world(storage),
-								(void*)scontext,
-								&librdf_storage_audiodb_find_statements_end_of_stream,
-								&librdf_storage_audiodb_find_statements_next_statement,
-								&librdf_storage_audiodb_find_statements_get_statement,
-								&librdf_storage_audiodb_find_statements_finished);
+	scontext->results = result_data_new();
+
+	// This will need factoring out
+	librdf_node* subject = librdf_statement_get_subject(statement);
+	librdf_node* object = librdf_statement_get_object(statement);
+	librdf_node* predicate = librdf_statement_get_predicate(statement);
+
+	librdf_uri* dimension = librdf_new_uri(world, "http://purl.org/ontology/af/dimension");
+	librdf_uri* vectors = librdf_new_uri(world, "http://purl.org/ontology/af/vectors");
+
+	if(librdf_node_is_resource(subject) && librdf_node_is_resource(predicate))
+	{
+		librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+			"Got SPX");
+		librdf_uri* predicate_uri = librdf_node_get_uri(predicate);
+		if(librdf_uri_equals(predicate_uri, dimension) || librdf_uri_equals(predicate_uri, vectors)) 
+		{
+			// Need dimension or vectors - so get the track datum.
+			adb_datum_t datum = {0};
+			librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+				"Retrieve datum");
+			int result = audiodb_retrieve_datum(
+				context->adb, 
+				librdf_uri_as_string(librdf_node_get_uri(subject)),
+				&datum);
+			if(result == 0)
+			{
+				librdf_node* value;
+				raptor_stringbuffer* buffer = raptor_new_stringbuffer();
+				
+				if(librdf_uri_equals(predicate_uri, dimension))
+				{
+					raptor_stringbuffer_append_decimal(buffer, datum.dim);
+					value = librdf_new_node_from_typed_literal(world, raptor_stringbuffer_as_string(buffer), NULL, librdf_new_uri(world, "xsd:integer"));
+				}
+				else if(librdf_uri_equals(predicate_uri, vectors))
+				{
+					raptor_stringbuffer_append_decimal(buffer, datum.nvectors);
+					value = librdf_new_node_from_typed_literal(world, raptor_stringbuffer_as_string(buffer), NULL, librdf_new_uri(world, "xsd:integer"));
+				}
+			
+			//	raptor_free_stringbuffer(value);
+
+				result_data_add(world, scontext->results);
+				
+				result_list* list = scontext->results;
+				
+
+				list->tail->statement = librdf_new_statement(world);
+				librdf_statement_set_subject(list->tail->statement, subject); 
+				librdf_statement_set_object(list->tail->statement, value);
+				librdf_statement_set_predicate(list->tail->statement, predicate);
+			}
+
+			librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+				"Done!");
+		}
+	}
+	librdf_free_uri(dimension);
+	librdf_free_uri(vectors);
+
+	stream = librdf_new_stream(world,
+		(void*)scontext,
+		&librdf_storage_audiodb_find_statements_end_of_stream,
+		&librdf_storage_audiodb_find_statements_next_statement,
+		&librdf_storage_audiodb_find_statements_get_statement,
+		&librdf_storage_audiodb_find_statements_finished);
 
 	if(!stream) {
+		librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+			"Couldn't create stream!");
 		librdf_storage_audiodb_find_statements_finished((void*)scontext);
 		return NULL;
 	}
@@ -267,6 +445,9 @@
 
 static void librdf_storage_audiodb_find_statements_finished(void* context) {
 	librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
+		
+	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+		"Finished!");
 
 	if(scontext->storage)
 		librdf_storage_remove_reference(scontext->storage);
@@ -283,102 +464,46 @@
 	librdf_sign_free(scontext);
 }
 
-static int librdf_storage_audiodb_get_next_common(librdf_storage_audiodb_instance* scontext,
-													librdf_statement **statement,
-													librdf_node **context_node) {
-
-	librdf_node* node;
-
-
-	if(!*statement) {
-		if(!(*statement = librdf_new_statement(librdf_storage_get_world(scontext->storage))))
-			return 1;
-	}
-	
-	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
-			"Handle statement %s", librdf_statement_to_string(*statement));
-
-	librdf_statement_clear(*statement);
-
-	node = librdf_new_node_from_uri_string(librdf_storage_get_world(scontext->storage), "testing");
-	
-	if(!node)
-		return 1;
-
-	librdf_statement_set_subject(*statement, node);
-
-	node = librdf_new_node_from_uri_string(librdf_storage_get_world(scontext->storage), "foootle");
-	
-	if(!node)
-		return 1;
-
-	librdf_statement_set_predicate(*statement, node);
-
-	node = librdf_new_node_from_uri_string(librdf_storage_get_world(scontext->storage), "barble");
-	
-	if(!node)
-		return 1;
-
-	librdf_statement_set_object(*statement, node);
-
-	return -1;
-}
-
 static int librdf_storage_audiodb_find_statements_end_of_stream(void* context) {
 	librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
+	librdf_world* world = librdf_storage_get_world(scontext->storage);
+	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+		"Finished?");
 
-	if(scontext->finished)
-		return 1;
-	
-	if(scontext->statement == NULL) {
-		int result;
-		result = librdf_storage_audiodb_get_next_common(scontext->audiodb_context,
-														&scontext->statement,
-														&scontext->context);
-
-		librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
-			"Handle eos statement %s %d", librdf_statement_to_string(scontext->query_statement), result);
-
-		if(result) {
-			scontext->finished = 1;
-		}
-	}
-	return scontext->finished;
-
+	return (scontext->results->head == NULL);
 }
 
 static int librdf_storage_audiodb_find_statements_next_statement(void* context) {
 	librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
-	int result;
-	
 
-	if(scontext->finished)
+	librdf_world* world = librdf_storage_get_world(scontext->storage);
+	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+		"to next");
+
+	if(scontext->results->head->next)
+	{
+		scontext->results->head = scontext->results->head->next;
+		return 0; 
+	}
+	else
+	{
 		return 1;
-		
-	result = librdf_storage_audiodb_get_next_common(scontext->audiodb_context,
-														&scontext->statement,
-														&scontext->context);
-
-	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
-		"Handle next statement %s %d", librdf_statement_to_string(scontext->query_statement), result);
-
-	if(result) {
-		scontext->finished = 1;
 	}
-
-	return result;
 }
 
 static void* librdf_storage_audiodb_find_statements_get_statement(void* context, int flags) {
 	librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
-	
+	librdf_world* world = librdf_storage_get_world(scontext->storage);
+	librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
+		"Get next");
+
 	switch(flags) {
 		case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
-			return scontext->statement;
+			return scontext->results->head->statement;
 		case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
 			return scontext->context;
 		default:
-			librdf_log(librdf_storage_get_world(scontext->storage),
+			librdf_log(world,
 				0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
  				"Unknown iterator method flag %d", flags);
 			return NULL;
--- a/sparql/mod_audiodb/Makefile.am	Wed Aug 12 14:57:11 2009 +0000
+++ b/sparql/mod_audiodb/Makefile.am	Thu Aug 13 11:20:56 2009 +0000
@@ -7,7 +7,7 @@
 EXTRA_DIST = $(SOURCE) $(HEAD)
 
 mod_audiodb.so: $(SOURCE) $(HEAD)
-		@APXS@ -Wc,-g\ -Wall `@APREQ2@ --ldflags --libs --includes` -lrdf -laudioDB -I/usr/include/ $(GLIB_CFLAGS) -c $(SOURCE)
+		@APXS@ -Wc,-g\ -Wall `@APREQ2@ --ldflags --libs --includes` `pkg-config rasqal --cflags --libs` -lrdf -laudioDB -I/usr/include/ $(GLIB_CFLAGS) -c $(SOURCE)
 
 install: mod_audiodb.so
 		@APXS@ -i -a `test -f mod_audiodb.so && echo "mod_audiodb.so" || echo "mod_audiodb.la"`
--- a/sparql/mod_audiodb/mod_audiodb.c	Wed Aug 12 14:57:11 2009 +0000
+++ b/sparql/mod_audiodb/mod_audiodb.c	Thu Aug 13 11:20:56 2009 +0000
@@ -9,6 +9,7 @@
 #include <apreq_parser.h>
 #include <apreq_param.h>
 #include "apreq2/apreq_module_apache2.h"
+#include <rasqal.h>
 
 static int ap_dump_table(void *baton, const char *key, const char *value)
 {
@@ -46,18 +47,10 @@
 	const unsigned char *query_string = apr_table_get(form_table, "query");
 
 	int rc = 0;
-
 	librdf_world* world = librdf_new_world();
-	if(!world)
-	{
-		rc = 1;
-		goto error;
-	}
-
-
 	librdf_world_open(world);
 	librdf_world_set_logger(world, NULL, log_out);
-	librdf_storage* storage = librdf_new_storage(world, "audiodb", "/tmp/test.adb", "new='yes'");
+	librdf_storage* storage = librdf_new_storage(world, "audiodb", "/tmp/test_database.adb", NULL);
 	if(!storage)
 	{
 		rc = 2;
@@ -85,7 +78,13 @@
 		goto error;
 	}
 
-	ap_rprintf(r, "Everything went awesomely!");
+	librdf_uri *sparql_uri = librdf_new_uri( world, "http://www.w3.org/TR/2006/WD-rdf-sparql-XMLres-20070614/");
+
+	unsigned char* out = librdf_query_results_to_string(results, sparql_uri, librdf_new_uri(world, "http://purl.org/ontology/af/")); 
+	librdf_storage_close(storage);
+	librdf_free_storage(storage);
+	librdf_free_world(world);
+	ap_rprintf(r, out); 
 
 	rc = 0;
 	return r->status;