Mercurial > hg > audiodb
changeset 548:e18843dc0aea
Implement a rudimentary API for audioDB::liszt
The API is rudimentary because we've dropped support for the incremental
retrieval of tracks and their number of vectors (at the API level; the
SOAP and command-line support is still there -- no changes should be
visible). This is potentially bad for the large-scale databases, of
course; one million tracks will take of the order of 16MB of RAM, more
if I'm unlucky about how std::string.c_str() is implemented.
Both this liszt operation and querying (and sampling, forthcoming...)
would benefit from a `cursor-like' interface to retrieval results: for
an API like that, instead of getting a struct with the data there, you
get a cookie with which you can ask the database for successive results.
This would be neat for all sorts of reasons. In the meantime, at least
this change fixes SOAP memory leaks related to liszt.
Make liszt.o part of LIBOBJS rather than ordinary OBJS, so that the
liszt functionality is actually compiled into the library.
Add a test for this library functionality; also modify the command-line
test file to run the SOAP server on its own port.
author | mas01cr |
---|---|
date | Wed, 11 Feb 2009 12:38:03 +0000 |
parents | 5a248cedd3e9 |
children | 0694bb74c5e9 |
files | Makefile audioDB.cpp audioDB.h audioDB_API.h libtests/0039/prog1.c libtests/0039/short-description libtests/test_utils_lib.h liszt.cpp soap.cpp tests/0039/run-test.sh |
diffstat | 10 files changed, 123 insertions(+), 38 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Wed Feb 11 10:42:23 2009 +0000 +++ b/Makefile Wed Feb 11 12:38:03 2009 +0000 @@ -8,8 +8,8 @@ SHARED_LIB_FLAGS=-shared -Wl,-soname, -LIBOBJS=lock.o pointpair.o create.o open.o power.o l2norm.o insert.o status.o query.o dump.o close.o lshlib.o index-utils.o query-indexed.o -OBJS=$(LIBOBJS) index.o soap.o liszt.o sample.o cmdline.o audioDB.o common.o +LIBOBJS=lock.o pointpair.o create.o open.o power.o l2norm.o insert.o status.o query.o dump.o close.o lshlib.o index-utils.o query-indexed.o liszt.o +OBJS=$(LIBOBJS) index.o soap.o sample.o cmdline.o audioDB.o common.o EXECUTABLE=audioDB
--- a/audioDB.cpp Wed Feb 11 10:42:23 2009 +0000 +++ b/audioDB.cpp Wed Feb 11 12:38:03 2009 +0000 @@ -111,7 +111,7 @@ } } -audioDB::audioDB(const unsigned argc, const char *argv[], adb__lisztResponse *adbLisztResponse): O2_AUDIODB_INITIALIZERS +audioDB::audioDB(const unsigned argc, const char *argv[], struct soap *soap, adb__lisztResponse *adbLisztResponse): O2_AUDIODB_INITIALIZERS { try { isServer = 1; // Set to make errors report over SOAP @@ -120,7 +120,7 @@ if(dbName && adb_root) prefix_name((char** const)&dbName, adb_root); assert(O2_ACTION(COM_LISZT)); - liszt(dbName, lisztOffset, lisztLength, adbLisztResponse); + liszt(dbName, lisztOffset, lisztLength, soap, adbLisztResponse); } catch(char *err) { cleanup(); throw(err); @@ -950,6 +950,44 @@ reporter->report(adb, soap, adbQueryResponse); } +void audioDB::liszt(const char* dbName, unsigned offset, unsigned numLines, struct soap *soap, adb__lisztResponse* adbLisztResponse) { + if(!adb) { + if(!(adb = audiodb_open(dbName, O_RDONLY))) { + error("failed to open database", dbName); + } + } + + adb_liszt_results_t *results = audiodb_liszt(adb); + if(!results) { + error("audiodb_liszt() failed"); + } + + if(offset > results->nresults) { + audiodb_liszt_free_results(adb, results); + error("listKeys offset out of range"); + } + + if(!adbLisztResponse){ + for(uint32_t k = 0; k < numLines && offset + k < results->nresults; k++) { + uint32_t index = offset + k; + printf("[%d] %s (%d)\n", index, results->entries[index].key, results->entries[index].nvectors); + } + } else { + adbLisztResponse->result.Rkey = (char **) soap_malloc(soap, numLines * sizeof(char *)); + adbLisztResponse->result.Rlen = (unsigned int *) soap_malloc(soap, numLines * sizeof(unsigned int)); + uint32_t k; + for(k = 0; k < numLines && offset + k < results->nresults; k++) { + uint32_t index = offset + k; + adbLisztResponse->result.Rkey[k] = (char *) soap_malloc(soap, O2_MAXFILESTR); + snprintf(adbLisztResponse->result.Rkey[k], O2_MAXFILESTR, "%s", results->entries[index].key); + adbLisztResponse->result.Rlen[k] = results->entries[index].nvectors; + } + adbLisztResponse->result.__sizeRkey = k; + adbLisztResponse->result.__sizeRlen = k; + } + audiodb_liszt_free_results(adb, results); +} + // This entry point is visited once per instance // so it is a good place to set any global state variables int main(const int argc, const char* argv[]){
--- a/audioDB.h Wed Feb 11 10:42:23 2009 +0000 +++ b/audioDB.h Wed Feb 11 12:38:03 2009 +0000 @@ -273,7 +273,7 @@ audioDB(const unsigned argc, const char *argv[]); audioDB(const unsigned argc, const char *argv[], struct soap *soap, adb__queryResponse *adbQueryResponse); audioDB(const unsigned argc, const char *argv[], adb__statusResponse *adbStatusResponse); - audioDB(const unsigned argc, const char *argv[], adb__lisztResponse *adbLisztResponse); + audioDB(const unsigned argc, const char *argv[], struct soap *soap, adb__lisztResponse *adbLisztResponse); void cleanup(); ~audioDB(); @@ -291,7 +291,7 @@ void l2norm(const char* dbName); void power_flag(const char *dbName); void dump(const char* dbName); - void liszt(const char* dbName, unsigned offset, unsigned numLines, adb__lisztResponse* adbLisztResponse=0); + void liszt(const char* dbName, unsigned offset, unsigned numLines, struct soap *soap=0, adb__lisztResponse* adbLisztResponse=0); // LSH indexing parameters and data structures LSH* lsh;
--- a/audioDB_API.h Wed Feb 11 10:42:23 2009 +0000 +++ b/audioDB_API.h Wed Feb 11 12:38:03 2009 +0000 @@ -163,6 +163,16 @@ adb_query_refine_t refine; } adb_query_spec_t; +typedef struct adbtrackentry { + uint32_t nvectors; + const char *key; +} adb_track_entry_t; + +typedef struct adblisztresults { + uint32_t nresults; + adb_track_entry_t *entries; +} adb_liszt_results_t; + /*******************************************************************/ /* Function prototypes for API */ @@ -198,4 +208,8 @@ /* varoius dump formats */ int audiodb_dump(adb_ptr mydb, const char *outputdir); +/* liszt */ +adb_liszt_results_t *audiodb_liszt(adb_t *); +int audiodb_liszt_free_results(adb_t *, adb_liszt_results_t *); + #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtests/0039/prog1.c Wed Feb 11 12:38:03 2009 +0000 @@ -0,0 +1,28 @@ +#include "audioDB_API.h" +#include "test_utils_lib.h" + +int main(int argc, char *argv[]) { + adb_t *adb; + adb_liszt_results_t *liszt; + + clean_remove_db(TESTDB); + if(!(adb = audiodb_create(TESTDB, 0, 0, 0))) + return 1; + adb_datum_t datum1 = {2, 2, "testfeature01", (double[4]) {0, 1, 1, 0}}; + adb_datum_t datum2 = {2, 2, "testfeature10", (double[4]) {1, 0, 0, 1}}; + if(audiodb_insert_datum(adb, &datum1)) + return 1; + if(audiodb_insert_datum(adb, &datum2)) + return 1; + + liszt = audiodb_liszt(adb); + if(!liszt || liszt->nresults != 2) + return 1; + entry_present_or_fail(liszt, "testfeature01", 2); + entry_present_or_fail(liszt, "testfeature10", 2); + audiodb_liszt_free_results(adb, liszt); + + audiodb_close(adb); + + return 104; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libtests/0039/short-description Wed Feb 11 12:38:03 2009 +0000 @@ -0,0 +1,1 @@ +liszt \ No newline at end of file
--- a/libtests/test_utils_lib.h Wed Feb 11 10:42:23 2009 +0000 +++ b/libtests/test_utils_lib.h Wed Feb 11 12:38:03 2009 +0000 @@ -40,3 +40,16 @@ #define result_present_or_fail(r, k, d, q, i) \ if(result_position(r, k, d, q, i) < 0) return 1; + +int entry_position(adb_liszt_results_t *l, const char *key, uint32_t nvectors) { + for(uint32_t k = 0; k < l->nresults; k++) { + adb_track_entry_t entry = l->entries[k]; + if((nvectors == entry.nvectors) && !strcmp(key, entry.key)) { + return k; + } + } + return -1; +} + +#define entry_present_or_fail(l, k, n) \ + if(entry_position(l, k, n) < 0) return 1;
--- a/liszt.cpp Wed Feb 11 10:42:23 2009 +0000 +++ b/liszt.cpp Wed Feb 11 12:38:03 2009 +0000 @@ -1,34 +1,25 @@ -#include "audioDB.h" +extern "C" { +#include "audioDB_API.h" +} +#include "audioDB-internals.h" -void audioDB::liszt(const char* dbName, unsigned offset, unsigned numLines, adb__lisztResponse* adbLisztResponse){ - if(!dbH) { - initTables(dbName, 0); +adb_liszt_results_t *audiodb_liszt(adb_t *adb) { + uint32_t nfiles = adb->header->numFiles; + adb_liszt_results_t *results; + results = (adb_liszt_results_t *) calloc(sizeof(adb_liszt_results_t),1); + results->nresults = nfiles; + if(nfiles > 0) { + results->entries = (adb_track_entry_t *) malloc(nfiles * sizeof(adb_track_entry_t)); } + for(uint32_t k = 0; k < nfiles; k++) { + results->entries[k].nvectors = (*adb->track_lengths)[k]; + results->entries[k].key = audiodb_index_key(adb, k); + } + return results; +} - assert(trackTable && fileTable); - - if(offset>dbH->numFiles){ - char tmpStr[MAXSTR]; - sprintf(tmpStr, "numFiles=%u, lisztOffset=%u", dbH->numFiles, offset); - error("listKeys offset out of range", tmpStr); - } - - if(!adbLisztResponse){ - for(Uns32T k=0; k<numLines && offset+k<dbH->numFiles; k++){ - fprintf(stdout, "[%d] %s (%d)\n", offset+k, fileTable+(offset+k)*O2_FILETABLE_ENTRY_SIZE, trackTable[offset+k]); - } - } - else{ - adbLisztResponse->result.Rkey = new char*[numLines]; - adbLisztResponse->result.Rlen = new unsigned int[numLines]; - Uns32T k = 0; - for( ; k<numLines && offset+k<dbH->numFiles; k++){ - adbLisztResponse->result.Rkey[k] = new char[MAXSTR]; - snprintf(adbLisztResponse->result.Rkey[k], O2_MAXFILESTR, "%s", fileTable+(offset+k)*O2_FILETABLE_ENTRY_SIZE); - adbLisztResponse->result.Rlen[k] = trackTable[offset+k]; - } - adbLisztResponse->result.__sizeRkey = k; - adbLisztResponse->result.__sizeRlen = k; - } - +int audiodb_liszt_free_results(adb_t *adb, adb_liszt_results_t *results) { + free(results->entries); + free(results); + return 0; }
--- a/soap.cpp Wed Feb 11 10:42:23 2009 +0000 +++ b/soap.cpp Wed Feb 11 12:38:03 2009 +0000 @@ -164,7 +164,7 @@ const char *argv[] = {"./audioDB", COM_LISZT, "-d",dbName, "--lisztOffset", lisztOffsetStr, "--lisztLength", lisztLengthStr}; const unsigned argc = 8; try{ - audioDB(argc, argv, &adbLisztResponse); + audioDB(argc, argv, soap, &adbLisztResponse); return SOAP_OK; } catch(char *err) { soap_receiver_fault(soap, err, "");
--- a/tests/0039/run-test.sh Wed Feb 11 10:42:23 2009 +0000 +++ b/tests/0039/run-test.sh Wed Feb 11 12:38:03 2009 +0000 @@ -46,7 +46,7 @@ echo "[1] testkey02 (2)" >> test-expected-output cmp testoutput test-expected-output -WSPORT=10020 +WSPORT=10039 start_server ${AUDIODB} ${WSPORT} expect_clean_error_exit ${AUDIODB} -d testdb -c localhost:${WSPORT} --LISZT --lisztOffset -1