annotate audioDB.cpp @ 142:c74048e9b569 powertable

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