Mercurial > hg > audiodb
diff audioDB.cpp @ 355:94c18f128ce8
First version of the API, committed to the main trunk. Thanks Christophe, for all the help!
author | mas01ik |
---|---|
date | Wed, 12 Nov 2008 10:21:06 +0000 |
parents | 30384a82983a |
children | 893bb90f6936 2d5c3f8e8c22 |
line wrap: on
line diff
--- a/audioDB.cpp Fri Nov 07 12:48:26 2008 +0000 +++ b/audioDB.cpp Wed Nov 12 10:21:06 2008 +0000 @@ -41,7 +41,11 @@ prefix_name((char** const)&dbName, adb_root); if(O2_ACTION(COM_SERVER)) + #ifdef BINARY startServer(); + #else + ; + #endif else if(O2_ACTION(COM_CREATE)) create(dbName); @@ -54,6 +58,7 @@ else if(O2_ACTION(COM_QUERY)) if(isClient){ + #ifdef BINARY if(query_from_key){ VERB_LOG(1, "Calling web services query %s on database %s, query=%s\n", radius>0?"(Radius)":"(NN)", dbName, (key&&strlen(key))?key:inFile); ws_query_by_key(dbName, key, inFile, (char*)hostport); @@ -62,13 +67,20 @@ VERB_LOG(1, "Calling web services query on database %s, query=%s\n", dbName, (key&&strlen(key))?key:inFile); ws_query(dbName, inFile, (char*)hostport); } + #else + ; + #endif } else query(dbName, inFile); else if(O2_ACTION(COM_STATUS)) if(isClient) + #ifdef BINARY ws_status(dbName,(char*)hostport); + #else + ; + #endif else status(dbName); @@ -86,7 +98,11 @@ else if(O2_ACTION(COM_LISZT)) if(isClient) + #ifdef BINARY ws_liszt(dbName, (char*) hostport); + #else + ; + #endif else liszt(dbName, lisztOffset, lisztLength); @@ -145,6 +161,141 @@ } } + +//for the lib / API +audioDB::audioDB(const unsigned argc, char* const argv[], int * apierror): O2_AUDIODB_INITIALIZERS +{ + + try { + UseApiError=1; + + if(processArgs(argc, argv)<0){ + printf("No command found.\n"); + cmdline_parser_print_version (); + if (strlen(gengetopt_args_info_purpose) > 0) + printf("%s\n", gengetopt_args_info_purpose); + printf("%s\n", gengetopt_args_info_usage); + printf("%s\n", gengetopt_args_info_help[1]); + printf("%s\n", gengetopt_args_info_help[2]); + printf("%s\n", gengetopt_args_info_help[0]); + error("No command found"); + } + + adb__queryResponse adbq; + + if(O2_ACTION(COM_CREATE)) + create(dbName); + + else if(O2_ACTION(COM_INSERT)) + insert(dbName, inFile); + + else if(O2_ACTION(COM_BATCHINSERT)) + batchinsert(dbName, inFile); + + else if(O2_ACTION(COM_QUERY)) + if(isClient) + ;//ws_query(dbName, inFile, (char*)hostport); + else + query(dbName, inFile, &adbq); + //query(dbName, inFile); + + else if(O2_ACTION(COM_STATUS)) + if(isClient) + ;//ws_status(dbName,(char*)hostport); + else + status(dbName); + + else if(O2_ACTION(COM_L2NORM)) + l2norm(dbName); + + else if(O2_ACTION(COM_POWER)) + power_flag(dbName); + + else if(O2_ACTION(COM_DUMP)) + dump(dbName); + + else + error("Unrecognized command",command); + + } catch(int a) { + *apierror=a; + return; + + } + *apierror=apierrortemp; + return; + +} + +//for API status +audioDB::audioDB(const unsigned argc, char* const argv[], cppstatusptr stat, int * apierror): O2_AUDIODB_INITIALIZERS +{ + + try { + UseApiError=1; + + + if(processArgs(argc, argv)<0){ + printf("No command found.\n"); + cmdline_parser_print_version (); + if (strlen(gengetopt_args_info_purpose) > 0) + printf("%s\n", gengetopt_args_info_purpose); + printf("%s\n", gengetopt_args_info_usage); + printf("%s\n", gengetopt_args_info_help[1]); + printf("%s\n", gengetopt_args_info_help[2]); + printf("%s\n", gengetopt_args_info_help[0]); + error("No command found"); + } + + status(dbName, stat); + + + } catch(int a) { + *apierror=a; + return; + + } + *apierror=apierrortemp; + return; + +} + + +//for API query +audioDB::audioDB(const unsigned argc, char* const argv[],adb__queryResponse *adbQueryResponse, int * apierror): O2_AUDIODB_INITIALIZERS +{ + + try { + UseApiError=1; + + if(processArgs(argc, argv)<0){ + printf("No command found.\n"); + cmdline_parser_print_version (); + if (strlen(gengetopt_args_info_purpose) > 0) + printf("%s\n", gengetopt_args_info_purpose); + printf("%s\n", gengetopt_args_info_usage); + printf("%s\n", gengetopt_args_info_help[1]); + printf("%s\n", gengetopt_args_info_help[2]); + printf("%s\n", gengetopt_args_info_help[0]); + error("No command found"); + } + + query(dbName, inFile, adbQueryResponse); + + } catch(int a) { + *apierror=a; + return; + + } + *apierror=apierrortemp; + return; + +} + + + + + void audioDB::cleanup() { cmdline_parser_free(&args_info); if(indata) @@ -170,7 +321,7 @@ if(powerFileNameTable) munmap(powerFileNameTable, fileTableLength); if(trackOffsetTable) - delete trackOffsetTable; + delete [] trackOffsetTable; if(reporter) delete reporter; if(exact_evaluation_queue) @@ -632,6 +783,35 @@ } } +///used by lib/API +void audioDB::status(const char* dbName, cppstatusptr status){ + if(!dbH) { + initTables(dbName, 0); + } + + unsigned dudCount=0; + unsigned nullCount=0; + for(unsigned k=0; k<dbH->numFiles; k++){ + if(trackTable[k]<sequenceLength){ + dudCount++; + if(!trackTable[k]) + nullCount++; + } + } + + status->numFiles = dbH->numFiles; + status->dim = dbH->dim; + status->length = dbH->length; + status->dudCount = dudCount; + status->nullCount = nullCount; + status->flags = dbH->flags; + + return; +} + + + + void audioDB::l2norm(const char* dbName) { forWrite = true; initTables(dbName, 0); @@ -713,3 +893,468 @@ SERVER_ADB_FEATURE_ROOT = 0; // Server-side features root prefix audioDB(argc, argv); } + + +extern "C" { + +/* for API questions contact + * Christophe Rhodes c.rhodes@gold.ac.uk + * Ian Knopke mas01ik@gold.ac.uk, ian.knopke@gmail.com */ + +#include "audioDB_API.h" + + + //adb_ptr audiodb_create(char * path,long ntracks, long datadim) { + adb_ptr audiodb_create(char * path,long datasize,long ntracks, long datadim) { + char *argv[12]; + int argvctr=0; + char tempstr1[200]; + char tempstr2[200]; + char tempstr3[200]; + int apierror=0; + + + argv[argvctr++] = "audioDB"; + argv[argvctr++] = "--NEW"; + argv[argvctr++] = "-d"; + argv[argvctr++] = path; + + if (datasize >0){ + argv[argvctr++]="--datasize"; + snprintf(tempstr1,sizeof(tempstr1),"%ld",datasize); + argv[argvctr++]=tempstr1; + } + + if (ntracks >0){ + argv[argvctr++]="--ntracks"; + snprintf(tempstr2,sizeof(tempstr2),"%ld",ntracks); + argv[argvctr++]=tempstr2; + } + + if (datadim > 0){ + argv[argvctr++]="--datadim"; + snprintf(tempstr3,sizeof(tempstr3),"%ld",datadim); + argv[argvctr++]=tempstr3; + } + + argv[argvctr+1]='\0'; + + audioDB::audioDB(argvctr, argv, &apierror); + + if (!apierror){ + return audiodb_open(path); + } + + /* database exists, so fail and pass NULL */ + return NULL; + } + + + + int audiodb_insert(adb_ptr mydb, adb_insert_ptr ins) { + char *argv[15]; + int argvctr=0; + int apierror=0; + + argv[argvctr++]="audioDB"; + argv[argvctr++]="-I"; + argv[argvctr++]="-d"; + argv[argvctr++]=mydb->dbname; + argv[argvctr++]="-f"; + argv[argvctr++]=ins->features; + + if (ins->times){ + argv[argvctr++]="--times"; + argv[argvctr++]=ins->times; + } + + if (ins->power){ + argv[argvctr++]="-w"; + argv[argvctr++]=ins->power; + } + + if (ins->key){ + argv[argvctr++]="--key"; + argv[argvctr++]=ins->key; + } + argv[argvctr+1]='\0'; + + audioDB::audioDB(argvctr,argv,&apierror); + return apierror; + } + + + int audiodb_batchinsert(adb_ptr mydb, adb_insert_ptr ins, unsigned int size) { + + char *argv[22]; + int argvctr=0; + unsigned int i=0; + int retval=0; + char tempfeaturename[]="tempfeatureXXXXXX"; + char temppowername[]="temppowerXXXXXX"; + char tempkeyname[]="tempkeyXXXXXX"; + char temptimesname[]="temptimesXXXXXX"; + int tempfeaturefd=0; + int temppowerfd=0; + int tempkeyfd=0; + int temptimesfd=0; + + int flags[4]={0}; + int apierror=0; + + /* So the final API should take an array of structs. However, the current + * version requires four separate text files. So temporarily, we need to + * unpack the struct array, make four separate text files, and then reinsert + * them into the command-line call. This should change as soon as possible */ + + + argv[argvctr++]="audioDB"; + argv[argvctr++]="-B"; + argv[argvctr++]="-d"; + argv[argvctr++]=mydb->dbname; + + + /* assume struct is well formed for all entries */ + if (ins[0].features){ flags[0]++;} else { + /* short circuit the case where there are no features in the structs */ + return -1; + } ; + if (ins[0].power){ flags[1]++;}; + if (ins[0].key){ flags[2]++;}; + if (ins[0].times){ flags[3]++;}; + + + /* make four temp files */ + tempfeaturefd=mkstemp(tempfeaturename); + if (tempfeaturefd !=-1){ + + temppowerfd=mkstemp(temppowername); + if (temppowerfd !=-1){ + + tempkeyfd=mkstemp(tempkeyname); + if (tempkeyfd !=-1){ + + temptimesfd=mkstemp(temptimesname); + if (temptimesfd !=-1){ + + } else { + retval=-1; + close(tempkeyfd); + remove(tempkeyname); + close(temppowerfd); + remove(temppowername); + close(tempfeaturefd); + remove(tempfeaturename); + } + + } else { + retval=-1; + close(temppowerfd); + remove(temppowername); + close(tempfeaturefd); + remove(tempfeaturename); + } + + } else { + retval=-1; + close(tempfeaturefd); + remove(tempfeaturename); + } + + } else { + retval=-1; + } + + + + + + if (retval == -1){ + return -1; + } + + /* Ok, so we should have a working set of files to write to */ + /* I'm going to assume that the same format is kept for all structs in the array */ + /* That is, each struct should be correctly formed, and contain at least a features file, because I'm just going to pass the terms along to the text files */ + for (i=0; i<size; i++){ + + write(tempfeaturefd,ins[i].features,strlen(ins[i].features)); + write(tempfeaturefd,"\n",1); + + if (flags[1]){ + write(temppowerfd,ins[i].power,strlen(ins[i].power)); + write(temppowerfd,"\n",1); + } + + if (flags[2]){ + write(tempkeyfd,ins[i].key,strlen(ins[i].key)); + write(tempkeyfd,"\n",1); + } + + if (flags[3]){ + write(temptimesfd,ins[i].times,strlen(ins[i].times)); + write(temptimesfd,"\n",1); + } + } + + argv[argvctr++]="-F"; + argv[argvctr++]=tempfeaturename; + close(tempfeaturefd); + close(temppowerfd); + close(tempkeyfd); + close(temptimesfd); + + if (flags[1]){ + argv[argvctr++]="--powerList"; + argv[argvctr++]=temppowername; + } + + if (flags[2]){ + argv[argvctr++]="--keyList"; + argv[argvctr++]=tempkeyname; + } + + if (flags[3]){ + argv[argvctr++]="--timesList"; + argv[argvctr++]=temptimesname; + } + + argv[argvctr+1]='\0'; + + audioDB::audioDB(argvctr,argv,&apierror); + + remove(tempfeaturename); + remove(temppowername); + remove(tempkeyname); + remove(temptimesname); + + + return apierror; + } + + + int audiodb_query(adb_ptr mydb, adb_query_ptr adbq, adb_queryresult_ptr adbqr){ + + char *argv[32]; + int argvctr=0; + char tempstr1[200]; + char tempstr2[200]; + char tempstr3[200]; + int apierror=0; + + adb__queryResponse adbQueryResponse; + + /* TODO: may need error checking here */ + /* currently counting on audioDB binary to fail for me */ + argv[argvctr++]="audioDB"; + + if(adbq->querytype){ + argv[argvctr++]="-Q"; + argv[argvctr++]=adbq->querytype; + } + + if(mydb->dbname){ + argv[argvctr++]="-d"; + argv[argvctr++]=mydb->dbname; + } + + if (adbq->feature){ + argv[argvctr++]="-f"; + argv[argvctr++]=adbq->feature; + } + + if (adbq->power){ + argv[argvctr++]="-w"; + argv[argvctr++]=adbq->power; + } + + if (adbq->qpoint){ + argv[argvctr++]="-p"; + argv[argvctr++]=adbq->qpoint; + } + if (adbq->numpoints){ + argv[argvctr++]="-n"; + argv[argvctr++]=adbq->numpoints; + } + if (adbq->radius){ + argv[argvctr++]="-R"; + argv[argvctr++]=adbq->radius; + } + if(adbq->resultlength){ + argv[argvctr++]="-r"; + argv[argvctr++]=adbq->resultlength; + } + if(adbq->sequencelength){ + argv[argvctr++]="-l"; + argv[argvctr++]=adbq->sequencelength; + } + if(adbq->sequencehop){ + argv[argvctr++]="-h"; + argv[argvctr++]=adbq->sequencehop; + } + + if (adbq->absolute_threshold){ + argv[argvctr++]="--absolute-threshold"; + snprintf(tempstr1,sizeof(tempstr1),"%f",adbq->absolute_threshold); + argv[argvctr++]=tempstr1; + } + + if (adbq->relative_threshold){ + argv[argvctr++]="--relative-threshold"; + snprintf(tempstr2,sizeof(tempstr2),"%f",adbq->relative_threshold); + argv[argvctr++]=tempstr2; + } + + if (adbq->exhaustive){ + argv[argvctr++]="--exhaustive"; + } + + if (adbq->expandfactor){ + argv[argvctr++]="--expandfactor"; + snprintf(tempstr3,sizeof(tempstr3),"%f",adbq->expandfactor); + argv[argvctr++]=tempstr3; + } + + if (adbq->rotate){ + argv[argvctr++]="--rotate"; + } + + if (adbq->keylist){ + argv[argvctr++]="-K"; + argv[argvctr++]=adbq->keylist; + } + argv[argvctr+1]='\0'; + + /* debugging */ + + audioDB::audioDB(argvctr,argv, &adbQueryResponse, &apierror); + + //copy data over here from adbQueryResponse to adbqr + adbqr->sizeRlist=adbQueryResponse.result.__sizeRlist; + adbqr->sizeDist=adbQueryResponse.result.__sizeDist; + adbqr->sizeQpos=adbQueryResponse.result.__sizeQpos; + adbqr->sizeSpos=adbQueryResponse.result.__sizeSpos; + adbqr->Rlist=adbQueryResponse.result.Rlist; + adbqr->Dist=adbQueryResponse.result.Dist; + adbqr->Qpos=adbQueryResponse.result.Qpos; + adbqr->Spos=adbQueryResponse.result.Spos; + + return apierror; + } + + ///* status command */ + int audiodb_status(adb_ptr mydb, adb_status_ptr status){ + + cppstatus sss; + int apierror=0; + + char * argv[5]; + + apierror=0; + argv[0]="audioDB"; + argv[1]="--STATUS"; + argv[2]="-d"; + argv[3]=mydb->dbname; + argv[4]='\0'; + + audioDB::audioDB(4,argv,&sss ,&apierror); + + status->numFiles=sss.numFiles; + status->dim=sss.dim; + status->length=sss.length; + status->dudCount=sss.dudCount; + status->nullCount=sss.nullCount; + status->flags=sss.flags; + + return apierror; + } + + int audiodb_dump(adb_ptr mydb){ + return audiodb_dump_withdir(mydb,"audioDB.dump"); + } + + int audiodb_dump_withdir(adb_ptr mydb, char * outputdir){ + + char * argv[7]; + int argvctr=0; + int apierror=0; + + argv[argvctr++]="audioDB"; + argv[argvctr++]="--DUMP"; + argv[argvctr++]="-d"; + argv[argvctr++]=mydb->dbname; + argv[argvctr++]="--output"; + argv[argvctr++]=(char *)outputdir; + argv[argvctr+1]='\0'; + + audioDB::audioDB(6,argv,&apierror); + + return apierror; + } + + int audiodb_l2norm(adb_ptr mydb){ + + char * argv[5]; + int apierror=0; + + argv[0]="audioDB"; + argv[1]="--L2NORM"; + argv[2]="-d"; + argv[3]=mydb->dbname; + argv[4]='\0'; + + audioDB::audioDB(4,argv,&apierror); + return apierror; + } + + int audiodb_power(adb_ptr mydb){ + + char * argv[5]; + int apierror=0; + + argv[0]="audioDB"; + argv[1]="--POWER"; + argv[2]="-d"; + argv[3]=mydb->dbname; + argv[4]='\0'; + + audioDB::audioDB(4,argv,&apierror); + return apierror; + } + + adb_ptr audiodb_open(char * path){ + + adb_ptr mydbp; + adbstatus mystatus; + + /* if db exists */ + + if (open(path, O_EXCL) != -1){ + + mydbp=(adb_ptr)malloc(sizeof(adb)); + mydbp->dbname=(char *)malloc(sizeof(path)); + + strcpy(mydbp->dbname,path); + + audiodb_status(mydbp, &mystatus); + mydbp->ntracks=mystatus.numFiles; + mydbp->datadim=mystatus.dim; + + return mydbp; + } + + return NULL; + }; + + + + void audiodb_close(adb_ptr db){ + + free(db->dbname); + free(db); + + } + + +} +