Mercurial > hg > audiodb
changeset 509:cc2b97d020b1
Code rearrangements to tease apart library code from C++ audioDB code.
There should be precisely no functional changes in this commit.
Instead, the only thing that has happened is that all the abstraction
violation and other horribleness is concentrated in one place: the
include of "audioDB-internals.h" in audioDB.h -- the separation will be
complete once that include can be removed.
This include is necessary because the command-line binary / SOAP server
still does some things directly rather than through an API: not least of
which the operations that have not yet been integrated into the API yet,
but also some messing around with constants, flags and nominally
internal functions. The intent is to remove as many of these as
possible and think quite hard about the rest.
In the meantime, the library is now much more self-contained: the only
things it uses are in the audioDB_API.h and audioDB-internals.h headers;
thus there are fewer nasty surprises lurking for readers of the code.
The Makefile has been adjusted to take advantage of this rearrangement
in the dependencies.
author | mas01cr |
---|---|
date | Thu, 15 Jan 2009 13:57:33 +0000 |
parents | 23c47e118bc6 |
children | 2b95e396f4d7 |
files | Makefile audioDB-internals.h audioDB.cpp audioDB.h audioDB_API.h close.cpp common.cpp create.cpp dump.cpp index-utils.cpp index.cpp insert.cpp l2norm.cpp lock.cpp open.cpp pointpair.cpp power.cpp query-indexed.cpp query.cpp soap.cpp status.cpp |
diffstat | 21 files changed, 544 insertions(+), 538 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Tue Jan 13 21:37:14 2009 +0000 +++ b/Makefile Thu Jan 15 13:57:33 2009 +0000 @@ -8,9 +8,8 @@ SHARED_LIB_FLAGS=-shared -Wl,-soname, -LIBOBJS=query.o index.o insert.o create.o common.o open.o close.o status.o dump.o power.o l2norm.o lshlib.o lock.o pointpair.o -OBJS=$(LIBOBJS) 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 +OBJS=$(LIBOBJS) index.o soap.o liszt.o sample.o cmdline.o audioDB.o common.o EXECUTABLE=audioDB @@ -48,7 +47,7 @@ soapServer.cpp soapClient.cpp soapC.cpp soapH.h adb.nsmap: audioDBws.h $(SOAPCPP2) audioDBws.h -$(LIBOBJS): %.o: %.cpp audioDB.h audioDB_API.h audioDB-internals.h accumulator.h accumulators.h cmdline.h soapH.h +$(LIBOBJS): %.o: %.cpp audioDB_API.h audioDB-internals.h accumulator.h accumulators.h g++ -c $(CFLAGS) $(GSL_INCLUDE) -Wall $< %.o: %.cpp audioDB.h audioDB_API.h adb.nsmap cmdline.h reporter.h ReporterBase.h lshlib.h @@ -85,8 +84,8 @@ test: $(EXECUTABLE) - -sh -c "cd tests && sh ./run-tests.sh" - -sh -c "cd libtests && sh ./run-tests.sh" + sh -c "cd libtests && sh ./run-tests.sh" + sh -c "cd tests && sh ./run-tests.sh" xthresh: xthresh.c gcc -o $@ $(CFLAGS) $(GSL_INCLUDE) $(LIBGSL) $<
--- a/audioDB-internals.h Tue Jan 13 21:37:14 2009 +0000 +++ b/audioDB-internals.h Thu Jan 15 13:57:33 2009 +0000 @@ -1,4 +1,11 @@ +#include <set> +#include <queue> +#include <map> +#include <string> + +#include "pointpair.h" #include "accumulator.h" +#include "lshlib.h" /* this struct is for writing polymorphic routines as puns. When * inserting, we might have a "datum" (with actual numerical data) or @@ -48,6 +55,32 @@ LSH *lsh; } adb_qstate_internal_t; +/* this struct is the in-memory representation of the binary + * information stored at the head of each adb file */ +typedef struct adbheader { + uint32_t magic; + uint32_t version; + uint32_t numFiles; + uint32_t dim; + uint32_t flags; + uint32_t headerSize; + off_t length; + off_t fileTableOffset; + off_t trackTableOffset; + off_t dataOffset; + off_t l2normTableOffset; + off_t timesTableOffset; + off_t powerTableOffset; + off_t dbSize; +} adb_header_t; + +#define ADB_HEADER_SIZE (sizeof(struct adbheader)) + +#define ADB_HEADER_FLAG_L2NORM (0x1U) +#define ADB_HEADER_FLAG_POWER (0x4U) +#define ADB_HEADER_FLAG_TIMES (0x20U) +#define ADB_HEADER_FLAG_REFERENCES (0x40U) + /* the transparent version of the opaque (forward-declared) adb_t. */ struct adb { char *path; @@ -111,6 +144,13 @@ } \ } +#define maybe_delete_array(pointer) \ + { if(pointer) { \ + delete [] pointer; \ + pointer = NULL; \ + } \ + } + #define write_or_goto_error(fd, buffer, size) \ { ssize_t tmp = size; \ if(write(fd, buffer, size) != tmp) { \ @@ -134,7 +174,7 @@ if(lseek(adb->fd, (off_t) 0, SEEK_SET) == (off_t) -1) { goto error; } - if(write(adb->fd, adb->header, O2_HEADERSIZE) != O2_HEADERSIZE) { + if(write(adb->fd, adb->header, ADB_HEADER_SIZE) != ADB_HEADER_SIZE) { goto error; } @@ -242,9 +282,14 @@ return ((track_id << n_point_bits) | track_pos); } +#define ADB_FIXME_DEFAULT_LSH_N_POINT_BITS 14 +#ifndef ADB_FIXME_LSH_N_POINT_BITS +#define ADB_FIXME_LSH_N_POINT_BITS ADB_FIXME_DEFAULT_LSH_N_POINT_BITS +#endif + static inline uint32_t audiodb_lsh_n_point_bits(adb_t *adb) { uint32_t nbits = adb->header->flags >> 28; - return (nbits ? nbits : O2_DEFAULT_LSH_N_POINT_BITS); + return (nbits ? nbits : ADB_FIXME_LSH_N_POINT_BITS); } int audiodb_read_data(adb_t *, int, int, double **, size_t *); @@ -258,3 +303,33 @@ char *audiodb_index_get_name(const char *, double, uint32_t); bool audiodb_index_exists(const char *, double, uint32_t); int audiodb_index_query_loop(adb_t *, const adb_query_spec_t *, adb_qstate_internal_t *); +LSH *audiodb_index_allocate(adb_t *, char *, bool); +vector<vector<float> > *audiodb_index_initialize_shingles(uint32_t, uint32_t, uint32_t); +void audiodb_index_delete_shingles(vector<vector<float> > *); +void audiodb_index_make_shingle(vector<vector<float> > *, uint32_t, double *, uint32_t, uint32_t); +int audiodb_index_norm_shingles(vector<vector<float> > *, double *, double *, uint32_t, uint32_t, double, bool, bool, float); + +#define ADB_MAXSTR (512U) +#define ADB_FILETABLE_ENTRY_SIZE (256U) +#define ADB_TRACKTABLE_ENTRY_SIZE (sizeof(uint32_t)) +#define ADB_DISTANCE_TOLERANCE (1e-6) + +#define ADB_DEFAULT_DATASIZE (1355U) /* in MB */ +#define ADB_DEFAULT_NTRACKS (20000U) +#define ADB_DEFAULT_DATADIM (9U) + +#define ADB_FIXME_LARGE_ADB_SIZE (ADB_DEFAULT_DATASIZE+1) +#define ADB_FIXME_LARGE_ADB_NTRACKS (ADB_DEFAULT_NTRACKS+1) + +#define ADB_OLD_MAGIC ('O'|'2'<<8|'D'<<16|'B'<<24) +#define ADB_MAGIC ('o'|'2'<<8|'d'<<16|'b'<<24) +#define ADB_FORMAT_VERSION (4U) + +#define ADB_LSH_MAXTRACKLEN (1 << ADB_FIXME_LSH_N_POINT_BITS) + +#define align_up(x,w) (((x) + ((1<<w)-1)) & ~((1<<w)-1)) +#define align_down(x,w) ((x) & ~((1<<w)-1)) + +#define align_page_up(x) (((x) + (getpagesize()-1)) & ~(getpagesize()-1)) +#define align_page_down(x) ((x) & ~(getpagesize()-1)) +
--- a/audioDB.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/audioDB.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,4 @@ #include "audioDB.h" -extern "C" { -#include "audioDB_API.h" -#include "audioDB-internals.h" -} #include "reporter.h" char* SERVER_ADB_ROOT;
--- a/audioDB.h Tue Jan 13 21:37:14 2009 +0000 +++ b/audioDB.h Thu Jan 15 13:57:33 2009 +0000 @@ -24,6 +24,7 @@ extern "C" { #include "audioDB_API.h" } +#include "audioDB-internals.h" #include "ReporterBase.h" #include "accumulator.h" #include "lshlib.h" @@ -32,17 +33,7 @@ #include "soapH.h" #include "cmdline.h" -// should probably be rewritten -class PointPair{ - public: - Uns32T trackID; - Uns32T qpos; - Uns32T spos; - PointPair(Uns32T a, Uns32T b, Uns32T c); -}; -bool operator<(const PointPair& a, const PointPair& b); - -#define MAXSTR 512 +#define MAXSTR ADB_MAXSTR // Databse PRIMARY commands #define COM_CREATE "--NEW" @@ -79,54 +70,41 @@ #define COM_LSH_EXACT "--lsh_exact" #define COM_NO_UNIT_NORMING "--no_unit_norming" -#define O2_OLD_MAGIC ('O'|'2'<<8|'D'<<16|'B'<<24) -#define O2_MAGIC ('o'|'2'<<8|'d'<<16|'b'<<24) -#define O2_FORMAT_VERSION (4U) - #define O2_DEFAULT_POINTNN (10U) #define O2_DEFAULT_TRACKNN (10U) //#define O2_DEFAULTDBSIZE (4000000000) // 4GB table size #define O2_DEFAULTDBSIZE (2000000000) // 2GB table size -// Bit masks for packing (trackID,pointID) into 32-bit unsigned int -// This can be controlled at compile time -#define O2_DEFAULT_LSH_N_POINT_BITS 14 - -// Override the default point bit width for large database support -#ifndef LSH_N_POINT_BITS -#define LSH_N_POINT_BITS O2_DEFAULT_LSH_N_POINT_BITS -#endif +#define O2_DEFAULT_DATASIZE (1355U) /* in MB */ +#define O2_DEFAULT_NTRACKS (20000U) +#define O2_DEFAULT_DATADIM (9U) // LIMIT PARAMETERS -#define O2_DEFAULT_DATASIZE (1355U) // in MB -#define O2_DEFAULT_NTRACKS (20000U) -#define O2_DEFAULT_DATADIM (9U) #define O2_REALTYPE (double) #define O2_MAXFILES (1000000U) -#define O2_MAXFILESTR (256U) -#define O2_FILETABLE_ENTRY_SIZE (O2_MAXFILESTR) -#define O2_TRACKTABLE_ENTRY_SIZE (sizeof(unsigned)) +#define O2_MAXFILESTR ADB_FILETABLE_ENTRY_SIZE +#define O2_FILETABLE_ENTRY_SIZE ADB_FILETABLE_ENTRY_SIZE +#define O2_TRACKTABLE_ENTRY_SIZE ADB_TRACKTABLE_ENTRY_SIZE #define O2_HEADERSIZE (sizeof(dbTableHeaderT)) #define O2_MEANNUMVECTORS (1000U) #define O2_MAXDIM (20000U) #define O2_MAXNN (1000000U) #define O2_MAXSEQLEN (8000U) // maximum feature vectors in a sequence #define O2_MAXTRACKS (1000000U) // maximum number of tracks -#define O2_MAXTRACKLEN (1<<LSH_N_POINT_BITS) // maximum shingles in a track +#define O2_MAXTRACKLEN ADB_LSH_MAXTRACKLEN #define O2_MAXDOTPRODUCTMEMORY (sizeof(O2_REALTYPE)*O2_MAXSEQLEN*O2_MAXSEQLEN) // 512MB -#define O2_DISTANCE_TOLERANCE (1e-6) #define O2_SERIAL_MAX_TRACKBATCH (1000000) #define O2_LARGE_ADB_SIZE (O2_DEFAULT_DATASIZE+1) // datasize at which features are kept externally (in Mbytes) #define O2_LARGE_ADB_NTRACKS (O2_DEFAULT_NTRACKS+1) // ntracks at which features are kept externally #define O2_MAX_VECTORS ( O2_MEANNUMVECTORS * O2_MAXTRACKS ) // Flags -#define O2_FLAG_L2NORM (0x1U) +#define O2_FLAG_L2NORM ADB_HEADER_FLAG_L2NORM #define O2_FLAG_MINMAX (0x2U) -#define O2_FLAG_POWER (0x4U) -#define O2_FLAG_TIMES (0x20U) -#define O2_FLAG_LARGE_ADB (0x40U) +#define O2_FLAG_POWER ADB_HEADER_FLAG_POWER +#define O2_FLAG_TIMES ADB_HEADER_FLAG_TIMES +#define O2_FLAG_LARGE_ADB ADB_HEADER_FLAG_REFERENCES #define DISPLAY_FLAG(x) (x?"on":"off") // Query types @@ -195,23 +173,6 @@ extern char* SERVER_ADB_ROOT; extern char* SERVER_ADB_FEATURE_ROOT; -typedef struct dbTableHeader { - uint32_t magic; - uint32_t version; - uint32_t numFiles; - uint32_t dim; - uint32_t flags; - uint32_t headerSize; - off_t length; - off_t fileTableOffset; - off_t trackTableOffset; - off_t dataOffset; - off_t l2normTableOffset; - off_t timesTableOffset; - off_t powerTableOffset; - off_t dbSize; -} dbTableHeaderT, *dbTableHeaderPtr; - class audioDB{ private: gengetopt_args_info args_info; @@ -237,7 +198,7 @@ bool forWrite; int infid; struct stat statbuf; - dbTableHeaderPtr dbH; + struct adbheader *dbH; struct adb *adb; gsl_rng *rng;
--- a/audioDB_API.h Tue Jan 13 21:37:14 2009 +0000 +++ b/audioDB_API.h Thu Jan 15 13:57:33 2009 +0000 @@ -9,7 +9,6 @@ * Ian Knopke mas01ik@gold.ac.uk, ian.knopke@gmail.com */ /* Temporary workarounds */ -typedef struct dbTableHeader adb_header_t; int acquire_lock(int, bool); int divest_lock(int);
--- a/close.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/close.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,7 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} void audiodb_close(adb_t *adb) { free(adb->path);
--- a/common.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/common.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,4 @@ #include "audioDB.h" -extern "C" { -#include "audioDB_API.h" -#include "audioDB-internals.h" -} #if defined(O2_DEBUG) void sigterm_action(int signal, siginfo_t *info, void *context) {
--- a/create.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/create.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,4 +1,3 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" } @@ -6,10 +5,14 @@ /* Make a new database. -IF size(featuredata) < O2_LARGE_ADB_SIZE +(FIXME: this text, in particular the conditional, will not be true +once we implement create flags rather than defaulting on format based +on the requested size arguments) + +IF size(featuredata) < ADB_FIXME_LARGE_ADB_SIZE The database consists of: - * a header (see dbTableHeader struct definition); + * a header (see adb_header_t definition); * keyTable: list of keys of tracks; * trackTable: Maps implicit feature index to a feature vector matrix (sizes of tracks) @@ -20,7 +23,7 @@ ELSE the database consists of: - * a header (see dbTableHeader struct definition); + * a header (see adb_header_t definition); * keyTable: list of keys of tracks * trackTable: sizes of tracks * featureTable: list of feature file names @@ -34,13 +37,13 @@ adb_header_t *header = 0; off_t databytes, auxbytes; if(datasize == 0) { - datasize = O2_DEFAULT_DATASIZE; + datasize = ADB_DEFAULT_DATASIZE; } if(ntracks == 0) { - ntracks = O2_DEFAULT_NTRACKS; + ntracks = ADB_DEFAULT_NTRACKS; } if(datadim == 0) { - datadim = O2_DEFAULT_DATADIM; + datadim = ADB_DEFAULT_DATADIM; } if ((fd = open(path, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { @@ -56,55 +59,46 @@ } // Initialize header - header->magic = O2_MAGIC; - header->version = O2_FORMAT_VERSION; + header->magic = ADB_MAGIC; + header->version = ADB_FORMAT_VERSION; header->numFiles = 0; header->dim = 0; header->flags = 0; - header->headerSize = O2_HEADERSIZE; + header->headerSize = ADB_HEADER_SIZE; header->length = 0; - header->fileTableOffset = ALIGN_PAGE_UP(O2_HEADERSIZE); - header->trackTableOffset = ALIGN_PAGE_UP(header->fileTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); - header->dataOffset = ALIGN_PAGE_UP(header->trackTableOffset + O2_TRACKTABLE_ENTRY_SIZE*ntracks); + header->fileTableOffset = align_page_up(ADB_HEADER_SIZE); + header->trackTableOffset = align_page_up(header->fileTableOffset + ADB_FILETABLE_ENTRY_SIZE*ntracks); // + header->dataOffset = align_page_up(header->trackTableOffset + ADB_TRACKTABLE_ENTRY_SIZE*ntracks); databytes = ((off_t) datasize) * 1024 * 1024; auxbytes = databytes / datadim; - /* FIXME: what's going on here? There are two distinct preprocessor - constants (O2_LSH_N_POINT_BITS, LSH_N_POINT_BITS); a third is - presumably some default (O2_DEFAULT_LSH_N_POINT_BITS), and then - there's this magic 28 bits [which needs to be the same as the 28 - in audiodb_lsh_n_point_bits()]. Should this really be part of - the flags structure at all? Putting it elsewhere will of course - break backwards compatibility, unless 14 is the only value that's - been used anywhere... */ - // For backward-compatibility, Record the point-encoding parameter for LSH indexing in the adb header // If this value is 0 then it will be set to 14 - #if LSH_N_POINT_BITS > 15 - #error "AudioDB Compile ERROR: consistency check of O2_LSH_POINT_BITS failed (>31)" - #endif +#if ADB_FIXME_LSH_N_POINT_BITS > 15 +#error "consistency check of ADB_FIXME_LSH_N_POINT_BITS failed (>31)" +#endif - header->flags |= LSH_N_POINT_BITS << 28; + header->flags |= ADB_FIXME_LSH_N_POINT_BITS << 28; // If database will fit in a single file the vectors are copied into the AudioDB instance // Else all the vectors are left on the FileSystem and we use the dataOffset as storage // for the location of the features, powers and times files (assuming that arbitrary keys are used for the fileTable) - if(ntracks<O2_LARGE_ADB_NTRACKS && datasize<O2_LARGE_ADB_SIZE){ - header->timesTableOffset = ALIGN_PAGE_UP(header->dataOffset + databytes); - header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + 2*auxbytes); - header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + auxbytes); - header->dbSize = ALIGN_PAGE_UP(header->l2normTableOffset + auxbytes); - } else { // Create LARGE_ADB, features and powers kept on filesystem - header->flags |= O2_FLAG_LARGE_ADB; - header->timesTableOffset = ALIGN_PAGE_UP(header->dataOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); - header->powerTableOffset = ALIGN_PAGE_UP(header->timesTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); - header->l2normTableOffset = ALIGN_PAGE_UP(header->powerTableOffset + O2_FILETABLE_ENTRY_SIZE*ntracks); + if(ntracks < ADB_FIXME_LARGE_ADB_NTRACKS && datasize < ADB_FIXME_LARGE_ADB_SIZE) { + header->timesTableOffset = align_page_up(header->dataOffset + databytes); + header->powerTableOffset = align_page_up(header->timesTableOffset + 2*auxbytes); + header->l2normTableOffset = align_page_up(header->powerTableOffset + auxbytes); + header->dbSize = align_page_up(header->l2normTableOffset + auxbytes); + } else { // Create REFERENCES ADB, features and powers kept on filesystem + header->flags |= ADB_HEADER_FLAG_REFERENCES; + header->timesTableOffset = align_page_up(header->dataOffset + ADB_FILETABLE_ENTRY_SIZE*ntracks); + header->powerTableOffset = align_page_up(header->timesTableOffset + ADB_FILETABLE_ENTRY_SIZE*ntracks); + header->l2normTableOffset = align_page_up(header->powerTableOffset + ADB_FILETABLE_ENTRY_SIZE*ntracks); header->dbSize = header->l2normTableOffset; } - write_or_goto_error(fd, header, O2_HEADERSIZE); + write_or_goto_error(fd, header, ADB_HEADER_SIZE); // go to the location corresponding to the last byte if (lseek (fd, header->dbSize - 1, SEEK_SET) == -1) {
--- a/dump.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/dump.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,7 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} int audiodb_dump(adb_t *adb, const char *output) { char *fileTable = 0; /* key_table */ @@ -36,16 +35,16 @@ unsigned nfiles = adb->header->numFiles; if(adb->header->length > 0) { - fileTableLength = ALIGN_PAGE_UP(nfiles * O2_FILETABLE_ENTRY_SIZE); - if(!(adb->header->flags & O2_FLAG_LARGE_ADB)) { + fileTableLength = align_page_up(nfiles * ADB_FILETABLE_ENTRY_SIZE); + if(!(adb->header->flags & ADB_HEADER_FLAG_REFERENCES)) { off_t length = adb->header->length; unsigned dim = adb->header->dim; - timesTableLength = ALIGN_PAGE_UP(2*length/dim); - powerTableLength = ALIGN_PAGE_UP(length/dim); + timesTableLength = align_page_up(2*length/dim); + powerTableLength = align_page_up(length/dim); } mmap_or_goto_error(char *, fileTable, adb->header->fileTableOffset, fileTableLength); - if (adb->header->flags & O2_FLAG_LARGE_ADB) { + if (adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { mmap_or_goto_error(char *, featureFileNameTable, adb->header->dataOffset, fileTableLength); mmap_or_goto_error(char *, powerFileNameTable, adb->header->powerTableOffset, fileTableLength); mmap_or_goto_error(char *, timesFileNameTable, adb->header->timesTableOffset, fileTableLength); @@ -74,14 +73,14 @@ goto error; } - times = adb->header->flags & O2_FLAG_TIMES; + times = adb->header->flags & ADB_HEADER_FLAG_TIMES; if (times) { if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { goto error; } } - power = adb->header->flags & O2_FLAG_POWER; + power = adb->header->flags & ADB_HEADER_FLAG_POWER; if (power) { if ((pLfd = open("powerList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) { goto error; @@ -105,22 +104,22 @@ lseek(adb->fd, adb->header->dataOffset, SEEK_SET); for(unsigned k = 0; k < nfiles; k++) { - fprintf(kLFile, "%s\n", fileTable + k*O2_FILETABLE_ENTRY_SIZE); - if(adb->header->flags & O2_FLAG_LARGE_ADB) { - char *featureFileName = featureFileNameTable+k*O2_FILETABLE_ENTRY_SIZE; + fprintf(kLFile, "%s\n", fileTable + k*ADB_FILETABLE_ENTRY_SIZE); + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { + char *featureFileName = featureFileNameTable+k*ADB_FILETABLE_ENTRY_SIZE; if(*featureFileName != '/') { goto error; } fprintf(fLFile, "%s\n", featureFileName); if(times) { - char *timesFileName = timesFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; + char *timesFileName = timesFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE; if(*timesFileName != '/') { goto error; } fprintf(tLFile, "%s\n", timesFileName); } if(power) { - char *powerFileName = powerFileNameTable + k*O2_FILETABLE_ENTRY_SIZE; + char *powerFileName = powerFileNameTable + k*ADB_FILETABLE_ENTRY_SIZE; if(*powerFileName != '/') { goto error; } @@ -189,7 +188,7 @@ } pos += (*adb->track_lengths)[k]; - std::cout << fileTable+k*O2_FILETABLE_ENTRY_SIZE << " " << (*adb->track_lengths)[k] << std::endl; + std::cout << fileTable+k*ADB_FILETABLE_ENTRY_SIZE << " " << (*adb->track_lengths)[k] << std::endl; } } @@ -205,9 +204,9 @@ (int) ((adb->header->timesTableOffset - adb->header->dataOffset) / (1024*1024)), // fileTable entries (char[256]) are bigger than trackTable // (int), so the granularity of page aligning is finer. - (int) ((adb->header->trackTableOffset - adb->header->fileTableOffset) / O2_FILETABLE_ENTRY_SIZE), + (int) ((adb->header->trackTableOffset - adb->header->fileTableOffset) / ADB_FILETABLE_ENTRY_SIZE), (int) ceil(((double) (adb->header->timesTableOffset - adb->header->dataOffset)) / ((double) (adb->header->dbSize - adb->header->l2normTableOffset)))); - if(adb->header->flags & O2_FLAG_L2NORM) { + if(adb->header->flags & ADB_HEADER_FLAG_L2NORM) { fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n"); } if(power) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/index-utils.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -0,0 +1,138 @@ +extern "C" { +#include "audioDB_API.h" +} +#include "audioDB-internals.h" + +/* + * Routines which are common to both indexed query and index creation: + * we put them in their own file for build logistics. + */ + +/* FIXME: there are several things wrong with this: the memory + * discipline isn't ideal, the radius printing is a bit lame, the name + * getting will succeed or fail depending on whether the path was + * relative or absolute -- but most importantly encoding all that + * information in a filename is going to lose: it's impossible to + * maintain backwards-compatibility. Instead we should probably store + * the index metadata inside the audiodb instance. */ +char *audiodb_index_get_name(const char *dbName, double radius, Uns32T sequenceLength) { + char *indexName; + if(strlen(dbName) > (ADB_MAXSTR - 32)) { + return NULL; + } + indexName = new char[ADB_MAXSTR]; + strncpy(indexName, dbName, ADB_MAXSTR); + sprintf(indexName+strlen(dbName), ".lsh.%019.9f.%d", radius, sequenceLength); + return indexName; +} + +bool audiodb_index_exists(const char *dbName, double radius, Uns32T sequenceLength) { + char *indexName = audiodb_index_get_name(dbName, radius, sequenceLength); + if(!indexName) { + return false; + } + struct stat st; + if(stat(indexName, &st)) { + delete [] indexName; + return false; + } + /* FIXME: other stat checks here? */ + /* FIXME: is there any better way to check whether we can open a + * file for reading than by opening a file for reading? */ + int fd = open(indexName, O_RDONLY); + delete [] indexName; + if(fd < 0) { + return false; + } else { + close(fd); + return true; + } +} + +/* FIXME: the indexName arg should be "const char *", but the LSH + * library doesn't like that. + */ +LSH *audiodb_index_allocate(adb_t *adb, char *indexName, bool load_tables) { + LSH *lsh; + if(adb->cached_lsh) { + if(!strncmp(adb->cached_lsh->get_indexName(), indexName, ADB_MAXSTR)) { + return adb->cached_lsh; + } else { + delete adb->cached_lsh; + } + } + lsh = new LSH(indexName, load_tables); + if(load_tables) { + adb->cached_lsh = lsh; + } + return lsh; +} + +vector<vector<float> > *audiodb_index_initialize_shingles(Uns32T sz, Uns32T dim, Uns32T seqLen) { + std::vector<std::vector<float> > *vv = new vector<vector<float> >(sz); + for(Uns32T i=0 ; i < sz ; i++) { + (*vv)[i]=vector<float>(dim * seqLen); + } + return vv; +} + +void audiodb_index_delete_shingles(vector<vector<float> > *vv) { + delete vv; +} + +void audiodb_index_make_shingle(vector<vector<float> >* vv, Uns32T idx, double* fvp, Uns32T dim, Uns32T seqLen){ + assert(idx<(*vv).size()); + vector<float>::iterator ve = (*vv)[idx].end(); + vector<float>::iterator vi = (*vv)[idx].begin(); + // First feature vector in shingle + if(idx == 0) { + while(vi!=ve) { + *vi++ = (float)(*fvp++); + } + } else { + // Not first feature vector in shingle + vector<float>::iterator ui=(*vv)[idx-1].begin() + dim; + // Previous seqLen-1 dim-vectors + while(vi!=ve-dim) { + *vi++ = *ui++; + } + // Move data pointer to next feature vector + fvp += ( seqLen + idx - 1 ) * dim ; + // New d-vector + while(vi!=ve) { + *vi++ = (float)(*fvp++); + } + } +} + +// in-place norming, no deletions. If using power, return number of +// shingles above power threshold. +int audiodb_index_norm_shingles(vector<vector<float> >* vv, double* snp, double* spp, Uns32T dim, Uns32T seqLen, double radius, bool normed_vectors, bool use_pthreshold, float pthreshold) { + int z = 0; // number of above-threshold shingles + float l2norm; + double power; + float oneOverRadius = 1./(float)sqrt(radius); // Passed radius is really radius^2 + float oneOverSqrtl2NormDivRad = oneOverRadius; + Uns32T shingleSize = seqLen * dim; + + if(!spp) { + return -1; + } + for(Uns32T a=0; a<(*vv).size(); a++){ + l2norm = (float)(*snp++); + if(normed_vectors) + oneOverSqrtl2NormDivRad = (1./l2norm)*oneOverRadius; + + for(Uns32T b=0; b < shingleSize ; b++) + (*vv)[a][b]*=oneOverSqrtl2NormDivRad; + + power = *spp++; + if(use_pthreshold){ + if (power >= pthreshold) + z++; + } + else + z++; + } + return z; +}
--- a/index.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/index.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -12,88 +12,8 @@ // 19th August 2008 - added O2_FLAG_LARGE_ADB support #include "audioDB.h" -#include "audioDB-internals.h" -typedef struct adb_qcallback { - adb_t *adb; - adb_qstate_internal_t *qstate; -} adb_qcallback_t; - -/************************* LSH indexing and query initialization *****************/ - -/* FIXME: there are several things wrong with this: the memory - * discipline isn't ideal, the radius printing is a bit lame, the name - * getting will succeed or fail depending on whether the path was - * relative or absolute -- but most importantly encoding all that - * information in a filename is going to lose: it's impossible to - * maintain backwards-compatibility. Instead we should probably store - * the index metadata inside the audiodb instance. */ -char *audiodb_index_get_name(const char *dbName, double radius, Uns32T sequenceLength) { - char *indexName; - if(strlen(dbName) > (MAXSTR - 32)) { - return NULL; - } - indexName = new char[MAXSTR]; - strncpy(indexName, dbName, MAXSTR); - sprintf(indexName+strlen(dbName), ".lsh.%019.9f.%d", radius, sequenceLength); - return indexName; -} - -bool audiodb_index_exists(const char *dbName, double radius, Uns32T sequenceLength) { - char *indexName = audiodb_index_get_name(dbName, radius, sequenceLength); - if(!indexName) { - return false; - } - struct stat st; - if(stat(indexName, &st)) { - delete [] indexName; - return false; - } - /* FIXME: other stat checks here? */ - /* FIXME: is there any better way to check whether we can open a - * file for reading than by opening a file for reading? */ - int fd = open(indexName, O_RDONLY); - delete [] indexName; - if(fd < 0) { - return false; - } else { - close(fd); - return true; - } -} - -/* FIXME: the indexName arg should be "const char *", but the LSH - * library doesn't like that. - */ -LSH *audiodb_index_allocate(adb_t *adb, char *indexName, bool load_tables) { - LSH *lsh; - if(adb->cached_lsh) { - if(!strncmp(adb->cached_lsh->get_indexName(), indexName, MAXSTR)) { - return adb->cached_lsh; - } else { - delete adb->cached_lsh; - } - } - lsh = new LSH(indexName, load_tables); - if(load_tables) { - adb->cached_lsh = lsh; - } - return lsh; -} - -vector<vector<float> > *audiodb_index_initialize_shingles(Uns32T sz, Uns32T dim, Uns32T seqLen) { - std::vector<std::vector<float> > *vv = new vector<vector<float> >(sz); - for(Uns32T i=0 ; i < sz ; i++) { - (*vv)[i]=vector<float>(dim * seqLen); - } - return vv; -} - -void audiodb_index_delete_shingles(vector<vector<float> > *vv) { - delete vv; -} - -/******************** LSH indexing audioDB database access forall s \in {S} ***********************/ +/******* LSH indexing audioDB database access forall s \in {S} *******/ // Prepare the AudioDB database for read access and allocate auxillary memory void audioDB::index_initialize(double **snp, double **vsnp, double **spp, double **vspp, Uns32T *dvp) { @@ -132,81 +52,6 @@ lseek(dbfid, dbH->dataOffset, SEEK_SET); } - -/********************* LSH shingle construction ***************************/ - -// Construct shingles out of a feature matrix -// inputs: -// idx is vector index in feature matrix -// fvp is base feature matrix pointer double* [numVecs x dbH->dim] -// -// pre-conditions: -// dbH->dim -// sequenceLength -// idx < numVectors - sequenceLength + 1 -// -// post-conditions: -// (*vv)[idx] contains a shingle with dbH->dim*sequenceLength float values - -static void audiodb_index_make_shingle(vector<vector<float> >* vv, Uns32T idx, double* fvp, Uns32T dim, Uns32T seqLen){ - assert(idx<(*vv).size()); - vector<float>::iterator ve = (*vv)[idx].end(); - vector<float>::iterator vi = (*vv)[idx].begin(); - // First feature vector in shingle - if(idx == 0) { - while(vi!=ve) { - *vi++ = (float)(*fvp++); - } - } else { - // Not first feature vector in shingle - vector<float>::iterator ui=(*vv)[idx-1].begin() + dim; - // Previous seqLen-1 dim-vectors - while(vi!=ve-dim) { - *vi++ = *ui++; - } - // Move data pointer to next feature vector - fvp += ( seqLen + idx - 1 ) * dim ; - // New d-vector - while(vi!=ve) { - *vi++ = (float)(*fvp++); - } - } -} - -// norm shingles -// in-place norming, no deletions -// If using power, return number of shingles above power threshold -int audiodb_index_norm_shingles(vector<vector<float> >* vv, double* snp, double* spp, Uns32T dim, Uns32T seqLen, double radius, bool normed_vectors, bool use_pthreshold, float pthreshold) { - int z = 0; // number of above-threshold shingles - float l2norm; - double power; - float oneOverRadius = 1./(float)sqrt(radius); // Passed radius is really radius^2 - float oneOverSqrtl2NormDivRad = oneOverRadius; - Uns32T shingleSize = seqLen * dim; - - if(!spp) { - return -1; - } - for(Uns32T a=0; a<(*vv).size(); a++){ - l2norm = (float)(*snp++); - if(normed_vectors) - oneOverSqrtl2NormDivRad = (1./l2norm)*oneOverRadius; - - for(Uns32T b=0; b < shingleSize ; b++) - (*vv)[a][b]*=oneOverSqrtl2NormDivRad; - - power = *spp++; - if(use_pthreshold){ - if (power >= pthreshold) - z++; - } - else - z++; - } - return z; -} - - /************************ LSH indexing ***********************************/ void audioDB::index_index_db(const char* dbName){ char* newIndexName; @@ -511,173 +356,3 @@ } return collisionCount; } - -/*********************** LSH retrieval ****************************/ - - -// return true if indexed query performed else return false -int audiodb_index_init_query(adb_t *adb, const adb_query_spec_t *spec, adb_qstate_internal_t *qstate, bool corep) { - - uint32_t sequence_length = spec->qid.sequence_length; - double radius = spec->refine.radius; - if(!(audiodb_index_exists(adb->path, radius, sequence_length))) - return false; - - char *indexName = audiodb_index_get_name(adb->path, radius, sequence_length); - if(!indexName) { - return false; - } - - qstate->lsh = audiodb_index_allocate(adb, indexName, corep); - - /* FIXME: it would be nice if the LSH library didn't make me do - * this. */ - if((!corep) && (qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2)) { - delete qstate->lsh; - qstate->lsh = audiodb_index_allocate(adb, indexName, true); - } - - delete[] indexName; - return true; -} - -void audiodb_index_add_point_approximate(void *user_data, Uns32T pointID, Uns32T qpos, float dist) { - adb_qcallback_t *data = (adb_qcallback_t *) user_data; - adb_t *adb = data->adb; - adb_qstate_internal_t *qstate = data->qstate; - uint32_t nbits = audiodb_lsh_n_point_bits(adb); - uint32_t trackID = audiodb_index_to_track_id(pointID, nbits); - uint32_t spos = audiodb_index_to_track_pos(pointID, nbits); - std::set<std::string>::iterator keys_end = qstate->allowed_keys->end(); - if(qstate->allowed_keys->find((*adb->keys)[trackID]) != keys_end) { - adb_result_t r; - r.key = (*adb->keys)[trackID].c_str(); - r.dist = dist; - r.qpos = qpos; - r.ipos = spos; - qstate->accumulator->add_point(&r); - } -} - -// Maintain a queue of points to pass to audiodb_query_queue_loop() -// for exact evaluation -void audiodb_index_add_point_exact(void *user_data, Uns32T pointID, Uns32T qpos, float dist) { - adb_qcallback_t *data = (adb_qcallback_t *) user_data; - adb_t *adb = data->adb; - adb_qstate_internal_t *qstate = data->qstate; - uint32_t nbits = audiodb_lsh_n_point_bits(adb); - uint32_t trackID = audiodb_index_to_track_id(pointID, nbits); - uint32_t spos = audiodb_index_to_track_pos(pointID, nbits); - std::set<std::string>::iterator keys_end = qstate->allowed_keys->end(); - if(qstate->allowed_keys->find((*adb->keys)[trackID]) != keys_end) { - PointPair p(trackID, qpos, spos); - qstate->exact_evaluation_queue->push(p); - } -} - -// return -1 on error -// return 0: if index does not exist -// return nqv: if index exists -int audiodb_index_query_loop(adb_t *adb, const adb_query_spec_t *spec, adb_qstate_internal_t *qstate) { - - double *query = 0, *query_data = 0; - adb_qpointers_internal_t qpointers = {0}; - - adb_qcallback_t callback_data; - callback_data.adb = adb; - callback_data.qstate = qstate; - - void (*add_point_func)(void *, uint32_t, uint32_t, float); - - uint32_t sequence_length = spec->qid.sequence_length; - bool normalized = (spec->params.distance == ADB_DISTANCE_EUCLIDEAN_NORMED); - double radius = spec->refine.radius; - bool use_absolute_threshold = spec->refine.flags & ADB_REFINE_ABSOLUTE_THRESHOLD; - double absolute_threshold = spec->refine.absolute_threshold; - - if(spec->qid.flags & ADB_QID_FLAG_ALLOW_FALSE_POSITIVES) { - add_point_func = &audiodb_index_add_point_approximate; - } else { - qstate->exact_evaluation_queue = new std::priority_queue<PointPair>; - add_point_func = &audiodb_index_add_point_exact; - } - - /* FIXME: this hardwired lsh_in_core is here to allow for a - * transition period while the need for the argument is worked - * through. Hopefully it will disappear again eventually. */ - bool lsh_in_core = true; - - if(!audiodb_index_init_query(adb, spec, qstate, lsh_in_core)) { - return 0; - } - - char *database = audiodb_index_get_name(adb->path, radius, sequence_length); - if(!database) { - return -1; - } - - if(audiodb_query_spec_qpointers(adb, spec, &query_data, &query, &qpointers)) { - delete [] database; - return -1; - } - - uint32_t Nq = (qpointers.nvectors > O2_MAXTRACKLEN ? O2_MAXTRACKLEN : qpointers.nvectors) - sequence_length + 1; - std::vector<std::vector<float> > *vv = audiodb_index_initialize_shingles(Nq, adb->header->dim, sequence_length); - - // Construct shingles from query features - for(uint32_t pointID = 0; pointID < Nq; pointID++) { - audiodb_index_make_shingle(vv, pointID, query, adb->header->dim, sequence_length); - } - - // Normalize query vectors - int vcount = audiodb_index_norm_shingles(vv, qpointers.l2norm, qpointers.power, adb->header->dim, sequence_length, radius, normalized, use_absolute_threshold, absolute_threshold); - if(vcount == -1) { - audiodb_index_delete_shingles(vv); - delete [] database; - return -1; - } - uint32_t numVecsAboveThreshold = vcount; - - // Nq contains number of inspected points in query file, - // numVecsAboveThreshold is number of points with power >= absolute_threshold - double *qpp = qpointers.power; // Keep original qpPtr for possible exact evaluation - if(!(spec->qid.flags & ADB_QID_FLAG_EXHAUSTIVE) && numVecsAboveThreshold) { - if((qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2) || lsh_in_core) { - qstate->lsh->retrieve_point((*vv)[0], spec->qid.sequence_start, add_point_func, &callback_data); - } else { - qstate->lsh->serial_retrieve_point(database, (*vv)[0], spec->qid.sequence_start, add_point_func, &callback_data); - } - } else if(numVecsAboveThreshold) { - for(uint32_t pointID = 0; pointID < Nq; pointID++) { - if(!use_absolute_threshold || (use_absolute_threshold && (*qpp++ >= absolute_threshold))) { - if((qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2) || lsh_in_core) { - qstate->lsh->retrieve_point((*vv)[pointID], pointID, add_point_func, &callback_data); - } else { - qstate->lsh->serial_retrieve_point(database, (*vv)[pointID], pointID, add_point_func, &callback_data); - } - } - } - } - audiodb_index_delete_shingles(vv); - - if(!(spec->qid.flags & ADB_QID_FLAG_ALLOW_FALSE_POSITIVES)) { - audiodb_query_queue_loop(adb, spec, qstate, query, &qpointers); - } - - // Clean up - if(query_data) - delete[] query_data; - if(qpointers.l2norm_data) - delete[] qpointers.l2norm_data; - if(qpointers.power_data) - delete[] qpointers.power_data; - if(qpointers.mean_duration) - delete[] qpointers.mean_duration; - if(database) - delete[] database; - if(qstate->lsh != adb->cached_lsh) - delete qstate->lsh; - - return Nq; -} -
--- a/insert.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/insert.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,4 +1,3 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" } @@ -6,7 +5,7 @@ static bool audiodb_enough_data_space_free(adb_t *adb, off_t size) { adb_header_t *header = adb->header; - if(header->flags & O2_FLAG_LARGE_ADB) { + if(header->flags & ADB_HEADER_FLAG_REFERENCES) { return true; } else { /* FIXME: timesTableOffset isn't necessarily the next biggest @@ -23,11 +22,11 @@ adb_header_t *header = adb->header; off_t file_table_length = header->trackTableOffset - header->fileTableOffset; off_t track_table_length = header->dataOffset - header->trackTableOffset; - int fmaxfiles = file_table_length / O2_FILETABLE_ENTRY_SIZE; - int tmaxfiles = track_table_length / O2_TRACKTABLE_ENTRY_SIZE; + int fmaxfiles = file_table_length / ADB_FILETABLE_ENTRY_SIZE; + int tmaxfiles = track_table_length / ADB_TRACKTABLE_ENTRY_SIZE; /* maxfiles is the _minimum_ of the two. Do not be confused... */ int maxfiles = fmaxfiles > tmaxfiles ? tmaxfiles : fmaxfiles; - if(header->flags & O2_FLAG_LARGE_ADB) { + if(header->flags & ADB_HEADER_FLAG_REFERENCES) { /* by default, these tables are created with the same size as the * fileTable (which should be called key_table); relying on that * always being the case, though, smacks of optimism, so instead @@ -35,9 +34,9 @@ off_t data_table_length = header->timesTableOffset - header->dataOffset; off_t times_table_length = header->powerTableOffset - header->timesTableOffset; off_t power_table_length = header->dbSize - header->powerTableOffset; - int dmaxfiles = data_table_length / O2_FILETABLE_ENTRY_SIZE; - int timaxfiles = times_table_length / O2_FILETABLE_ENTRY_SIZE; - int pmaxfiles = power_table_length / O2_FILETABLE_ENTRY_SIZE; + int dmaxfiles = data_table_length / ADB_FILETABLE_ENTRY_SIZE; + int timaxfiles = times_table_length / ADB_FILETABLE_ENTRY_SIZE; + int pmaxfiles = power_table_length / ADB_FILETABLE_ENTRY_SIZE; /* ... even though it means a certain amount of tedium. */ maxfiles = maxfiles > dmaxfiles ? dmaxfiles : maxfiles; maxfiles = maxfiles > timaxfiles ? timaxfiles : maxfiles; @@ -58,12 +57,12 @@ * header dimension is zero, in which case write datum->dim to * adb->header->dim). * 4. check for presence of datum->key in adb->keymap; - * 5. check for consistency between power and O2_FLAG_POWER, and - * times and O2_FLAG_TIMES; + * 5. check for consistency between power and ADB_HEADER_FLAG_POWER, + * and times and ADB_HEADER_FLAG_TIMES; * 6. write in data, power, times as appropriate; add to track * and key tables too; - * 7. if O2_FLAG_L2NORM and !O2_FLAG_LARGE_ADB, compute norms and fill - * in table; + * 7. if ADB_HEADER_FLAG_L2NORM and !ADB_HEADER_FLAG_REFERENCES, + * compute norms and fill in table; * 8. update adb->keys, adb->keymap, adb->track_lengths, * adb->track_offsets and adb->header; * 9. sync adb->header with disk. @@ -112,20 +111,20 @@ of audioDB::batchinsert. */ return 2; } - /* 5. check for consistency between power and O2_FLAG_POWER, and - * times and O2_FLAG_TIMES; + /* 5. check for consistency between power and ADB_HEADER_FLAG_POWER, + * and times and ADB_HEADER_FLAG_TIMES; */ - if((datum->power && !(adb->header->flags & O2_FLAG_POWER)) || - ((adb->header->flags & O2_FLAG_POWER) && !datum->power)) { + if((datum->power && !(adb->header->flags & ADB_HEADER_FLAG_POWER)) || + ((adb->header->flags & ADB_HEADER_FLAG_POWER) && !datum->power)) { return 1; } - if(datum->times && !(adb->header->flags & O2_FLAG_TIMES)) { + if(datum->times && !(adb->header->flags & ADB_HEADER_FLAG_TIMES)) { if(adb->header->numFiles == 0) { - adb->header->flags |= O2_FLAG_TIMES; + adb->header->flags |= ADB_HEADER_FLAG_TIMES; } else { return 1; } - } else if ((adb->header->flags & O2_FLAG_TIMES) && !datum->times) { + } else if ((adb->header->flags & ADB_HEADER_FLAG_TIMES) && !datum->times) { return 1; } /* 6. write in data, power, times as appropriate; add to track @@ -135,25 +134,25 @@ nfiles = adb->header->numFiles; /* FIXME: checking for all these lseek()s */ - lseek(adb->fd, adb->header->fileTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + lseek(adb->fd, adb->header->fileTableOffset + nfiles * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); write_or_goto_error(adb->fd, datum->key, strlen(datum->key)+1); - lseek(adb->fd, adb->header->trackTableOffset + nfiles * O2_TRACKTABLE_ENTRY_SIZE, SEEK_SET); - write_or_goto_error(adb->fd, &datum->nvectors, O2_TRACKTABLE_ENTRY_SIZE); - if(adb->header->flags & O2_FLAG_LARGE_ADB) { + lseek(adb->fd, adb->header->trackTableOffset + nfiles * ADB_TRACKTABLE_ENTRY_SIZE, SEEK_SET); + write_or_goto_error(adb->fd, &datum->nvectors, ADB_TRACKTABLE_ENTRY_SIZE); + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { char cwd[PATH_MAX]; char slash = '/'; if(!getcwd(cwd, PATH_MAX)) { goto error; } - lseek(adb->fd, adb->header->dataOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + lseek(adb->fd, adb->header->dataOffset + nfiles * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); if(*((char *) datum->data) != '/') { write_or_goto_error(adb->fd, cwd, strlen(cwd)); write_or_goto_error(adb->fd, &slash, 1); } write_or_goto_error(adb->fd, datum->data, strlen((const char *) datum->data)+1); if(datum->power) { - lseek(adb->fd, adb->header->powerTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + lseek(adb->fd, adb->header->powerTableOffset + nfiles * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); if(*((char *) datum->power) != '/') { write_or_goto_error(adb->fd, cwd, strlen(cwd)); write_or_goto_error(adb->fd, &slash, 1); @@ -161,7 +160,7 @@ write_or_goto_error(adb->fd, datum->power, strlen((const char *) datum->power)+1); } if(datum->times) { - lseek(adb->fd, adb->header->timesTableOffset + nfiles * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); + lseek(adb->fd, adb->header->timesTableOffset + nfiles * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); if(*((char *) datum->times) != '/') { write_or_goto_error(adb->fd, cwd, strlen(cwd)); write_or_goto_error(adb->fd, &slash, 1); @@ -181,11 +180,11 @@ } } - /* 7. if O2_FLAG_L2NORM and !O2_FLAG_LARGE_ADB, compute norms and fill - * in table; + /* 7. if ADB_HEADER_FLAG_L2NORM and !ADB_HEADER_FLAG_REFERENCES, + * compute norms and fill in table; */ - if((adb->header->flags & O2_FLAG_L2NORM) && - !(adb->header->flags & O2_FLAG_LARGE_ADB)) { + if((adb->header->flags & ADB_HEADER_FLAG_L2NORM) && + !(adb->header->flags & ADB_HEADER_FLAG_REFERENCES)) { l2norm_buffer = (double *) malloc(datum->nvectors * sizeof(double)); audiodb_l2norm_buffer((double *) datum->data, datum->dim, datum->nvectors, l2norm_buffer); @@ -216,7 +215,7 @@ } int audiodb_insert_datum(adb_t *adb, const adb_datum_t *datum) { - if(adb->header->flags & O2_FLAG_LARGE_ADB) { + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { return 1; } else { adb_datum_internal_t d; @@ -231,7 +230,7 @@ } int audiodb_insert_reference(adb_t *adb, const adb_reference_t *reference) { - if(!(adb->header->flags & O2_FLAG_LARGE_ADB)) { + if(!(adb->header->flags & ADB_HEADER_FLAG_REFERENCES)) { return 1; } else { adb_datum_internal_t d; @@ -404,7 +403,7 @@ } int audiodb_insert(adb_t *adb, adb_insert_t *insert) { - if(adb->header->flags & O2_FLAG_LARGE_ADB) { + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { adb_reference_t *reference = insert; int err; err = audiodb_insert_reference(adb, reference);
--- a/l2norm.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/l2norm.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,13 +1,12 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} static int audiodb_l2norm_existing(adb_t *adb) { double *data_buffer, *l2norm_buffer; adb_header_t *header = adb->header; - size_t data_buffer_size = ALIGN_PAGE_UP(header->length); + size_t data_buffer_size = align_page_up(header->length); size_t nvectors = header->length / (sizeof(double) * header->dim); /* FIXME: this map of the vector data will lose if we ever turn the * l2norm flag on when we have already inserted a large number of @@ -42,17 +41,17 @@ if(!(adb->flags & O_RDWR)) { return 1; } - if(header->flags & O2_FLAG_L2NORM) { + if(header->flags & ADB_HEADER_FLAG_L2NORM) { /* non-error code for forthcoming backwards-compatibility * reasons */ return 0; } - if((!(header->flags & O2_FLAG_LARGE_ADB)) && (header->length > 0)) { + if((!(header->flags & ADB_HEADER_FLAG_REFERENCES)) && (header->length > 0)) { if(audiodb_l2norm_existing(adb)) { goto error; } } - adb->header->flags |= O2_FLAG_L2NORM; + adb->header->flags |= ADB_HEADER_FLAG_L2NORM; return audiodb_sync_header(adb); error:
--- a/lock.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/lock.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,4 +1,7 @@ -#include "audioDB.h" +extern "C" { +#include "audioDB_API.h" +} +#include "audioDB-internals.h" int acquire_lock(int fd, bool exclusive) { struct flock lock;
--- a/open.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/open.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,22 +1,21 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} static bool audiodb_check_header(adb_header_t *header) { /* FIXME: use syslog() or write to stderr or something to give the poor user some diagnostics. */ - if(header->magic == O2_OLD_MAGIC) { + if(header->magic == ADB_OLD_MAGIC) { return false; } - if(header->magic != O2_MAGIC) { + if(header->magic != ADB_MAGIC) { return false; } - if(header->version != O2_FORMAT_VERSION) { + if(header->version != ADB_FORMAT_VERSION) { return false; } - if(header->headerSize != O2_HEADERSIZE) { + if(header->headerSize != ADB_HEADER_SIZE) { return false; } return true; @@ -28,11 +27,11 @@ if(adb->header->length > 0) { unsigned nfiles = adb->header->numFiles; - key_table_length = ALIGN_PAGE_UP(nfiles * O2_FILETABLE_ENTRY_SIZE); + key_table_length = align_page_up(nfiles * ADB_FILETABLE_ENTRY_SIZE); mmap_or_goto_error(char *, key_table, adb->header->fileTableOffset, key_table_length); for (unsigned int k = 0; k < nfiles; k++) { - adb->keys->push_back(key_table + k*O2_FILETABLE_ENTRY_SIZE); - (*adb->keymap)[(key_table + k*O2_FILETABLE_ENTRY_SIZE)] = k; + adb->keys->push_back(key_table + k*ADB_FILETABLE_ENTRY_SIZE); + (*adb->keymap)[(key_table + k*ADB_FILETABLE_ENTRY_SIZE)] = k; } munmap(key_table, key_table_length); } @@ -49,7 +48,7 @@ size_t track_table_length = 0; if(adb->header->length > 0) { unsigned nfiles = adb->header->numFiles; - track_table_length = ALIGN_PAGE_UP(nfiles * O2_TRACKTABLE_ENTRY_SIZE); + track_table_length = align_page_up(nfiles * ADB_TRACKTABLE_ENTRY_SIZE); mmap_or_goto_error(uint32_t *, track_table, adb->header->trackTableOffset, track_table_length); off_t offset = 0; for (unsigned int k = 0; k < nfiles; k++) { @@ -97,7 +96,7 @@ if(!(adb->header)) { goto error; } - if(read(fd, (char *) adb->header, O2_HEADERSIZE) != O2_HEADERSIZE) { + if(read(fd, (char *) adb->header, ADB_HEADER_SIZE) != ADB_HEADER_SIZE) { goto error; } if(!audiodb_check_header(adb->header)) {
--- a/pointpair.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/pointpair.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,7 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} PointPair::PointPair(Uns32T a, Uns32T b, Uns32T c) : trackID(a), qpos(b), spos(c) {
--- a/power.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/power.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,7 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} int audiodb_power(adb_t *adb) { if(!(adb->flags & O_RDWR)) { @@ -12,6 +11,6 @@ return 1; } - adb->header->flags |= O2_FLAG_POWER; + adb->header->flags |= ADB_HEADER_FLAG_POWER; return audiodb_sync_header(adb); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/query-indexed.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -0,0 +1,178 @@ +extern "C" { +#include "audioDB_API.h" +} +#include "audioDB-internals.h" + +/* + * Routines and datastructures which are specific to indexed queries. + */ +typedef struct adb_qcallback { + adb_t *adb; + adb_qstate_internal_t *qstate; +} adb_qcallback_t; + +// return true if indexed query performed else return false +int audiodb_index_init_query(adb_t *adb, const adb_query_spec_t *spec, adb_qstate_internal_t *qstate, bool corep) { + + uint32_t sequence_length = spec->qid.sequence_length; + double radius = spec->refine.radius; + if(!(audiodb_index_exists(adb->path, radius, sequence_length))) + return false; + + char *indexName = audiodb_index_get_name(adb->path, radius, sequence_length); + if(!indexName) { + return false; + } + + qstate->lsh = audiodb_index_allocate(adb, indexName, corep); + + /* FIXME: it would be nice if the LSH library didn't make me do + * this. */ + if((!corep) && (qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2)) { + delete qstate->lsh; + qstate->lsh = audiodb_index_allocate(adb, indexName, true); + } + + delete[] indexName; + return true; +} + +void audiodb_index_add_point_approximate(void *user_data, Uns32T pointID, Uns32T qpos, float dist) { + adb_qcallback_t *data = (adb_qcallback_t *) user_data; + adb_t *adb = data->adb; + adb_qstate_internal_t *qstate = data->qstate; + uint32_t nbits = audiodb_lsh_n_point_bits(adb); + uint32_t trackID = audiodb_index_to_track_id(pointID, nbits); + uint32_t spos = audiodb_index_to_track_pos(pointID, nbits); + std::set<std::string>::iterator keys_end = qstate->allowed_keys->end(); + if(qstate->allowed_keys->find((*adb->keys)[trackID]) != keys_end) { + adb_result_t r; + r.key = (*adb->keys)[trackID].c_str(); + r.dist = dist; + r.qpos = qpos; + r.ipos = spos; + qstate->accumulator->add_point(&r); + } +} + +// Maintain a queue of points to pass to audiodb_query_queue_loop() +// for exact evaluation +void audiodb_index_add_point_exact(void *user_data, Uns32T pointID, Uns32T qpos, float dist) { + adb_qcallback_t *data = (adb_qcallback_t *) user_data; + adb_t *adb = data->adb; + adb_qstate_internal_t *qstate = data->qstate; + uint32_t nbits = audiodb_lsh_n_point_bits(adb); + uint32_t trackID = audiodb_index_to_track_id(pointID, nbits); + uint32_t spos = audiodb_index_to_track_pos(pointID, nbits); + std::set<std::string>::iterator keys_end = qstate->allowed_keys->end(); + if(qstate->allowed_keys->find((*adb->keys)[trackID]) != keys_end) { + PointPair p(trackID, qpos, spos); + qstate->exact_evaluation_queue->push(p); + } +} + +// return -1 on error +// return 0: if index does not exist +// return nqv: if index exists +int audiodb_index_query_loop(adb_t *adb, const adb_query_spec_t *spec, adb_qstate_internal_t *qstate) { + + double *query = 0, *query_data = 0; + adb_qpointers_internal_t qpointers = {0}; + + adb_qcallback_t callback_data; + callback_data.adb = adb; + callback_data.qstate = qstate; + + void (*add_point_func)(void *, uint32_t, uint32_t, float); + + uint32_t sequence_length = spec->qid.sequence_length; + bool normalized = (spec->params.distance == ADB_DISTANCE_EUCLIDEAN_NORMED); + double radius = spec->refine.radius; + bool use_absolute_threshold = spec->refine.flags & ADB_REFINE_ABSOLUTE_THRESHOLD; + double absolute_threshold = spec->refine.absolute_threshold; + + if(spec->qid.flags & ADB_QID_FLAG_ALLOW_FALSE_POSITIVES) { + add_point_func = &audiodb_index_add_point_approximate; + } else { + qstate->exact_evaluation_queue = new std::priority_queue<PointPair>; + add_point_func = &audiodb_index_add_point_exact; + } + + /* FIXME: this hardwired lsh_in_core is here to allow for a + * transition period while the need for the argument is worked + * through. Hopefully it will disappear again eventually. */ + bool lsh_in_core = true; + + if(!audiodb_index_init_query(adb, spec, qstate, lsh_in_core)) { + return 0; + } + + char *database = audiodb_index_get_name(adb->path, radius, sequence_length); + if(!database) { + return -1; + } + + if(audiodb_query_spec_qpointers(adb, spec, &query_data, &query, &qpointers)) { + delete [] database; + return -1; + } + + uint32_t Nq = (qpointers.nvectors > ADB_LSH_MAXTRACKLEN ? ADB_LSH_MAXTRACKLEN : qpointers.nvectors) - sequence_length + 1; + std::vector<std::vector<float> > *vv = audiodb_index_initialize_shingles(Nq, adb->header->dim, sequence_length); + + // Construct shingles from query features + for(uint32_t pointID = 0; pointID < Nq; pointID++) { + audiodb_index_make_shingle(vv, pointID, query, adb->header->dim, sequence_length); + } + + // Normalize query vectors + int vcount = audiodb_index_norm_shingles(vv, qpointers.l2norm, qpointers.power, adb->header->dim, sequence_length, radius, normalized, use_absolute_threshold, absolute_threshold); + if(vcount == -1) { + audiodb_index_delete_shingles(vv); + delete [] database; + return -1; + } + uint32_t numVecsAboveThreshold = vcount; + + // Nq contains number of inspected points in query file, + // numVecsAboveThreshold is number of points with power >= absolute_threshold + double *qpp = qpointers.power; // Keep original qpPtr for possible exact evaluation + if(!(spec->qid.flags & ADB_QID_FLAG_EXHAUSTIVE) && numVecsAboveThreshold) { + if((qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2) || lsh_in_core) { + qstate->lsh->retrieve_point((*vv)[0], spec->qid.sequence_start, add_point_func, &callback_data); + } else { + qstate->lsh->serial_retrieve_point(database, (*vv)[0], spec->qid.sequence_start, add_point_func, &callback_data); + } + } else if(numVecsAboveThreshold) { + for(uint32_t pointID = 0; pointID < Nq; pointID++) { + if(!use_absolute_threshold || (use_absolute_threshold && (*qpp++ >= absolute_threshold))) { + if((qstate->lsh->get_lshHeader()->flags & O2_SERIAL_FILEFORMAT2) || lsh_in_core) { + qstate->lsh->retrieve_point((*vv)[pointID], pointID, add_point_func, &callback_data); + } else { + qstate->lsh->serial_retrieve_point(database, (*vv)[pointID], pointID, add_point_func, &callback_data); + } + } + } + } + audiodb_index_delete_shingles(vv); + + if(!(spec->qid.flags & ADB_QID_FLAG_ALLOW_FALSE_POSITIVES)) { + audiodb_query_queue_loop(adb, spec, qstate, query, &qpointers); + } + + // Clean up + if(query_data) + delete[] query_data; + if(qpointers.l2norm_data) + delete[] qpointers.l2norm_data; + if(qpointers.power_data) + delete[] qpointers.power_data; + if(qpointers.mean_duration) + delete[] qpointers.mean_duration; + if(database) + delete[] database; + if(qstate->lsh != adb->cached_lsh) + delete qstate->lsh; + + return Nq; +}
--- a/query.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/query.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,4 +1,6 @@ -#include "audioDB.h" +extern "C" { +#include "audioDB_API.h" +} #include "audioDB-internals.h" #include "accumulators.h" @@ -198,21 +200,21 @@ int audiodb_track_id_datum(adb_t *adb, uint32_t track_id, adb_datum_t *d) { off_t track_offset = (*adb->track_offsets)[track_id]; - if(adb->header->flags & O2_FLAG_LARGE_ADB) { + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { /* create a reference/insert, then use adb_insert_create_datum() */ adb_reference_t reference = {0}; - char features[MAXSTR], power[MAXSTR], times[MAXSTR]; - lseek(adb->fd, adb->header->dataOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); - read_or_goto_error(adb->fd, features, MAXSTR); + char features[ADB_MAXSTR], power[ADB_MAXSTR], times[ADB_MAXSTR]; + lseek(adb->fd, adb->header->dataOffset + track_id * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); + read_or_goto_error(adb->fd, features, ADB_MAXSTR); reference.features = features; - if(adb->header->flags & O2_FLAG_POWER) { - lseek(adb->fd, adb->header->powerTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); - read_or_goto_error(adb->fd, power, MAXSTR); + if(adb->header->flags & ADB_HEADER_FLAG_POWER) { + lseek(adb->fd, adb->header->powerTableOffset + track_id * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); + read_or_goto_error(adb->fd, power, ADB_MAXSTR); reference.power = power; } - if(adb->header->flags & O2_FLAG_TIMES) { - lseek(adb->fd, adb->header->timesTableOffset + track_id * O2_FILETABLE_ENTRY_SIZE, SEEK_SET); - read_or_goto_error(adb->fd, times, MAXSTR); + if(adb->header->flags & ADB_HEADER_FLAG_TIMES) { + lseek(adb->fd, adb->header->timesTableOffset + track_id * ADB_FILETABLE_ENTRY_SIZE, SEEK_SET); + read_or_goto_error(adb->fd, times, ADB_MAXSTR); reference.times = times; } return audiodb_insert_create_datum(&reference, d); @@ -225,12 +227,12 @@ d->data = (double *) malloc(d->nvectors * d->dim * sizeof(double)); lseek(adb->fd, adb->header->dataOffset + track_offset, SEEK_SET); read_or_goto_error(adb->fd, d->data, d->nvectors * d->dim * sizeof(double)); - if(adb->header->flags & O2_FLAG_POWER) { + if(adb->header->flags & ADB_HEADER_FLAG_POWER) { d->power = (double *) malloc(d->nvectors * sizeof(double)); lseek(adb->fd, adb->header->powerTableOffset + track_offset / d->dim, SEEK_SET); read_or_goto_error(adb->fd, d->power, d->nvectors * sizeof(double)); } - if(adb->header->flags & O2_FLAG_TIMES) { + if(adb->header->flags & ADB_HEADER_FLAG_TIMES) { d->times = (double *) malloc(2 * d->nvectors * sizeof(double)); lseek(adb->fd, adb->header->timesTableOffset + track_offset / d->dim, SEEK_SET); read_or_goto_error(adb->fd, d->times, 2 * d->nvectors * sizeof(double)); @@ -354,7 +356,7 @@ read_or_goto_error(adb->fd, dbpointers->l2norm_data, nvectors * sizeof(double)); if (using_power) { - if (!(adb->header->flags & O2_FLAG_POWER)) { + if (!(adb->header->flags & ADB_HEADER_FLAG_POWER)) { goto error; } dbpointers->power_data = new double[nvectors]; @@ -380,7 +382,7 @@ } if (using_times) { - if(!(adb->header->flags & O2_FLAG_TIMES)) { + if(!(adb->header->flags & ADB_HEADER_FLAG_TIMES)) { goto error; } @@ -450,10 +452,10 @@ while(npairs--) { PointPair pp = qstate->exact_evaluation_queue->top(); if(currentTrack != pp.trackID) { - SAFE_DELETE_ARRAY(dbdata); - SAFE_DELETE_ARRAY(dbpointers.l2norm_data); - SAFE_DELETE_ARRAY(dbpointers.power_data); - SAFE_DELETE_ARRAY(dbpointers.mean_duration); + maybe_delete_array(dbdata); + maybe_delete_array(dbpointers.l2norm_data); + maybe_delete_array(dbpointers.power_data); + maybe_delete_array(dbpointers.mean_duration); currentTrack = pp.trackID; adb_datum_t d = {0}; if(audiodb_track_id_datum(adb, pp.trackID, &d)) { @@ -485,7 +487,7 @@ break; } if((!(spec->refine.flags & ADB_REFINE_RADIUS)) || - dist <= (spec->refine.radius+O2_DISTANCE_TOLERANCE)) { + dist <= (spec->refine.radius + ADB_DISTANCE_TOLERANCE)) { adb_result_t r; r.key = (*adb->keys)[pp.trackID].c_str(); r.dist = dist; @@ -497,12 +499,11 @@ qstate->exact_evaluation_queue->pop(); } - // Cleanup - SAFE_DELETE_ARRAY(dbdata); - SAFE_DELETE_ARRAY(dbpointers.l2norm_data); - SAFE_DELETE_ARRAY(dbpointers.power_data); - SAFE_DELETE_ARRAY(dbpointers.mean_duration); + maybe_delete_array(dbdata); + maybe_delete_array(dbpointers.l2norm_data); + maybe_delete_array(dbpointers.power_data); + maybe_delete_array(dbpointers.mean_duration); delete qstate->exact_evaluation_queue; return 0; } @@ -514,7 +515,7 @@ bool power_refine = spec->refine.flags & (ADB_REFINE_ABSOLUTE_THRESHOLD|ADB_REFINE_RELATIVE_THRESHOLD); - if(adb->header->flags & O2_FLAG_LARGE_ADB) { + if(adb->header->flags & ADB_HEADER_FLAG_REFERENCES) { /* FIXME: actually it would be nice to support this mode of * operation, but for now... */ return 1; @@ -590,7 +591,7 @@ if ((!power_refine) || audiodb_powers_acceptable(&spec->refine, qpointers.power[j], dbpointers.power[trackIndexOffset + k])) { // radius test if((!(spec->refine.flags & ADB_REFINE_RADIUS)) || - thisDist <= (spec->refine.radius+O2_DISTANCE_TOLERANCE)) { + thisDist <= (spec->refine.radius + ADB_DISTANCE_TOLERANCE)) { adb_result_t r; r.key = (*adb->keys)[track].c_str(); r.dist = thisDist;
--- a/soap.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/soap.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,5 +1,4 @@ #include "audioDB.h" -#include "audioDB-internals.h" #include "adb.nsmap" /* Command-line client definitions */
--- a/status.cpp Tue Jan 13 21:37:14 2009 +0000 +++ b/status.cpp Thu Jan 15 13:57:33 2009 +0000 @@ -1,8 +1,7 @@ -#include "audioDB.h" extern "C" { #include "audioDB_API.h" +} #include "audioDB-internals.h" -} int audiodb_status(adb_t *adb, adb_status_t *status) { /* FIXME: it would be nice to be able to test for "is this database