Mercurial > hg > audiodb
diff audioDB.cpp @ 107:1521d46bc1ac audiodb-debian
Merge trunk changes -r96:122 to audiodb-debian branch.
(and new version in debian/changelog)
author | mas01cr |
---|---|
date | Fri, 05 Oct 2007 11:45:03 +0000 |
parents | a1d462d592dd |
children | ae045842d29f |
line wrap: on
line diff
--- a/audioDB.cpp Mon Oct 01 14:59:03 2007 +0000 +++ b/audioDB.cpp Fri Oct 05 11:45:03 2007 +0000 @@ -1,9 +1,21 @@ #include "audioDB.h" -#define O2_DEBUG +#if defined(O2_DEBUG) +void sigterm_action(int signal, siginfo_t *info, void *context) { + exit(128+signal); +} + +void sighup_action(int signal, siginfo_t *info, void *context) { + // FIXME: reread any configuration files +} +#endif void audioDB::error(const char* a, const char* b, const char *sysFunc) { if(isServer) { + /* FIXME: I think this is leaky -- we never delete err. actually + deleting it is tricky, though; it gets placed into some + soap-internal struct with uncertain extent... -- CSR, + 2007-10-01 */ char *err = new char[256]; /* FIXME: overflows */ snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : ""); /* FIXME: actually we could usefully do with a properly structured @@ -19,42 +31,6 @@ } } -#define O2_AUDIODB_INITIALIZERS \ - dim(0), \ - dbName(0), \ - inFile(0), \ - key(0), \ - trackFileName(0), \ - trackFile(0), \ - command(0), \ - timesFileName(0), \ - timesFile(0), \ - dbfid(0), \ - infid(0), \ - db(0), \ - indata(0), \ - dbH(0), \ - fileTable(0), \ - trackTable(0), \ - dataBuf(0), \ - l2normTable(0), \ - qNorm(0), \ - timesTable(0), \ - verbosity(1), \ - queryType(O2_FLAG_POINT_QUERY), \ - pointNN(O2_DEFAULT_POINTNN), \ - trackNN(O2_DEFAULT_TRACKNN), \ - sequenceLength(16), \ - sequenceHop(1), \ - queryPoint(0), \ - usingQueryPoint(0), \ - usingTimes(0), \ - isClient(0), \ - isServer(0), \ - port(0), \ - timesTol(0.1), \ - radius(0) - audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS { if(processArgs(argc, argv)<0){ @@ -105,22 +81,31 @@ audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResult *adbQueryResult): O2_AUDIODB_INITIALIZERS { - processArgs(argc, argv); - isServer = 1; // FIXME: Hack - assert(O2_ACTION(COM_QUERY)); - query(dbName, inFile, adbQueryResult); + try { + processArgs(argc, argv); + isServer = 1; // FIXME: Hack + assert(O2_ACTION(COM_QUERY)); + query(dbName, inFile, adbQueryResult); + } catch(char *err) { + cleanup(); + throw(err); + } } audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResult *adbStatusResult): O2_AUDIODB_INITIALIZERS { - processArgs(argc, argv); - isServer = 1; // FIXME: Hack - assert(O2_ACTION(COM_STATUS)); - status(dbName, adbStatusResult); + try { + processArgs(argc, argv); + isServer = 1; // FIXME: Hack + assert(O2_ACTION(COM_STATUS)); + status(dbName, adbStatusResult); + } catch(char *err) { + cleanup(); + throw(err); + } } -audioDB::~audioDB(){ - // Clean up +void audioDB::cleanup() { if(indata) munmap(indata,statbuf.st_size); if(db) @@ -133,6 +118,10 @@ delete dbH; } +audioDB::~audioDB(){ + cleanup(); +} + int audioDB::processArgs(const unsigned argc, char* const argv[]){ if(argc<2){ @@ -179,145 +168,150 @@ if(port<100 || port > 100000) error("port out of range"); isServer=1; +#if defined(O2_DEBUG) + struct sigaction sa; + sa.sa_sigaction = sigterm_action; + sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + sigaction(SIGTERM, &sa, NULL); + sa.sa_sigaction = sighup_action; + sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; + sigaction(SIGHUP, &sa, NULL); +#endif return 0; } // No return on client command, find database command - if(args_info.client_given){ - command=COM_CLIENT; - hostport=args_info.client_arg; - isClient=1; - } + if(args_info.client_given){ + command=COM_CLIENT; + hostport=args_info.client_arg; + isClient=1; + } - if(args_info.NEW_given){ - command=COM_CREATE; - dbName=args_info.database_arg; - return 0; - } + if(args_info.NEW_given){ + command=COM_CREATE; + dbName=args_info.database_arg; + return 0; + } - if(args_info.STATUS_given){ - command=COM_STATUS; - dbName=args_info.database_arg; - return 0; - } + if(args_info.STATUS_given){ + command=COM_STATUS; + dbName=args_info.database_arg; + return 0; + } - if(args_info.DUMP_given){ - command=COM_DUMP; - dbName=args_info.database_arg; - return 0; - } + if(args_info.DUMP_given){ + command=COM_DUMP; + dbName=args_info.database_arg; + return 0; + } - if(args_info.L2NORM_given){ - command=COM_L2NORM; - dbName=args_info.database_arg; - return 0; - } + if(args_info.L2NORM_given){ + command=COM_L2NORM; + dbName=args_info.database_arg; + return 0; + } - if(args_info.INSERT_given){ - command=COM_INSERT; - dbName=args_info.database_arg; - inFile=args_info.features_arg; - if(args_info.key_given) - key=args_info.key_arg; - if(args_info.times_given){ - timesFileName=args_info.times_arg; - if(strlen(timesFileName)>0){ - if(!(timesFile = new ifstream(timesFileName,ios::in))) - error("Could not open times file for reading", timesFileName); - usingTimes=1; - } - } - return 0; - } - - if(args_info.BATCHINSERT_given){ - command=COM_BATCHINSERT; - dbName=args_info.database_arg; - inFile=args_info.featureList_arg; - if(args_info.keyList_given) - key=args_info.keyList_arg; // INCONSISTENT NO CHECK + if(args_info.INSERT_given){ + command=COM_INSERT; + dbName=args_info.database_arg; + inFile=args_info.features_arg; + if(args_info.key_given) + key=args_info.key_arg; + if(args_info.times_given){ + timesFileName=args_info.times_arg; + if(strlen(timesFileName)>0){ + if(!(timesFile = new ifstream(timesFileName,ios::in))) + error("Could not open times file for reading", timesFileName); + usingTimes=1; + } + } + return 0; + } + + if(args_info.BATCHINSERT_given){ + command=COM_BATCHINSERT; + dbName=args_info.database_arg; + inFile=args_info.featureList_arg; + if(args_info.keyList_given) + key=args_info.keyList_arg; // INCONSISTENT NO CHECK - /* TO DO: REPLACE WITH + /* TO DO: REPLACE WITH if(args_info.keyList_given){ trackFileName=args_info.keyList_arg; if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in))) error("Could not open keyList file for reading",trackFileName); } AND UPDATE BATCHINSERT() - */ - - if(args_info.timesList_given){ - timesFileName=args_info.timesList_arg; - if(strlen(timesFileName)>0){ - if(!(timesFile = new ifstream(timesFileName,ios::in))) - error("Could not open timesList file for reading", timesFileName); - usingTimes=1; - } - } - return 0; - } - - // Query command and arguments - if(args_info.QUERY_given){ - command=COM_QUERY; - dbName=args_info.database_arg; - inFile=args_info.features_arg; - - if(args_info.keyList_given){ - trackFileName=args_info.keyList_arg; - if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in))) - error("Could not open keyList file for reading",trackFileName); - } - - if(args_info.times_given){ - timesFileName=args_info.times_arg; - if(strlen(timesFileName)>0){ - if(!(timesFile = new ifstream(timesFileName,ios::in))) - error("Could not open times file for reading", timesFileName); - usingTimes=1; - } - } - - // query type - if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0) - queryType=O2_FLAG_TRACK_QUERY; - else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0) - queryType=O2_FLAG_POINT_QUERY; - else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0) - queryType=O2_FLAG_SEQUENCE_QUERY; - else - error("unsupported query type",args_info.QUERY_arg); - - if(!args_info.exhaustive_flag){ - queryPoint = args_info.qpoint_arg; - usingQueryPoint=1; - if(queryPoint<0 || queryPoint >10000) - error("queryPoint out of range: 0 <= queryPoint <= 10000"); - } - - - pointNN=args_info.pointnn_arg; - if(pointNN<1 || pointNN >1000) - error("pointNN out of range: 1 <= pointNN <= 1000"); - - - - trackNN=args_info.resultlength_arg; - if(trackNN<1 || trackNN >10000) - error("resultlength out of range: 1 <= resultlength <= 1000"); - - - sequenceLength=args_info.sequencelength_arg; - if(sequenceLength<1 || sequenceLength >1000) - error("seqlen out of range: 1 <= seqlen <= 1000"); - - sequenceHop=args_info.sequencehop_arg; - if(sequenceHop<1 || sequenceHop >1000) - error("seqhop out of range: 1 <= seqhop <= 1000"); - - return 0; - } - return -1; // no command found + */ + + if(args_info.timesList_given){ + timesFileName=args_info.timesList_arg; + if(strlen(timesFileName)>0){ + if(!(timesFile = new ifstream(timesFileName,ios::in))) + error("Could not open timesList file for reading", timesFileName); + usingTimes=1; + } + } + return 0; + } + + // Query command and arguments + if(args_info.QUERY_given){ + command=COM_QUERY; + dbName=args_info.database_arg; + inFile=args_info.features_arg; + + if(args_info.keyList_given){ + trackFileName=args_info.keyList_arg; + if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in))) + error("Could not open keyList file for reading",trackFileName); + } + + if(args_info.times_given){ + timesFileName=args_info.times_arg; + if(strlen(timesFileName)>0){ + if(!(timesFile = new ifstream(timesFileName,ios::in))) + error("Could not open times file for reading", timesFileName); + usingTimes=1; + } + } + + // query type + if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0) + queryType=O2_TRACK_QUERY; + else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0) + queryType=O2_POINT_QUERY; + else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0) + queryType=O2_SEQUENCE_QUERY; + else + error("unsupported query type",args_info.QUERY_arg); + + if(!args_info.exhaustive_flag){ + queryPoint = args_info.qpoint_arg; + usingQueryPoint=1; + if(queryPoint<0 || queryPoint >10000) + error("queryPoint out of range: 0 <= queryPoint <= 10000"); + } + + pointNN = args_info.pointnn_arg; + if(pointNN < 1 || pointNN > 1000) { + error("pointNN out of range: 1 <= pointNN <= 1000"); + } + trackNN = args_info.resultlength_arg; + if(trackNN < 1 || trackNN > 1000) { + error("resultlength out of range: 1 <= resultlength <= 1000"); + } + sequenceLength = args_info.sequencelength_arg; + if(sequenceLength < 1 || sequenceLength > 1000) { + error("seqlen out of range: 1 <= seqlen <= 1000"); + } + sequenceHop = args_info.sequencehop_arg; + if(sequenceHop < 1 || sequenceHop > 1000) { + error("seqhop out of range: 1 <= seqhop <= 1000"); + } + return 0; + } + return -1; // no command found } /* Make a new database @@ -334,31 +328,31 @@ -------------------------------------------------------------------------- | key 256 bytes | -------------------------------------------------------------------------- - O2_MAXFILES*02_FILENAMELENGTH + O2_MAXFILES*O2_FILENAMELENGTH trackTable : Maps implicit feature index to a feature vector matrix -------------------------------------------------------------------------- | numVectors (4 bytes) | -------------------------------------------------------------------------- - O2_MAXFILES * 02_MEANNUMFEATURES * sizeof(INT) + O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(INT) featureTable -------------------------------------------------------------------------- | v1 v2 v3 ... vd (double) | -------------------------------------------------------------------------- - O2_MAXFILES * 02_MEANNUMFEATURES * DIM * sizeof(DOUBLE) + O2_MAXFILES * O2_MEANNUMFEATURES * DIM * sizeof(DOUBLE) timesTable -------------------------------------------------------------------------- | timestamp (double) | -------------------------------------------------------------------------- - O2_MAXFILES * 02_MEANNUMFEATURES * sizeof(DOUBLE) + O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(DOUBLE) l2normTable -------------------------------------------------------------------------- | nm (double) | -------------------------------------------------------------------------- - O2_MAXFILES * 02_MEANNUMFEATURES * sizeof(DOUBLE) + O2_MAXFILES * O2_MEANNUMFEATURES * sizeof(DOUBLE) */ @@ -446,25 +440,27 @@ // initTables - memory map files passed as arguments // Precondition: database has already been created -void audioDB::initTables(const char* dbName, bool forWrite, const char* inFile=0){ - if ((dbfid = open (dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) +void audioDB::initTables(const char* dbName, bool forWrite, const char* inFile = 0) { + if ((dbfid = open(dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) { error("Can't open database file", dbName, "open"); + } get_lock(dbfid, forWrite); // open the input file - if (inFile && (infid = open (inFile, O_RDONLY)) < 0) + if (inFile && (infid = open(inFile, O_RDONLY)) < 0) { error("can't open input file for reading", inFile, "open"); - + } // find size of input file - if (inFile && fstat (infid,&statbuf) < 0) - error("fstat error finding size of input", "", "fstat"); - + if (inFile && fstat(infid, &statbuf) < 0) { + error("fstat error finding size of input", inFile, "fstat"); + } // Get the database header info dbH = new dbTableHeaderT(); assert(dbH); - if(read(dbfid,(char*)dbH,sizeof(dbTableHeaderT))!=sizeof(dbTableHeaderT)) - error("error reading db header"); + if(read(dbfid, (char *) dbH, O2_HEADERSIZE) != O2_HEADERSIZE) { + error("error reading db header", dbName, "read"); + } fileTableOffset = O2_HEADERSIZE; trackTableOffset = fileTableOffset + O2_FILETABLESIZE*O2_MAXFILES; @@ -472,19 +468,20 @@ l2normTableOffset = O2_DEFAULTDBSIZE - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double); timesTableOffset = l2normTableOffset - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double); - if(dbH->magic!=O2_MAGIC){ - cerr << "expected: " << O2_MAGIC << ", got:" << dbH->magic << endl; + if(dbH->magic != O2_MAGIC) { + cerr << "expected: " << O2_MAGIC << ", got: " << dbH->magic << endl; error("database file has incorrect header",dbName); } if(inFile) - if(dbH->dim==0 && dbH->length==0) // empty database - read(infid,&dbH->dim,sizeof(unsigned)); // initialize with input dimensionality + if(dbH->dim == 0 && dbH->length == 0) // empty database + // initialize with input dimensionality + read(infid, &dbH->dim, sizeof(unsigned)); else { unsigned test; - read(infid,&test,sizeof(unsigned)); - if(dbH->dim!=test){ - cerr << "error: expected dimension: " << dbH->dim << ", got :" << test <<endl; + read(infid, &test, sizeof(unsigned)); + if(dbH->dim != test) { + cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<endl; error("feature dimensions do not match database table dimensions"); } } @@ -492,7 +489,7 @@ // mmap the input file if (inFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0)) == (caddr_t) -1) - error("mmap error for input", "", "mmap"); + error("mmap error for input", inFile, "mmap"); // mmap the database file if ((db = (char*) mmap(0, O2_DEFAULTDBSIZE, PROT_READ | (forWrite ? PROT_WRITE : 0), @@ -505,7 +502,6 @@ dataBuf = (double*)(db+dataoffset); l2normTable = (double*)(db+l2normTableOffset); timesTable = (double*)(db+timesTableOffset); - } void audioDB::insert(const char* dbName, const char* inFile){ @@ -944,16 +940,16 @@ void audioDB::query(const char* dbName, const char* inFile, adb__queryResult *adbQueryResult){ switch(queryType){ - case O2_FLAG_POINT_QUERY: + case O2_POINT_QUERY: pointQuery(dbName, inFile, adbQueryResult); break; - case O2_FLAG_SEQUENCE_QUERY: + case O2_SEQUENCE_QUERY: if(radius==0) trackSequenceQueryNN(dbName, inFile, adbQueryResult); else trackSequenceQueryRad(dbName, inFile, adbQueryResult); break; - case O2_FLAG_TRACK_QUERY: + case O2_TRACK_QUERY: trackPointQuery(dbName, inFile, adbQueryResult); break; default: @@ -1110,15 +1106,21 @@ } } else{ // Process Web Services Query - int listLen = pointNN; + int listLen; + for(k = 0; k < pointNN; k++) { + if(distances[k] == -DBL_MAX) + break; + } + listLen = k; + adbQueryResult->__sizeRlist=listLen; adbQueryResult->__sizeDist=listLen; adbQueryResult->__sizeQpos=listLen; adbQueryResult->__sizeSpos=listLen; adbQueryResult->Rlist= new char*[listLen]; adbQueryResult->Dist = new double[listLen]; - adbQueryResult->Qpos = new int[listLen]; - adbQueryResult->Spos = new int[listLen]; + adbQueryResult->Qpos = new unsigned int[listLen]; + adbQueryResult->Spos = new unsigned int[listLen]; for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){ adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR]; adbQueryResult->Dist[k]=distances[k]; @@ -1372,8 +1374,8 @@ adbQueryResult->__sizeSpos=listLen; adbQueryResult->Rlist= new char*[listLen]; adbQueryResult->Dist = new double[listLen]; - adbQueryResult->Qpos = new int[listLen]; - adbQueryResult->Spos = new int[listLen]; + adbQueryResult->Qpos = new unsigned int[listLen]; + adbQueryResult->Spos = new unsigned int[listLen]; for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){ adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR]; adbQueryResult->Dist[k]=trackDistances[k]; @@ -1870,8 +1872,8 @@ adbQueryResult->__sizeSpos=listLen; adbQueryResult->Rlist= new char*[listLen]; adbQueryResult->Dist = new double[listLen]; - adbQueryResult->Qpos = new int[listLen]; - adbQueryResult->Spos = new int[listLen]; + adbQueryResult->Qpos = new unsigned int[listLen]; + adbQueryResult->Spos = new unsigned int[listLen]; for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){ adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR]; adbQueryResult->Dist[k]=trackDistances[k]; @@ -2346,8 +2348,8 @@ adbQueryResult->__sizeSpos=listLen; adbQueryResult->Rlist= new char*[listLen]; adbQueryResult->Dist = new double[listLen]; - adbQueryResult->Qpos = new int[listLen]; - adbQueryResult->Spos = new int[listLen]; + adbQueryResult->Qpos = new unsigned int[listLen]; + adbQueryResult->Spos = new unsigned int[listLen]; for(k=0; k<(unsigned)adbQueryResult->__sizeRlist; k++){ adbQueryResult->Rlist[k]=new char[O2_MAXFILESTR]; adbQueryResult->Dist[k]=trackDistances[k]; @@ -2449,10 +2451,15 @@ X+=dim; } unsigned offset; - if(append) - offset=dbH->length/(dbH->dim*sizeof(double)); // number of vectors - else + if(append) { + // FIXME: a hack, a very palpable hack: the vectors have already + // been inserted, and dbH->length has already been updated. We + // need to subtract off again the number of vectors that we've + // inserted this time... + offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors + } else { offset=0; + } memcpy(l2normTable+offset, l2buf, n*sizeof(double)); if(l2buf) delete[] l2buf; @@ -2467,6 +2474,13 @@ struct soap soap; int m, s; // master and slave sockets soap_init(&soap); + // FIXME: largely this use of SO_REUSEADDR is to make writing (and + // running) test cases more convenient, so that multiple test runs + // in close succession don't fail because of a bin() error. + // Investigate whether there are any potential drawbacks in this, + // and also whether there's a better way to write the tests. -- + // CSR, 2007-10-03 + soap.bind_flags |= SO_REUSEADDR; m = soap_bind(&soap, NULL, port, 100); if (m < 0) soap_print_fault(&soap, stderr); @@ -2515,11 +2529,11 @@ char queryType[256]; for(int k=0; k<256; k++) queryType[k]='\0'; - if(qType == O2_FLAG_POINT_QUERY) + if(qType == O2_POINT_QUERY) strncpy(queryType, "point", strlen("point")); - else if (qType == O2_FLAG_SEQUENCE_QUERY) + else if (qType == O2_SEQUENCE_QUERY) strncpy(queryType, "sequence", strlen("sequence")); - else if(qType == O2_FLAG_TRACK_QUERY) + else if(qType == O2_TRACK_QUERY) strncpy(queryType,"track", strlen("track")); else strncpy(queryType, "", strlen("")); @@ -2575,3 +2589,4 @@ int main(const unsigned argc, char* const argv[]){ audioDB(argc, argv); } +