Mercurial > hg > audiodb
diff audioDB.cpp @ 469:d3afc91d205d api-inversion
Move audioDB::query over to audioDB.cpp
At the same time, remove all the abstraction violations in
audioDB::query, which came in two flavours: use of dbH->numFiles, which
is dealt with by getting the database status instead (and is eventually
unnecessary, being only needed now because reporters are implemented in
terms of vectors indexed by ID), and use of fileTable in reporter's
report functions (dealt with by passing in the adb instead).
To actually implement reporting as of now, we continue to use stuff from
audioDB-internals.h; maybe someday we will be clean and shiny.
author | mas01cr |
---|---|
date | Wed, 31 Dec 2008 15:44:16 +0000 |
parents | 1030664df98c |
children | 8fb85fbcaba6 |
line wrap: on
line diff
--- a/audioDB.cpp Wed Dec 31 15:44:12 2008 +0000 +++ b/audioDB.cpp Wed Dec 31 15:44:16 2008 +0000 @@ -3,6 +3,7 @@ #include "audioDB_API.h" #include "audioDB-internals.h" } +#include "reporter.h" char* SERVER_ADB_ROOT; char* SERVER_ADB_FEATURE_ROOT; @@ -822,6 +823,184 @@ status(dbName); } +void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse) { + + if(!adb) { + if(!(adb = audiodb_open(dbName, O_RDWR))) { + error("failed to open database", dbName); + } + } + + /* FIXME: we only need this for getting nfiles, which we only need + * because the reporters aren't desperately well implemented, + * relying on statically-sized vectors rather than adjustable data + * structures. Rework reporter.h to be less lame. */ + adb_status_t status; + audiodb_status(adb, &status); + uint32_t nfiles = status.numFiles; + + adb_query_spec_t qspec; + adb_datum_t datum = {0}; + + qspec.refine.flags = 0; + if(trackFile) { + qspec.refine.flags |= ADB_REFINE_INCLUDE_KEYLIST; + std::vector<const char *> v; + char *k = new char[MAXSTR]; + trackFile->getline(k, MAXSTR); + while(!trackFile->eof()) { + v.push_back(k); + k = new char[MAXSTR]; + trackFile->getline(k, MAXSTR); + } + delete [] k; + qspec.refine.include.nkeys = v.size(); + qspec.refine.include.keys = new const char *[qspec.refine.include.nkeys]; + for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) { + qspec.refine.include.keys[k] = v[k]; + } + } + if(query_from_key) { + qspec.refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST; + qspec.refine.exclude.nkeys = 1; + qspec.refine.exclude.keys = &key; + } + if(radius) { + qspec.refine.flags |= ADB_REFINE_RADIUS; + qspec.refine.radius = radius; + } + if(use_absolute_threshold) { + qspec.refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD; + qspec.refine.absolute_threshold = absolute_threshold; + } + if(use_relative_threshold) { + qspec.refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD; + qspec.refine.relative_threshold = relative_threshold; + } + if(usingTimes) { + qspec.refine.flags |= ADB_REFINE_DURATION_RATIO; + qspec.refine.duration_ratio = timesTol; + } + /* FIXME: not sure about this any more; maybe it belongs in + query_id? Or maybe we just don't need a flag for it? */ + qspec.refine.hopsize = sequenceHop; + if(sequenceHop != 1) { + qspec.refine.flags |= ADB_REFINE_HOP_SIZE; + } + + if(query_from_key) { + datum.key = key; + } else { + int fd; + struct stat st; + + /* FIXME: around here there are all sorts of hideous leaks. */ + fd = open(inFile, O_RDONLY); + if(fd < 0) { + error("failed to open feature file", inFile); + } + fstat(fd, &st); + read(fd, &datum.dim, sizeof(uint32_t)); + datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double)); + datum.data = (double *) malloc(st.st_size - sizeof(uint32_t)); + read(fd, datum.data, st.st_size - sizeof(uint32_t)); + close(fd); + if(usingPower) { + uint32_t one; + fd = open(powerFileName, O_RDONLY); + if(fd < 0) { + error("failed to open power file", powerFileName); + } + read(fd, &one, sizeof(uint32_t)); + if(one != 1) { + error("malformed power file dimensionality", powerFileName); + } + datum.power = (double *) malloc(datum.nvectors * sizeof(double)); + if(read(fd, datum.power, datum.nvectors * sizeof(double)) != (ssize_t) (datum.nvectors * sizeof(double))) { + error("malformed power file", powerFileName); + } + close(fd); + } + if(usingTimes) { + datum.times = (double *) malloc(2 * datum.nvectors * sizeof(double)); + insertTimeStamps(datum.nvectors, timesFile, datum.times); + } + } + + qspec.qid.datum = &datum; + qspec.qid.sequence_length = sequenceLength; + qspec.qid.flags = 0; + qspec.qid.flags |= usingQueryPoint ? 0 : ADB_QID_FLAG_EXHAUSTIVE; + qspec.qid.flags |= lsh_exact ? 0 : ADB_QID_FLAG_ALLOW_FALSE_POSITIVES; + qspec.qid.sequence_start = queryPoint; + + switch(queryType) { + case O2_POINT_QUERY: + qspec.qid.sequence_length = 1; + qspec.params.accumulation = ADB_ACCUMULATION_DB; + qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT; + qspec.params.npoints = pointNN; + qspec.params.ntracks = 0; + reporter = new pointQueryReporter< std::greater < NNresult > >(pointNN); + break; + case O2_TRACK_QUERY: + qspec.qid.sequence_length = 1; + qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; + qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT; + qspec.params.npoints = pointNN; + qspec.params.ntracks = trackNN; + reporter = new trackAveragingReporter< std::greater< NNresult > >(pointNN, trackNN, nfiles); + break; + case O2_SEQUENCE_QUERY: + case O2_N_SEQUENCE_QUERY: + qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK; + qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED; + qspec.params.npoints = pointNN; + qspec.params.ntracks = trackNN; + switch(queryType) { + case O2_SEQUENCE_QUERY: + if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) { + reporter = new trackAveragingReporter< std::less< NNresult > >(pointNN, trackNN, nfiles); + } else { + reporter = new trackSequenceQueryRadReporter(trackNN, nfiles); + } + break; + case O2_N_SEQUENCE_QUERY: + if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) { + reporter = new trackSequenceQueryNNReporter< std::less < NNresult > >(pointNN, trackNN, nfiles); + } else { + reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, nfiles); + } + break; + } + break; + case O2_ONE_TO_ONE_N_SEQUENCE_QUERY: + qspec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE; + qspec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED; + qspec.params.npoints = 0; + qspec.params.ntracks = 0; + break; + default: + error("unrecognized queryType"); + } + + adb_query_results_t *rs = audiodb_query_spec(adb, &qspec); + + // FIXME: free bits of datum if !query_from_key + + if(rs == NULL) { + error("audiodb_query_spec failed"); + } + + for(unsigned int k = 0; k < rs->nresults; k++) { + adb_result_t r = rs->results[k]; + reporter->add_point(audiodb_key_index(adb, r.key), r.qpos, r.ipos, r.dist); + } + audiodb_query_free_results(adb, &qspec, rs); + + reporter->report(adb, adbQueryResponse); +} + // 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[]){