annotate audioDB.cpp @ 133:a5d5a55a412d

Friendlier Actionscript/SOAP behaviour. As suggested in the gsoap documentation, we wrap the struct that we actually want to return inside a response structure. (It should be said that I didn't understand a _word_ of the gsoap documentation; I want in particular to highlight section 8.1.1 of the gsoap 2.7.6 user guide, which reads in its entirety "If the single output parameter of a remote method is a complex data type such as a struct or class it is necessary to specify the response element of the remote method as a struct or class at all times. Otherwise, the output parameter will be considered the response element (!), because of the response element specification convention used by gSOAP, as discussed in 8.1.7." and tells me absolutely nothing of use.) Nevertheless, cargo-cult from the documentation...
author mas01cr
date Tue, 23 Oct 2007 17:21:08 +0000
parents 3d931368fab3
children ddd83d773d6c
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@0 2
mas01cr@105 3 #if defined(O2_DEBUG)
mas01cr@104 4 void sigterm_action(int signal, siginfo_t *info, void *context) {
mas01cr@104 5 exit(128+signal);
mas01cr@104 6 }
mas01cr@104 7
mas01cr@104 8 void sighup_action(int signal, siginfo_t *info, void *context) {
mas01cr@104 9 // FIXME: reread any configuration files
mas01cr@104 10 }
mas01cr@105 11 #endif
mas01cr@0 12
mas01cr@32 13 void audioDB::error(const char* a, const char* b, const char *sysFunc) {
mas01cr@77 14 if(isServer) {
mas01cr@81 15 /* FIXME: I think this is leaky -- we never delete err. actually
mas01cr@81 16 deleting it is tricky, though; it gets placed into some
mas01cr@81 17 soap-internal struct with uncertain extent... -- CSR,
mas01cr@81 18 2007-10-01 */
mas01cr@77 19 char *err = new char[256]; /* FIXME: overflows */
mas01cr@77 20 snprintf(err, 255, "%s: %s\n%s", a, b, sysFunc ? strerror(errno) : "");
mas01cr@77 21 /* FIXME: actually we could usefully do with a properly structured
mas01cr@77 22 type, so that we can throw separate faultstring and details.
mas01cr@77 23 -- CSR, 2007-10-01 */
mas01cr@77 24 throw(err);
mas01cr@77 25 } else {
mas01cr@77 26 cerr << a << ": " << b << endl;
mas01cr@77 27 if (sysFunc) {
mas01cr@77 28 perror(sysFunc);
mas01cr@77 29 }
mas01cr@77 30 exit(1);
mas01cr@32 31 }
mas01cr@0 32 }
mas01cr@0 33
mas01cr@76 34 audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@76 35 {
mas01cr@0 36 if(processArgs(argc, argv)<0){
mas01cr@0 37 printf("No command found.\n");
mas01cr@0 38 cmdline_parser_print_version ();
mas01cr@0 39 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 40 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 41 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 42 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 43 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 44 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 45 exit(1);
mas01cr@0 46 }
mas01cr@77 47
mas01cr@0 48 if(O2_ACTION(COM_SERVER))
mas01cr@0 49 startServer();
mas01cr@0 50
mas01cr@0 51 else if(O2_ACTION(COM_CREATE))
mas01cr@0 52 create(dbName);
mas01cr@0 53
mas01cr@0 54 else if(O2_ACTION(COM_INSERT))
mas01cr@0 55 insert(dbName, inFile);
mas01cr@0 56
mas01cr@0 57 else if(O2_ACTION(COM_BATCHINSERT))
mas01cr@0 58 batchinsert(dbName, inFile);
mas01cr@0 59
mas01cr@0 60 else if(O2_ACTION(COM_QUERY))
mas01cr@0 61 if(isClient)
mas01cr@0 62 ws_query(dbName, inFile, (char*)hostport);
mas01cr@0 63 else
mas01cr@76 64 query(dbName, inFile);
mas01cr@0 65
mas01cr@0 66 else if(O2_ACTION(COM_STATUS))
mas01cr@0 67 if(isClient)
mas01cr@0 68 ws_status(dbName,(char*)hostport);
mas01cr@0 69 else
mas01cr@0 70 status(dbName);
mas01cr@0 71
mas01cr@0 72 else if(O2_ACTION(COM_L2NORM))
mas01cr@0 73 l2norm(dbName);
mas01cr@0 74
mas01cr@0 75 else if(O2_ACTION(COM_DUMP))
mas01cr@0 76 dump(dbName);
mas01cr@0 77
mas01cr@0 78 else
mas01cr@0 79 error("Unrecognized command",command);
mas01cr@0 80 }
mas01cr@0 81
mas01cr@133 82 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResponse *adbQueryResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 83 {
mas01cr@97 84 try {
mas01cr@97 85 processArgs(argc, argv);
mas01cr@97 86 isServer = 1; // FIXME: Hack
mas01cr@97 87 assert(O2_ACTION(COM_QUERY));
mas01cr@133 88 query(dbName, inFile, adbQueryResponse);
mas01cr@97 89 } catch(char *err) {
mas01cr@97 90 cleanup();
mas01cr@97 91 throw(err);
mas01cr@97 92 }
mas01cr@76 93 }
mas01cr@76 94
mas01cr@133 95 audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResponse *adbStatusResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 96 {
mas01cr@97 97 try {
mas01cr@97 98 processArgs(argc, argv);
mas01cr@97 99 isServer = 1; // FIXME: Hack
mas01cr@97 100 assert(O2_ACTION(COM_STATUS));
mas01cr@133 101 status(dbName, adbStatusResponse);
mas01cr@97 102 } catch(char *err) {
mas01cr@97 103 cleanup();
mas01cr@97 104 throw(err);
mas01cr@97 105 }
mas01cr@76 106 }
mas01cr@76 107
mas01cr@97 108 void audioDB::cleanup() {
mas01cr@122 109 cmdline_parser_free(&args_info);
mas01cr@0 110 if(indata)
mas01cr@0 111 munmap(indata,statbuf.st_size);
mas01cr@0 112 if(db)
mas01cr@128 113 munmap(db,dbH->dbSize);
mas01cr@0 114 if(dbfid>0)
mas01cr@0 115 close(dbfid);
mas01cr@0 116 if(infid>0)
mas01cr@0 117 close(infid);
mas01cr@0 118 if(dbH)
mas01cr@0 119 delete dbH;
mas01cr@0 120 }
mas01cr@0 121
mas01cr@97 122 audioDB::~audioDB(){
mas01cr@97 123 cleanup();
mas01cr@97 124 }
mas01cr@97 125
mas01cr@0 126 int audioDB::processArgs(const unsigned argc, char* const argv[]){
mas01cr@0 127
mas01cr@0 128 if(argc<2){
mas01cr@0 129 cmdline_parser_print_version ();
mas01cr@0 130 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 131 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 132 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 133 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 134 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 135 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 136 exit(0);
mas01cr@0 137 }
mas01cr@0 138
mas01cr@0 139 if (cmdline_parser (argc, argv, &args_info) != 0)
mas01cr@0 140 exit(1) ;
mas01cr@0 141
mas01cr@0 142 if(args_info.help_given){
mas01cr@0 143 cmdline_parser_print_help();
mas01cr@0 144 exit(0);
mas01cr@0 145 }
mas01cr@0 146
mas01cr@0 147 if(args_info.verbosity_given){
mas01cr@0 148 verbosity=args_info.verbosity_arg;
mas01cr@0 149 if(verbosity<0 || verbosity>10){
mas01cr@0 150 cerr << "Warning: verbosity out of range, setting to 1" << endl;
mas01cr@0 151 verbosity=1;
mas01cr@0 152 }
mas01cr@0 153 }
mas01cr@0 154
mas01cr@129 155 if(args_info.size_given) {
mas01cr@129 156 if (args_info.size_arg < 250 || args_info.size_arg > 4000) {
mas01cr@129 157 error("Size out of range", "");
mas01cr@129 158 }
mas01cr@129 159 size = args_info.size_arg * 1000000;
mas01cr@129 160 }
mas01cr@129 161
mas01mc@17 162 if(args_info.radius_given){
mas01mc@17 163 radius=args_info.radius_arg;
mas01mc@17 164 if(radius<=0 || radius>1000000000){
mas01cr@77 165 error("radius out of range");
mas01mc@17 166 }
mas01mc@17 167 else
mas01cr@60 168 if(verbosity>3) {
mas01mc@17 169 cerr << "Setting radius to " << radius << endl;
mas01cr@60 170 }
mas01mc@17 171 }
mas01mc@17 172
mas01cr@0 173 if(args_info.SERVER_given){
mas01cr@0 174 command=COM_SERVER;
mas01cr@0 175 port=args_info.SERVER_arg;
mas01cr@0 176 if(port<100 || port > 100000)
mas01cr@0 177 error("port out of range");
mas01cr@0 178 isServer=1;
mas01cr@105 179 #if defined(O2_DEBUG)
mas01cr@104 180 struct sigaction sa;
mas01cr@104 181 sa.sa_sigaction = sigterm_action;
mas01cr@104 182 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 183 sigaction(SIGTERM, &sa, NULL);
mas01cr@104 184 sa.sa_sigaction = sighup_action;
mas01cr@104 185 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 186 sigaction(SIGHUP, &sa, NULL);
mas01cr@105 187 #endif
mas01cr@0 188 return 0;
mas01cr@0 189 }
mas01cr@0 190
mas01cr@0 191 // No return on client command, find database command
mas01cr@105 192 if(args_info.client_given){
mas01cr@105 193 command=COM_CLIENT;
mas01cr@105 194 hostport=args_info.client_arg;
mas01cr@105 195 isClient=1;
mas01cr@105 196 }
mas01cr@0 197
mas01cr@105 198 if(args_info.NEW_given){
mas01cr@105 199 command=COM_CREATE;
mas01cr@105 200 dbName=args_info.database_arg;
mas01cr@105 201 return 0;
mas01cr@105 202 }
mas01cr@0 203
mas01cr@105 204 if(args_info.STATUS_given){
mas01cr@105 205 command=COM_STATUS;
mas01cr@105 206 dbName=args_info.database_arg;
mas01cr@105 207 return 0;
mas01cr@105 208 }
mas01cr@0 209
mas01cr@105 210 if(args_info.DUMP_given){
mas01cr@105 211 command=COM_DUMP;
mas01cr@105 212 dbName=args_info.database_arg;
mas01cr@131 213 output = args_info.output_arg;
mas01cr@105 214 return 0;
mas01cr@105 215 }
mas01cr@0 216
mas01cr@105 217 if(args_info.L2NORM_given){
mas01cr@105 218 command=COM_L2NORM;
mas01cr@105 219 dbName=args_info.database_arg;
mas01cr@105 220 return 0;
mas01cr@105 221 }
mas01cr@0 222
mas01cr@105 223 if(args_info.INSERT_given){
mas01cr@105 224 command=COM_INSERT;
mas01cr@105 225 dbName=args_info.database_arg;
mas01cr@105 226 inFile=args_info.features_arg;
mas01cr@105 227 if(args_info.key_given)
mas01cr@105 228 key=args_info.key_arg;
mas01cr@105 229 if(args_info.times_given){
mas01cr@105 230 timesFileName=args_info.times_arg;
mas01cr@105 231 if(strlen(timesFileName)>0){
mas01cr@105 232 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@105 233 error("Could not open times file for reading", timesFileName);
mas01cr@105 234 usingTimes=1;
mas01cr@105 235 }
mas01cr@105 236 }
mas01cr@105 237 return 0;
mas01cr@105 238 }
mas01cr@105 239
mas01cr@105 240 if(args_info.BATCHINSERT_given){
mas01cr@105 241 command=COM_BATCHINSERT;
mas01cr@105 242 dbName=args_info.database_arg;
mas01cr@105 243 inFile=args_info.featureList_arg;
mas01cr@105 244 if(args_info.keyList_given)
mas01cr@105 245 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@0 246
mas01cr@105 247 /* TO DO: REPLACE WITH
mas01cr@0 248 if(args_info.keyList_given){
mas01mc@18 249 trackFileName=args_info.keyList_arg;
mas01mc@18 250 if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in)))
mas01mc@18 251 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 252 }
mas01cr@0 253 AND UPDATE BATCHINSERT()
mas01cr@105 254 */
mas01cr@105 255
mas01cr@105 256 if(args_info.timesList_given){
mas01cr@105 257 timesFileName=args_info.timesList_arg;
mas01cr@105 258 if(strlen(timesFileName)>0){
mas01cr@105 259 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@105 260 error("Could not open timesList file for reading", timesFileName);
mas01cr@105 261 usingTimes=1;
mas01cr@105 262 }
mas01cr@105 263 }
mas01cr@105 264 return 0;
mas01cr@105 265 }
mas01cr@105 266
mas01cr@105 267 // Query command and arguments
mas01cr@105 268 if(args_info.QUERY_given){
mas01cr@105 269 command=COM_QUERY;
mas01cr@105 270 dbName=args_info.database_arg;
mas01cr@105 271 inFile=args_info.features_arg;
mas01cr@105 272
mas01cr@105 273 if(args_info.keyList_given){
mas01cr@105 274 trackFileName=args_info.keyList_arg;
mas01cr@105 275 if(strlen(trackFileName)>0 && !(trackFile = new ifstream(trackFileName,ios::in)))
mas01cr@105 276 error("Could not open keyList file for reading",trackFileName);
mas01cr@105 277 }
mas01cr@105 278
mas01cr@105 279 if(args_info.times_given){
mas01cr@105 280 timesFileName=args_info.times_arg;
mas01cr@105 281 if(strlen(timesFileName)>0){
mas01cr@105 282 if(!(timesFile = new ifstream(timesFileName,ios::in)))
mas01cr@105 283 error("Could not open times file for reading", timesFileName);
mas01cr@105 284 usingTimes=1;
mas01cr@105 285 }
mas01cr@105 286 }
mas01cr@105 287
mas01cr@105 288 // query type
mas01cr@105 289 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01cr@105 290 queryType=O2_TRACK_QUERY;
mas01cr@105 291 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@105 292 queryType=O2_POINT_QUERY;
mas01cr@105 293 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@105 294 queryType=O2_SEQUENCE_QUERY;
mas01cr@105 295 else
mas01cr@105 296 error("unsupported query type",args_info.QUERY_arg);
mas01cr@105 297
mas01cr@105 298 if(!args_info.exhaustive_flag){
mas01cr@105 299 queryPoint = args_info.qpoint_arg;
mas01cr@105 300 usingQueryPoint=1;
mas01cr@105 301 if(queryPoint<0 || queryPoint >10000)
mas01cr@105 302 error("queryPoint out of range: 0 <= queryPoint <= 10000");
mas01cr@105 303 }
mas01cr@105 304
mas01cr@105 305 pointNN = args_info.pointnn_arg;
mas01cr@105 306 if(pointNN < 1 || pointNN > 1000) {
mas01cr@105 307 error("pointNN out of range: 1 <= pointNN <= 1000");
mas01cr@105 308 }
mas01cr@105 309 trackNN = args_info.resultlength_arg;
mas01cr@105 310 if(trackNN < 1 || trackNN > 1000) {
mas01cr@105 311 error("resultlength out of range: 1 <= resultlength <= 1000");
mas01cr@105 312 }
mas01cr@105 313 sequenceLength = args_info.sequencelength_arg;
mas01cr@105 314 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01cr@105 315 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@105 316 }
mas01cr@105 317 sequenceHop = args_info.sequencehop_arg;
mas01cr@105 318 if(sequenceHop < 1 || sequenceHop > 1000) {
mas01cr@105 319 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01cr@105 320 }
mas01cr@105 321 return 0;
mas01cr@105 322 }
mas01cr@105 323 return -1; // no command found
mas01cr@0 324 }
mas01cr@0 325
mas01cr@30 326 void audioDB::get_lock(int fd, bool exclusive) {
mas01cr@30 327 struct flock lock;
mas01cr@30 328 int status;
mas01cr@30 329
mas01cr@30 330 lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
mas01cr@30 331 lock.l_whence = SEEK_SET;
mas01cr@30 332 lock.l_start = 0;
mas01cr@30 333 lock.l_len = 0; /* "the whole file" */
mas01cr@30 334
mas01cr@30 335 retry:
mas01cr@30 336 do {
mas01cr@30 337 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@30 338 } while (status != 0 && errno == EINTR);
mas01cr@30 339
mas01cr@30 340 if (status) {
mas01cr@30 341 if (errno == EAGAIN) {
mas01cr@30 342 sleep(1);
mas01cr@30 343 goto retry;
mas01cr@30 344 } else {
mas01cr@32 345 error("fcntl lock error", "", "fcntl");
mas01cr@30 346 }
mas01cr@30 347 }
mas01cr@30 348 }
mas01cr@30 349
mas01cr@30 350 void audioDB::release_lock(int fd) {
mas01cr@30 351 struct flock lock;
mas01cr@30 352 int status;
mas01cr@30 353
mas01cr@30 354 lock.l_type = F_UNLCK;
mas01cr@30 355 lock.l_whence = SEEK_SET;
mas01cr@30 356 lock.l_start = 0;
mas01cr@30 357 lock.l_len = 0;
mas01cr@30 358
mas01cr@30 359 status = fcntl(fd, F_SETLKW, &lock);
mas01cr@30 360
mas01cr@30 361 if (status)
mas01cr@32 362 error("fcntl unlock error", "", "fcntl");
mas01cr@30 363 }
mas01cr@30 364
mas01cr@120 365 /* Make a new database.
mas01cr@120 366
mas01cr@120 367 The database consists of:
mas01cr@120 368
mas01cr@120 369 * a header (see dbTableHeader struct definition);
mas01cr@120 370 * keyTable: list of keys of tracks;
mas01cr@120 371 * trackTable: Maps implicit feature index to a feature vector
mas01cr@120 372 matrix (sizes of tracks)
mas01cr@120 373 * featureTable: Lots of doubles;
mas01cr@120 374 * timesTable: time points for each feature vector;
mas01cr@120 375 * l2normTable: squared l2norms for each feature vector.
mas01cr@120 376 */
mas01cr@0 377 void audioDB::create(const char* dbName){
mas01cr@31 378 if ((dbfid = open (dbName, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
mas01cr@32 379 error("Can't create database file", dbName, "open");
mas01cr@30 380 get_lock(dbfid, 1);
mas01cr@0 381
mas01cr@0 382 // go to the location corresponding to the last byte
mas01cr@129 383 if (lseek (dbfid, size - 1, SEEK_SET) == -1)
mas01cr@32 384 error("lseek error in db file", "", "lseek");
mas01cr@0 385
mas01cr@0 386 // write a dummy byte at the last location
mas01cr@0 387 if (write (dbfid, "", 1) != 1)
mas01cr@32 388 error("write error", "", "write");
mas01cr@0 389
mas01cr@0 390 // mmap the output file
mas01cr@60 391 if(verbosity) {
mas01cr@0 392 cerr << "header size:" << O2_HEADERSIZE << endl;
mas01cr@60 393 }
mas01cr@129 394 if ((db = (char*) mmap(0, size, PROT_READ | PROT_WRITE,
mas01cr@0 395 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@32 396 error("mmap error for creating database", "", "mmap");
mas01cr@0 397
mas01cr@0 398 dbH = new dbTableHeaderT();
mas01cr@0 399 assert(dbH);
mas01cr@0 400
mas01cr@0 401 // Initialize header
mas01cr@108 402 dbH->magic = O2_MAGIC;
mas01cr@108 403 dbH->version = O2_FORMAT_VERSION;
mas01cr@108 404 dbH->numFiles = 0;
mas01cr@108 405 dbH->dim = 0;
mas01cr@108 406 dbH->flags = 0;
mas01cr@108 407 dbH->length = 0;
mas01cr@108 408 dbH->fileTableOffset = ALIGN_UP(O2_HEADERSIZE, 8);
mas01cr@108 409 dbH->trackTableOffset = ALIGN_UP(dbH->fileTableOffset + O2_FILETABLESIZE*O2_MAXFILES, 8);
mas01cr@108 410 dbH->dataOffset = ALIGN_UP(dbH->trackTableOffset + O2_TRACKTABLESIZE*O2_MAXFILES, 8);
mas01cr@129 411 dbH->l2normTableOffset = ALIGN_DOWN(size - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double), 8);
mas01cr@108 412 dbH->timesTableOffset = ALIGN_DOWN(dbH->l2normTableOffset - O2_MAXFILES*O2_MEANNUMVECTORS*sizeof(double), 8);
mas01cr@129 413 dbH->dbSize = size;
mas01cr@0 414
mas01cr@0 415 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@60 416 if(verbosity) {
mas01cr@0 417 cerr << COM_CREATE << " " << dbName << endl;
mas01cr@60 418 }
mas01cr@0 419 }
mas01cr@0 420
mas01cr@0 421
mas01cr@0 422 void audioDB::drop(){
mas01cr@108 423 // FIXME: drop something? Should we even allow this?
mas01cr@0 424 }
mas01cr@0 425
mas01cr@120 426 void audioDB::initDBHeader(const char* dbName, bool forWrite) {
mas01cr@106 427 if ((dbfid = open(dbName, forWrite ? O_RDWR : O_RDONLY)) < 0) {
mas01cr@32 428 error("Can't open database file", dbName, "open");
mas01cr@106 429 }
mas01cr@120 430
mas01cr@30 431 get_lock(dbfid, forWrite);
mas01cr@0 432 // Get the database header info
mas01cr@0 433 dbH = new dbTableHeaderT();
mas01cr@0 434 assert(dbH);
mas01cr@0 435
mas01cr@106 436 if(read(dbfid, (char *) dbH, O2_HEADERSIZE) != O2_HEADERSIZE) {
mas01cr@106 437 error("error reading db header", dbName, "read");
mas01cr@106 438 }
mas01cr@0 439
mas01cr@108 440 if(dbH->magic == O2_OLD_MAGIC) {
mas01cr@108 441 // FIXME: if anyone ever complains, write the program to convert
mas01cr@108 442 // from the old audioDB format to the new...
mas01cr@108 443 error("database file has old O2 header", dbName);
mas01cr@108 444 }
mas01cr@0 445
mas01cr@106 446 if(dbH->magic != O2_MAGIC) {
mas01cr@106 447 cerr << "expected: " << O2_MAGIC << ", got: " << dbH->magic << endl;
mas01cr@108 448 error("database file has incorrect header", dbName);
mas01cr@108 449 }
mas01cr@108 450
mas01cr@108 451 if(dbH->version != O2_FORMAT_VERSION) {
mas01cr@108 452 error("database file has incorect version", dbName);
mas01cr@0 453 }
mas01cr@0 454
mas01cr@128 455 // FIXME: when changing file format version, remove this workaround.
mas01cr@128 456 if(dbH->dbSize == 0) {
mas01cr@128 457 dbH->dbSize = O2_DEFAULTDBSIZE;
mas01cr@128 458 }
mas01cr@128 459
mas01cr@120 460 // mmap the database file
mas01cr@128 461 if ((db = (char*) mmap(0, dbH->dbSize, PROT_READ | (forWrite ? PROT_WRITE : 0),
mas01cr@120 462 MAP_SHARED, dbfid, 0)) == (caddr_t) -1)
mas01cr@120 463 error("mmap error for initting tables of database", "", "mmap");
mas01cr@120 464
mas01cr@120 465 // Make some handy tables with correct types
mas01cr@120 466 fileTable = (char *) (db + dbH->fileTableOffset);
mas01cr@120 467 trackTable = (unsigned *) (db + dbH->trackTableOffset);
mas01cr@120 468 dataBuf = (double *) (db + dbH->dataOffset);
mas01cr@120 469 l2normTable = (double *) (db + dbH->l2normTableOffset);
mas01cr@120 470 timesTable = (double *) (db + dbH->timesTableOffset);
mas01cr@120 471 }
mas01cr@120 472
mas01cr@120 473 void audioDB::initTables(const char* dbName, bool forWrite, const char* inFile = 0) {
mas01cr@120 474
mas01cr@120 475 initDBHeader(dbName, forWrite);
mas01cr@120 476
mas01cr@120 477 // open the input file
mas01cr@120 478 if (inFile && (infid = open(inFile, O_RDONLY)) < 0) {
mas01cr@120 479 error("can't open input file for reading", inFile, "open");
mas01cr@120 480 }
mas01cr@120 481 // find size of input file
mas01cr@120 482 if (inFile && fstat(infid, &statbuf) < 0) {
mas01cr@120 483 error("fstat error finding size of input", inFile, "fstat");
mas01cr@120 484 }
mas01cr@0 485 if(inFile)
mas01cr@106 486 if(dbH->dim == 0 && dbH->length == 0) // empty database
mas01cr@106 487 // initialize with input dimensionality
mas01cr@106 488 read(infid, &dbH->dim, sizeof(unsigned));
mas01cr@0 489 else {
mas01cr@0 490 unsigned test;
mas01cr@106 491 read(infid, &test, sizeof(unsigned));
mas01cr@106 492 if(dbH->dim != test) {
mas01cr@106 493 cerr << "error: expected dimension: " << dbH->dim << ", got : " << test <<endl;
mas01cr@0 494 error("feature dimensions do not match database table dimensions");
mas01cr@0 495 }
mas01cr@0 496 }
mas01cr@0 497
mas01cr@0 498 // mmap the input file
mas01cr@0 499 if (inFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
mas01cr@0 500 == (caddr_t) -1)
mas01cr@106 501 error("mmap error for input", inFile, "mmap");
mas01cr@0 502 }
mas01cr@0 503
mas01cr@0 504 void audioDB::insert(const char* dbName, const char* inFile){
mas01cr@0 505
mas01cr@27 506 initTables(dbName, 1, inFile);
mas01cr@0 507
mas01cr@0 508 if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 509 error("Must use timestamps with timestamped database","use --times");
mas01cr@0 510
mas01cr@0 511 // Check that there is room for at least 1 more file
mas01cr@0 512 if((char*)timesTable<((char*)dataBuf+dbH->length+statbuf.st_size-sizeof(int)))
mas01cr@0 513 error("No more room in database","insert failed: reason database is full.");
mas01cr@0 514
mas01cr@0 515 if(!key)
mas01cr@0 516 key=inFile;
mas01cr@0 517 // Linear scan of filenames check for pre-existing feature
mas01cr@0 518 unsigned alreadyInserted=0;
mas01cr@0 519 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 520 if(strncmp(fileTable + k*O2_FILETABLESIZE, key, strlen(key))==0){
mas01cr@0 521 alreadyInserted=1;
mas01cr@0 522 break;
mas01cr@0 523 }
mas01cr@0 524
mas01cr@0 525 if(alreadyInserted){
mas01cr@60 526 if(verbosity) {
mas01cr@0 527 cerr << "Warning: key already exists in database, ignoring: " <<inFile << endl;
mas01cr@60 528 }
mas01cr@0 529 return;
mas01cr@0 530 }
mas01cr@0 531
mas01mc@18 532 // Make a track index table of features to file indexes
mas01cr@0 533 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 534 if(!numVectors){
mas01cr@60 535 if(verbosity) {
mas01cr@0 536 cerr << "Warning: ignoring zero-length feature vector file:" << key << endl;
mas01cr@60 537 }
mas01cr@0 538 // CLEAN UP
mas01cr@0 539 munmap(indata,statbuf.st_size);
mas01cr@128 540 munmap(db,dbH->dbSize);
mas01cr@0 541 close(infid);
mas01cr@0 542 return;
mas01cr@0 543 }
mas01cr@0 544
mas01cr@0 545 strncpy(fileTable + dbH->numFiles*O2_FILETABLESIZE, key, strlen(key));
mas01cr@0 546
mas01cr@0 547 unsigned insertoffset = dbH->length;// Store current state
mas01cr@0 548
mas01cr@0 549 // Check times status and insert times from file
mas01cr@0 550 unsigned timesoffset=insertoffset/(dbH->dim*sizeof(double));
mas01cr@0 551 double* timesdata=timesTable+timesoffset;
mas01cr@0 552 assert(timesdata+numVectors<l2normTable);
mas01cr@0 553 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 554
mas01cr@0 555 // Increment file count
mas01cr@0 556 dbH->numFiles++;
mas01cr@0 557
mas01cr@0 558 // Update Header information
mas01cr@0 559 dbH->length+=(statbuf.st_size-sizeof(int));
mas01cr@0 560
mas01cr@0 561 // Copy the header back to the database
mas01cr@0 562 memcpy (db, dbH, sizeof(dbTableHeaderT));
mas01cr@0 563
mas01mc@18 564 // Update track to file index map
mas01mc@18 565 //memcpy (db+trackTableOffset+(dbH->numFiles-1)*sizeof(unsigned), &numVectors, sizeof(unsigned));
mas01mc@18 566 memcpy (trackTable+dbH->numFiles-1, &numVectors, sizeof(unsigned));
mas01cr@0 567
mas01cr@0 568 // Update the feature database
mas01cr@108 569 memcpy (db+dbH->dataOffset+insertoffset, indata+sizeof(int), statbuf.st_size-sizeof(int));
mas01cr@0 570
mas01cr@0 571 // Norm the vectors on input if the database is already L2 normed
mas01cr@0 572 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@108 573 unitNormAndInsertL2((double*)(db+dbH->dataOffset+insertoffset), dbH->dim, numVectors, 1); // append
mas01cr@0 574
mas01cr@0 575 // Report status
mas01cr@0 576 status(dbName);
mas01cr@60 577 if(verbosity) {
mas01cr@0 578 cerr << COM_INSERT << " " << dbName << " " << numVectors << " vectors "
mas01cr@0 579 << (statbuf.st_size-sizeof(int)) << " bytes." << endl;
mas01cr@60 580 }
mas01cr@0 581
mas01cr@0 582 // CLEAN UP
mas01cr@0 583 munmap(indata,statbuf.st_size);
mas01cr@0 584 close(infid);
mas01cr@0 585 }
mas01cr@0 586
mas01cr@0 587 void audioDB::insertTimeStamps(unsigned numVectors, ifstream* timesFile, double* timesdata){
mas01cr@0 588 unsigned numtimes=0;
mas01cr@0 589 if(usingTimes){
mas01cr@0 590 if(!(dbH->flags & O2_FLAG_TIMES) && !dbH->numFiles)
mas01cr@0 591 dbH->flags=dbH->flags|O2_FLAG_TIMES;
mas01cr@0 592 else if(!(dbH->flags&O2_FLAG_TIMES)){
mas01cr@0 593 cerr << "Warning: timestamp file used with non time-stamped database: ignoring timestamps" << endl;
mas01cr@0 594 usingTimes=0;
mas01cr@0 595 }
mas01cr@0 596
mas01cr@0 597 if(!timesFile->is_open()){
mas01cr@0 598 if(dbH->flags & O2_FLAG_TIMES){
mas01cr@0 599 munmap(indata,statbuf.st_size);
mas01cr@128 600 munmap(db,dbH->dbSize);
mas01cr@0 601 error("problem opening times file on timestamped database",timesFileName);
mas01cr@0 602 }
mas01cr@0 603 else{
mas01cr@0 604 cerr << "Warning: problem opening times file. But non-timestamped database, so ignoring times file." << endl;
mas01cr@0 605 usingTimes=0;
mas01cr@0 606 }
mas01cr@0 607 }
mas01cr@0 608
mas01cr@0 609 // Process time file
mas01cr@0 610 if(usingTimes){
mas01cr@0 611 do{
mas01cr@0 612 *timesFile>>*timesdata++;
mas01cr@0 613 if(timesFile->eof())
mas01cr@0 614 break;
mas01cr@0 615 numtimes++;
mas01cr@0 616 }while(!timesFile->eof() && numtimes<numVectors);
mas01cr@0 617 if(!timesFile->eof()){
mas01cr@0 618 double dummy;
mas01cr@0 619 do{
mas01cr@0 620 *timesFile>>dummy;
mas01cr@0 621 if(timesFile->eof())
mas01cr@0 622 break;
mas01cr@0 623 numtimes++;
mas01cr@0 624 }while(!timesFile->eof());
mas01cr@0 625 }
mas01cr@0 626 if(numtimes<numVectors || numtimes>numVectors+2){
mas01cr@0 627 munmap(indata,statbuf.st_size);
mas01cr@128 628 munmap(db,dbH->dbSize);
mas01cr@0 629 close(infid);
mas01cr@0 630 cerr << "expected " << numVectors << " found " << numtimes << endl;
mas01cr@0 631 error("Times file is incorrect length for features file",inFile);
mas01cr@0 632 }
mas01cr@60 633 if(verbosity>2) {
mas01cr@0 634 cerr << "numtimes: " << numtimes << endl;
mas01cr@60 635 }
mas01cr@0 636 }
mas01cr@0 637 }
mas01cr@0 638 }
mas01cr@0 639
mas01cr@120 640 void audioDB::batchinsert(const char* dbName, const char* inFile) {
mas01cr@0 641
mas01cr@120 642 initDBHeader(dbName, true);
mas01cr@0 643
mas01cr@0 644 if(!key)
mas01cr@0 645 key=inFile;
mas01cr@0 646 ifstream *filesIn = 0;
mas01cr@0 647 ifstream *keysIn = 0;
mas01cr@0 648 ifstream* thisTimesFile = 0;
mas01cr@0 649
mas01cr@0 650 if(!(filesIn = new ifstream(inFile)))
mas01cr@0 651 error("Could not open batch in file", inFile);
mas01cr@0 652 if(key && key!=inFile)
mas01cr@0 653 if(!(keysIn = new ifstream(key)))
mas01cr@0 654 error("Could not open batch key file",key);
mas01cr@0 655
mas01cr@0 656 if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 657 error("Must use timestamps with timestamped database","use --times");
mas01cr@0 658
mas01cr@0 659 unsigned totalVectors=0;
mas01cr@0 660 char *thisKey = new char[MAXSTR];
mas01cr@0 661 char *thisFile = new char[MAXSTR];
mas01cr@0 662 char *thisTimesFileName = new char[MAXSTR];
mas01cr@120 663
mas01cr@0 664 do{
mas01cr@0 665 filesIn->getline(thisFile,MAXSTR);
mas01cr@0 666 if(key && key!=inFile)
mas01cr@0 667 keysIn->getline(thisKey,MAXSTR);
mas01cr@0 668 else
mas01cr@0 669 thisKey = thisFile;
mas01cr@0 670 if(usingTimes)
mas01cr@0 671 timesFile->getline(thisTimesFileName,MAXSTR);
mas01cr@0 672
mas01cr@0 673 if(filesIn->eof())
mas01cr@0 674 break;
mas01cr@0 675
mas01cr@0 676 // open the input file
mas01cr@0 677 if (thisFile && (infid = open (thisFile, O_RDONLY)) < 0)
mas01cr@32 678 error("can't open feature file for reading", thisFile, "open");
mas01cr@0 679
mas01cr@0 680 // find size of input file
mas01cr@0 681 if (thisFile && fstat (infid,&statbuf) < 0)
mas01cr@32 682 error("fstat error finding size of input", "", "fstat");
mas01cr@0 683
mas01cr@0 684 // Check that there is room for at least 1 more file
mas01cr@0 685 if((char*)timesTable<((char*)dataBuf+(dbH->length+statbuf.st_size-sizeof(int))))
mas01cr@0 686 error("No more room in database","insert failed: reason database is full.");
mas01cr@0 687
mas01cr@0 688 if(thisFile)
mas01cr@0 689 if(dbH->dim==0 && dbH->length==0) // empty database
mas01cr@0 690 read(infid,&dbH->dim,sizeof(unsigned)); // initialize with input dimensionality
mas01cr@0 691 else {
mas01cr@0 692 unsigned test;
mas01cr@0 693 read(infid,&test,sizeof(unsigned));
mas01cr@0 694 if(dbH->dim!=test){
mas01cr@0 695 cerr << "error: expected dimension: " << dbH->dim << ", got :" << test <<endl;
mas01cr@0 696 error("feature dimensions do not match database table dimensions");
mas01cr@0 697 }
mas01cr@0 698 }
mas01cr@0 699
mas01cr@0 700 // mmap the input file
mas01cr@0 701 if (thisFile && (indata = (char*)mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, infid, 0))
mas01cr@0 702 == (caddr_t) -1)
mas01cr@32 703 error("mmap error for input", "", "mmap");
mas01cr@0 704
mas01cr@0 705
mas01cr@0 706 // Linear scan of filenames check for pre-existing feature
mas01cr@0 707 unsigned alreadyInserted=0;
mas01cr@0 708
mas01cr@0 709 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 710 if(strncmp(fileTable + k*O2_FILETABLESIZE, thisKey, strlen(thisKey))==0){
mas01cr@0 711 alreadyInserted=1;
mas01cr@0 712 break;
mas01cr@0 713 }
mas01cr@0 714
mas01cr@0 715 if(alreadyInserted){
mas01cr@60 716 if(verbosity) {
mas01cr@0 717 cerr << "Warning: key already exists in database:" << thisKey << endl;
mas01cr@60 718 }
mas01cr@0 719 }
mas01cr@0 720 else{
mas01cr@0 721
mas01mc@18 722 // Make a track index table of features to file indexes
mas01cr@0 723 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 724 if(!numVectors){
mas01cr@60 725 if(verbosity) {
mas01cr@0 726 cerr << "Warning: ignoring zero-length feature vector file:" << thisKey << endl;
mas01cr@60 727 }
mas01cr@0 728 }
mas01cr@0 729 else{
mas01cr@0 730 if(usingTimes){
mas01cr@0 731 if(timesFile->eof())
mas01cr@0 732 error("not enough timestamp files in timesList");
mas01cr@0 733 thisTimesFile=new ifstream(thisTimesFileName,ios::in);
mas01cr@0 734 if(!thisTimesFile->is_open())
mas01cr@0 735 error("Cannot open timestamp file",thisTimesFileName);
mas01cr@0 736 unsigned insertoffset=dbH->length;
mas01cr@0 737 unsigned timesoffset=insertoffset/(dbH->dim*sizeof(double));
mas01cr@0 738 double* timesdata=timesTable+timesoffset;
mas01cr@0 739 assert(timesdata+numVectors<l2normTable);
mas01cr@0 740 insertTimeStamps(numVectors,thisTimesFile,timesdata);
mas01cr@0 741 if(thisTimesFile)
mas01cr@0 742 delete thisTimesFile;
mas01cr@0 743 }
mas01cr@0 744
mas01cr@0 745 strncpy(fileTable + dbH->numFiles*O2_FILETABLESIZE, thisKey, strlen(thisKey));
mas01cr@0 746
mas01cr@0 747 unsigned insertoffset = dbH->length;// Store current state
mas01cr@0 748
mas01cr@0 749 // Increment file count
mas01cr@0 750 dbH->numFiles++;
mas01cr@0 751
mas01cr@0 752 // Update Header information
mas01cr@0 753 dbH->length+=(statbuf.st_size-sizeof(int));
mas01cr@0 754 // Copy the header back to the database
mas01cr@0 755 memcpy (db, dbH, sizeof(dbTableHeaderT));
mas01cr@0 756
mas01mc@18 757 // Update track to file index map
mas01mc@18 758 //memcpy (db+trackTableOffset+(dbH->numFiles-1)*sizeof(unsigned), &numVectors, sizeof(unsigned));
mas01mc@18 759 memcpy (trackTable+dbH->numFiles-1, &numVectors, sizeof(unsigned));
mas01cr@0 760
mas01cr@0 761 // Update the feature database
mas01cr@108 762 memcpy (db+dbH->dataOffset+insertoffset, indata+sizeof(int), statbuf.st_size-sizeof(int));
mas01cr@0 763
mas01cr@0 764 // Norm the vectors on input if the database is already L2 normed
mas01cr@0 765 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@108 766 unitNormAndInsertL2((double*)(db+dbH->dataOffset+insertoffset), dbH->dim, numVectors, 1); // append
mas01cr@0 767
mas01cr@0 768 totalVectors+=numVectors;
mas01cr@0 769 }
mas01cr@0 770 }
mas01cr@0 771 // CLEAN UP
mas01cr@0 772 munmap(indata,statbuf.st_size);
mas01cr@0 773 close(infid);
mas01cr@0 774 }while(!filesIn->eof());
mas01mc@12 775
mas01cr@60 776 if(verbosity) {
mas01cr@0 777 cerr << COM_BATCHINSERT << " " << dbName << " " << totalVectors << " vectors "
mas01cr@0 778 << totalVectors*dbH->dim*sizeof(double) << " bytes." << endl;
mas01cr@60 779 }
mas01cr@0 780
mas01cr@0 781 // Report status
mas01cr@0 782 status(dbName);
mas01cr@0 783 }
mas01cr@0 784
mas01cr@76 785 // FIXME: this can't propagate the sequence length argument (used for
mas01cr@76 786 // dudCount). See adb__status() definition for the other half of
mas01cr@76 787 // this. -- CSR, 2007-10-01
mas01cr@0 788 void audioDB::ws_status(const char*dbName, char* hostport){
mas01cr@0 789 struct soap soap;
mas01cr@133 790 adb__statusResponse adbStatusResponse;
mas01cr@0 791
mas01cr@0 792 // Query an existing adb database
mas01cr@0 793 soap_init(&soap);
mas01cr@133 794 if(soap_call_adb__status(&soap,hostport,NULL,(char*)dbName,adbStatusResponse)==SOAP_OK) {
mas01cr@133 795 cout << "numFiles = " << adbStatusResponse.result.numFiles << endl;
mas01cr@133 796 cout << "dim = " << adbStatusResponse.result.dim << endl;
mas01cr@133 797 cout << "length = " << adbStatusResponse.result.length << endl;
mas01cr@133 798 cout << "dudCount = " << adbStatusResponse.result.dudCount << endl;
mas01cr@133 799 cout << "nullCount = " << adbStatusResponse.result.nullCount << endl;
mas01cr@133 800 cout << "flags = " << adbStatusResponse.result.flags << endl;
mas01cr@76 801 } else {
mas01cr@0 802 soap_print_fault(&soap,stderr);
mas01cr@76 803 }
mas01cr@0 804
mas01cr@0 805 soap_destroy(&soap);
mas01cr@0 806 soap_end(&soap);
mas01cr@0 807 soap_done(&soap);
mas01cr@0 808 }
mas01cr@0 809
mas01mc@18 810 void audioDB::ws_query(const char*dbName, const char *trackKey, const char* hostport){
mas01cr@0 811 struct soap soap;
mas01cr@133 812 adb__queryResponse adbQueryResponse;
mas01cr@0 813
mas01cr@0 814 soap_init(&soap);
mas01cr@0 815 if(soap_call_adb__query(&soap,hostport,NULL,
mas01mc@18 816 (char*)dbName,(char*)trackKey,(char*)trackFileName,(char*)timesFileName,
mas01cr@133 817 queryType, queryPoint, pointNN, trackNN, sequenceLength, adbQueryResponse)==SOAP_OK){
mas01cr@133 818 //std::cerr << "result list length:" << adbQueryResponse.result.__sizeRlist << std::endl;
mas01cr@133 819 for(int i=0; i<adbQueryResponse.result.__sizeRlist; i++)
mas01cr@133 820 std::cout << adbQueryResponse.result.Rlist[i] << " " << adbQueryResponse.result.Dist[i]
mas01cr@133 821 << " " << adbQueryResponse.result.Qpos[i] << " " << adbQueryResponse.result.Spos[i] << std::endl;
mas01cr@0 822 }
mas01cr@0 823 else
mas01cr@0 824 soap_print_fault(&soap,stderr);
mas01cr@0 825
mas01cr@0 826 soap_destroy(&soap);
mas01cr@0 827 soap_end(&soap);
mas01cr@0 828 soap_done(&soap);
mas01cr@0 829
mas01cr@0 830 }
mas01cr@0 831
mas01cr@0 832
mas01cr@133 833 void audioDB::status(const char* dbName, adb__statusResponse *adbStatusResponse){
mas01cr@0 834 if(!dbH)
mas01cr@27 835 initTables(dbName, 0, 0);
mas01cr@0 836
mas01cr@0 837 unsigned dudCount=0;
mas01cr@0 838 unsigned nullCount=0;
mas01cr@0 839 for(unsigned k=0; k<dbH->numFiles; k++){
mas01mc@18 840 if(trackTable[k]<sequenceLength){
mas01cr@0 841 dudCount++;
mas01mc@18 842 if(!trackTable[k])
mas01cr@76 843 nullCount++;
mas01cr@0 844 }
mas01cr@0 845 }
mas01cr@76 846
mas01cr@133 847 if(adbStatusResponse == 0) {
mas01cr@76 848
mas01cr@76 849 // Update Header information
mas01cr@76 850 cout << "num files:" << dbH->numFiles << endl;
mas01cr@76 851 cout << "data dim:" << dbH->dim <<endl;
mas01cr@76 852 if(dbH->dim>0){
mas01cr@76 853 cout << "total vectors:" << dbH->length/(sizeof(double)*dbH->dim)<<endl;
mas01cr@108 854 cout << "vectors available:" << (dbH->timesTableOffset-(dbH->dataOffset+dbH->length))/(sizeof(double)*dbH->dim) << endl;
mas01cr@76 855 }
mas01cr@108 856 cout << "total bytes:" << dbH->length << " (" << (100.0*dbH->length)/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << endl;
mas01cr@108 857 cout << "bytes available:" << dbH->timesTableOffset-(dbH->dataOffset+dbH->length) << " (" <<
mas01cr@108 858 (100.0*(dbH->timesTableOffset-(dbH->dataOffset+dbH->length)))/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << endl;
mas01cr@76 859 cout << "flags:" << dbH->flags << endl;
mas01cr@76 860
mas01cr@76 861 cout << "null count: " << nullCount << " small sequence count " << dudCount-nullCount << endl;
mas01cr@76 862 } else {
mas01cr@133 863 adbStatusResponse->result.numFiles = dbH->numFiles;
mas01cr@133 864 adbStatusResponse->result.dim = dbH->dim;
mas01cr@133 865 adbStatusResponse->result.length = dbH->length;
mas01cr@133 866 adbStatusResponse->result.dudCount = dudCount;
mas01cr@133 867 adbStatusResponse->result.nullCount = nullCount;
mas01cr@133 868 adbStatusResponse->result.flags = dbH->flags;
mas01cr@76 869 }
mas01cr@0 870 }
mas01cr@0 871
mas01cr@0 872 void audioDB::dump(const char* dbName){
mas01cr@131 873 if(!dbH) {
mas01cr@27 874 initTables(dbName, 0, 0);
mas01mc@17 875 }
mas01cr@0 876
mas01cr@131 877 if((mkdir(output, S_IRWXU|S_IRWXG|S_IRWXO)) < 0) {
mas01cr@131 878 error("error making output directory", output, "mkdir");
mas01cr@131 879 }
mas01cr@131 880
mas01cr@131 881 char *cwd = new char[PATH_MAX];
mas01cr@131 882
mas01cr@131 883 if ((getcwd(cwd, PATH_MAX)) == 0) {
mas01cr@131 884 error("error getting working directory", "", "getcwd");
mas01cr@131 885 }
mas01cr@131 886
mas01cr@131 887 if((chdir(output)) < 0) {
mas01cr@131 888 error("error changing working directory", output, "chdir");
mas01cr@131 889 }
mas01cr@131 890
mas01cr@131 891 int fLfd, tLfd = 0, kLfd;
mas01cr@131 892 FILE *fLFile, *tLFile = 0, *kLFile;
mas01cr@131 893
mas01cr@131 894 if ((fLfd = open("featureList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) {
mas01cr@131 895 error("error creating featureList file", "featureList.txt", "open");
mas01cr@131 896 }
mas01cr@131 897 int times = dbH->flags & O2_FLAG_TIMES;
mas01cr@131 898 if (times) {
mas01cr@131 899 if ((tLfd = open("timesList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) {
mas01cr@131 900 error("error creating timesList file", "timesList.txt", "open");
mas01cr@131 901 }
mas01cr@131 902 }
mas01cr@131 903 if ((kLfd = open("keyList.txt", O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) {
mas01cr@131 904 error("error creating keyList file", "keyList.txt", "open");
mas01cr@131 905 }
mas01cr@131 906
mas01cr@131 907 /* can these fail? I sincerely hope not. */
mas01cr@131 908 fLFile = fdopen(fLfd, "w");
mas01cr@131 909 if (times) {
mas01cr@131 910 tLFile = fdopen(tLfd, "w");
mas01cr@131 911 }
mas01cr@131 912 kLFile = fdopen(kLfd, "w");
mas01cr@131 913
mas01cr@131 914 char *fName = new char[256];
mas01cr@131 915 int ffd;
mas01cr@131 916 FILE *tFile;
mas01cr@131 917 unsigned pos = 0;
mas01cr@131 918 for(unsigned k = 0; k < dbH->numFiles; k++) {
mas01cr@131 919 fprintf(kLFile, "%s\n", fileTable + k*O2_FILETABLESIZE);
mas01cr@131 920 snprintf(fName, 256, "%05d.features", k);
mas01cr@131 921 if ((ffd = open(fName, O_CREAT|O_RDWR|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) {
mas01cr@131 922 error("error creating feature file", fName, "open");
mas01cr@131 923 }
mas01cr@131 924 if ((write(ffd, &dbH->dim, sizeof(uint32_t))) < 0) {
mas01cr@131 925 error("error writing dimensions", fName, "write");
mas01cr@131 926 }
mas01cr@131 927
mas01cr@131 928 if ((write(ffd, dataBuf + pos * dbH->dim, trackTable[k] * dbH->dim * sizeof(double))) < 0) {
mas01cr@131 929 error("error writing data", fName, "write");
mas01cr@131 930 }
mas01cr@131 931 fprintf(fLFile, "%s\n", fName);
mas01cr@131 932 close(ffd);
mas01cr@131 933
mas01cr@131 934 if(times) {
mas01cr@131 935 snprintf(fName, 256, "%05d.times", k);
mas01cr@131 936 tFile = fopen(fName, "w");
mas01cr@131 937 for(unsigned i = 0; i < trackTable[k]; i++) {
mas01cr@131 938 // KLUDGE: specifying 16 digits of precision after the decimal
mas01cr@131 939 // point is (but check this!) sufficient to uniquely identify
mas01cr@131 940 // doubles; however, that will cause ugliness, as that's
mas01cr@131 941 // vastly too many for most values of interest. Moving to %a
mas01cr@131 942 // here and scanf() in the timesFile reading might fix this.
mas01cr@131 943 // -- CSR, 2007-10-19
mas01cr@131 944 fprintf(tFile, "%.16e\n", *(timesTable + pos + i));
mas01cr@131 945 }
mas01cr@131 946 fprintf(tLFile, "%s\n", fName);
mas01cr@131 947 }
mas01cr@131 948
mas01cr@131 949 pos += trackTable[k];
mas01cr@131 950 cout << fileTable+k*O2_FILETABLESIZE << " " << trackTable[k] << endl;
mas01cr@131 951 }
mas01cr@131 952
mas01cr@131 953 FILE *scriptFile;
mas01cr@131 954 scriptFile = fopen("restore.sh", "w");
mas01cr@131 955 fprintf(scriptFile, "\
mas01cr@131 956 #! /bin/sh\n\
mas01cr@131 957 #\n\
mas01cr@131 958 # usage: AUDIODB=/path/to/audioDB sh ./restore.sh <newdb>\n\
mas01cr@131 959 \n\
mas01cr@131 960 if [ -z \"${AUDIODB}\" ]; then echo set AUDIODB variable; exit 1; fi\n\
mas01cr@131 961 if [ -z \"$1\" ]; then echo usage: $0 newdb; exit 1; fi\n\n\
mas01cr@131 962 \"${AUDIODB}\" -d \"$1\" -N --size=%d\n", dbH->dbSize / 1000000);
mas01cr@131 963 if(dbH->flags & O2_FLAG_L2NORM) {
mas01cr@131 964 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -L\n");
mas01cr@131 965 }
mas01cr@131 966 fprintf(scriptFile, "\"${AUDIODB}\" -d \"$1\" -B -F featureList.txt -K keyList.txt");
mas01cr@131 967 if(times) {
mas01cr@131 968 fprintf(scriptFile, " -T timesList.txt");
mas01cr@131 969 }
mas01cr@131 970 fprintf(scriptFile, "\n");
mas01cr@131 971 fclose(scriptFile);
mas01cr@131 972
mas01cr@131 973 if((chdir(cwd)) < 0) {
mas01cr@131 974 error("error changing working directory", cwd, "chdir");
mas01cr@131 975 }
mas01cr@131 976
mas01cr@131 977 fclose(fLFile);
mas01cr@131 978 if(times) {
mas01cr@131 979 fclose(tLFile);
mas01cr@131 980 }
mas01cr@131 981 fclose(kLFile);
mas01cr@131 982 delete[] fName;
mas01cr@131 983
mas01cr@0 984 status(dbName);
mas01cr@0 985 }
mas01cr@0 986
mas01cr@0 987 void audioDB::l2norm(const char* dbName){
mas01cr@50 988 initTables(dbName, true, 0);
mas01cr@0 989 if(dbH->length>0){
mas01cr@0 990 unsigned numVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01cr@0 991 unitNormAndInsertL2(dataBuf, dbH->dim, numVectors, 0); // No append
mas01cr@0 992 }
mas01cr@0 993 // Update database flags
mas01cr@0 994 dbH->flags = dbH->flags|O2_FLAG_L2NORM;
mas01cr@0 995 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@0 996 }
mas01cr@0 997
mas01cr@0 998
mas01cr@0 999
mas01cr@133 1000 void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){
mas01cr@0 1001 switch(queryType){
mas01cr@105 1002 case O2_POINT_QUERY:
mas01cr@133 1003 pointQuery(dbName, inFile, adbQueryResponse);
mas01cr@0 1004 break;
mas01cr@105 1005 case O2_SEQUENCE_QUERY:
mas01mc@17 1006 if(radius==0)
mas01cr@133 1007 trackSequenceQueryNN(dbName, inFile, adbQueryResponse);
mas01mc@17 1008 else
mas01cr@133 1009 trackSequenceQueryRad(dbName, inFile, adbQueryResponse);
mas01cr@0 1010 break;
mas01cr@105 1011 case O2_TRACK_QUERY:
mas01cr@133 1012 trackPointQuery(dbName, inFile, adbQueryResponse);
mas01cr@0 1013 break;
mas01cr@0 1014 default:
mas01cr@0 1015 error("unrecognized queryType in query()");
mas01cr@0 1016
mas01cr@0 1017 }
mas01cr@0 1018 }
mas01cr@0 1019
mas01cr@0 1020 //return ordinal position of key in keyTable
mas01cr@0 1021 unsigned audioDB::getKeyPos(char* key){
mas01cr@0 1022 for(unsigned k=0; k<dbH->numFiles; k++)
mas01cr@0 1023 if(strncmp(fileTable + k*O2_FILETABLESIZE, key, strlen(key))==0)
mas01cr@0 1024 return k;
mas01cr@0 1025 error("Key not found",key);
mas01cr@0 1026 return O2_ERR_KEYNOTFOUND;
mas01cr@0 1027 }
mas01cr@0 1028
mas01cr@0 1029 // Basic point query engine
mas01cr@133 1030 void audioDB::pointQuery(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){
mas01cr@0 1031
mas01cr@27 1032 initTables(dbName, 0, inFile);
mas01cr@0 1033
mas01cr@0 1034 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1035 // we use stdout in this stub version
mas01cr@0 1036 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1037
mas01cr@0 1038 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1039 double* data = dataBuf;
mas01cr@0 1040 double* queryCopy = 0;
mas01cr@0 1041
mas01cr@0 1042 if( dbH->flags & O2_FLAG_L2NORM ){
mas01cr@0 1043 // Make a copy of the query
mas01cr@0 1044 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1045 qNorm = new double[numVectors];
mas01cr@0 1046 assert(queryCopy&&qNorm);
mas01cr@0 1047 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1048 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1049 query = queryCopy;
mas01cr@0 1050 }
mas01cr@0 1051
mas01cr@0 1052 // Make temporary dynamic memory for results
mas01cr@0 1053 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01cr@0 1054 double distances[pointNN];
mas01cr@0 1055 unsigned qIndexes[pointNN];
mas01cr@0 1056 unsigned sIndexes[pointNN];
mas01cr@0 1057 for(unsigned k=0; k<pointNN; k++){
mas01cr@62 1058 distances[k]=-DBL_MAX;
mas01cr@0 1059 qIndexes[k]=~0;
mas01cr@0 1060 sIndexes[k]=~0;
mas01cr@0 1061 }
mas01cr@0 1062
mas01cr@0 1063 unsigned j=numVectors;
mas01cr@0 1064 unsigned k,l,n;
mas01cr@0 1065 double thisDist;
mas01cr@0 1066
mas01cr@0 1067 unsigned totalVecs=dbH->length/(dbH->dim*sizeof(double));
mas01cr@0 1068 double meanQdur = 0;
mas01cr@0 1069 double* timesdata = 0;
mas01cr@0 1070 double* dbdurs = 0;
mas01cr@0 1071
mas01cr@0 1072 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1073 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1074 usingTimes=0;
mas01cr@0 1075 }
mas01cr@0 1076
mas01cr@0 1077 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1078 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1079
mas01cr@0 1080 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1081 timesdata = new double[numVectors];
mas01cr@0 1082 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1083 // Calculate durations of points
mas01cr@0 1084 for(k=0; k<numVectors-1; k++){
mas01cr@0 1085 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1086 meanQdur+=timesdata[k];
mas01cr@0 1087 }
mas01cr@0 1088 meanQdur/=k;
mas01cr@0 1089 // Individual exhaustive timepoint durations
mas01cr@0 1090 dbdurs = new double[totalVecs];
mas01cr@0 1091 for(k=0; k<totalVecs-1; k++)
mas01cr@0 1092 dbdurs[k]=timesTable[k+1]-timesTable[k];
mas01cr@0 1093 j--; // decrement vector counter by one
mas01cr@0 1094 }
mas01cr@0 1095
mas01cr@0 1096 if(usingQueryPoint)
mas01cr@0 1097 if(queryPoint>numVectors-1)
mas01cr@0 1098 error("queryPoint > numVectors in query");
mas01cr@0 1099 else{
mas01cr@60 1100 if(verbosity>1) {
mas01cr@0 1101 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1102 }
mas01cr@0 1103 query=query+queryPoint*dbH->dim;
mas01cr@0 1104 numVectors=queryPoint+1;
mas01cr@0 1105 j=1;
mas01cr@0 1106 }
mas01cr@0 1107
mas01cr@0 1108 gettimeofday(&tv1, NULL);
mas01cr@0 1109 while(j--){ // query
mas01cr@0 1110 data=dataBuf;
mas01cr@0 1111 k=totalVecs; // number of database vectors
mas01cr@0 1112 while(k--){ // database
mas01cr@0 1113 thisDist=0;
mas01cr@0 1114 l=dbH->dim;
mas01cr@0 1115 double* q=query;
mas01cr@0 1116 while(l--)
mas01cr@0 1117 thisDist+=*q++**data++;
mas01cr@0 1118 if(!usingTimes ||
mas01cr@0 1119 (usingTimes
mas01cr@0 1120 && fabs(dbdurs[totalVecs-k-1]-timesdata[numVectors-j-1])<timesdata[numVectors-j-1]*timesTol)){
mas01cr@0 1121 n=pointNN;
mas01cr@0 1122 while(n--){
mas01cr@0 1123 if(thisDist>=distances[n]){
mas01cr@0 1124 if((n==0 || thisDist<=distances[n-1])){
mas01cr@0 1125 // Copy all values above up the queue
mas01cr@0 1126 for( l=pointNN-1 ; l >= n+1 ; l--){
mas01cr@0 1127 distances[l]=distances[l-1];
mas01cr@0 1128 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1129 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1130 }
mas01cr@0 1131 distances[n]=thisDist;
mas01cr@0 1132 qIndexes[n]=numVectors-j-1;
mas01cr@0 1133 sIndexes[n]=dbH->length/(sizeof(double)*dbH->dim)-k-1;
mas01cr@0 1134 break;
mas01cr@0 1135 }
mas01cr@0 1136 }
mas01cr@0 1137 else
mas01cr@0 1138 break;
mas01cr@0 1139 }
mas01cr@0 1140 }
mas01cr@0 1141 }
mas01cr@0 1142 // Move query pointer to next query point
mas01cr@0 1143 query+=dbH->dim;
mas01cr@0 1144 }
mas01cr@0 1145
mas01cr@0 1146 gettimeofday(&tv2, NULL);
mas01cr@60 1147 if(verbosity>1) {
mas01cr@0 1148 cerr << endl << " elapsed time:" << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01cr@60 1149 }
mas01cr@0 1150
mas01cr@133 1151 if(adbQueryResponse==0){
mas01cr@0 1152 // Output answer
mas01cr@0 1153 // Loop over nearest neighbours
mas01cr@0 1154 for(k=0; k < pointNN; k++){
mas01cr@0 1155 // Scan for key
mas01mc@18 1156 unsigned cumTrack=0;
mas01cr@0 1157 for(l=0 ; l<dbH->numFiles; l++){
mas01mc@18 1158 cumTrack+=trackTable[l];
mas01mc@18 1159 if(sIndexes[k]<cumTrack){
mas01cr@0 1160 cout << fileTable+l*O2_FILETABLESIZE << " " << distances[k] << " " << qIndexes[k] << " "
mas01mc@18 1161 << sIndexes[k]+trackTable[l]-cumTrack << endl;
mas01cr@0 1162 break;
mas01cr@0 1163 }
mas01cr@0 1164 }
mas01cr@0 1165 }
mas01cr@0 1166 }
mas01cr@0 1167 else{ // Process Web Services Query
mas01cr@89 1168 int listLen;
mas01cr@89 1169 for(k = 0; k < pointNN; k++) {
mas01cr@89 1170 if(distances[k] == -DBL_MAX)
mas01cr@89 1171 break;
mas01cr@89 1172 }
mas01cr@89 1173 listLen = k;
mas01cr@89 1174
mas01cr@133 1175 adbQueryResponse->result.__sizeRlist=listLen;
mas01cr@133 1176 adbQueryResponse->result.__sizeDist=listLen;
mas01cr@133 1177 adbQueryResponse->result.__sizeQpos=listLen;
mas01cr@133 1178 adbQueryResponse->result.__sizeSpos=listLen;
mas01cr@133 1179 adbQueryResponse->result.Rlist= new char*[listLen];
mas01cr@133 1180 adbQueryResponse->result.Dist = new double[listLen];
mas01cr@133 1181 adbQueryResponse->result.Qpos = new unsigned int[listLen];
mas01cr@133 1182 adbQueryResponse->result.Spos = new unsigned int[listLen];
mas01cr@133 1183 for(k=0; k<(unsigned)adbQueryResponse->result.__sizeRlist; k++){
mas01cr@133 1184 adbQueryResponse->result.Rlist[k]=new char[O2_MAXFILESTR];
mas01cr@133 1185 adbQueryResponse->result.Dist[k]=distances[k];
mas01cr@133 1186 adbQueryResponse->result.Qpos[k]=qIndexes[k];
mas01mc@18 1187 unsigned cumTrack=0;
mas01cr@0 1188 for(l=0 ; l<dbH->numFiles; l++){
mas01mc@18 1189 cumTrack+=trackTable[l];
mas01mc@18 1190 if(sIndexes[k]<cumTrack){
mas01cr@133 1191 sprintf(adbQueryResponse->result.Rlist[k], "%s", fileTable+l*O2_FILETABLESIZE);
mas01cr@0 1192 break;
mas01cr@0 1193 }
mas01cr@0 1194 }
mas01cr@133 1195 adbQueryResponse->result.Spos[k]=sIndexes[k]+trackTable[l]-cumTrack;
mas01cr@0 1196 }
mas01cr@0 1197 }
mas01cr@0 1198
mas01cr@0 1199 // Clean up
mas01cr@0 1200 if(queryCopy)
mas01cr@0 1201 delete queryCopy;
mas01cr@0 1202 if(qNorm)
mas01cr@0 1203 delete qNorm;
mas01cr@0 1204 if(timesdata)
mas01cr@0 1205 delete timesdata;
mas01cr@0 1206 if(dbdurs)
mas01cr@0 1207 delete dbdurs;
mas01cr@0 1208 }
mas01cr@0 1209
mas01mc@18 1210 // trackPointQuery
mas01mc@18 1211 // return the trackNN closest tracks to the query track
mas01mc@18 1212 // uses average of pointNN points per track
mas01cr@133 1213 void audioDB::trackPointQuery(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){
mas01cr@27 1214 initTables(dbName, 0, inFile);
mas01cr@0 1215
mas01cr@0 1216 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1217 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1218 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1219 double* data = dataBuf;
mas01cr@0 1220 double* queryCopy = 0;
mas01cr@0 1221
mas01cr@0 1222 if( dbH->flags & O2_FLAG_L2NORM ){
mas01cr@0 1223 // Make a copy of the query
mas01cr@0 1224 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1225 qNorm = new double[numVectors];
mas01cr@0 1226 assert(queryCopy&&qNorm);
mas01cr@0 1227 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1228 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1229 query = queryCopy;
mas01cr@0 1230 }
mas01cr@0 1231
mas01cr@0 1232 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 1233 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01cr@0 1234
mas01cr@0 1235 // Make temporary dynamic memory for results
mas01mc@18 1236 double trackDistances[trackNN];
mas01mc@18 1237 unsigned trackIDs[trackNN];
mas01mc@18 1238 unsigned trackQIndexes[trackNN];
mas01mc@18 1239 unsigned trackSIndexes[trackNN];
mas01cr@0 1240
mas01cr@0 1241 double distances[pointNN];
mas01cr@0 1242 unsigned qIndexes[pointNN];
mas01cr@0 1243 unsigned sIndexes[pointNN];
mas01cr@0 1244
mas01cr@0 1245 unsigned j=numVectors; // number of query points
mas01mc@18 1246 unsigned k,l,n, track, trackOffset=0, processedTracks=0;
mas01cr@0 1247 double thisDist;
mas01cr@0 1248
mas01cr@0 1249 for(k=0; k<pointNN; k++){
mas01cr@66 1250 distances[k]=-DBL_MAX;
mas01cr@0 1251 qIndexes[k]=~0;
mas01cr@0 1252 sIndexes[k]=~0;
mas01cr@0 1253 }
mas01cr@0 1254
mas01mc@18 1255 for(k=0; k<trackNN; k++){
mas01cr@66 1256 trackDistances[k]=-DBL_MAX;
mas01mc@18 1257 trackQIndexes[k]=~0;
mas01mc@18 1258 trackSIndexes[k]=~0;
mas01mc@18 1259 trackIDs[k]=~0;
mas01cr@0 1260 }
mas01cr@0 1261
mas01cr@0 1262 double meanQdur = 0;
mas01cr@0 1263 double* timesdata = 0;
mas01cr@0 1264 double* meanDBdur = 0;
mas01cr@0 1265
mas01cr@0 1266 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1267 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1268 usingTimes=0;
mas01cr@0 1269 }
mas01cr@0 1270
mas01cr@0 1271 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1272 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1273
mas01cr@0 1274 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1275 timesdata = new double[numVectors];
mas01cr@0 1276 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1277 // Calculate durations of points
mas01cr@0 1278 for(k=0; k<numVectors-1; k++){
mas01cr@0 1279 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1280 meanQdur+=timesdata[k];
mas01cr@0 1281 }
mas01cr@0 1282 meanQdur/=k;
mas01cr@0 1283 meanDBdur = new double[dbH->numFiles];
mas01cr@0 1284 for(k=0; k<dbH->numFiles; k++){
mas01cr@0 1285 meanDBdur[k]=0.0;
mas01mc@18 1286 for(j=0; j<trackTable[k]-1 ; j++)
mas01cr@0 1287 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01cr@0 1288 meanDBdur[k]/=j;
mas01cr@0 1289 }
mas01cr@0 1290 }
mas01cr@0 1291
mas01cr@0 1292 if(usingQueryPoint)
mas01cr@0 1293 if(queryPoint>numVectors-1)
mas01cr@0 1294 error("queryPoint > numVectors in query");
mas01cr@0 1295 else{
mas01cr@60 1296 if(verbosity>1) {
mas01cr@0 1297 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1298 }
mas01cr@0 1299 query=query+queryPoint*dbH->dim;
mas01cr@0 1300 numVectors=queryPoint+1;
mas01cr@0 1301 }
mas01cr@0 1302
mas01mc@18 1303 // build track offset table
mas01mc@18 1304 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 1305 unsigned cumTrack=0;
mas01mc@18 1306 unsigned trackIndexOffset;
mas01cr@0 1307 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 1308 trackOffsetTable[k]=cumTrack;
mas01mc@18 1309 cumTrack+=trackTable[k]*dbH->dim;
mas01cr@0 1310 }
mas01cr@0 1311
mas01cr@0 1312 char nextKey[MAXSTR];
mas01cr@0 1313
mas01cr@0 1314 gettimeofday(&tv1, NULL);
mas01cr@0 1315
mas01mc@18 1316 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01mc@18 1317 if(trackFile){
mas01mc@18 1318 if(!trackFile->eof()){
mas01mc@18 1319 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 1320 track=getKeyPos(nextKey);
mas01cr@0 1321 }
mas01cr@0 1322 else
mas01cr@0 1323 break;
mas01cr@0 1324 }
mas01mc@18 1325 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 1326 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01cr@60 1327 if(verbosity>7) {
mas01mc@18 1328 cerr << track << "." << trackOffset/(dbH->dim) << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 1329 }
mas01cr@0 1330
mas01cr@0 1331 if(dbH->flags & O2_FLAG_L2NORM)
mas01cr@0 1332 usingQueryPoint?query=queryCopy+queryPoint*dbH->dim:query=queryCopy;
mas01cr@0 1333 else
mas01cr@0 1334 usingQueryPoint?query=(double*)(indata+sizeof(int))+queryPoint*dbH->dim:query=(double*)(indata+sizeof(int));
mas01cr@0 1335 if(usingQueryPoint)
mas01cr@0 1336 j=1;
mas01cr@0 1337 else
mas01cr@0 1338 j=numVectors;
mas01cr@0 1339 while(j--){
mas01mc@18 1340 k=trackTable[track]; // number of vectors in track
mas01mc@18 1341 data=dataBuf+trackOffset; // data for track
mas01cr@0 1342 while(k--){
mas01cr@0 1343 thisDist=0;
mas01cr@0 1344 l=dbH->dim;
mas01cr@0 1345 double* q=query;
mas01cr@0 1346 while(l--)
mas01cr@0 1347 thisDist+=*q++**data++;
mas01cr@0 1348 if(!usingTimes ||
mas01cr@0 1349 (usingTimes
mas01mc@18 1350 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01cr@0 1351 n=pointNN;
mas01cr@0 1352 while(n--){
mas01cr@0 1353 if(thisDist>=distances[n]){
mas01cr@0 1354 if((n==0 || thisDist<=distances[n-1])){
mas01cr@0 1355 // Copy all values above up the queue
mas01cr@0 1356 for( l=pointNN-1 ; l > n ; l--){
mas01cr@0 1357 distances[l]=distances[l-1];
mas01cr@0 1358 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1359 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1360 }
mas01cr@0 1361 distances[n]=thisDist;
mas01cr@0 1362 qIndexes[n]=numVectors-j-1;
mas01mc@18 1363 sIndexes[n]=trackTable[track]-k-1;
mas01cr@0 1364 break;
mas01cr@0 1365 }
mas01cr@0 1366 }
mas01cr@0 1367 else
mas01cr@0 1368 break;
mas01cr@0 1369 }
mas01cr@0 1370 }
mas01mc@18 1371 } // track
mas01cr@0 1372 // Move query pointer to next query point
mas01cr@0 1373 query+=dbH->dim;
mas01cr@0 1374 } // query
mas01mc@18 1375 // Take the average of this track's distance
mas01mc@18 1376 // Test the track distances
mas01cr@0 1377 thisDist=0;
mas01cr@66 1378 for (n = 0; n < pointNN; n++) {
mas01cr@66 1379 if (distances[n] == -DBL_MAX) break;
mas01cr@66 1380 thisDist += distances[n];
mas01cr@66 1381 }
mas01cr@66 1382 thisDist /= n;
mas01cr@66 1383
mas01mc@18 1384 n=trackNN;
mas01cr@0 1385 while(n--){
mas01mc@18 1386 if(thisDist>=trackDistances[n]){
mas01mc@18 1387 if((n==0 || thisDist<=trackDistances[n-1])){
mas01cr@0 1388 // Copy all values above up the queue
mas01cr@74 1389 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 1390 trackDistances[l]=trackDistances[l-1];
mas01mc@18 1391 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 1392 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 1393 trackIDs[l]=trackIDs[l-1];
mas01cr@0 1394 }
mas01mc@18 1395 trackDistances[n]=thisDist;
mas01mc@18 1396 trackQIndexes[n]=qIndexes[0];
mas01mc@18 1397 trackSIndexes[n]=sIndexes[0];
mas01mc@18 1398 trackIDs[n]=track;
mas01cr@0 1399 break;
mas01cr@0 1400 }
mas01cr@0 1401 }
mas01cr@0 1402 else
mas01cr@0 1403 break;
mas01cr@0 1404 }
mas01cr@0 1405 for(unsigned k=0; k<pointNN; k++){
mas01cr@66 1406 distances[k]=-DBL_MAX;
mas01cr@0 1407 qIndexes[k]=~0;
mas01cr@0 1408 sIndexes[k]=~0;
mas01cr@0 1409 }
mas01mc@18 1410 } // tracks
mas01cr@0 1411 gettimeofday(&tv2, NULL);
mas01cr@0 1412
mas01cr@60 1413 if(verbosity>1) {
mas01mc@18 1414 cerr << endl << "processed tracks :" << processedTracks
mas01cr@0 1415 << " elapsed time:" << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01cr@60 1416 }
mas01cr@0 1417
mas01cr@133 1418 if(adbQueryResponse==0){
mas01cr@60 1419 if(verbosity>1) {
mas01cr@0 1420 cerr<<endl;
mas01cr@60 1421 }
mas01cr@0 1422 // Output answer
mas01cr@0 1423 // Loop over nearest neighbours
mas01mc@18 1424 for(k=0; k < min(trackNN,processedTracks); k++)
mas01mc@18 1425 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE
mas01mc@18 1426 << " " << trackDistances[k] << " " << trackQIndexes[k] << " " << trackSIndexes[k] << endl;
mas01cr@0 1427 }
mas01cr@0 1428 else{ // Process Web Services Query
mas01mc@18 1429 int listLen = min(trackNN, processedTracks);
mas01cr@133 1430 adbQueryResponse->result.__sizeRlist=listLen;
mas01cr@133 1431 adbQueryResponse->result.__sizeDist=listLen;
mas01cr@133 1432 adbQueryResponse->result.__sizeQpos=listLen;
mas01cr@133 1433 adbQueryResponse->result.__sizeSpos=listLen;
mas01cr@133 1434 adbQueryResponse->result.Rlist= new char*[listLen];
mas01cr@133 1435 adbQueryResponse->result.Dist = new double[listLen];
mas01cr@133 1436 adbQueryResponse->result.Qpos = new unsigned int[listLen];
mas01cr@133 1437 adbQueryResponse->result.Spos = new unsigned int[listLen];
mas01cr@133 1438 for(k=0; k<(unsigned)adbQueryResponse->result.__sizeRlist; k++){
mas01cr@133 1439 adbQueryResponse->result.Rlist[k]=new char[O2_MAXFILESTR];
mas01cr@133 1440 adbQueryResponse->result.Dist[k]=trackDistances[k];
mas01cr@133 1441 adbQueryResponse->result.Qpos[k]=trackQIndexes[k];
mas01cr@133 1442 adbQueryResponse->result.Spos[k]=trackSIndexes[k];
mas01cr@133 1443 sprintf(adbQueryResponse->result.Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01cr@0 1444 }
mas01cr@0 1445 }
mas01cr@0 1446
mas01cr@0 1447
mas01cr@0 1448 // Clean up
mas01mc@18 1449 if(trackOffsetTable)
mas01mc@18 1450 delete trackOffsetTable;
mas01cr@0 1451 if(queryCopy)
mas01cr@0 1452 delete queryCopy;
mas01cr@0 1453 if(qNorm)
mas01cr@0 1454 delete qNorm;
mas01cr@0 1455 if(timesdata)
mas01cr@0 1456 delete timesdata;
mas01cr@0 1457 if(meanDBdur)
mas01cr@0 1458 delete meanDBdur;
mas01cr@0 1459
mas01cr@0 1460 }
mas01cr@0 1461
mas01cr@0 1462
mas01mc@20 1463 // k nearest-neighbor (k-NN) search between query and target tracks
mas01mc@20 1464 // efficient implementation based on matched filter
mas01mc@20 1465 // assumes normed shingles
mas01mc@20 1466 // outputs distances of retrieved shingles, max retreived = pointNN shingles per per track
mas01cr@133 1467 void audioDB::trackSequenceQueryNN(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){
mas01cr@0 1468
mas01cr@27 1469 initTables(dbName, 0, inFile);
mas01cr@0 1470
mas01cr@0 1471 // For each input vector, find the closest pointNN matching output vectors and report
mas01cr@0 1472 // we use stdout in this stub version
mas01cr@0 1473 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01cr@0 1474 double* query = (double*)(indata+sizeof(int));
mas01cr@0 1475 double* queryCopy = 0;
mas01cr@0 1476
mas01cr@0 1477 double qMeanL2;
mas01cr@0 1478 double* sMeanL2;
mas01cr@0 1479
mas01cr@0 1480 unsigned USE_THRESH=0;
mas01cr@0 1481 double SILENCE_THRESH=0;
mas01cr@0 1482 double DIFF_THRESH=0;
mas01cr@0 1483
mas01cr@0 1484 if(!(dbH->flags & O2_FLAG_L2NORM) )
mas01cr@55 1485 error("Database must be L2 normed for sequence query","use -L2NORM");
mas01cr@55 1486
mas01cr@55 1487 if(numVectors<sequenceLength)
mas01cr@55 1488 error("Query shorter than requested sequence length", "maybe use -l");
mas01cr@0 1489
mas01cr@60 1490 if(verbosity>1) {
mas01cr@0 1491 cerr << "performing norms ... "; cerr.flush();
mas01cr@60 1492 }
mas01cr@0 1493 unsigned dbVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01mc@20 1494
mas01cr@0 1495 // Make a copy of the query
mas01cr@0 1496 queryCopy = new double[numVectors*dbH->dim];
mas01cr@0 1497 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01cr@0 1498 qNorm = new double[numVectors];
mas01cr@0 1499 sNorm = new double[dbVectors];
mas01cr@0 1500 sMeanL2=new double[dbH->numFiles];
mas01cr@0 1501 assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength);
mas01cr@0 1502 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01cr@0 1503 query = queryCopy;
mas01mc@20 1504
mas01cr@0 1505 // Make norm measurements relative to sequenceLength
mas01cr@0 1506 unsigned w = sequenceLength-1;
mas01cr@0 1507 unsigned i,j;
mas01cr@0 1508 double* ps;
mas01cr@0 1509 double tmp1,tmp2;
mas01mc@20 1510
mas01cr@0 1511 // Copy the L2 norm values to core to avoid disk random access later on
mas01cr@0 1512 memcpy(sNorm, l2normTable, dbVectors*sizeof(double));
mas01cr@125 1513 double* qnPtr = qNorm;
mas01cr@0 1514 double* snPtr = sNorm;
mas01cr@0 1515 for(i=0; i<dbH->numFiles; i++){
mas01mc@20 1516 if(trackTable[i]>=sequenceLength){
mas01cr@0 1517 tmp1=*snPtr;
mas01cr@0 1518 j=1;
mas01cr@0 1519 w=sequenceLength-1;
mas01cr@0 1520 while(w--)
mas01cr@0 1521 *snPtr+=snPtr[j++];
mas01cr@0 1522 ps = snPtr+1;
mas01mc@18 1523 w=trackTable[i]-sequenceLength; // +1 - 1
mas01cr@0 1524 while(w--){
mas01cr@0 1525 tmp2=*ps;
mas01mc@20 1526 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01cr@0 1527 tmp1=tmp2;
mas01cr@0 1528 ps++;
mas01cr@0 1529 }
mas01mc@20 1530 ps = snPtr;
mas01mc@20 1531 w=trackTable[i]-sequenceLength+1;
mas01mc@20 1532 while(w--){
mas01mc@20 1533 *ps=sqrt(*ps);
mas01mc@20 1534 ps++;
mas01mc@20 1535 }
mas01cr@0 1536 }
mas01mc@18 1537 snPtr+=trackTable[i];
mas01cr@0 1538 }
mas01cr@0 1539
mas01cr@0 1540 double* pn = sMeanL2;
mas01cr@0 1541 w=dbH->numFiles;
mas01cr@0 1542 while(w--)
mas01cr@0 1543 *pn++=0.0;
mas01cr@0 1544 ps=sNorm;
mas01mc@18 1545 unsigned processedTracks=0;
mas01cr@0 1546 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 1547 if(trackTable[i]>sequenceLength-1){
mas01cr@57 1548 w = trackTable[i]-sequenceLength+1;
mas01cr@0 1549 pn = sMeanL2+i;
mas01mc@20 1550 *pn=0;
mas01cr@0 1551 while(w--)
mas01mc@20 1552 if(*ps>0)
mas01mc@20 1553 *pn+=*ps++;
mas01cr@57 1554 *pn/=trackTable[i]-sequenceLength+1;
mas01cr@0 1555 SILENCE_THRESH+=*pn;
mas01mc@18 1556 processedTracks++;
mas01cr@0 1557 }
mas01mc@18 1558 ps = sNorm + trackTable[i];
mas01cr@0 1559 }
mas01cr@60 1560 if(verbosity>1) {
mas01mc@18 1561 cerr << "processedTracks: " << processedTracks << endl;
mas01cr@60 1562 }
mas01mc@20 1563
mas01mc@18 1564 SILENCE_THRESH/=processedTracks;
mas01cr@0 1565 USE_THRESH=1; // Turn thresholding on
mas01mc@20 1566 DIFF_THRESH=SILENCE_THRESH; // mean shingle power
mas01mc@20 1567 SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE
mas01cr@60 1568 if(verbosity>4) {
mas01mc@20 1569 cerr << "silence thresh: " << SILENCE_THRESH;
mas01cr@60 1570 }
mas01cr@0 1571 w=sequenceLength-1;
mas01cr@0 1572 i=1;
mas01cr@125 1573 tmp1=*qnPtr;
mas01cr@0 1574 while(w--)
mas01cr@125 1575 *qnPtr+=qnPtr[i++];
mas01cr@125 1576 ps = qnPtr+1;
mas01mc@20 1577 w=numVectors-sequenceLength; // +1 -1
mas01cr@0 1578 while(w--){
mas01cr@0 1579 tmp2=*ps;
mas01mc@20 1580 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01cr@0 1581 tmp1=tmp2;
mas01mc@20 1582 ps++;
mas01mc@20 1583 }
mas01cr@125 1584 ps = qnPtr;
mas01mc@20 1585 qMeanL2 = 0;
mas01mc@20 1586 w=numVectors-sequenceLength+1;
mas01mc@20 1587 while(w--){
mas01mc@20 1588 *ps=sqrt(*ps);
mas01mc@20 1589 qMeanL2+=*ps++;
mas01cr@0 1590 }
mas01cr@0 1591 qMeanL2 /= numVectors-sequenceLength+1;
mas01mc@20 1592
mas01cr@60 1593 if(verbosity>1) {
mas01cr@60 1594 cerr << "done." << endl;
mas01cr@60 1595 }
mas01cr@0 1596
mas01cr@60 1597 if(verbosity>1) {
mas01mc@18 1598 cerr << "matching tracks..." << endl;
mas01cr@60 1599 }
mas01cr@0 1600
mas01cr@0 1601 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 1602 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01cr@0 1603
mas01cr@0 1604 // Make temporary dynamic memory for results
mas01mc@18 1605 double trackDistances[trackNN];
mas01mc@18 1606 unsigned trackIDs[trackNN];
mas01mc@18 1607 unsigned trackQIndexes[trackNN];
mas01mc@18 1608 unsigned trackSIndexes[trackNN];
mas01cr@0 1609
mas01cr@0 1610 double distances[pointNN];
mas01cr@0 1611 unsigned qIndexes[pointNN];
mas01cr@0 1612 unsigned sIndexes[pointNN];
mas01cr@0 1613
mas01cr@0 1614
mas01mc@18 1615 unsigned k,l,m,n,track,trackOffset=0, HOP_SIZE=sequenceHop, wL=sequenceLength;
mas01cr@0 1616 double thisDist;
mas01cr@0 1617
mas01cr@0 1618 for(k=0; k<pointNN; k++){
mas01mc@20 1619 distances[k]=1.0e6;
mas01cr@0 1620 qIndexes[k]=~0;
mas01cr@0 1621 sIndexes[k]=~0;
mas01cr@0 1622 }
mas01cr@0 1623
mas01mc@18 1624 for(k=0; k<trackNN; k++){
mas01mc@20 1625 trackDistances[k]=1.0e6;
mas01mc@18 1626 trackQIndexes[k]=~0;
mas01mc@18 1627 trackSIndexes[k]=~0;
mas01mc@18 1628 trackIDs[k]=~0;
mas01cr@0 1629 }
mas01cr@0 1630
mas01cr@0 1631 // Timestamp and durations processing
mas01cr@0 1632 double meanQdur = 0;
mas01cr@0 1633 double* timesdata = 0;
mas01cr@0 1634 double* meanDBdur = 0;
mas01cr@0 1635
mas01cr@0 1636 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1637 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01cr@0 1638 usingTimes=0;
mas01cr@0 1639 }
mas01cr@0 1640
mas01cr@0 1641 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01cr@0 1642 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01cr@0 1643
mas01cr@0 1644 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01cr@0 1645 timesdata = new double[numVectors];
mas01cr@0 1646 assert(timesdata);
mas01cr@0 1647 insertTimeStamps(numVectors, timesFile, timesdata);
mas01cr@0 1648 // Calculate durations of points
mas01cr@0 1649 for(k=0; k<numVectors-1; k++){
mas01cr@0 1650 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01cr@0 1651 meanQdur+=timesdata[k];
mas01cr@0 1652 }
mas01cr@0 1653 meanQdur/=k;
mas01cr@60 1654 if(verbosity>1) {
mas01cr@0 1655 cerr << "mean query file duration: " << meanQdur << endl;
mas01cr@60 1656 }
mas01cr@0 1657 meanDBdur = new double[dbH->numFiles];
mas01cr@0 1658 assert(meanDBdur);
mas01cr@0 1659 for(k=0; k<dbH->numFiles; k++){
mas01cr@0 1660 meanDBdur[k]=0.0;
mas01mc@18 1661 for(j=0; j<trackTable[k]-1 ; j++)
mas01cr@0 1662 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01cr@0 1663 meanDBdur[k]/=j;
mas01cr@0 1664 }
mas01cr@0 1665 }
mas01cr@0 1666
mas01cr@0 1667 if(usingQueryPoint)
mas01cr@0 1668 if(queryPoint>numVectors || queryPoint>numVectors-wL+1)
mas01cr@0 1669 error("queryPoint > numVectors-wL+1 in query");
mas01cr@0 1670 else{
mas01cr@60 1671 if(verbosity>1) {
mas01cr@0 1672 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 1673 }
mas01cr@0 1674 query=query+queryPoint*dbH->dim;
mas01cr@125 1675 qnPtr=qnPtr+queryPoint;
mas01cr@0 1676 numVectors=wL;
mas01cr@0 1677 }
mas01cr@0 1678
mas01mc@20 1679 double ** D = 0; // Differences query and target
mas01cr@0 1680 double ** DD = 0; // Matched filter distance
mas01cr@0 1681
mas01cr@0 1682 D = new double*[numVectors];
mas01cr@0 1683 assert(D);
mas01cr@0 1684 DD = new double*[numVectors];
mas01cr@0 1685 assert(DD);
mas01cr@0 1686
mas01cr@0 1687 gettimeofday(&tv1, NULL);
mas01mc@18 1688 processedTracks=0;
mas01mc@18 1689 unsigned successfulTracks=0;
mas01cr@0 1690
mas01cr@0 1691 double* qp;
mas01cr@0 1692 double* sp;
mas01cr@0 1693 double* dp;
mas01cr@0 1694
mas01mc@18 1695 // build track offset table
mas01mc@18 1696 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 1697 unsigned cumTrack=0;
mas01mc@18 1698 unsigned trackIndexOffset;
mas01cr@0 1699 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 1700 trackOffsetTable[k]=cumTrack;
mas01mc@18 1701 cumTrack+=trackTable[k]*dbH->dim;
mas01cr@0 1702 }
mas01cr@0 1703
mas01cr@0 1704 char nextKey [MAXSTR];
mas01mc@20 1705
mas01mc@20 1706 // chi^2 statistics
mas01mc@20 1707 double sampleCount = 0;
mas01mc@20 1708 double sampleSum = 0;
mas01mc@20 1709 double logSampleSum = 0;
mas01mc@20 1710 double minSample = 1e9;
mas01mc@20 1711 double maxSample = 0;
mas01mc@20 1712
mas01mc@20 1713 // Track loop
mas01mc@18 1714 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01cr@0 1715
mas01mc@18 1716 // get trackID from file if using a control file
mas01mc@18 1717 if(trackFile){
mas01mc@18 1718 if(!trackFile->eof()){
mas01mc@18 1719 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 1720 track=getKeyPos(nextKey);
mas01cr@0 1721 }
mas01cr@0 1722 else
mas01cr@0 1723 break;
mas01cr@0 1724 }
mas01mc@12 1725
mas01mc@18 1726 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 1727 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01cr@0 1728
mas01cr@57 1729 if(sequenceLength<=trackTable[track]){ // test for short sequences
mas01cr@0 1730
mas01cr@60 1731 if(verbosity>7) {
mas01mc@18 1732 cerr << track << "." << trackIndexOffset << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 1733 }
mas01cr@0 1734
mas01mc@20 1735 // Sum products matrix
mas01cr@0 1736 for(j=0; j<numVectors;j++){
mas01mc@18 1737 D[j]=new double[trackTable[track]];
mas01cr@0 1738 assert(D[j]);
mas01cr@0 1739
mas01cr@0 1740 }
mas01cr@0 1741
mas01cr@0 1742 // Matched filter matrix
mas01cr@0 1743 for(j=0; j<numVectors;j++){
mas01mc@18 1744 DD[j]=new double[trackTable[track]];
mas01cr@0 1745 assert(DD[j]);
mas01cr@0 1746 }
mas01cr@0 1747
mas01mc@20 1748 // Dot product
mas01cr@0 1749 for(j=0; j<numVectors; j++)
mas01mc@18 1750 for(k=0; k<trackTable[track]; k++){
mas01cr@0 1751 qp=query+j*dbH->dim;
mas01mc@18 1752 sp=dataBuf+trackOffset+k*dbH->dim;
mas01cr@0 1753 DD[j][k]=0.0; // Initialize matched filter array
mas01cr@0 1754 dp=&D[j][k]; // point to correlation cell j,k
mas01cr@0 1755 *dp=0.0; // initialize correlation cell
mas01cr@0 1756 l=dbH->dim; // size of vectors
mas01cr@0 1757 while(l--)
mas01cr@0 1758 *dp+=*qp++**sp++;
mas01cr@0 1759 }
mas01cr@0 1760
mas01cr@0 1761 // Matched Filter
mas01cr@0 1762 // HOP SIZE == 1
mas01cr@0 1763 double* spd;
mas01cr@0 1764 if(HOP_SIZE==1){ // HOP_SIZE = shingleHop
mas01cr@0 1765 for(w=0; w<wL; w++)
mas01cr@0 1766 for(j=0; j<numVectors-w; j++){
mas01cr@0 1767 sp=DD[j];
mas01cr@0 1768 spd=D[j+w]+w;
mas01mc@18 1769 k=trackTable[track]-w;
mas01cr@0 1770 while(k--)
mas01cr@0 1771 *sp+++=*spd++;
mas01cr@0 1772 }
mas01cr@0 1773 }
mas01mc@20 1774
mas01cr@0 1775 else{ // HOP_SIZE != 1
mas01cr@0 1776 for(w=0; w<wL; w++)
mas01cr@0 1777 for(j=0; j<numVectors-w; j+=HOP_SIZE){
mas01cr@0 1778 sp=DD[j];
mas01cr@0 1779 spd=D[j+w]+w;
mas01mc@18 1780 for(k=0; k<trackTable[track]-w; k+=HOP_SIZE){
mas01cr@0 1781 *sp+=*spd;
mas01cr@0 1782 sp+=HOP_SIZE;
mas01cr@0 1783 spd+=HOP_SIZE;
mas01cr@0 1784 }
mas01cr@0 1785 }
mas01cr@0 1786 }
mas01cr@0 1787
mas01cr@60 1788 if(verbosity>3 && usingTimes) {
mas01mc@18 1789 cerr << "meanQdur=" << meanQdur << " meanDBdur=" << meanDBdur[track] << endl;
mas01cr@0 1790 cerr.flush();
mas01cr@0 1791 }
mas01cr@0 1792
mas01cr@0 1793 if(!usingTimes ||
mas01cr@0 1794 (usingTimes
mas01mc@18 1795 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01cr@0 1796
mas01cr@60 1797 if(verbosity>3 && usingTimes) {
mas01cr@0 1798 cerr << "within duration tolerance." << endl;
mas01cr@0 1799 cerr.flush();
mas01cr@0 1800 }
mas01cr@0 1801
mas01cr@0 1802 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@53 1803 for(j=0;j<=numVectors-wL;j+=HOP_SIZE)
mas01cr@53 1804 for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){
mas01cr@125 1805 thisDist=2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
mas01cr@60 1806 if(verbosity>10) {
mas01cr@125 1807 cerr << thisDist << " " << qnPtr[j] << " " << sNorm[trackIndexOffset+k] << endl;
mas01cr@60 1808 }
mas01mc@20 1809 // Gather chi^2 statistics
mas01mc@20 1810 if(thisDist<minSample)
mas01mc@20 1811 minSample=thisDist;
mas01mc@20 1812 else if(thisDist>maxSample)
mas01mc@20 1813 maxSample=thisDist;
mas01mc@20 1814 if(thisDist>1e-9){
mas01mc@20 1815 sampleCount++;
mas01mc@20 1816 sampleSum+=thisDist;
mas01mc@20 1817 logSampleSum+=log(thisDist);
mas01mc@20 1818 }
mas01mc@20 1819
mas01cr@125 1820 // diffL2 = fabs(qnPtr[j] - sNorm[trackIndexOffset+k]);
mas01cr@0 1821 // Power test
mas01cr@0 1822 if(!USE_THRESH ||
mas01cr@0 1823 // Threshold on mean L2 of Q and S sequences
mas01cr@125 1824 (USE_THRESH && qnPtr[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH &&
mas01cr@0 1825 // Are both query and target windows above mean energy?
mas01cr@125 1826 (qnPtr[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH )))
mas01mc@20 1827 thisDist=thisDist; // Computed above
mas01cr@0 1828 else
mas01mc@20 1829 thisDist=1000000.0;
mas01mc@20 1830
mas01mc@20 1831 // k-NN match algorithm
mas01cr@58 1832 m=pointNN;
mas01mc@20 1833 while(m--){
mas01mc@20 1834 if(thisDist<=distances[m])
mas01mc@20 1835 if(m==0 || thisDist>=distances[m-1]){
mas01cr@0 1836 // Shuffle distances up the list
mas01cr@0 1837 for(l=pointNN-1; l>m; l--){
mas01cr@0 1838 distances[l]=distances[l-1];
mas01cr@0 1839 qIndexes[l]=qIndexes[l-1];
mas01cr@0 1840 sIndexes[l]=sIndexes[l-1];
mas01cr@0 1841 }
mas01cr@0 1842 distances[m]=thisDist;
mas01cr@0 1843 if(usingQueryPoint)
mas01cr@0 1844 qIndexes[m]=queryPoint;
mas01cr@0 1845 else
mas01cr@0 1846 qIndexes[m]=j;
mas01cr@0 1847 sIndexes[m]=k;
mas01cr@0 1848 break;
mas01mc@20 1849 }
mas01cr@0 1850 }
mas01cr@0 1851 }
mas01cr@0 1852 // Calculate the mean of the N-Best matches
mas01cr@0 1853 thisDist=0.0;
mas01cr@53 1854 for(m=0; m<pointNN; m++) {
mas01cr@53 1855 if (distances[m] == 1000000.0) break;
mas01mc@20 1856 thisDist+=distances[m];
mas01cr@53 1857 }
mas01cr@53 1858 thisDist/=m;
mas01cr@0 1859
mas01mc@12 1860 // Let's see the distances then...
mas01cr@60 1861 if(verbosity>3) {
mas01mc@18 1862 cerr << fileTable+track*O2_FILETABLESIZE << " " << thisDist << endl;
mas01cr@60 1863 }
mas01mc@12 1864
mas01mc@20 1865
mas01mc@18 1866 // All the track stuff goes here
mas01cr@58 1867 n=trackNN;
mas01cr@0 1868 while(n--){
mas01mc@20 1869 if(thisDist<=trackDistances[n]){
mas01mc@20 1870 if((n==0 || thisDist>=trackDistances[n-1])){
mas01cr@0 1871 // Copy all values above up the queue
mas01mc@18 1872 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 1873 trackDistances[l]=trackDistances[l-1];
mas01mc@18 1874 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 1875 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 1876 trackIDs[l]=trackIDs[l-1];
mas01cr@0 1877 }
mas01mc@18 1878 trackDistances[n]=thisDist;
mas01mc@18 1879 trackQIndexes[n]=qIndexes[0];
mas01mc@18 1880 trackSIndexes[n]=sIndexes[0];
mas01mc@18 1881 successfulTracks++;
mas01mc@18 1882 trackIDs[n]=track;
mas01cr@0 1883 break;
mas01cr@0 1884 }
mas01cr@0 1885 }
mas01cr@0 1886 else
mas01cr@0 1887 break;
mas01cr@0 1888 }
mas01cr@0 1889 } // Duration match
mas01mc@20 1890
mas01mc@18 1891 // Clean up current track
mas01cr@0 1892 if(D!=NULL){
mas01cr@0 1893 for(j=0; j<numVectors; j++)
mas01cr@0 1894 delete[] D[j];
mas01cr@0 1895 }
mas01cr@0 1896
mas01cr@0 1897 if(DD!=NULL){
mas01cr@0 1898 for(j=0; j<numVectors; j++)
mas01cr@0 1899 delete[] DD[j];
mas01cr@0 1900 }
mas01cr@0 1901 }
mas01mc@20 1902 // per-track reset array values
mas01mc@20 1903 for(unsigned k=0; k<pointNN; k++){
mas01mc@20 1904 distances[k]=1.0e6;
mas01mc@20 1905 qIndexes[k]=~0;
mas01mc@20 1906 sIndexes[k]=~0;
mas01mc@20 1907 }
mas01cr@0 1908 }
mas01cr@0 1909
mas01cr@0 1910 gettimeofday(&tv2,NULL);
mas01cr@60 1911 if(verbosity>1) {
mas01mc@18 1912 cerr << endl << "processed tracks :" << processedTracks << " matched tracks: " << successfulTracks << " elapsed time:"
mas01cr@0 1913 << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01mc@20 1914 cerr << "sampleCount: " << sampleCount << " sampleSum: " << sampleSum << " logSampleSum: " << logSampleSum
mas01mc@20 1915 << " minSample: " << minSample << " maxSample: " << maxSample << endl;
mas01mc@20 1916 }
mas01cr@133 1917 if(adbQueryResponse==0){
mas01cr@60 1918 if(verbosity>1) {
mas01cr@0 1919 cerr<<endl;
mas01cr@60 1920 }
mas01cr@0 1921 // Output answer
mas01cr@0 1922 // Loop over nearest neighbours
mas01mc@18 1923 for(k=0; k < min(trackNN,successfulTracks); k++)
mas01mc@20 1924 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE << " " << trackDistances[k] << " "
mas01mc@20 1925 << trackQIndexes[k] << " " << trackSIndexes[k] << endl;
mas01cr@0 1926 }
mas01cr@0 1927 else{ // Process Web Services Query
mas01mc@18 1928 int listLen = min(trackNN, processedTracks);
mas01cr@133 1929 adbQueryResponse->result.__sizeRlist=listLen;
mas01cr@133 1930 adbQueryResponse->result.__sizeDist=listLen;
mas01cr@133 1931 adbQueryResponse->result.__sizeQpos=listLen;
mas01cr@133 1932 adbQueryResponse->result.__sizeSpos=listLen;
mas01cr@133 1933 adbQueryResponse->result.Rlist= new char*[listLen];
mas01cr@133 1934 adbQueryResponse->result.Dist = new double[listLen];
mas01cr@133 1935 adbQueryResponse->result.Qpos = new unsigned int[listLen];
mas01cr@133 1936 adbQueryResponse->result.Spos = new unsigned int[listLen];
mas01cr@133 1937 for(k=0; k<(unsigned)adbQueryResponse->result.__sizeRlist; k++){
mas01cr@133 1938 adbQueryResponse->result.Rlist[k]=new char[O2_MAXFILESTR];
mas01cr@133 1939 adbQueryResponse->result.Dist[k]=trackDistances[k];
mas01cr@133 1940 adbQueryResponse->result.Qpos[k]=trackQIndexes[k];
mas01cr@133 1941 adbQueryResponse->result.Spos[k]=trackSIndexes[k];
mas01cr@133 1942 sprintf(adbQueryResponse->result.Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01cr@0 1943 }
mas01cr@0 1944 }
mas01cr@0 1945
mas01cr@0 1946
mas01cr@0 1947 // Clean up
mas01mc@18 1948 if(trackOffsetTable)
mas01mc@20 1949 delete[] trackOffsetTable;
mas01cr@0 1950 if(queryCopy)
mas01mc@20 1951 delete[] queryCopy;
mas01cr@121 1952 if(qNorm)
mas01cr@121 1953 delete[] qNorm;
mas01cr@121 1954 if(sNorm)
mas01cr@121 1955 delete[] sNorm;
mas01cr@121 1956 if(sMeanL2)
mas01cr@121 1957 delete[] sMeanL2;
mas01cr@0 1958 if(D)
mas01cr@0 1959 delete[] D;
mas01cr@0 1960 if(DD)
mas01cr@0 1961 delete[] DD;
mas01cr@0 1962 if(timesdata)
mas01mc@20 1963 delete[] timesdata;
mas01cr@0 1964 if(meanDBdur)
mas01mc@20 1965 delete[] meanDBdur;
mas01cr@0 1966
mas01cr@0 1967
mas01cr@0 1968 }
mas01cr@0 1969
mas01mc@20 1970 // Radius search between query and target tracks
mas01mc@20 1971 // efficient implementation based on matched filter
mas01mc@20 1972 // assumes normed shingles
mas01mc@20 1973 // outputs count of retrieved shingles, max retreived = one shingle per query shingle per track
mas01cr@133 1974 void audioDB::trackSequenceQueryRad(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse){
mas01mc@17 1975
mas01cr@27 1976 initTables(dbName, 0, inFile);
mas01mc@17 1977
mas01mc@17 1978 // For each input vector, find the closest pointNN matching output vectors and report
mas01mc@17 1979 // we use stdout in this stub version
mas01mc@17 1980 unsigned numVectors = (statbuf.st_size-sizeof(int))/(sizeof(double)*dbH->dim);
mas01mc@17 1981 double* query = (double*)(indata+sizeof(int));
mas01mc@17 1982 double* queryCopy = 0;
mas01mc@17 1983
mas01mc@17 1984 double qMeanL2;
mas01mc@17 1985 double* sMeanL2;
mas01mc@17 1986
mas01mc@17 1987 unsigned USE_THRESH=0;
mas01mc@17 1988 double SILENCE_THRESH=0;
mas01mc@17 1989 double DIFF_THRESH=0;
mas01mc@17 1990
mas01mc@17 1991 if(!(dbH->flags & O2_FLAG_L2NORM) )
mas01mc@17 1992 error("Database must be L2 normed for sequence query","use -l2norm");
mas01mc@17 1993
mas01cr@60 1994 if(verbosity>1) {
mas01mc@17 1995 cerr << "performing norms ... "; cerr.flush();
mas01cr@60 1996 }
mas01mc@17 1997 unsigned dbVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01mc@18 1998
mas01mc@17 1999 // Make a copy of the query
mas01mc@17 2000 queryCopy = new double[numVectors*dbH->dim];
mas01mc@17 2001 memcpy(queryCopy, query, numVectors*dbH->dim*sizeof(double));
mas01mc@17 2002 qNorm = new double[numVectors];
mas01mc@17 2003 sNorm = new double[dbVectors];
mas01mc@17 2004 sMeanL2=new double[dbH->numFiles];
mas01mc@17 2005 assert(qNorm&&sNorm&&queryCopy&&sMeanL2&&sequenceLength);
mas01mc@17 2006 unitNorm(queryCopy, dbH->dim, numVectors, qNorm);
mas01mc@17 2007 query = queryCopy;
mas01mc@18 2008
mas01mc@17 2009 // Make norm measurements relative to sequenceLength
mas01mc@17 2010 unsigned w = sequenceLength-1;
mas01mc@17 2011 unsigned i,j;
mas01mc@17 2012 double* ps;
mas01mc@17 2013 double tmp1,tmp2;
mas01mc@18 2014
mas01mc@17 2015 // Copy the L2 norm values to core to avoid disk random access later on
mas01mc@17 2016 memcpy(sNorm, l2normTable, dbVectors*sizeof(double));
mas01mc@17 2017 double* snPtr = sNorm;
mas01cr@125 2018 double* qnPtr = qNorm;
mas01mc@17 2019 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 2020 if(trackTable[i]>=sequenceLength){
mas01mc@17 2021 tmp1=*snPtr;
mas01mc@17 2022 j=1;
mas01mc@17 2023 w=sequenceLength-1;
mas01mc@17 2024 while(w--)
mas01mc@17 2025 *snPtr+=snPtr[j++];
mas01mc@17 2026 ps = snPtr+1;
mas01mc@18 2027 w=trackTable[i]-sequenceLength; // +1 - 1
mas01mc@17 2028 while(w--){
mas01mc@17 2029 tmp2=*ps;
mas01mc@17 2030 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01mc@17 2031 tmp1=tmp2;
mas01mc@17 2032 ps++;
mas01mc@17 2033 }
mas01mc@17 2034 ps = snPtr;
mas01mc@18 2035 w=trackTable[i]-sequenceLength+1;
mas01mc@17 2036 while(w--){
mas01mc@17 2037 *ps=sqrt(*ps);
mas01mc@17 2038 ps++;
mas01mc@17 2039 }
mas01mc@17 2040 }
mas01mc@18 2041 snPtr+=trackTable[i];
mas01mc@17 2042 }
mas01mc@17 2043
mas01mc@17 2044 double* pn = sMeanL2;
mas01mc@17 2045 w=dbH->numFiles;
mas01mc@17 2046 while(w--)
mas01mc@17 2047 *pn++=0.0;
mas01mc@17 2048 ps=sNorm;
mas01mc@18 2049 unsigned processedTracks=0;
mas01mc@17 2050 for(i=0; i<dbH->numFiles; i++){
mas01mc@18 2051 if(trackTable[i]>sequenceLength-1){
mas01cr@70 2052 w = trackTable[i]-sequenceLength+1;
mas01mc@17 2053 pn = sMeanL2+i;
mas01mc@17 2054 *pn=0;
mas01mc@17 2055 while(w--)
mas01mc@17 2056 if(*ps>0)
mas01mc@17 2057 *pn+=*ps++;
mas01cr@70 2058 *pn/=trackTable[i]-sequenceLength+1;
mas01mc@17 2059 SILENCE_THRESH+=*pn;
mas01mc@18 2060 processedTracks++;
mas01mc@17 2061 }
mas01mc@18 2062 ps = sNorm + trackTable[i];
mas01mc@17 2063 }
mas01cr@60 2064 if(verbosity>1) {
mas01mc@18 2065 cerr << "processedTracks: " << processedTracks << endl;
mas01cr@60 2066 }
mas01mc@17 2067
mas01mc@18 2068 SILENCE_THRESH/=processedTracks;
mas01mc@17 2069 USE_THRESH=1; // Turn thresholding on
mas01mc@18 2070 DIFF_THRESH=SILENCE_THRESH; // mean shingle power
mas01mc@17 2071 SILENCE_THRESH/=5; // 20% of the mean shingle power is SILENCE
mas01cr@60 2072 if(verbosity>4) {
mas01mc@17 2073 cerr << "silence thresh: " << SILENCE_THRESH;
mas01cr@60 2074 }
mas01mc@17 2075 w=sequenceLength-1;
mas01mc@17 2076 i=1;
mas01cr@125 2077 tmp1=*qnPtr;
mas01mc@17 2078 while(w--)
mas01cr@125 2079 *qnPtr+=qnPtr[i++];
mas01cr@125 2080 ps = qnPtr+1;
mas01mc@17 2081 w=numVectors-sequenceLength; // +1 -1
mas01mc@17 2082 while(w--){
mas01mc@17 2083 tmp2=*ps;
mas01mc@17 2084 *ps=*(ps-1)-tmp1+*(ps+sequenceLength-1);
mas01mc@17 2085 tmp1=tmp2;
mas01mc@17 2086 ps++;
mas01mc@17 2087 }
mas01cr@125 2088 ps = qnPtr;
mas01mc@17 2089 qMeanL2 = 0;
mas01mc@17 2090 w=numVectors-sequenceLength+1;
mas01mc@17 2091 while(w--){
mas01mc@17 2092 *ps=sqrt(*ps);
mas01mc@17 2093 qMeanL2+=*ps++;
mas01mc@17 2094 }
mas01mc@17 2095 qMeanL2 /= numVectors-sequenceLength+1;
mas01mc@17 2096
mas01cr@60 2097 if(verbosity>1) {
mas01mc@17 2098 cerr << "done." << endl;
mas01cr@60 2099 }
mas01mc@17 2100
mas01cr@60 2101 if(verbosity>1) {
mas01mc@18 2102 cerr << "matching tracks..." << endl;
mas01cr@60 2103 }
mas01mc@17 2104
mas01mc@17 2105 assert(pointNN>0 && pointNN<=O2_MAXNN);
mas01mc@18 2106 assert(trackNN>0 && trackNN<=O2_MAXNN);
mas01mc@17 2107
mas01mc@17 2108 // Make temporary dynamic memory for results
mas01mc@18 2109 double trackDistances[trackNN];
mas01mc@18 2110 unsigned trackIDs[trackNN];
mas01mc@18 2111 unsigned trackQIndexes[trackNN];
mas01mc@18 2112 unsigned trackSIndexes[trackNN];
mas01mc@17 2113
mas01mc@17 2114 double distances[pointNN];
mas01mc@17 2115 unsigned qIndexes[pointNN];
mas01mc@17 2116 unsigned sIndexes[pointNN];
mas01mc@17 2117
mas01mc@17 2118
mas01cr@59 2119 unsigned k,l,n,track,trackOffset=0, HOP_SIZE=sequenceHop, wL=sequenceLength;
mas01mc@17 2120 double thisDist;
mas01mc@17 2121
mas01mc@17 2122 for(k=0; k<pointNN; k++){
mas01mc@17 2123 distances[k]=0.0;
mas01mc@17 2124 qIndexes[k]=~0;
mas01mc@17 2125 sIndexes[k]=~0;
mas01mc@17 2126 }
mas01mc@17 2127
mas01mc@18 2128 for(k=0; k<trackNN; k++){
mas01mc@18 2129 trackDistances[k]=0.0;
mas01mc@18 2130 trackQIndexes[k]=~0;
mas01mc@18 2131 trackSIndexes[k]=~0;
mas01mc@18 2132 trackIDs[k]=~0;
mas01mc@17 2133 }
mas01mc@17 2134
mas01mc@17 2135 // Timestamp and durations processing
mas01mc@17 2136 double meanQdur = 0;
mas01mc@17 2137 double* timesdata = 0;
mas01mc@17 2138 double* meanDBdur = 0;
mas01mc@17 2139
mas01mc@17 2140 if(usingTimes && !(dbH->flags & O2_FLAG_TIMES)){
mas01mc@17 2141 cerr << "warning: ignoring query timestamps for non-timestamped database" << endl;
mas01mc@17 2142 usingTimes=0;
mas01mc@17 2143 }
mas01mc@17 2144
mas01mc@17 2145 else if(!usingTimes && (dbH->flags & O2_FLAG_TIMES))
mas01mc@17 2146 cerr << "warning: no timestamps given for query. Ignoring database timestamps." << endl;
mas01mc@17 2147
mas01mc@17 2148 else if(usingTimes && (dbH->flags & O2_FLAG_TIMES)){
mas01mc@17 2149 timesdata = new double[numVectors];
mas01mc@17 2150 assert(timesdata);
mas01mc@17 2151 insertTimeStamps(numVectors, timesFile, timesdata);
mas01mc@17 2152 // Calculate durations of points
mas01mc@17 2153 for(k=0; k<numVectors-1; k++){
mas01mc@17 2154 timesdata[k]=timesdata[k+1]-timesdata[k];
mas01mc@17 2155 meanQdur+=timesdata[k];
mas01mc@17 2156 }
mas01mc@17 2157 meanQdur/=k;
mas01cr@60 2158 if(verbosity>1) {
mas01mc@17 2159 cerr << "mean query file duration: " << meanQdur << endl;
mas01cr@60 2160 }
mas01mc@17 2161 meanDBdur = new double[dbH->numFiles];
mas01mc@17 2162 assert(meanDBdur);
mas01mc@17 2163 for(k=0; k<dbH->numFiles; k++){
mas01mc@17 2164 meanDBdur[k]=0.0;
mas01mc@18 2165 for(j=0; j<trackTable[k]-1 ; j++)
mas01mc@17 2166 meanDBdur[k]+=timesTable[j+1]-timesTable[j];
mas01mc@17 2167 meanDBdur[k]/=j;
mas01mc@17 2168 }
mas01mc@17 2169 }
mas01mc@17 2170
mas01mc@17 2171 if(usingQueryPoint)
mas01mc@17 2172 if(queryPoint>numVectors || queryPoint>numVectors-wL+1)
mas01mc@17 2173 error("queryPoint > numVectors-wL+1 in query");
mas01mc@17 2174 else{
mas01cr@60 2175 if(verbosity>1) {
mas01mc@17 2176 cerr << "query point: " << queryPoint << endl; cerr.flush();
mas01cr@60 2177 }
mas01mc@17 2178 query=query+queryPoint*dbH->dim;
mas01cr@125 2179 qnPtr=qnPtr+queryPoint;
mas01mc@17 2180 numVectors=wL;
mas01mc@17 2181 }
mas01mc@17 2182
mas01mc@17 2183 double ** D = 0; // Differences query and target
mas01mc@17 2184 double ** DD = 0; // Matched filter distance
mas01mc@17 2185
mas01mc@17 2186 D = new double*[numVectors];
mas01mc@17 2187 assert(D);
mas01mc@17 2188 DD = new double*[numVectors];
mas01mc@17 2189 assert(DD);
mas01mc@17 2190
mas01mc@17 2191 gettimeofday(&tv1, NULL);
mas01mc@18 2192 processedTracks=0;
mas01mc@18 2193 unsigned successfulTracks=0;
mas01mc@17 2194
mas01mc@17 2195 double* qp;
mas01mc@17 2196 double* sp;
mas01mc@17 2197 double* dp;
mas01mc@17 2198
mas01mc@18 2199 // build track offset table
mas01mc@18 2200 unsigned *trackOffsetTable = new unsigned[dbH->numFiles];
mas01mc@18 2201 unsigned cumTrack=0;
mas01mc@18 2202 unsigned trackIndexOffset;
mas01mc@17 2203 for(k=0; k<dbH->numFiles;k++){
mas01mc@18 2204 trackOffsetTable[k]=cumTrack;
mas01mc@18 2205 cumTrack+=trackTable[k]*dbH->dim;
mas01mc@17 2206 }
mas01mc@17 2207
mas01mc@17 2208 char nextKey [MAXSTR];
mas01mc@17 2209
mas01mc@17 2210 // chi^2 statistics
mas01mc@17 2211 double sampleCount = 0;
mas01mc@17 2212 double sampleSum = 0;
mas01mc@17 2213 double logSampleSum = 0;
mas01mc@17 2214 double minSample = 1e9;
mas01mc@17 2215 double maxSample = 0;
mas01mc@17 2216
mas01mc@17 2217 // Track loop
mas01mc@18 2218 for(processedTracks=0, track=0 ; processedTracks < dbH->numFiles ; track++, processedTracks++){
mas01mc@17 2219
mas01mc@18 2220 // get trackID from file if using a control file
mas01mc@18 2221 if(trackFile){
mas01mc@18 2222 if(!trackFile->eof()){
mas01mc@18 2223 trackFile->getline(nextKey,MAXSTR);
mas01mc@18 2224 track=getKeyPos(nextKey);
mas01mc@17 2225 }
mas01mc@17 2226 else
mas01mc@17 2227 break;
mas01mc@17 2228 }
mas01mc@17 2229
mas01mc@18 2230 trackOffset=trackOffsetTable[track]; // numDoubles offset
mas01mc@18 2231 trackIndexOffset=trackOffset/dbH->dim; // numVectors offset
mas01mc@17 2232
mas01cr@70 2233 if(sequenceLength<=trackTable[track]){ // test for short sequences
mas01mc@17 2234
mas01cr@60 2235 if(verbosity>7) {
mas01mc@18 2236 cerr << track << "." << trackIndexOffset << "." << trackTable[track] << " | ";cerr.flush();
mas01cr@60 2237 }
mas01cr@60 2238
mas01mc@17 2239 // Sum products matrix
mas01mc@17 2240 for(j=0; j<numVectors;j++){
mas01mc@18 2241 D[j]=new double[trackTable[track]];
mas01mc@17 2242 assert(D[j]);
mas01mc@17 2243
mas01mc@17 2244 }
mas01mc@17 2245
mas01mc@17 2246 // Matched filter matrix
mas01mc@17 2247 for(j=0; j<numVectors;j++){
mas01mc@18 2248 DD[j]=new double[trackTable[track]];
mas01mc@17 2249 assert(DD[j]);
mas01mc@17 2250 }
mas01mc@17 2251
mas01mc@17 2252 // Dot product
mas01mc@17 2253 for(j=0; j<numVectors; j++)
mas01mc@18 2254 for(k=0; k<trackTable[track]; k++){
mas01mc@17 2255 qp=query+j*dbH->dim;
mas01mc@18 2256 sp=dataBuf+trackOffset+k*dbH->dim;
mas01mc@17 2257 DD[j][k]=0.0; // Initialize matched filter array
mas01mc@17 2258 dp=&D[j][k]; // point to correlation cell j,k
mas01mc@17 2259 *dp=0.0; // initialize correlation cell
mas01mc@17 2260 l=dbH->dim; // size of vectors
mas01mc@17 2261 while(l--)
mas01mc@17 2262 *dp+=*qp++**sp++;
mas01mc@17 2263 }
mas01mc@17 2264
mas01mc@17 2265 // Matched Filter
mas01mc@17 2266 // HOP SIZE == 1
mas01mc@17 2267 double* spd;
mas01mc@17 2268 if(HOP_SIZE==1){ // HOP_SIZE = shingleHop
mas01mc@17 2269 for(w=0; w<wL; w++)
mas01mc@17 2270 for(j=0; j<numVectors-w; j++){
mas01mc@17 2271 sp=DD[j];
mas01mc@17 2272 spd=D[j+w]+w;
mas01mc@18 2273 k=trackTable[track]-w;
mas01mc@17 2274 while(k--)
mas01mc@17 2275 *sp+++=*spd++;
mas01mc@17 2276 }
mas01mc@17 2277 }
mas01mc@17 2278
mas01mc@17 2279 else{ // HOP_SIZE != 1
mas01mc@17 2280 for(w=0; w<wL; w++)
mas01mc@17 2281 for(j=0; j<numVectors-w; j+=HOP_SIZE){
mas01mc@17 2282 sp=DD[j];
mas01mc@17 2283 spd=D[j+w]+w;
mas01mc@18 2284 for(k=0; k<trackTable[track]-w; k+=HOP_SIZE){
mas01mc@17 2285 *sp+=*spd;
mas01mc@17 2286 sp+=HOP_SIZE;
mas01mc@17 2287 spd+=HOP_SIZE;
mas01mc@17 2288 }
mas01mc@17 2289 }
mas01mc@17 2290 }
mas01mc@17 2291
mas01cr@60 2292 if(verbosity>3 && usingTimes) {
mas01mc@18 2293 cerr << "meanQdur=" << meanQdur << " meanDBdur=" << meanDBdur[track] << endl;
mas01mc@17 2294 cerr.flush();
mas01mc@17 2295 }
mas01mc@17 2296
mas01mc@17 2297 if(!usingTimes ||
mas01mc@17 2298 (usingTimes
mas01mc@18 2299 && fabs(meanDBdur[track]-meanQdur)<meanQdur*timesTol)){
mas01mc@17 2300
mas01cr@60 2301 if(verbosity>3 && usingTimes) {
mas01mc@17 2302 cerr << "within duration tolerance." << endl;
mas01mc@17 2303 cerr.flush();
mas01mc@17 2304 }
mas01mc@17 2305
mas01mc@17 2306 // Search for minimum distance by shingles (concatenated vectors)
mas01cr@70 2307 for(j=0;j<=numVectors-wL;j+=HOP_SIZE)
mas01cr@70 2308 for(k=0;k<=trackTable[track]-wL;k+=HOP_SIZE){
mas01cr@125 2309 thisDist=2-(2/(qnPtr[j]*sNorm[trackIndexOffset+k]))*DD[j][k];
mas01cr@60 2310 if(verbosity>10) {
mas01cr@125 2311 cerr << thisDist << " " << qnPtr[j] << " " << sNorm[trackIndexOffset+k] << endl;
mas01cr@60 2312 }
mas01mc@17 2313 // Gather chi^2 statistics
mas01mc@17 2314 if(thisDist<minSample)
mas01mc@17 2315 minSample=thisDist;
mas01mc@17 2316 else if(thisDist>maxSample)
mas01mc@17 2317 maxSample=thisDist;
mas01mc@17 2318 if(thisDist>1e-9){
mas01mc@17 2319 sampleCount++;
mas01mc@17 2320 sampleSum+=thisDist;
mas01mc@17 2321 logSampleSum+=log(thisDist);
mas01mc@17 2322 }
mas01mc@17 2323
mas01cr@125 2324 // diffL2 = fabs(qnPtr[j] - sNorm[trackIndexOffset+k]);
mas01mc@17 2325 // Power test
mas01mc@17 2326 if(!USE_THRESH ||
mas01mc@17 2327 // Threshold on mean L2 of Q and S sequences
mas01cr@125 2328 (USE_THRESH && qnPtr[j]>SILENCE_THRESH && sNorm[trackIndexOffset+k]>SILENCE_THRESH &&
mas01mc@17 2329 // Are both query and target windows above mean energy?
mas01cr@125 2330 (qnPtr[j]>qMeanL2*.25 && sNorm[trackIndexOffset+k]>sMeanL2[track]*.25))) // && diffL2 < DIFF_THRESH )))
mas01mc@17 2331 thisDist=thisDist; // Computed above
mas01mc@17 2332 else
mas01mc@17 2333 thisDist=1000000.0;
mas01mc@17 2334 if(thisDist>=0 && thisDist<=radius){
mas01mc@17 2335 distances[0]++; // increment count
mas01mc@18 2336 break; // only need one track point per query point
mas01mc@17 2337 }
mas01mc@17 2338 }
mas01mc@17 2339 // How many points were below threshold ?
mas01mc@17 2340 thisDist=distances[0];
mas01mc@17 2341
mas01mc@17 2342 // Let's see the distances then...
mas01cr@60 2343 if(verbosity>3) {
mas01mc@18 2344 cerr << fileTable+track*O2_FILETABLESIZE << " " << thisDist << endl;
mas01cr@60 2345 }
mas01mc@17 2346
mas01mc@18 2347 // All the track stuff goes here
mas01mc@18 2348 n=trackNN;
mas01mc@17 2349 while(n--){
mas01mc@18 2350 if(thisDist>trackDistances[n]){
mas01mc@18 2351 if((n==0 || thisDist<=trackDistances[n-1])){
mas01mc@17 2352 // Copy all values above up the queue
mas01mc@18 2353 for( l=trackNN-1 ; l > n ; l--){
mas01mc@18 2354 trackDistances[l]=trackDistances[l-1];
mas01mc@18 2355 trackQIndexes[l]=trackQIndexes[l-1];
mas01mc@18 2356 trackSIndexes[l]=trackSIndexes[l-1];
mas01mc@18 2357 trackIDs[l]=trackIDs[l-1];
mas01mc@17 2358 }
mas01mc@18 2359 trackDistances[n]=thisDist;
mas01mc@18 2360 trackQIndexes[n]=qIndexes[0];
mas01mc@18 2361 trackSIndexes[n]=sIndexes[0];
mas01mc@18 2362 successfulTracks++;
mas01mc@18 2363 trackIDs[n]=track;
mas01mc@17 2364 break;
mas01mc@17 2365 }
mas01mc@17 2366 }
mas01mc@17 2367 else
mas01mc@17 2368 break;
mas01mc@17 2369 }
mas01mc@17 2370 } // Duration match
mas01mc@17 2371
mas01mc@18 2372 // Clean up current track
mas01mc@17 2373 if(D!=NULL){
mas01mc@17 2374 for(j=0; j<numVectors; j++)
mas01mc@17 2375 delete[] D[j];
mas01mc@17 2376 }
mas01mc@17 2377
mas01mc@17 2378 if(DD!=NULL){
mas01mc@17 2379 for(j=0; j<numVectors; j++)
mas01mc@17 2380 delete[] DD[j];
mas01mc@17 2381 }
mas01mc@17 2382 }
mas01mc@18 2383 // per-track reset array values
mas01mc@17 2384 for(unsigned k=0; k<pointNN; k++){
mas01mc@17 2385 distances[k]=0.0;
mas01mc@17 2386 qIndexes[k]=~0;
mas01mc@17 2387 sIndexes[k]=~0;
mas01mc@17 2388 }
mas01mc@17 2389 }
mas01mc@17 2390
mas01mc@17 2391 gettimeofday(&tv2,NULL);
mas01cr@60 2392 if(verbosity>1) {
mas01mc@18 2393 cerr << endl << "processed tracks :" << processedTracks << " matched tracks: " << successfulTracks << " elapsed time:"
mas01mc@17 2394 << ( tv2.tv_sec*1000 + tv2.tv_usec/1000 ) - ( tv1.tv_sec*1000+tv1.tv_usec/1000 ) << " msec" << endl;
mas01mc@17 2395 cerr << "sampleCount: " << sampleCount << " sampleSum: " << sampleSum << " logSampleSum: " << logSampleSum
mas01mc@17 2396 << " minSample: " << minSample << " maxSample: " << maxSample << endl;
mas01mc@17 2397 }
mas01mc@17 2398
mas01cr@133 2399 if(adbQueryResponse==0){
mas01cr@60 2400 if(verbosity>1) {
mas01mc@17 2401 cerr<<endl;
mas01cr@60 2402 }
mas01mc@17 2403 // Output answer
mas01mc@17 2404 // Loop over nearest neighbours
mas01mc@18 2405 for(k=0; k < min(trackNN,successfulTracks); k++)
mas01mc@18 2406 cout << fileTable+trackIDs[k]*O2_FILETABLESIZE << " " << trackDistances[k] << endl;
mas01mc@17 2407 }
mas01mc@17 2408 else{ // Process Web Services Query
mas01mc@18 2409 int listLen = min(trackNN, processedTracks);
mas01cr@133 2410 adbQueryResponse->result.__sizeRlist=listLen;
mas01cr@133 2411 adbQueryResponse->result.__sizeDist=listLen;
mas01cr@133 2412 adbQueryResponse->result.__sizeQpos=listLen;
mas01cr@133 2413 adbQueryResponse->result.__sizeSpos=listLen;
mas01cr@133 2414 adbQueryResponse->result.Rlist= new char*[listLen];
mas01cr@133 2415 adbQueryResponse->result.Dist = new double[listLen];
mas01cr@133 2416 adbQueryResponse->result.Qpos = new unsigned int[listLen];
mas01cr@133 2417 adbQueryResponse->result.Spos = new unsigned int[listLen];
mas01cr@133 2418 for(k=0; k<(unsigned)adbQueryResponse->result.__sizeRlist; k++){
mas01cr@133 2419 adbQueryResponse->result.Rlist[k]=new char[O2_MAXFILESTR];
mas01cr@133 2420 adbQueryResponse->result.Dist[k]=trackDistances[k];
mas01cr@133 2421 adbQueryResponse->result.Qpos[k]=trackQIndexes[k];
mas01cr@133 2422 adbQueryResponse->result.Spos[k]=trackSIndexes[k];
mas01cr@133 2423 sprintf(adbQueryResponse->result.Rlist[k], "%s", fileTable+trackIDs[k]*O2_FILETABLESIZE);
mas01mc@17 2424 }
mas01mc@17 2425 }
mas01mc@17 2426
mas01mc@17 2427 // Clean up
mas01mc@18 2428 if(trackOffsetTable)
mas01mc@18 2429 delete[] trackOffsetTable;
mas01mc@17 2430 if(queryCopy)
mas01mc@17 2431 delete[] queryCopy;
mas01cr@121 2432 if(qNorm)
mas01cr@121 2433 delete[] qNorm;
mas01cr@121 2434 if(sNorm)
mas01cr@121 2435 delete[] sNorm;
mas01cr@121 2436 if(sMeanL2)
mas01cr@121 2437 delete[] sMeanL2;
mas01mc@17 2438 if(D)
mas01mc@17 2439 delete[] D;
mas01mc@17 2440 if(DD)
mas01mc@17 2441 delete[] DD;
mas01mc@17 2442 if(timesdata)
mas01mc@17 2443 delete[] timesdata;
mas01mc@17 2444 if(meanDBdur)
mas01mc@17 2445 delete[] meanDBdur;
mas01mc@17 2446
mas01mc@17 2447
mas01mc@17 2448 }
mas01mc@17 2449
mas01cr@0 2450 // Unit norm block of features
mas01cr@0 2451 void audioDB::unitNorm(double* X, unsigned dim, unsigned n, double* qNorm){
mas01cr@0 2452 unsigned d;
mas01cr@59 2453 double L2, *p;
mas01cr@60 2454 if(verbosity>2) {
mas01cr@0 2455 cerr << "norming " << n << " vectors...";cerr.flush();
mas01cr@60 2456 }
mas01cr@0 2457 while(n--){
mas01cr@0 2458 p=X;
mas01cr@0 2459 L2=0.0;
mas01cr@0 2460 d=dim;
mas01cr@0 2461 while(d--){
mas01cr@0 2462 L2+=*p**p;
mas01cr@0 2463 p++;
mas01cr@0 2464 }
mas01mc@17 2465 /* L2=sqrt(L2);*/
mas01cr@0 2466 if(qNorm)
mas01cr@0 2467 *qNorm++=L2;
mas01mc@17 2468 /*
mas01cr@0 2469 oneOverL2 = 1.0/L2;
mas01cr@0 2470 d=dim;
mas01cr@0 2471 while(d--){
mas01cr@0 2472 *X*=oneOverL2;
mas01cr@0 2473 X++;
mas01mc@17 2474 */
mas01mc@17 2475 X+=dim;
mas01cr@0 2476 }
mas01cr@60 2477 if(verbosity>2) {
mas01cr@0 2478 cerr << "done..." << endl;
mas01cr@60 2479 }
mas01cr@0 2480 }
mas01cr@0 2481
mas01cr@0 2482 // Unit norm block of features
mas01cr@0 2483 void audioDB::unitNormAndInsertL2(double* X, unsigned dim, unsigned n, unsigned append=0){
mas01cr@0 2484 unsigned d;
mas01cr@59 2485 double *p;
mas01cr@0 2486 unsigned nn = n;
mas01cr@0 2487
mas01cr@0 2488 assert(l2normTable);
mas01cr@0 2489
mas01cr@0 2490 if( !append && (dbH->flags & O2_FLAG_L2NORM) )
mas01cr@0 2491 error("Database is already L2 normed", "automatic norm on insert is enabled");
mas01cr@0 2492
mas01cr@60 2493 if(verbosity>2) {
mas01cr@0 2494 cerr << "norming " << n << " vectors...";cerr.flush();
mas01cr@60 2495 }
mas01cr@0 2496
mas01cr@0 2497 double* l2buf = new double[n];
mas01cr@0 2498 double* l2ptr = l2buf;
mas01cr@0 2499 assert(l2buf);
mas01cr@0 2500 assert(X);
mas01cr@0 2501
mas01cr@0 2502 while(nn--){
mas01cr@0 2503 p=X;
mas01cr@0 2504 *l2ptr=0.0;
mas01cr@0 2505 d=dim;
mas01cr@0 2506 while(d--){
mas01cr@0 2507 *l2ptr+=*p**p;
mas01cr@0 2508 p++;
mas01cr@0 2509 }
mas01mc@17 2510 l2ptr++;
mas01mc@17 2511 /*
mas01mc@17 2512 oneOverL2 = 1.0/(*l2ptr++);
mas01mc@17 2513 d=dim;
mas01mc@17 2514 while(d--){
mas01cr@0 2515 *X*=oneOverL2;
mas01cr@0 2516 X++;
mas01mc@17 2517 }
mas01mc@17 2518 */
mas01mc@17 2519 X+=dim;
mas01cr@0 2520 }
mas01cr@0 2521 unsigned offset;
mas01cr@84 2522 if(append) {
mas01cr@84 2523 // FIXME: a hack, a very palpable hack: the vectors have already
mas01cr@84 2524 // been inserted, and dbH->length has already been updated. We
mas01cr@84 2525 // need to subtract off again the number of vectors that we've
mas01cr@84 2526 // inserted this time...
mas01cr@84 2527 offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors
mas01cr@84 2528 } else {
mas01cr@0 2529 offset=0;
mas01cr@84 2530 }
mas01cr@0 2531 memcpy(l2normTable+offset, l2buf, n*sizeof(double));
mas01cr@0 2532 if(l2buf)
mas01mc@17 2533 delete[] l2buf;
mas01cr@60 2534 if(verbosity>2) {
mas01cr@0 2535 cerr << "done..." << endl;
mas01cr@60 2536 }
mas01cr@0 2537 }
mas01cr@0 2538
mas01cr@0 2539
mas01cr@0 2540 // Start an audioDB server on the host
mas01cr@0 2541 void audioDB::startServer(){
mas01cr@0 2542 struct soap soap;
mas01cr@0 2543 int m, s; // master and slave sockets
mas01cr@0 2544 soap_init(&soap);
mas01cr@92 2545 // FIXME: largely this use of SO_REUSEADDR is to make writing (and
mas01cr@92 2546 // running) test cases more convenient, so that multiple test runs
mas01cr@92 2547 // in close succession don't fail because of a bin() error.
mas01cr@92 2548 // Investigate whether there are any potential drawbacks in this,
mas01cr@92 2549 // and also whether there's a better way to write the tests. --
mas01cr@92 2550 // CSR, 2007-10-03
mas01cr@92 2551 soap.bind_flags |= SO_REUSEADDR;
mas01cr@0 2552 m = soap_bind(&soap, NULL, port, 100);
mas01cr@0 2553 if (m < 0)
mas01cr@0 2554 soap_print_fault(&soap, stderr);
mas01cr@0 2555 else
mas01cr@0 2556 {
mas01cr@0 2557 fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
mas01cr@0 2558 for (int i = 1; ; i++)
mas01cr@0 2559 {
mas01cr@0 2560 s = soap_accept(&soap);
mas01cr@0 2561 if (s < 0)
mas01cr@0 2562 {
mas01cr@0 2563 soap_print_fault(&soap, stderr);
mas01cr@0 2564 break;
mas01cr@0 2565 }
mas01cr@75 2566 fprintf(stderr, "%d: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d\n", i,
mas01cr@0 2567 (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
mas01cr@0 2568 if (soap_serve(&soap) != SOAP_OK) // process RPC request
mas01cr@0 2569 soap_print_fault(&soap, stderr); // print error
mas01cr@0 2570 fprintf(stderr, "request served\n");
mas01cr@0 2571 soap_destroy(&soap); // clean up class instances
mas01cr@0 2572 soap_end(&soap); // clean up everything and close socket
mas01cr@0 2573 }
mas01cr@0 2574 }
mas01cr@0 2575 soap_done(&soap); // close master socket and detach environment
mas01cr@0 2576 }
mas01cr@0 2577
mas01cr@0 2578
mas01cr@0 2579 // web services
mas01cr@0 2580
mas01cr@0 2581 // SERVER SIDE
mas01cr@133 2582 int adb__status(struct soap* soap, xsd__string dbName, adb__statusResponse &adbStatusResponse){
mas01cr@21 2583 char* const argv[]={"audioDB",COM_STATUS,"-d",dbName};
mas01cr@21 2584 const unsigned argc = 4;
mas01cr@77 2585 try {
mas01cr@133 2586 audioDB(argc, argv, &adbStatusResponse);
mas01cr@77 2587 return SOAP_OK;
mas01cr@77 2588 } catch(char *err) {
mas01cr@77 2589 soap_receiver_fault(soap, err, "");
mas01cr@77 2590 return SOAP_FAULT;
mas01cr@77 2591 }
mas01cr@0 2592 }
mas01cr@0 2593
mas01cr@0 2594 // Literal translation of command line to web service
mas01cr@0 2595
mas01cr@133 2596 int adb__query(struct soap* soap, xsd__string dbName, xsd__string qKey, xsd__string keyList, xsd__string timesFileName, xsd__int qType, xsd__int qPos, xsd__int pointNN, xsd__int trackNN, xsd__int seqLen, adb__queryResponse &adbQueryResponse){
mas01cr@0 2597 char queryType[256];
mas01cr@0 2598 for(int k=0; k<256; k++)
mas01cr@0 2599 queryType[k]='\0';
mas01cr@105 2600 if(qType == O2_POINT_QUERY)
mas01cr@0 2601 strncpy(queryType, "point", strlen("point"));
mas01cr@105 2602 else if (qType == O2_SEQUENCE_QUERY)
mas01cr@0 2603 strncpy(queryType, "sequence", strlen("sequence"));
mas01cr@105 2604 else if(qType == O2_TRACK_QUERY)
mas01mc@18 2605 strncpy(queryType,"track", strlen("track"));
mas01cr@0 2606 else
mas01cr@0 2607 strncpy(queryType, "", strlen(""));
mas01cr@0 2608
mas01cr@0 2609 if(pointNN==0)
mas01cr@0 2610 pointNN=10;
mas01mc@18 2611 if(trackNN==0)
mas01mc@18 2612 trackNN=10;
mas01cr@0 2613 if(seqLen==0)
mas01cr@0 2614 seqLen=16;
mas01cr@0 2615
mas01cr@0 2616 char qPosStr[256];
mas01cr@0 2617 sprintf(qPosStr, "%d", qPos);
mas01cr@0 2618 char pointNNStr[256];
mas01cr@0 2619 sprintf(pointNNStr,"%d",pointNN);
mas01mc@18 2620 char trackNNStr[256];
mas01mc@18 2621 sprintf(trackNNStr,"%d",trackNN);
mas01cr@0 2622 char seqLenStr[256];
mas01cr@0 2623 sprintf(seqLenStr,"%d",seqLen);
mas01cr@0 2624
mas01cr@0 2625 const char* argv[] ={
mas01cr@0 2626 "./audioDB",
mas01cr@0 2627 COM_QUERY,
mas01cr@0 2628 queryType, // Need to pass a parameter
mas01cr@0 2629 COM_DATABASE,
mas01cr@0 2630 dbName,
mas01cr@0 2631 COM_FEATURES,
mas01cr@0 2632 qKey,
mas01cr@0 2633 COM_KEYLIST,
mas01cr@0 2634 keyList==0?"":keyList,
mas01cr@0 2635 COM_TIMES,
mas01cr@0 2636 timesFileName==0?"":timesFileName,
mas01cr@0 2637 COM_QPOINT,
mas01cr@0 2638 qPosStr,
mas01cr@0 2639 COM_POINTNN,
mas01cr@0 2640 pointNNStr,
mas01mc@18 2641 COM_TRACKNN,
mas01mc@18 2642 trackNNStr, // Need to pass a parameter
mas01cr@0 2643 COM_SEQLEN,
mas01cr@0 2644 seqLenStr
mas01cr@0 2645 };
mas01cr@0 2646
mas01cr@0 2647 const unsigned argc = 19;
mas01cr@79 2648 try {
mas01cr@133 2649 audioDB(argc, (char* const*)argv, &adbQueryResponse);
mas01cr@79 2650 return SOAP_OK;
mas01cr@79 2651 } catch (char *err) {
mas01cr@79 2652 soap_receiver_fault(soap, err, "");
mas01cr@79 2653 return SOAP_FAULT;
mas01cr@79 2654 }
mas01cr@0 2655 }
mas01cr@0 2656
mas01cr@0 2657 int main(const unsigned argc, char* const argv[]){
mas01cr@0 2658 audioDB(argc, argv);
mas01cr@0 2659 }
mas01cr@104 2660