annotate audioDB.cpp @ 116:531ce5162861 endian-neutral

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