mas01mj@585: #include mas01mj@584: #include mas01mj@584: #include mas01mj@584: #include mas01mj@584: #include mas01mj@584: #ifdef HAVE_STDLIB_H mas01mj@584: #include /* for abort() as used in errors */ mas01mj@584: #endif mas01mj@584: #include mas01mj@585: #include mas01mj@584: #include mas01mj@584: mas01mj@599: /** mas01mj@599: * NB : This is pulled through from librdf internals. Not ideal, but mas01mj@599: * otherwise we'd need to compile against their source tree! mas01mj@599: **/ mas01mj@599: mas01mj@585: #define LIBRDF_SIGN_KEY 0x04Ed1A7D mas01mj@584: mas01mj@603: #define AF_DIMENSION "http://purl.org/ontology/af/dimension" mas01mj@603: #define AF_VECTORS "http://purl.org/ontology/af/vectors" mas01mj@603: #define MO_SIGNAL "http://purl.org/ontology/mo/Signal" mas01mj@603: #define RDF_TYPE "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" mas01mj@660: #define SIMILARITY_ELEMENT "http://purl.org/ontology/similarity/element" mas01mj@660: #define SIMILARITY_DISTANCE "http://purl.org/ontology/similarity/distance" mas01mj@660: #define SIMILARITY_SIMILARITY "http://purl.org/ontology/similarity/Similarity" mas01mj@599: mas01mj@584: typedef struct { mas01mj@584: librdf_model* model; mas01mj@584: librdf_storage* storage; mas01mj@599: char* name; mas01mj@584: size_t name_len; mas01mj@584: int is_new; mas01mj@599: adb_t* adb; mas01mj@584: mas01mj@584: } librdf_storage_audiodb_instance; mas01mj@584: mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_init(librdf_storage* storage, const char *name, librdf_hash* options); mas01mj@584: static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model); mas01mj@584: static int librdf_storage_audiodb_close(librdf_storage* storage); mas01mj@584: static int librdf_storage_audiodb_size(librdf_storage* storage); mas01mj@584: static int librdf_storage_audiodb_add_statement(librdf_storage* storage, librdf_statement* statement); mas01mj@584: static int librdf_storage_audiodb_add_statements(librdf_storage* storage, librdf_stream* statement_stream); mas01mj@584: static int librdf_storage_audiodb_remove_statement(librdf_storage* storage, librdf_statement* statement); mas01mj@584: static int librdf_storage_audiodb_contains_statement(librdf_storage* storage, librdf_statement* statement); mas01mj@584: static librdf_stream* librdf_storage_audiodb_serialise(librdf_storage* storage); mas01mj@584: static librdf_stream* librdf_storage_audiodb_find_statements(librdf_storage* storage, librdf_statement* statement); mas01mj@584: mas01mj@584: /* find_statements implementing functions */ mas01mj@584: static int librdf_storage_audiodb_find_statements_end_of_stream(void* context); mas01mj@584: static int librdf_storage_audiodb_find_statements_next_statement(void* context); mas01mj@584: static void* librdf_storage_audiodb_find_statements_get_statement(void* context, int flags); mas01mj@584: static void librdf_storage_audiodb_find_statements_finished(void* context); mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_sync(librdf_storage *storage); mas01mj@584: mas01mj@584: static void librdf_storage_audiodb_register_factory(librdf_storage_factory *factory); mas01mj@584: void librdf_storage_module_register_factory(librdf_world *world); mas01mj@585: mas01mj@599: /** mas01mj@599: * These 3 are from librdf's rdf_internals - simplify the mallocing/freeing a bit. mas01mj@599: */ mas01mj@599: mas01mj@585: void librdf_sign_free(void *ptr) mas01mj@585: { mas01mj@585: int *p; mas01mj@585: mas01mj@585: if(!ptr) mas01mj@585: return; mas01mj@585: mas01mj@585: p=(int*)ptr; mas01mj@585: p--; mas01mj@585: mas01mj@585: if(*p != LIBRDF_SIGN_KEY) mas01mj@585: return; mas01mj@585: mas01mj@585: free(p); mas01mj@585: } mas01mj@585: mas01mj@585: mas01mj@585: void* librdf_sign_calloc(size_t nmemb, size_t size) mas01mj@585: { mas01mj@585: int *p; mas01mj@585: mas01mj@585: /* turn into bytes */ mas01mj@585: size = nmemb*size + sizeof(int); mas01mj@585: mas01mj@585: p=(int*)calloc(1, size); mas01mj@585: *p++ = LIBRDF_SIGN_KEY; mas01mj@585: return p; mas01mj@585: } mas01mj@585: mas01mj@585: void* librdf_sign_malloc(size_t size) mas01mj@585: { mas01mj@585: int *p; mas01mj@585: mas01mj@585: size += sizeof(int); mas01mj@585: mas01mj@585: p=(int*)malloc(size); mas01mj@585: *p++ = LIBRDF_SIGN_KEY; mas01mj@585: return p; mas01mj@585: } mas01mj@584: mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_init(librdf_storage* storage, const char *name, librdf_hash* options) { mas01mj@584: mas01mj@584: librdf_storage_audiodb_instance* context; mas01mj@584: char* name_copy; mas01mj@584: mas01mj@585: context = (librdf_storage_audiodb_instance*)librdf_sign_calloc(1, sizeof(librdf_storage_audiodb_instance)); mas01mj@584: mas01mj@584: if(!context) mas01mj@584: { mas01mj@584: if(options) mas01mj@584: librdf_free_hash(options); mas01mj@584: return 1; mas01mj@584: } mas01mj@584: mas01mj@584: librdf_storage_set_instance(storage, context); mas01mj@584: mas01mj@584: context->storage = storage; mas01mj@584: mas01mj@584: // Store the name of the db mas01mj@584: context->name_len=strlen(name); mas01mj@585: name_copy=(char*)librdf_sign_malloc(context->name_len+1); mas01mj@584: if(!name_copy) { mas01mj@584: if(options) mas01mj@584: librdf_free_hash(options); mas01mj@584: return 1; mas01mj@584: } mas01mj@584: strncpy(name_copy, name, context->name_len+1); mas01mj@584: context->name=name_copy; mas01mj@584: mas01mj@584: if(librdf_hash_get_as_boolean(options, "new") > 0) mas01mj@584: context->is_new = 1; mas01mj@584: mas01mj@584: if(options) mas01mj@584: librdf_free_hash(options); mas01mj@584: mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "Initialised!"); mas01mj@584: mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model) { mas01mj@585: librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage); mas01mj@584: int db_file_exists = 0; mas01mj@584: mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "open"); mas01mj@584: mas01mj@584: if(!access((const char*)context->name, F_OK)) mas01mj@584: db_file_exists = 1; mas01mj@584: else mas01mj@584: context->is_new = 1; mas01mj@584: mas01mj@584: if(context->is_new && db_file_exists) mas01mj@584: unlink(context->name); mas01mj@584: mas01mj@584: context->adb = NULL; mas01mj@608: context->model = librdf_new_model(librdf_storage_get_world(storage), mas01mj@608: librdf_new_storage(librdf_storage_get_world(storage), "memory", NULL, NULL), NULL); mas01mj@608: mas01mj@584: if(context->is_new) { mas01mj@584: if(!(context->adb = audiodb_create(context->name, 0, 0, 0))) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "Unable to create %s", context->name); mas01mj@584: return 1; mas01mj@584: } mas01mj@584: } mas01mj@584: else mas01mj@584: { mas01mj@608: if(!(context->adb = audiodb_open(context->name, O_RDONLY))) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "Unable to open %s", context->name); mas01mj@584: return 1; mas01mj@584: } mas01mj@584: } mas01mj@584: mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_close(librdf_storage* storage) { mas01mj@585: librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage); mas01mj@584: mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "close"); mas01mj@584: mas01mj@584: if(context->adb) mas01mj@584: { mas01mj@584: audiodb_close(context->adb); mas01mj@584: context->adb = NULL; mas01mj@584: } mas01mj@584: mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_size(librdf_storage* storage) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "size"); mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_add_statement(librdf_storage* storage, librdf_statement* statement) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "add statement"); mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_add_statements(librdf_storage* storage, librdf_stream* statement_stream) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "add statements"); mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_remove_statement(librdf_storage* storage, librdf_statement* statement) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "remove statement"); mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_contains_statement(librdf_storage* storage, librdf_statement* statement) { mas01mj@599: mas01mj@599: librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage); mas01mj@599: librdf_world* world = librdf_storage_get_world(storage); mas01mj@599: mas01mj@599: librdf_node* subject = librdf_statement_get_subject(statement); mas01mj@599: librdf_node* object = librdf_statement_get_object(statement); mas01mj@599: librdf_node* predicate = librdf_statement_get_predicate(statement); mas01mj@603: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@603: "Contains statement %s?", librdf_statement_to_string(statement)); mas01mj@599: mas01mj@599: mas01mj@599: if(subject && object && predicate) mas01mj@599: { mas01mj@599: // audioDBs only contain Signals (tracks are held in a separate store). mas01mj@599: mas01mj@599: librdf_uri* type_uri = librdf_new_uri(world, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); mas01mj@599: librdf_uri* signal_uri = librdf_new_uri(world, "http://purl.org/ontology/mo/Signal"); mas01mj@599: if(librdf_uri_equals(type_uri, librdf_node_get_uri(predicate))) mas01mj@599: { mas01mj@599: librdf_uri* object_uri = librdf_node_get_uri(object); mas01mj@599: if(librdf_uri_equals(object_uri, signal_uri)) mas01mj@599: { mas01mj@599: // Grab the track via audioDB mas01mj@599: adb_datum_t datum = {0}; mas01mj@599: int result = audiodb_retrieve_datum( mas01mj@599: context->adb, mas01mj@599: librdf_uri_as_string(librdf_node_get_uri(subject)), mas01mj@599: &datum); mas01mj@599: if(result == 0) mas01mj@599: { mas01mj@599: // Found it! Free up the datum. mas01mj@599: audiodb_free_datum(context->adb, &datum); mas01mj@599: return 1; mas01mj@599: } mas01mj@599: } mas01mj@599: } mas01mj@599: librdf_free_uri(type_uri); mas01mj@599: librdf_free_uri(signal_uri); mas01mj@599: } mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static librdf_stream* librdf_storage_audiodb_serialise(librdf_storage* storage) { mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "serialise"); mas01mj@584: return NULL; mas01mj@584: } mas01mj@584: mas01mj@599: /** mas01mj@599: * Linked list bits mas01mj@599: */ mas01mj@599: mas01mj@599: mas01mj@599: struct list_node_s mas01mj@599: { mas01mj@599: struct list_node_s* next; mas01mj@599: struct list_node_s* prev; mas01mj@599: librdf_statement* statement; mas01mj@599: }; mas01mj@599: mas01mj@599: typedef struct list_node_s list_node; mas01mj@599: mas01mj@599: struct list_s { mas01mj@599: list_node* head; mas01mj@599: list_node* tail; mas01mj@599: }; mas01mj@599: mas01mj@599: typedef struct list_s result_list; mas01mj@599: mas01mj@599: result_list* result_data_new() mas01mj@599: { mas01mj@599: result_list* list = (result_list*)calloc(1, sizeof(result_list)); mas01mj@599: if(!list) mas01mj@599: return NULL; mas01mj@599: return list; mas01mj@599: } mas01mj@599: mas01mj@599: int result_data_add(librdf_world* world, result_list* list) { mas01mj@599: mas01mj@599: // First create the node mas01mj@599: list_node* node = (list_node*)calloc(1, sizeof(list_node)); mas01mj@599: mas01mj@599: if(!node) mas01mj@599: return 1; mas01mj@599: mas01mj@599: if(list->tail) mas01mj@599: { mas01mj@599: node->prev = list->tail; mas01mj@599: list->tail->next = node; mas01mj@599: } mas01mj@599: mas01mj@599: list->tail = node; mas01mj@599: if(!list->head) mas01mj@599: list->head = node; mas01mj@599: return 0; mas01mj@599: } mas01mj@599: mas01mj@599: /** mas01mj@599: * Querying bits. mas01mj@599: **/ mas01mj@599: mas01mj@599: typedef struct { mas01mj@599: librdf_storage* storage; mas01mj@599: librdf_storage_audiodb_instance* audiodb_context; mas01mj@599: int finished; mas01mj@599: librdf_statement* statement; mas01mj@599: librdf_node* context; mas01mj@599: result_list *results; mas01mj@599: mas01mj@599: } librdf_storage_audiodb_find_statements_stream_context; mas01mj@599: mas01mj@599: mas01mj@599: mas01mj@599: mas01mj@584: static librdf_stream* librdf_storage_audiodb_find_statements(librdf_storage* storage, librdf_statement* statement) { mas01mj@584: mas01mj@585: librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage); mas01mj@584: librdf_storage_audiodb_find_statements_stream_context* scontext; mas01mj@584: librdf_stream* stream; mas01mj@599: mas01mj@599: mas01mj@599: librdf_world* world = librdf_storage_get_world(storage); mas01mj@599: mas01mj@585: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@599: "find statements %s", librdf_statement_to_string(statement)); mas01mj@584: mas01mj@599: // Create stream context mas01mj@585: scontext = (librdf_storage_audiodb_find_statements_stream_context*)librdf_sign_calloc(1, sizeof(librdf_storage_audiodb_find_statements_stream_context)); mas01mj@584: mas01mj@584: if(!scontext) mas01mj@584: return NULL; mas01mj@584: mas01mj@584: scontext->storage = storage; mas01mj@584: librdf_storage_add_reference(scontext->storage); mas01mj@599: mas01mj@599: // Store a reference to the storage instance. mas01mj@584: scontext->audiodb_context = context; mas01mj@584: mas01mj@599: scontext->results = result_data_new(); mas01mj@608: mas01mj@599: // This will need factoring out mas01mj@599: librdf_node* subject = librdf_statement_get_subject(statement); mas01mj@599: librdf_node* object = librdf_statement_get_object(statement); mas01mj@599: librdf_node* predicate = librdf_statement_get_predicate(statement); mas01mj@599: mas01mj@603: librdf_uri* dimension = librdf_new_uri(world, AF_DIMENSION); mas01mj@603: librdf_uri* vectors = librdf_new_uri(world, AF_VECTORS); mas01mj@603: librdf_uri* signal = librdf_new_uri(world, MO_SIGNAL); mas01mj@603: librdf_uri* type = librdf_new_uri(world, RDF_TYPE); mas01mj@660: librdf_uri* element = librdf_new_uri(world, SIMILARITY_ELEMENT); mas01mj@660: librdf_uri* distance = librdf_new_uri(world, SIMILARITY_DISTANCE); mas01mj@660: librdf_uri* similarity = librdf_new_uri(world, SIMILARITY_SIMILARITY); mas01mj@603: mas01mj@608: // SPX (given a resource and a predicate, but no object) mas01mj@608: if(subject && librdf_node_is_resource(subject) && mas01mj@608: predicate && librdf_node_is_resource(predicate) && mas01mj@608: (!object || object && librdf_node_is_blank(object))) { mas01mj@603: librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Got SPX"); mas01mj@599: librdf_uri* predicate_uri = librdf_node_get_uri(predicate); mas01mj@603: librdf_uri* subject_uri = librdf_node_get_uri(subject); mas01mj@608: mas01mj@608: // Need dimension or vectors - so get the track datum and populate. mas01mj@599: if(librdf_uri_equals(predicate_uri, dimension) || librdf_uri_equals(predicate_uri, vectors)) mas01mj@599: { mas01mj@599: adb_datum_t datum = {0}; mas01mj@599: int result = audiodb_retrieve_datum( mas01mj@599: context->adb, mas01mj@603: librdf_uri_as_string(subject_uri), mas01mj@599: &datum); mas01mj@599: if(result == 0) mas01mj@599: { mas01mj@599: librdf_node* value; mas01mj@608: char buffer[16]; mas01mj@599: mas01mj@599: if(librdf_uri_equals(predicate_uri, dimension)) mas01mj@608: snprintf(buffer, 16, "%d", datum.dim); mas01mj@599: else if(librdf_uri_equals(predicate_uri, vectors)) mas01mj@608: snprintf(buffer, 16, "%d", datum.nvectors); mas01mj@603: mas01mj@608: value = librdf_new_node_from_typed_literal(world, buffer, NULL, librdf_new_uri(world, "http://www.w3.org/2001/XMLSchema#integer")); mas01mj@599: mas01mj@599: result_data_add(world, scontext->results); mas01mj@599: mas01mj@599: result_list* list = scontext->results; mas01mj@599: mas01mj@599: list->tail->statement = librdf_new_statement(world); mas01mj@599: librdf_statement_set_subject(list->tail->statement, subject); mas01mj@599: librdf_statement_set_object(list->tail->statement, value); mas01mj@599: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Return statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@599: } mas01mj@608: } mas01mj@608: } // XPO (given a predicate and an object, but no subject) mas01mj@608: else if(!subject && mas01mj@608: predicate && librdf_node_is_resource(predicate) && mas01mj@608: object && librdf_node_is_resource(object)) { mas01mj@599: mas01mj@603: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "XPO"); mas01mj@603: librdf_uri* predicate_uri = librdf_node_get_uri(predicate); mas01mj@603: librdf_uri* object_uri = librdf_node_get_uri(object); mas01mj@603: mas01mj@608: if(librdf_uri_equals(predicate_uri, type)) { mas01mj@608: // Need everything of type mo:Signal - currently all track IDs. mas01mj@608: if(librdf_uri_equals(object_uri, signal)) { mas01mj@608: adb_liszt_results_t* liszt_results = audiodb_liszt(context->adb); mas01mj@608: mas01mj@608: uint32_t k; mas01mj@608: for(k = 0; k < liszt_results->nresults; k++) { mas01mj@608: result_data_add(world, scontext->results); mas01mj@608: result_list* list = scontext->results; mas01mj@608: list->tail->statement = librdf_new_statement(world); mas01mj@608: librdf_statement_set_subject(list->tail->statement, librdf_new_node_from_uri(world, librdf_new_uri(world, liszt_results->entries[k].key))); mas01mj@608: mas01mj@608: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: librdf_statement_set_object(list->tail->statement, object); mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Return statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: } mas01mj@608: mas01mj@608: audiodb_liszt_free_results(context->adb, liszt_results); mas01mj@608: } mas01mj@608: else if(librdf_uri_equals(object_uri, similarity)) { mas01mj@608: // mo:Similarity doesn't actually exist in our store - so we create one mas01mj@608: // and put it into an in-memory store. mas01mj@608: result_data_add(world, scontext->results); mas01mj@608: result_list* list = scontext->results; mas01mj@608: list->tail->statement = librdf_new_statement(world); mas01mj@608: librdf_statement_set_subject(list->tail->statement, librdf_new_node_from_blank_identifier(world, NULL)); mas01mj@608: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: librdf_statement_set_object(list->tail->statement, object); mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: librdf_model_add_statement(context->model, list->tail->statement); mas01mj@608: } mas01mj@608: } mas01mj@608: } // sPO (given a blank identifier as the subject, a predicate and an object - this just stores them in the cache). mas01mj@608: else if(subject && librdf_node_is_blank(subject) && mas01mj@608: predicate && librdf_node_is_resource(predicate) && mas01mj@608: object && librdf_node_is_resource(object)) { mas01mj@608: mas01mj@608: // TODO : Verify that the contents are plausible entries in the store. mas01mj@608: mas01mj@608: result_data_add(world, scontext->results); mas01mj@608: result_list* list = scontext->results; mas01mj@608: list->tail->statement = librdf_new_statement(world); mas01mj@608: mas01mj@608: librdf_statement_set_subject(list->tail->statement, subject); mas01mj@608: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: librdf_statement_set_object(list->tail->statement, object); mas01mj@608: mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: librdf_model_add_statement(context->model, list->tail->statement); mas01mj@608: } // sPX (given a blank identifier as the subject, a predicate, and no object) mas01mj@608: else if(subject && (librdf_node_is_blank(subject) || librdf_node_is_resource(subject)) && mas01mj@608: predicate && librdf_node_is_resource(predicate) && mas01mj@608: !object) { mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "sPX"); mas01mj@608: librdf_uri* predicate_uri = librdf_node_get_uri(predicate); mas01mj@608: mas01mj@608: if(librdf_uri_equals(predicate_uri, element)) mas01mj@603: { mas01mj@608: // Fill in all possible elements, and cache the statements. mas01mj@603: adb_liszt_results_t* liszt_results = audiodb_liszt(context->adb); mas01mj@603: mas01mj@603: uint32_t k; mas01mj@603: for(k = 0; k < liszt_results->nresults; k++) { mas01mj@603: result_data_add(world, scontext->results); mas01mj@603: result_list* list = scontext->results; mas01mj@603: list->tail->statement = librdf_new_statement(world); mas01mj@603: mas01mj@608: librdf_statement_set_subject(list->tail->statement, subject); mas01mj@608: librdf_statement_set_object(list->tail->statement, librdf_new_node_from_uri(world, librdf_new_uri(world, liszt_results->entries[k].key))); mas01mj@603: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: librdf_model_add_statement(context->model, list->tail->statement); mas01mj@603: } mas01mj@608: mas01mj@608: audiodb_liszt_free_results(context->adb, liszt_results); mas01mj@608: mas01mj@608: } mas01mj@608: if(librdf_uri_equals(predicate_uri, distance)) mas01mj@608: { mas01mj@608: // This requires both elements to be defined - check those first, mas01mj@608: // and use a blank identifier if not. mas01mj@608: librdf_statement* element_search = librdf_new_statement(world); mas01mj@608: librdf_statement_set_subject(element_search, subject); mas01mj@608: librdf_statement_set_predicate(element_search, librdf_new_node_from_uri(world, element)); mas01mj@608: librdf_stream* elements = librdf_model_find_statements(context->model, element_search); mas01mj@608: int count = 0; mas01mj@608: mas01mj@608: char* keys[2]; mas01mj@608: mas01mj@608: while (!librdf_stream_end(elements) && count < 2) { mas01mj@608: keys[count] = librdf_uri_as_string( mas01mj@608: librdf_node_get_uri( mas01mj@608: librdf_statement_get_object( mas01mj@608: librdf_new_statement_from_statement( mas01mj@608: librdf_stream_get_object(elements))))); mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Key %d %s", count, keys[count]); mas01mj@608: librdf_stream_next(elements); mas01mj@608: count++; mas01mj@608: } mas01mj@608: mas01mj@608: double dist = 0; mas01mj@603: mas01mj@608: // TODO : Trigger an error case here. mas01mj@608: mas01mj@608: if(count == 2) mas01mj@608: { mas01mj@608: // Calculate the distance mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Calculate distance"); mas01mj@608: mas01mj@608: adb_query_spec_t qspec = {0}; mas01mj@608: adb_datum_t datum = {0}; mas01mj@608: datum.key = keys[0]; mas01mj@608: mas01mj@608: qspec.refine.flags = ADB_REFINE_INCLUDE_KEYLIST; mas01mj@608: qspec.refine.include.nkeys = 1; mas01mj@608: qspec.refine.include.keys = &keys[1]; mas01mj@608: qspec.refine.hopsize = 1; mas01mj@608: mas01mj@608: qspec.qid.datum = &datum; mas01mj@608: qspec.qid.sequence_length = 10; mas01mj@608: qspec.qid.flags = ADB_QID_FLAG_EXHAUSTIVE; mas01mj@608: qspec.qid.sequence_start = 0; mas01mj@608: mas01mj@608: qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; mas01mj@608: qspec.params.distance = ADB_DISTANCE_EUCLIDEAN; mas01mj@608: qspec.params.npoints = 1; mas01mj@608: qspec.params.ntracks = 1; mas01mj@608: mas01mj@608: adb_query_results_t* results = audiodb_query_spec(context->adb, &qspec); mas01mj@608: dist = results->results[0].dist; mas01mj@608: mas01mj@608: char value[16]; mas01mj@608: snprintf(value, 16, "%f", dist); mas01mj@608: mas01mj@608: result_data_add(world, scontext->results); mas01mj@608: result_list* list = scontext->results; mas01mj@608: list->tail->statement = librdf_new_statement(world); mas01mj@608: mas01mj@608: librdf_statement_set_subject(list->tail->statement, subject); mas01mj@608: librdf_statement_set_predicate(list->tail->statement, predicate); mas01mj@608: librdf_statement_set_object(list->tail->statement, mas01mj@608: librdf_new_node_from_typed_literal(world, value, NULL, librdf_new_uri(world, "http://www.w3.org/2001/XMLSchema#decimal"))); mas01mj@608: mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: librdf_model_add_statement(context->model, list->tail->statement); mas01mj@608: } mas01mj@603: } mas01mj@608: mas01mj@608: } mas01mj@608: else if(subject && predicate && object) mas01mj@608: { mas01mj@608: result_data_add(world, scontext->results); mas01mj@608: result_list* list = scontext->results; mas01mj@608: list->tail->statement = librdf_new_statement_from_statement(statement); mas01mj@608: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement)); mas01mj@608: librdf_model_add_statement(context->model, list->tail->statement); mas01mj@603: } mas01mj@603: else mas01mj@603: { mas01mj@603: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Halp?"); mas01mj@603: } mas01mj@608: mas01mj@599: librdf_free_uri(dimension); mas01mj@599: librdf_free_uri(vectors); mas01mj@603: librdf_free_uri(signal); mas01mj@603: librdf_free_uri(type); mas01mj@608: librdf_free_uri(element); mas01mj@608: librdf_free_uri(distance); mas01mj@608: librdf_free_uri(similarity); mas01mj@603: mas01mj@599: stream = librdf_new_stream(world, mas01mj@599: (void*)scontext, mas01mj@599: &librdf_storage_audiodb_find_statements_end_of_stream, mas01mj@599: &librdf_storage_audiodb_find_statements_next_statement, mas01mj@599: &librdf_storage_audiodb_find_statements_get_statement, mas01mj@599: &librdf_storage_audiodb_find_statements_finished); mas01mj@584: mas01mj@584: if(!stream) { mas01mj@599: librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@599: "Couldn't create stream!"); mas01mj@584: librdf_storage_audiodb_find_statements_finished((void*)scontext); mas01mj@584: return NULL; mas01mj@584: } mas01mj@584: mas01mj@584: return stream; mas01mj@584: } mas01mj@584: mas01mj@584: static void librdf_storage_audiodb_find_statements_finished(void* context) { mas01mj@584: librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context; mas01mj@599: mas01mj@584: if(scontext->storage) mas01mj@584: librdf_storage_remove_reference(scontext->storage); mas01mj@584: mas01mj@584: if(scontext->statement) mas01mj@584: librdf_free_statement(scontext->statement); mas01mj@584: mas01mj@584: if(scontext->context) mas01mj@584: librdf_free_node(scontext->context); mas01mj@584: mas01mj@585: librdf_sign_free(scontext); mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_find_statements_end_of_stream(void* context) { mas01mj@584: librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context; mas01mj@599: librdf_world* world = librdf_storage_get_world(scontext->storage); mas01mj@599: librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@603: "Finished? %d", (scontext->results->head == NULL)); mas01mj@584: mas01mj@599: return (scontext->results->head == NULL); mas01mj@584: } mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_find_statements_next_statement(void* context) { mas01mj@584: librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context; mas01mj@584: mas01mj@599: librdf_world* world = librdf_storage_get_world(scontext->storage); mas01mj@599: librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@599: "to next"); mas01mj@599: mas01mj@599: if(scontext->results->head->next) mas01mj@599: { mas01mj@599: scontext->results->head = scontext->results->head->next; mas01mj@599: return 0; mas01mj@599: } mas01mj@599: else mas01mj@599: { mas01mj@584: return 1; mas01mj@584: } mas01mj@584: } mas01mj@584: mas01mj@584: static void* librdf_storage_audiodb_find_statements_get_statement(void* context, int flags) { mas01mj@584: librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context; mas01mj@599: librdf_world* world = librdf_storage_get_world(scontext->storage); mas01mj@599: librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, mas01mj@599: "Get next"); mas01mj@603: mas01mj@584: switch(flags) { mas01mj@584: case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT: mas01mj@599: return scontext->results->head->statement; mas01mj@584: case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT: mas01mj@584: return scontext->context; mas01mj@584: default: mas01mj@599: librdf_log(world, mas01mj@584: 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL, mas01mj@584: "Unknown iterator method flag %d", flags); mas01mj@584: return NULL; mas01mj@584: } mas01mj@584: } mas01mj@584: mas01mj@584: mas01mj@584: mas01mj@584: static int librdf_storage_audiodb_sync(librdf_storage *storage) { mas01mj@584: return 0; mas01mj@584: } mas01mj@584: mas01mj@584: static void mas01mj@584: librdf_storage_audiodb_register_factory(librdf_storage_factory *factory) { mas01mj@584: factory->version = LIBRDF_STORAGE_INTERFACE_VERSION; mas01mj@584: factory->init = librdf_storage_audiodb_init; mas01mj@584: factory->open = librdf_storage_audiodb_open; mas01mj@584: factory->close = librdf_storage_audiodb_close; mas01mj@584: factory->size = librdf_storage_audiodb_size; mas01mj@584: factory->add_statement = librdf_storage_audiodb_add_statement; mas01mj@584: factory->remove_statement = librdf_storage_audiodb_remove_statement; mas01mj@584: factory->contains_statement = librdf_storage_audiodb_contains_statement; mas01mj@584: factory->serialise = librdf_storage_audiodb_serialise; mas01mj@584: factory->find_statements = librdf_storage_audiodb_find_statements; mas01mj@584: } mas01mj@584: mas01mj@584: /** Entry point for dynamically loaded storage module */ mas01mj@584: void librdf_storage_module_register_factory(librdf_world *world) { mas01mj@584: librdf_storage_register_factory(world, "audiodb", "AudioDB", mas01mj@584: &librdf_storage_audiodb_register_factory); mas01mj@584: }