mas01mj@585
|
1 #include <stdlib.h>
|
mas01mj@584
|
2 #include <unistd.h>
|
mas01mj@584
|
3 #include <fcntl.h>
|
mas01mj@584
|
4 #include <stdio.h>
|
mas01mj@584
|
5 #include <string.h>
|
mas01mj@584
|
6 #ifdef HAVE_STDLIB_H
|
mas01mj@584
|
7 #include <stdlib.h> /* for abort() as used in errors */
|
mas01mj@584
|
8 #endif
|
mas01mj@584
|
9 #include <sys/types.h>
|
mas01mj@585
|
10 #include <librdf.h>
|
mas01mj@584
|
11 #include <audioDB_API.h>
|
mas01mj@584
|
12
|
mas01mj@599
|
13 /**
|
mas01mj@599
|
14 * NB : This is pulled through from librdf internals. Not ideal, but
|
mas01mj@599
|
15 * otherwise we'd need to compile against their source tree!
|
mas01mj@599
|
16 **/
|
mas01mj@599
|
17
|
mas01mj@585
|
18 #define LIBRDF_SIGN_KEY 0x04Ed1A7D
|
mas01mj@584
|
19
|
mas01mj@603
|
20 #define AF_DIMENSION "http://purl.org/ontology/af/dimension"
|
mas01mj@603
|
21 #define AF_VECTORS "http://purl.org/ontology/af/vectors"
|
mas01mj@603
|
22 #define MO_SIGNAL "http://purl.org/ontology/mo/Signal"
|
mas01mj@603
|
23 #define RDF_TYPE "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
|
mas01mj@660
|
24 #define SIMILARITY_ELEMENT "http://purl.org/ontology/similarity/element"
|
mas01mj@660
|
25 #define SIMILARITY_DISTANCE "http://purl.org/ontology/similarity/distance"
|
mas01mj@660
|
26 #define SIMILARITY_SIMILARITY "http://purl.org/ontology/similarity/Similarity"
|
mas01mj@599
|
27
|
mas01mj@584
|
28 typedef struct {
|
mas01mj@584
|
29 librdf_model* model;
|
mas01mj@584
|
30 librdf_storage* storage;
|
mas01mj@599
|
31 char* name;
|
mas01mj@584
|
32 size_t name_len;
|
mas01mj@584
|
33 int is_new;
|
mas01mj@599
|
34 adb_t* adb;
|
mas01mj@584
|
35
|
mas01mj@584
|
36 } librdf_storage_audiodb_instance;
|
mas01mj@584
|
37
|
mas01mj@584
|
38
|
mas01mj@584
|
39 static int librdf_storage_audiodb_init(librdf_storage* storage, const char *name, librdf_hash* options);
|
mas01mj@584
|
40 static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model);
|
mas01mj@584
|
41 static int librdf_storage_audiodb_close(librdf_storage* storage);
|
mas01mj@584
|
42 static int librdf_storage_audiodb_size(librdf_storage* storage);
|
mas01mj@584
|
43 static int librdf_storage_audiodb_add_statement(librdf_storage* storage, librdf_statement* statement);
|
mas01mj@584
|
44 static int librdf_storage_audiodb_add_statements(librdf_storage* storage, librdf_stream* statement_stream);
|
mas01mj@584
|
45 static int librdf_storage_audiodb_remove_statement(librdf_storage* storage, librdf_statement* statement);
|
mas01mj@584
|
46 static int librdf_storage_audiodb_contains_statement(librdf_storage* storage, librdf_statement* statement);
|
mas01mj@584
|
47 static librdf_stream* librdf_storage_audiodb_serialise(librdf_storage* storage);
|
mas01mj@584
|
48 static librdf_stream* librdf_storage_audiodb_find_statements(librdf_storage* storage, librdf_statement* statement);
|
mas01mj@584
|
49
|
mas01mj@584
|
50 /* find_statements implementing functions */
|
mas01mj@584
|
51 static int librdf_storage_audiodb_find_statements_end_of_stream(void* context);
|
mas01mj@584
|
52 static int librdf_storage_audiodb_find_statements_next_statement(void* context);
|
mas01mj@584
|
53 static void* librdf_storage_audiodb_find_statements_get_statement(void* context, int flags);
|
mas01mj@584
|
54 static void librdf_storage_audiodb_find_statements_finished(void* context);
|
mas01mj@584
|
55
|
mas01mj@584
|
56 static int librdf_storage_audiodb_sync(librdf_storage *storage);
|
mas01mj@584
|
57
|
mas01mj@584
|
58 static void librdf_storage_audiodb_register_factory(librdf_storage_factory *factory);
|
mas01mj@584
|
59 void librdf_storage_module_register_factory(librdf_world *world);
|
mas01mj@585
|
60
|
mas01mj@599
|
61 /**
|
mas01mj@599
|
62 * These 3 are from librdf's rdf_internals - simplify the mallocing/freeing a bit.
|
mas01mj@599
|
63 */
|
mas01mj@599
|
64
|
mas01mj@585
|
65 void librdf_sign_free(void *ptr)
|
mas01mj@585
|
66 {
|
mas01mj@585
|
67 int *p;
|
mas01mj@585
|
68
|
mas01mj@585
|
69 if(!ptr)
|
mas01mj@585
|
70 return;
|
mas01mj@585
|
71
|
mas01mj@585
|
72 p=(int*)ptr;
|
mas01mj@585
|
73 p--;
|
mas01mj@585
|
74
|
mas01mj@585
|
75 if(*p != LIBRDF_SIGN_KEY)
|
mas01mj@585
|
76 return;
|
mas01mj@585
|
77
|
mas01mj@585
|
78 free(p);
|
mas01mj@585
|
79 }
|
mas01mj@585
|
80
|
mas01mj@585
|
81
|
mas01mj@585
|
82 void* librdf_sign_calloc(size_t nmemb, size_t size)
|
mas01mj@585
|
83 {
|
mas01mj@585
|
84 int *p;
|
mas01mj@585
|
85
|
mas01mj@585
|
86 /* turn into bytes */
|
mas01mj@585
|
87 size = nmemb*size + sizeof(int);
|
mas01mj@585
|
88
|
mas01mj@585
|
89 p=(int*)calloc(1, size);
|
mas01mj@585
|
90 *p++ = LIBRDF_SIGN_KEY;
|
mas01mj@585
|
91 return p;
|
mas01mj@585
|
92 }
|
mas01mj@585
|
93
|
mas01mj@585
|
94 void* librdf_sign_malloc(size_t size)
|
mas01mj@585
|
95 {
|
mas01mj@585
|
96 int *p;
|
mas01mj@585
|
97
|
mas01mj@585
|
98 size += sizeof(int);
|
mas01mj@585
|
99
|
mas01mj@585
|
100 p=(int*)malloc(size);
|
mas01mj@585
|
101 *p++ = LIBRDF_SIGN_KEY;
|
mas01mj@585
|
102 return p;
|
mas01mj@585
|
103 }
|
mas01mj@584
|
104
|
mas01mj@584
|
105
|
mas01mj@584
|
106 static int librdf_storage_audiodb_init(librdf_storage* storage, const char *name, librdf_hash* options) {
|
mas01mj@584
|
107
|
mas01mj@584
|
108 librdf_storage_audiodb_instance* context;
|
mas01mj@584
|
109 char* name_copy;
|
mas01mj@584
|
110
|
mas01mj@585
|
111 context = (librdf_storage_audiodb_instance*)librdf_sign_calloc(1, sizeof(librdf_storage_audiodb_instance));
|
mas01mj@584
|
112
|
mas01mj@584
|
113 if(!context)
|
mas01mj@584
|
114 {
|
mas01mj@584
|
115 if(options)
|
mas01mj@584
|
116 librdf_free_hash(options);
|
mas01mj@584
|
117 return 1;
|
mas01mj@584
|
118 }
|
mas01mj@584
|
119
|
mas01mj@584
|
120 librdf_storage_set_instance(storage, context);
|
mas01mj@584
|
121
|
mas01mj@584
|
122 context->storage = storage;
|
mas01mj@584
|
123
|
mas01mj@584
|
124 // Store the name of the db
|
mas01mj@584
|
125 context->name_len=strlen(name);
|
mas01mj@585
|
126 name_copy=(char*)librdf_sign_malloc(context->name_len+1);
|
mas01mj@584
|
127 if(!name_copy) {
|
mas01mj@584
|
128 if(options)
|
mas01mj@584
|
129 librdf_free_hash(options);
|
mas01mj@584
|
130 return 1;
|
mas01mj@584
|
131 }
|
mas01mj@584
|
132 strncpy(name_copy, name, context->name_len+1);
|
mas01mj@584
|
133 context->name=name_copy;
|
mas01mj@584
|
134
|
mas01mj@584
|
135 if(librdf_hash_get_as_boolean(options, "new") > 0)
|
mas01mj@584
|
136 context->is_new = 1;
|
mas01mj@584
|
137
|
mas01mj@584
|
138 if(options)
|
mas01mj@584
|
139 librdf_free_hash(options);
|
mas01mj@584
|
140
|
mas01mj@585
|
141 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
142 "Initialised!");
|
mas01mj@584
|
143
|
mas01mj@584
|
144 return 0;
|
mas01mj@584
|
145 }
|
mas01mj@584
|
146
|
mas01mj@584
|
147 static int librdf_storage_audiodb_open(librdf_storage* storage, librdf_model* model) {
|
mas01mj@585
|
148 librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);
|
mas01mj@584
|
149 int db_file_exists = 0;
|
mas01mj@584
|
150
|
mas01mj@585
|
151 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
152 "open");
|
mas01mj@584
|
153
|
mas01mj@584
|
154 if(!access((const char*)context->name, F_OK))
|
mas01mj@584
|
155 db_file_exists = 1;
|
mas01mj@584
|
156 else
|
mas01mj@584
|
157 context->is_new = 1;
|
mas01mj@584
|
158
|
mas01mj@584
|
159 if(context->is_new && db_file_exists)
|
mas01mj@584
|
160 unlink(context->name);
|
mas01mj@584
|
161
|
mas01mj@584
|
162 context->adb = NULL;
|
mas01mj@608
|
163 context->model = librdf_new_model(librdf_storage_get_world(storage),
|
mas01mj@608
|
164 librdf_new_storage(librdf_storage_get_world(storage), "memory", NULL, NULL), NULL);
|
mas01mj@608
|
165
|
mas01mj@584
|
166 if(context->is_new) {
|
mas01mj@584
|
167 if(!(context->adb = audiodb_create(context->name, 0, 0, 0))) {
|
mas01mj@585
|
168 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
169 "Unable to create %s", context->name);
|
mas01mj@584
|
170 return 1;
|
mas01mj@584
|
171 }
|
mas01mj@584
|
172 }
|
mas01mj@584
|
173 else
|
mas01mj@584
|
174 {
|
mas01mj@608
|
175 if(!(context->adb = audiodb_open(context->name, O_RDONLY))) {
|
mas01mj@585
|
176 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
177 "Unable to open %s", context->name);
|
mas01mj@584
|
178 return 1;
|
mas01mj@584
|
179 }
|
mas01mj@584
|
180 }
|
mas01mj@584
|
181
|
mas01mj@584
|
182 return 0;
|
mas01mj@584
|
183 }
|
mas01mj@584
|
184
|
mas01mj@584
|
185 static int librdf_storage_audiodb_close(librdf_storage* storage) {
|
mas01mj@585
|
186 librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);
|
mas01mj@584
|
187
|
mas01mj@585
|
188 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
189 "close");
|
mas01mj@584
|
190
|
mas01mj@584
|
191 if(context->adb)
|
mas01mj@584
|
192 {
|
mas01mj@584
|
193 audiodb_close(context->adb);
|
mas01mj@584
|
194 context->adb = NULL;
|
mas01mj@584
|
195 }
|
mas01mj@584
|
196
|
mas01mj@584
|
197 return 0;
|
mas01mj@584
|
198 }
|
mas01mj@584
|
199
|
mas01mj@584
|
200 static int librdf_storage_audiodb_size(librdf_storage* storage) {
|
mas01mj@585
|
201 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
202 "size");
|
mas01mj@584
|
203 return 0;
|
mas01mj@584
|
204 }
|
mas01mj@584
|
205
|
mas01mj@584
|
206 static int librdf_storage_audiodb_add_statement(librdf_storage* storage, librdf_statement* statement) {
|
mas01mj@585
|
207 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
208 "add statement");
|
mas01mj@584
|
209 return 0;
|
mas01mj@584
|
210 }
|
mas01mj@584
|
211
|
mas01mj@584
|
212 static int librdf_storage_audiodb_add_statements(librdf_storage* storage, librdf_stream* statement_stream) {
|
mas01mj@585
|
213 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
214 "add statements");
|
mas01mj@584
|
215 return 0;
|
mas01mj@584
|
216 }
|
mas01mj@584
|
217
|
mas01mj@584
|
218 static int librdf_storage_audiodb_remove_statement(librdf_storage* storage, librdf_statement* statement) {
|
mas01mj@585
|
219 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
220 "remove statement");
|
mas01mj@584
|
221 return 0;
|
mas01mj@584
|
222 }
|
mas01mj@584
|
223
|
mas01mj@584
|
224 static int librdf_storage_audiodb_contains_statement(librdf_storage* storage, librdf_statement* statement) {
|
mas01mj@599
|
225
|
mas01mj@599
|
226 librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);
|
mas01mj@599
|
227 librdf_world* world = librdf_storage_get_world(storage);
|
mas01mj@599
|
228
|
mas01mj@599
|
229 librdf_node* subject = librdf_statement_get_subject(statement);
|
mas01mj@599
|
230 librdf_node* object = librdf_statement_get_object(statement);
|
mas01mj@599
|
231 librdf_node* predicate = librdf_statement_get_predicate(statement);
|
mas01mj@603
|
232 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@603
|
233 "Contains statement %s?", librdf_statement_to_string(statement));
|
mas01mj@599
|
234
|
mas01mj@599
|
235
|
mas01mj@599
|
236 if(subject && object && predicate)
|
mas01mj@599
|
237 {
|
mas01mj@599
|
238 // audioDBs only contain Signals (tracks are held in a separate store).
|
mas01mj@599
|
239
|
mas01mj@599
|
240 librdf_uri* type_uri = librdf_new_uri(world, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
mas01mj@599
|
241 librdf_uri* signal_uri = librdf_new_uri(world, "http://purl.org/ontology/mo/Signal");
|
mas01mj@599
|
242 if(librdf_uri_equals(type_uri, librdf_node_get_uri(predicate)))
|
mas01mj@599
|
243 {
|
mas01mj@599
|
244 librdf_uri* object_uri = librdf_node_get_uri(object);
|
mas01mj@599
|
245 if(librdf_uri_equals(object_uri, signal_uri))
|
mas01mj@599
|
246 {
|
mas01mj@599
|
247 // Grab the track via audioDB
|
mas01mj@599
|
248 adb_datum_t datum = {0};
|
mas01mj@599
|
249 int result = audiodb_retrieve_datum(
|
mas01mj@599
|
250 context->adb,
|
mas01mj@599
|
251 librdf_uri_as_string(librdf_node_get_uri(subject)),
|
mas01mj@599
|
252 &datum);
|
mas01mj@599
|
253 if(result == 0)
|
mas01mj@599
|
254 {
|
mas01mj@599
|
255 // Found it! Free up the datum.
|
mas01mj@599
|
256 audiodb_free_datum(context->adb, &datum);
|
mas01mj@599
|
257 return 1;
|
mas01mj@599
|
258 }
|
mas01mj@599
|
259 }
|
mas01mj@599
|
260 }
|
mas01mj@599
|
261 librdf_free_uri(type_uri);
|
mas01mj@599
|
262 librdf_free_uri(signal_uri);
|
mas01mj@599
|
263 }
|
mas01mj@584
|
264 return 0;
|
mas01mj@584
|
265 }
|
mas01mj@584
|
266
|
mas01mj@584
|
267 static librdf_stream* librdf_storage_audiodb_serialise(librdf_storage* storage) {
|
mas01mj@585
|
268 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
269 "serialise");
|
mas01mj@584
|
270 return NULL;
|
mas01mj@584
|
271 }
|
mas01mj@584
|
272
|
mas01mj@599
|
273 /**
|
mas01mj@599
|
274 * Linked list bits
|
mas01mj@599
|
275 */
|
mas01mj@599
|
276
|
mas01mj@599
|
277
|
mas01mj@599
|
278 struct list_node_s
|
mas01mj@599
|
279 {
|
mas01mj@599
|
280 struct list_node_s* next;
|
mas01mj@599
|
281 struct list_node_s* prev;
|
mas01mj@599
|
282 librdf_statement* statement;
|
mas01mj@599
|
283 };
|
mas01mj@599
|
284
|
mas01mj@599
|
285 typedef struct list_node_s list_node;
|
mas01mj@599
|
286
|
mas01mj@599
|
287 struct list_s {
|
mas01mj@599
|
288 list_node* head;
|
mas01mj@599
|
289 list_node* tail;
|
mas01mj@599
|
290 };
|
mas01mj@599
|
291
|
mas01mj@599
|
292 typedef struct list_s result_list;
|
mas01mj@599
|
293
|
mas01mj@599
|
294 result_list* result_data_new()
|
mas01mj@599
|
295 {
|
mas01mj@599
|
296 result_list* list = (result_list*)calloc(1, sizeof(result_list));
|
mas01mj@599
|
297 if(!list)
|
mas01mj@599
|
298 return NULL;
|
mas01mj@599
|
299 return list;
|
mas01mj@599
|
300 }
|
mas01mj@599
|
301
|
mas01mj@599
|
302 int result_data_add(librdf_world* world, result_list* list) {
|
mas01mj@599
|
303
|
mas01mj@599
|
304 // First create the node
|
mas01mj@599
|
305 list_node* node = (list_node*)calloc(1, sizeof(list_node));
|
mas01mj@599
|
306
|
mas01mj@599
|
307 if(!node)
|
mas01mj@599
|
308 return 1;
|
mas01mj@599
|
309
|
mas01mj@599
|
310 if(list->tail)
|
mas01mj@599
|
311 {
|
mas01mj@599
|
312 node->prev = list->tail;
|
mas01mj@599
|
313 list->tail->next = node;
|
mas01mj@599
|
314 }
|
mas01mj@599
|
315
|
mas01mj@599
|
316 list->tail = node;
|
mas01mj@599
|
317 if(!list->head)
|
mas01mj@599
|
318 list->head = node;
|
mas01mj@599
|
319 return 0;
|
mas01mj@599
|
320 }
|
mas01mj@599
|
321
|
mas01mj@599
|
322 /**
|
mas01mj@599
|
323 * Querying bits.
|
mas01mj@599
|
324 **/
|
mas01mj@599
|
325
|
mas01mj@599
|
326 typedef struct {
|
mas01mj@599
|
327 librdf_storage* storage;
|
mas01mj@599
|
328 librdf_storage_audiodb_instance* audiodb_context;
|
mas01mj@599
|
329 int finished;
|
mas01mj@599
|
330 librdf_statement* statement;
|
mas01mj@599
|
331 librdf_node* context;
|
mas01mj@599
|
332 result_list *results;
|
mas01mj@599
|
333
|
mas01mj@599
|
334 } librdf_storage_audiodb_find_statements_stream_context;
|
mas01mj@599
|
335
|
mas01mj@599
|
336
|
mas01mj@599
|
337
|
mas01mj@599
|
338
|
mas01mj@584
|
339 static librdf_stream* librdf_storage_audiodb_find_statements(librdf_storage* storage, librdf_statement* statement) {
|
mas01mj@584
|
340
|
mas01mj@585
|
341 librdf_storage_audiodb_instance* context = (librdf_storage_audiodb_instance*)librdf_storage_get_instance(storage);
|
mas01mj@584
|
342 librdf_storage_audiodb_find_statements_stream_context* scontext;
|
mas01mj@584
|
343 librdf_stream* stream;
|
mas01mj@599
|
344
|
mas01mj@599
|
345
|
mas01mj@599
|
346 librdf_world* world = librdf_storage_get_world(storage);
|
mas01mj@599
|
347
|
mas01mj@585
|
348 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@599
|
349 "find statements %s", librdf_statement_to_string(statement));
|
mas01mj@584
|
350
|
mas01mj@599
|
351 // Create stream context
|
mas01mj@585
|
352 scontext = (librdf_storage_audiodb_find_statements_stream_context*)librdf_sign_calloc(1, sizeof(librdf_storage_audiodb_find_statements_stream_context));
|
mas01mj@584
|
353
|
mas01mj@584
|
354 if(!scontext)
|
mas01mj@584
|
355 return NULL;
|
mas01mj@584
|
356
|
mas01mj@584
|
357 scontext->storage = storage;
|
mas01mj@584
|
358 librdf_storage_add_reference(scontext->storage);
|
mas01mj@599
|
359
|
mas01mj@599
|
360 // Store a reference to the storage instance.
|
mas01mj@584
|
361 scontext->audiodb_context = context;
|
mas01mj@584
|
362
|
mas01mj@599
|
363 scontext->results = result_data_new();
|
mas01mj@608
|
364
|
mas01mj@599
|
365 // This will need factoring out
|
mas01mj@599
|
366 librdf_node* subject = librdf_statement_get_subject(statement);
|
mas01mj@599
|
367 librdf_node* object = librdf_statement_get_object(statement);
|
mas01mj@599
|
368 librdf_node* predicate = librdf_statement_get_predicate(statement);
|
mas01mj@599
|
369
|
mas01mj@603
|
370 librdf_uri* dimension = librdf_new_uri(world, AF_DIMENSION);
|
mas01mj@603
|
371 librdf_uri* vectors = librdf_new_uri(world, AF_VECTORS);
|
mas01mj@603
|
372 librdf_uri* signal = librdf_new_uri(world, MO_SIGNAL);
|
mas01mj@603
|
373 librdf_uri* type = librdf_new_uri(world, RDF_TYPE);
|
mas01mj@660
|
374 librdf_uri* element = librdf_new_uri(world, SIMILARITY_ELEMENT);
|
mas01mj@660
|
375 librdf_uri* distance = librdf_new_uri(world, SIMILARITY_DISTANCE);
|
mas01mj@660
|
376 librdf_uri* similarity = librdf_new_uri(world, SIMILARITY_SIMILARITY);
|
mas01mj@603
|
377
|
mas01mj@608
|
378 // SPX (given a resource and a predicate, but no object)
|
mas01mj@608
|
379 if(subject && librdf_node_is_resource(subject) &&
|
mas01mj@608
|
380 predicate && librdf_node_is_resource(predicate) &&
|
mas01mj@608
|
381 (!object || object && librdf_node_is_blank(object))) {
|
mas01mj@603
|
382 librdf_log(librdf_storage_get_world(storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Got SPX");
|
mas01mj@599
|
383 librdf_uri* predicate_uri = librdf_node_get_uri(predicate);
|
mas01mj@603
|
384 librdf_uri* subject_uri = librdf_node_get_uri(subject);
|
mas01mj@608
|
385
|
mas01mj@608
|
386 // Need dimension or vectors - so get the track datum and populate.
|
mas01mj@599
|
387 if(librdf_uri_equals(predicate_uri, dimension) || librdf_uri_equals(predicate_uri, vectors))
|
mas01mj@599
|
388 {
|
mas01mj@599
|
389 adb_datum_t datum = {0};
|
mas01mj@599
|
390 int result = audiodb_retrieve_datum(
|
mas01mj@599
|
391 context->adb,
|
mas01mj@603
|
392 librdf_uri_as_string(subject_uri),
|
mas01mj@599
|
393 &datum);
|
mas01mj@599
|
394 if(result == 0)
|
mas01mj@599
|
395 {
|
mas01mj@599
|
396 librdf_node* value;
|
mas01mj@608
|
397 char buffer[16];
|
mas01mj@599
|
398
|
mas01mj@599
|
399 if(librdf_uri_equals(predicate_uri, dimension))
|
mas01mj@608
|
400 snprintf(buffer, 16, "%d", datum.dim);
|
mas01mj@599
|
401 else if(librdf_uri_equals(predicate_uri, vectors))
|
mas01mj@608
|
402 snprintf(buffer, 16, "%d", datum.nvectors);
|
mas01mj@603
|
403
|
mas01mj@608
|
404 value = librdf_new_node_from_typed_literal(world, buffer, NULL, librdf_new_uri(world, "http://www.w3.org/2001/XMLSchema#integer"));
|
mas01mj@599
|
405
|
mas01mj@599
|
406 result_data_add(world, scontext->results);
|
mas01mj@599
|
407
|
mas01mj@599
|
408 result_list* list = scontext->results;
|
mas01mj@599
|
409
|
mas01mj@599
|
410 list->tail->statement = librdf_new_statement(world);
|
mas01mj@599
|
411 librdf_statement_set_subject(list->tail->statement, subject);
|
mas01mj@599
|
412 librdf_statement_set_object(list->tail->statement, value);
|
mas01mj@599
|
413 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
414 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Return statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@599
|
415 }
|
mas01mj@608
|
416 }
|
mas01mj@608
|
417 } // XPO (given a predicate and an object, but no subject)
|
mas01mj@608
|
418 else if(!subject &&
|
mas01mj@608
|
419 predicate && librdf_node_is_resource(predicate) &&
|
mas01mj@608
|
420 object && librdf_node_is_resource(object)) {
|
mas01mj@599
|
421
|
mas01mj@603
|
422 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "XPO");
|
mas01mj@603
|
423 librdf_uri* predicate_uri = librdf_node_get_uri(predicate);
|
mas01mj@603
|
424 librdf_uri* object_uri = librdf_node_get_uri(object);
|
mas01mj@603
|
425
|
mas01mj@608
|
426 if(librdf_uri_equals(predicate_uri, type)) {
|
mas01mj@608
|
427 // Need everything of type mo:Signal - currently all track IDs.
|
mas01mj@608
|
428 if(librdf_uri_equals(object_uri, signal)) {
|
mas01mj@608
|
429 adb_liszt_results_t* liszt_results = audiodb_liszt(context->adb);
|
mas01mj@608
|
430
|
mas01mj@608
|
431 uint32_t k;
|
mas01mj@608
|
432 for(k = 0; k < liszt_results->nresults; k++) {
|
mas01mj@608
|
433 result_data_add(world, scontext->results);
|
mas01mj@608
|
434 result_list* list = scontext->results;
|
mas01mj@608
|
435 list->tail->statement = librdf_new_statement(world);
|
mas01mj@608
|
436 librdf_statement_set_subject(list->tail->statement, librdf_new_node_from_uri(world, librdf_new_uri(world, liszt_results->entries[k].key)));
|
mas01mj@608
|
437
|
mas01mj@608
|
438 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
439 librdf_statement_set_object(list->tail->statement, object);
|
mas01mj@608
|
440 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Return statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
441 }
|
mas01mj@608
|
442
|
mas01mj@608
|
443 audiodb_liszt_free_results(context->adb, liszt_results);
|
mas01mj@608
|
444 }
|
mas01mj@608
|
445 else if(librdf_uri_equals(object_uri, similarity)) {
|
mas01mj@608
|
446 // mo:Similarity doesn't actually exist in our store - so we create one
|
mas01mj@608
|
447 // and put it into an in-memory store.
|
mas01mj@608
|
448 result_data_add(world, scontext->results);
|
mas01mj@608
|
449 result_list* list = scontext->results;
|
mas01mj@608
|
450 list->tail->statement = librdf_new_statement(world);
|
mas01mj@608
|
451 librdf_statement_set_subject(list->tail->statement, librdf_new_node_from_blank_identifier(world, NULL));
|
mas01mj@608
|
452 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
453 librdf_statement_set_object(list->tail->statement, object);
|
mas01mj@608
|
454 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
455 librdf_model_add_statement(context->model, list->tail->statement);
|
mas01mj@608
|
456 }
|
mas01mj@608
|
457 }
|
mas01mj@608
|
458 } // sPO (given a blank identifier as the subject, a predicate and an object - this just stores them in the cache).
|
mas01mj@608
|
459 else if(subject && librdf_node_is_blank(subject) &&
|
mas01mj@608
|
460 predicate && librdf_node_is_resource(predicate) &&
|
mas01mj@608
|
461 object && librdf_node_is_resource(object)) {
|
mas01mj@608
|
462
|
mas01mj@608
|
463 // TODO : Verify that the contents are plausible entries in the store.
|
mas01mj@608
|
464
|
mas01mj@608
|
465 result_data_add(world, scontext->results);
|
mas01mj@608
|
466 result_list* list = scontext->results;
|
mas01mj@608
|
467 list->tail->statement = librdf_new_statement(world);
|
mas01mj@608
|
468
|
mas01mj@608
|
469 librdf_statement_set_subject(list->tail->statement, subject);
|
mas01mj@608
|
470 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
471 librdf_statement_set_object(list->tail->statement, object);
|
mas01mj@608
|
472
|
mas01mj@608
|
473 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
474 librdf_model_add_statement(context->model, list->tail->statement);
|
mas01mj@608
|
475 } // sPX (given a blank identifier as the subject, a predicate, and no object)
|
mas01mj@608
|
476 else if(subject && (librdf_node_is_blank(subject) || librdf_node_is_resource(subject)) &&
|
mas01mj@608
|
477 predicate && librdf_node_is_resource(predicate) &&
|
mas01mj@608
|
478 !object) {
|
mas01mj@608
|
479 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "sPX");
|
mas01mj@608
|
480 librdf_uri* predicate_uri = librdf_node_get_uri(predicate);
|
mas01mj@608
|
481
|
mas01mj@608
|
482 if(librdf_uri_equals(predicate_uri, element))
|
mas01mj@603
|
483 {
|
mas01mj@608
|
484 // Fill in all possible elements, and cache the statements.
|
mas01mj@603
|
485 adb_liszt_results_t* liszt_results = audiodb_liszt(context->adb);
|
mas01mj@603
|
486
|
mas01mj@603
|
487 uint32_t k;
|
mas01mj@603
|
488 for(k = 0; k < liszt_results->nresults; k++) {
|
mas01mj@603
|
489 result_data_add(world, scontext->results);
|
mas01mj@603
|
490 result_list* list = scontext->results;
|
mas01mj@603
|
491 list->tail->statement = librdf_new_statement(world);
|
mas01mj@603
|
492
|
mas01mj@608
|
493 librdf_statement_set_subject(list->tail->statement, subject);
|
mas01mj@608
|
494 librdf_statement_set_object(list->tail->statement, librdf_new_node_from_uri(world, librdf_new_uri(world, liszt_results->entries[k].key)));
|
mas01mj@603
|
495 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
496
|
mas01mj@608
|
497 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
498 librdf_model_add_statement(context->model, list->tail->statement);
|
mas01mj@603
|
499 }
|
mas01mj@608
|
500
|
mas01mj@608
|
501 audiodb_liszt_free_results(context->adb, liszt_results);
|
mas01mj@608
|
502
|
mas01mj@608
|
503 }
|
mas01mj@608
|
504 if(librdf_uri_equals(predicate_uri, distance))
|
mas01mj@608
|
505 {
|
mas01mj@608
|
506 // This requires both elements to be defined - check those first,
|
mas01mj@608
|
507 // and use a blank identifier if not.
|
mas01mj@608
|
508 librdf_statement* element_search = librdf_new_statement(world);
|
mas01mj@608
|
509 librdf_statement_set_subject(element_search, subject);
|
mas01mj@608
|
510 librdf_statement_set_predicate(element_search, librdf_new_node_from_uri(world, element));
|
mas01mj@608
|
511 librdf_stream* elements = librdf_model_find_statements(context->model, element_search);
|
mas01mj@608
|
512 int count = 0;
|
mas01mj@608
|
513
|
mas01mj@608
|
514 char* keys[2];
|
mas01mj@608
|
515
|
mas01mj@608
|
516 while (!librdf_stream_end(elements) && count < 2) {
|
mas01mj@608
|
517 keys[count] = librdf_uri_as_string(
|
mas01mj@608
|
518 librdf_node_get_uri(
|
mas01mj@608
|
519 librdf_statement_get_object(
|
mas01mj@608
|
520 librdf_new_statement_from_statement(
|
mas01mj@608
|
521 librdf_stream_get_object(elements)))));
|
mas01mj@608
|
522 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Key %d %s", count, keys[count]);
|
mas01mj@608
|
523 librdf_stream_next(elements);
|
mas01mj@608
|
524 count++;
|
mas01mj@608
|
525 }
|
mas01mj@608
|
526
|
mas01mj@608
|
527 double dist = 0;
|
mas01mj@603
|
528
|
mas01mj@608
|
529 // TODO : Trigger an error case here.
|
mas01mj@608
|
530
|
mas01mj@608
|
531 if(count == 2)
|
mas01mj@608
|
532 {
|
mas01mj@608
|
533 // Calculate the distance
|
mas01mj@608
|
534 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Calculate distance");
|
mas01mj@608
|
535
|
mas01mj@608
|
536 adb_query_spec_t qspec = {0};
|
mas01mj@608
|
537 adb_datum_t datum = {0};
|
mas01mj@608
|
538 datum.key = keys[0];
|
mas01mj@608
|
539
|
mas01mj@608
|
540 qspec.refine.flags = ADB_REFINE_INCLUDE_KEYLIST;
|
mas01mj@608
|
541 qspec.refine.include.nkeys = 1;
|
mas01mj@608
|
542 qspec.refine.include.keys = &keys[1];
|
mas01mj@608
|
543 qspec.refine.hopsize = 1;
|
mas01mj@608
|
544
|
mas01mj@608
|
545 qspec.qid.datum = &datum;
|
mas01mj@608
|
546 qspec.qid.sequence_length = 10;
|
mas01mj@608
|
547 qspec.qid.flags = ADB_QID_FLAG_EXHAUSTIVE;
|
mas01mj@608
|
548 qspec.qid.sequence_start = 0;
|
mas01mj@608
|
549
|
mas01mj@608
|
550 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
|
mas01mj@608
|
551 qspec.params.distance = ADB_DISTANCE_EUCLIDEAN;
|
mas01mj@608
|
552 qspec.params.npoints = 1;
|
mas01mj@608
|
553 qspec.params.ntracks = 1;
|
mas01mj@608
|
554
|
mas01mj@608
|
555 adb_query_results_t* results = audiodb_query_spec(context->adb, &qspec);
|
mas01mj@608
|
556 dist = results->results[0].dist;
|
mas01mj@608
|
557
|
mas01mj@608
|
558 char value[16];
|
mas01mj@608
|
559 snprintf(value, 16, "%f", dist);
|
mas01mj@608
|
560
|
mas01mj@608
|
561 result_data_add(world, scontext->results);
|
mas01mj@608
|
562 result_list* list = scontext->results;
|
mas01mj@608
|
563 list->tail->statement = librdf_new_statement(world);
|
mas01mj@608
|
564
|
mas01mj@608
|
565 librdf_statement_set_subject(list->tail->statement, subject);
|
mas01mj@608
|
566 librdf_statement_set_predicate(list->tail->statement, predicate);
|
mas01mj@608
|
567 librdf_statement_set_object(list->tail->statement,
|
mas01mj@608
|
568 librdf_new_node_from_typed_literal(world, value, NULL, librdf_new_uri(world, "http://www.w3.org/2001/XMLSchema#decimal")));
|
mas01mj@608
|
569
|
mas01mj@608
|
570 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
571 librdf_model_add_statement(context->model, list->tail->statement);
|
mas01mj@608
|
572 }
|
mas01mj@603
|
573 }
|
mas01mj@608
|
574
|
mas01mj@608
|
575 }
|
mas01mj@608
|
576 else if(subject && predicate && object)
|
mas01mj@608
|
577 {
|
mas01mj@608
|
578 result_data_add(world, scontext->results);
|
mas01mj@608
|
579 result_list* list = scontext->results;
|
mas01mj@608
|
580 list->tail->statement = librdf_new_statement_from_statement(statement);
|
mas01mj@608
|
581 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Cache statement %s", librdf_statement_to_string(list->tail->statement));
|
mas01mj@608
|
582 librdf_model_add_statement(context->model, list->tail->statement);
|
mas01mj@603
|
583 }
|
mas01mj@603
|
584 else
|
mas01mj@603
|
585 {
|
mas01mj@603
|
586 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL, "Halp?");
|
mas01mj@603
|
587 }
|
mas01mj@608
|
588
|
mas01mj@599
|
589 librdf_free_uri(dimension);
|
mas01mj@599
|
590 librdf_free_uri(vectors);
|
mas01mj@603
|
591 librdf_free_uri(signal);
|
mas01mj@603
|
592 librdf_free_uri(type);
|
mas01mj@608
|
593 librdf_free_uri(element);
|
mas01mj@608
|
594 librdf_free_uri(distance);
|
mas01mj@608
|
595 librdf_free_uri(similarity);
|
mas01mj@603
|
596
|
mas01mj@599
|
597 stream = librdf_new_stream(world,
|
mas01mj@599
|
598 (void*)scontext,
|
mas01mj@599
|
599 &librdf_storage_audiodb_find_statements_end_of_stream,
|
mas01mj@599
|
600 &librdf_storage_audiodb_find_statements_next_statement,
|
mas01mj@599
|
601 &librdf_storage_audiodb_find_statements_get_statement,
|
mas01mj@599
|
602 &librdf_storage_audiodb_find_statements_finished);
|
mas01mj@584
|
603
|
mas01mj@584
|
604 if(!stream) {
|
mas01mj@599
|
605 librdf_log(world, 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@599
|
606 "Couldn't create stream!");
|
mas01mj@584
|
607 librdf_storage_audiodb_find_statements_finished((void*)scontext);
|
mas01mj@584
|
608 return NULL;
|
mas01mj@584
|
609 }
|
mas01mj@584
|
610
|
mas01mj@584
|
611 return stream;
|
mas01mj@584
|
612 }
|
mas01mj@584
|
613
|
mas01mj@584
|
614 static void librdf_storage_audiodb_find_statements_finished(void* context) {
|
mas01mj@584
|
615 librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
|
mas01mj@599
|
616
|
mas01mj@584
|
617 if(scontext->storage)
|
mas01mj@584
|
618 librdf_storage_remove_reference(scontext->storage);
|
mas01mj@584
|
619
|
mas01mj@584
|
620 if(scontext->statement)
|
mas01mj@584
|
621 librdf_free_statement(scontext->statement);
|
mas01mj@584
|
622
|
mas01mj@584
|
623 if(scontext->context)
|
mas01mj@584
|
624 librdf_free_node(scontext->context);
|
mas01mj@584
|
625
|
mas01mj@585
|
626 librdf_sign_free(scontext);
|
mas01mj@584
|
627 }
|
mas01mj@584
|
628
|
mas01mj@584
|
629 static int librdf_storage_audiodb_find_statements_end_of_stream(void* context) {
|
mas01mj@584
|
630 librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
|
mas01mj@599
|
631 librdf_world* world = librdf_storage_get_world(scontext->storage);
|
mas01mj@599
|
632 librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@603
|
633 "Finished? %d", (scontext->results->head == NULL));
|
mas01mj@584
|
634
|
mas01mj@599
|
635 return (scontext->results->head == NULL);
|
mas01mj@584
|
636 }
|
mas01mj@584
|
637
|
mas01mj@584
|
638 static int librdf_storage_audiodb_find_statements_next_statement(void* context) {
|
mas01mj@584
|
639 librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
|
mas01mj@584
|
640
|
mas01mj@599
|
641 librdf_world* world = librdf_storage_get_world(scontext->storage);
|
mas01mj@599
|
642 librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@599
|
643 "to next");
|
mas01mj@599
|
644
|
mas01mj@599
|
645 if(scontext->results->head->next)
|
mas01mj@599
|
646 {
|
mas01mj@599
|
647 scontext->results->head = scontext->results->head->next;
|
mas01mj@599
|
648 return 0;
|
mas01mj@599
|
649 }
|
mas01mj@599
|
650 else
|
mas01mj@599
|
651 {
|
mas01mj@584
|
652 return 1;
|
mas01mj@584
|
653 }
|
mas01mj@584
|
654 }
|
mas01mj@584
|
655
|
mas01mj@584
|
656 static void* librdf_storage_audiodb_find_statements_get_statement(void* context, int flags) {
|
mas01mj@584
|
657 librdf_storage_audiodb_find_statements_stream_context* scontext=(librdf_storage_audiodb_find_statements_stream_context*)context;
|
mas01mj@599
|
658 librdf_world* world = librdf_storage_get_world(scontext->storage);
|
mas01mj@599
|
659 librdf_log(librdf_storage_get_world(scontext->storage), 0, LIBRDF_LOG_INFO, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@599
|
660 "Get next");
|
mas01mj@603
|
661
|
mas01mj@584
|
662 switch(flags) {
|
mas01mj@584
|
663 case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
|
mas01mj@599
|
664 return scontext->results->head->statement;
|
mas01mj@584
|
665 case LIBRDF_ITERATOR_GET_METHOD_GET_CONTEXT:
|
mas01mj@584
|
666 return scontext->context;
|
mas01mj@584
|
667 default:
|
mas01mj@599
|
668 librdf_log(world,
|
mas01mj@584
|
669 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_STORAGE, NULL,
|
mas01mj@584
|
670 "Unknown iterator method flag %d", flags);
|
mas01mj@584
|
671 return NULL;
|
mas01mj@584
|
672 }
|
mas01mj@584
|
673 }
|
mas01mj@584
|
674
|
mas01mj@584
|
675
|
mas01mj@584
|
676
|
mas01mj@584
|
677 static int librdf_storage_audiodb_sync(librdf_storage *storage) {
|
mas01mj@584
|
678 return 0;
|
mas01mj@584
|
679 }
|
mas01mj@584
|
680
|
mas01mj@584
|
681 static void
|
mas01mj@584
|
682 librdf_storage_audiodb_register_factory(librdf_storage_factory *factory) {
|
mas01mj@584
|
683 factory->version = LIBRDF_STORAGE_INTERFACE_VERSION;
|
mas01mj@584
|
684 factory->init = librdf_storage_audiodb_init;
|
mas01mj@584
|
685 factory->open = librdf_storage_audiodb_open;
|
mas01mj@584
|
686 factory->close = librdf_storage_audiodb_close;
|
mas01mj@584
|
687 factory->size = librdf_storage_audiodb_size;
|
mas01mj@584
|
688 factory->add_statement = librdf_storage_audiodb_add_statement;
|
mas01mj@584
|
689 factory->remove_statement = librdf_storage_audiodb_remove_statement;
|
mas01mj@584
|
690 factory->contains_statement = librdf_storage_audiodb_contains_statement;
|
mas01mj@584
|
691 factory->serialise = librdf_storage_audiodb_serialise;
|
mas01mj@584
|
692 factory->find_statements = librdf_storage_audiodb_find_statements;
|
mas01mj@584
|
693 }
|
mas01mj@584
|
694
|
mas01mj@584
|
695 /** Entry point for dynamically loaded storage module */
|
mas01mj@584
|
696 void librdf_storage_module_register_factory(librdf_world *world) {
|
mas01mj@584
|
697 librdf_storage_register_factory(world, "audiodb", "AudioDB",
|
mas01mj@584
|
698 &librdf_storage_audiodb_register_factory);
|
mas01mj@584
|
699 }
|