annotate audioDB.cpp @ 537:5da228727a2d

Removed obsolete dbH header pointer dereferences in audioDB.cpp. Replaced with the API adb->header type calls. The dbH calls were causing segfaults when attempting to index an empty database or during batch inserts in some rare cases.
author mas01mc
date Fri, 06 Feb 2009 17:08:21 +0000
parents c7bdb7913762
children e18843dc0aea
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@498 2 #include "reporter.h"
mas01cr@0 3
mas01mc@324 4 char* SERVER_ADB_ROOT;
mas01mc@324 5 char* SERVER_ADB_FEATURE_ROOT;
mas01mc@308 6
mas01cr@370 7 audioDB::audioDB(const unsigned argc, const char *argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@76 8 {
mas01cr@0 9 if(processArgs(argc, argv)<0){
mas01cr@0 10 printf("No command found.\n");
mas01cr@0 11 cmdline_parser_print_version ();
mas01cr@0 12 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 13 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 14 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 15 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 16 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 17 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@151 18 error("No command found");
mas01cr@0 19 }
mas01cr@77 20
mas01mc@324 21 // Perform database prefix substitution
mas01mc@328 22 if(dbName && adb_root)
mas01mc@324 23 prefix_name((char** const)&dbName, adb_root);
mas01mc@324 24
mas01mc@474 25 if(O2_ACTION(COM_SERVER)){
mas01cr@0 26 startServer();
mas01mc@474 27 }
mas01cr@0 28 else if(O2_ACTION(COM_CREATE))
mas01cr@0 29 create(dbName);
mas01cr@0 30
mas01cr@0 31 else if(O2_ACTION(COM_INSERT))
mas01cr@0 32 insert(dbName, inFile);
mas01cr@0 33
mas01cr@0 34 else if(O2_ACTION(COM_BATCHINSERT))
mas01cr@0 35 batchinsert(dbName, inFile);
mas01cr@0 36
mas01cr@0 37 else if(O2_ACTION(COM_QUERY))
mas01mc@307 38 if(isClient){
mas01mc@329 39 if(query_from_key){
mas01mc@332 40 VERB_LOG(1, "Calling web services query %s on database %s, query=%s\n", radius>0?"(Radius)":"(NN)", dbName, (key&&strlen(key))?key:inFile);
mas01mc@328 41 ws_query_by_key(dbName, key, inFile, (char*)hostport);
mas01mc@329 42 }
mas01mc@329 43 else{
mas01mc@332 44 VERB_LOG(1, "Calling web services query on database %s, query=%s\n", dbName, (key&&strlen(key))?key:inFile);
mas01mc@307 45 ws_query(dbName, inFile, (char*)hostport);
mas01mc@329 46 }
mas01mc@307 47 }
mas01cr@0 48 else
mas01cr@76 49 query(dbName, inFile);
mas01cr@0 50
mas01cr@0 51 else if(O2_ACTION(COM_STATUS))
mas01cr@0 52 if(isClient)
mas01cr@0 53 ws_status(dbName,(char*)hostport);
mas01cr@0 54 else
mas01cr@0 55 status(dbName);
mas01cr@280 56
mas01cr@280 57 else if(O2_ACTION(COM_SAMPLE))
mas01cr@280 58 sample(dbName);
mas01cr@0 59
mas01cr@0 60 else if(O2_ACTION(COM_L2NORM))
mas01cr@0 61 l2norm(dbName);
mas01cr@0 62
mas01cr@193 63 else if(O2_ACTION(COM_POWER))
mas01cr@193 64 power_flag(dbName);
mas01cr@193 65
mas01cr@0 66 else if(O2_ACTION(COM_DUMP))
mas01cr@0 67 dump(dbName);
mas01mc@292 68
mas01mc@334 69 else if(O2_ACTION(COM_LISZT))
mas01mc@334 70 if(isClient)
mas01mc@334 71 ws_liszt(dbName, (char*) hostport);
mas01mc@334 72 else
mas01mc@334 73 liszt(dbName, lisztOffset, lisztLength);
mas01mc@334 74
mas01mc@292 75 else if(O2_ACTION(COM_INDEX))
mas01mc@292 76 index_index_db(dbName);
mas01cr@0 77
mas01cr@0 78 else
mas01cr@0 79 error("Unrecognized command",command);
mas01cr@0 80 }
mas01cr@0 81
mas01cr@508 82 audioDB::audioDB(const unsigned argc, const char *argv[], struct soap *soap, adb__queryResponse *adbQueryResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 83 {
mas01cr@97 84 try {
mas01mc@338 85 isServer = 1; // Set to make errors report over SOAP
mas01cr@97 86 processArgs(argc, argv);
mas01mc@324 87 // Perform database prefix substitution
mas01mc@328 88 if(dbName && adb_root)
mas01mc@324 89 prefix_name((char** const)&dbName, adb_root);
mas01cr@97 90 assert(O2_ACTION(COM_QUERY));
mas01cr@508 91 query(dbName, inFile, soap, adbQueryResponse);
mas01cr@97 92 } catch(char *err) {
mas01cr@97 93 cleanup();
mas01cr@97 94 throw(err);
mas01cr@97 95 }
mas01cr@76 96 }
mas01cr@76 97
mas01cr@370 98 audioDB::audioDB(const unsigned argc, const char *argv[], adb__statusResponse *adbStatusResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 99 {
mas01cr@97 100 try {
mas01mc@338 101 isServer = 1; // Set to make errors report over SOAP
mas01cr@97 102 processArgs(argc, argv);
mas01mc@324 103 // Perform database prefix substitution
mas01mc@328 104 if(dbName && adb_root)
mas01mc@324 105 prefix_name((char** const)&dbName, adb_root);
mas01cr@97 106 assert(O2_ACTION(COM_STATUS));
mas01cr@133 107 status(dbName, adbStatusResponse);
mas01cr@97 108 } catch(char *err) {
mas01cr@97 109 cleanup();
mas01cr@97 110 throw(err);
mas01cr@97 111 }
mas01cr@76 112 }
mas01cr@76 113
mas01cr@370 114 audioDB::audioDB(const unsigned argc, const char *argv[], adb__lisztResponse *adbLisztResponse): O2_AUDIODB_INITIALIZERS
mas01mc@334 115 {
mas01mc@334 116 try {
mas01mc@338 117 isServer = 1; // Set to make errors report over SOAP
mas01mc@338 118 processArgs(argc, argv);
mas01mc@334 119 // Perform database prefix substitution
mas01mc@334 120 if(dbName && adb_root)
mas01mc@334 121 prefix_name((char** const)&dbName, adb_root);
mas01mc@334 122 assert(O2_ACTION(COM_LISZT));
mas01mc@334 123 liszt(dbName, lisztOffset, lisztLength, adbLisztResponse);
mas01mc@334 124 } catch(char *err) {
mas01mc@334 125 cleanup();
mas01mc@334 126 throw(err);
mas01mc@334 127 }
mas01mc@334 128 }
mas01mc@334 129
mas01cr@97 130 void audioDB::cleanup() {
mas01cr@122 131 cmdline_parser_free(&args_info);
mas01cr@196 132 if(fileTable)
mas01cr@196 133 munmap(fileTable, fileTableLength);
mas01cr@196 134 if(trackTable)
mas01cr@196 135 munmap(trackTable, trackTableLength);
mas01cr@196 136 if(timesTable)
mas01cr@196 137 munmap(timesTable, timesTableLength);
mas01mc@314 138 if(powerTable)
mas01mc@314 139 munmap(powerTable, powerTableLength);
mas01cr@196 140 if(l2normTable)
mas01cr@196 141 munmap(l2normTable, l2normTableLength);
mas01mc@324 142 if(featureFileNameTable)
mas01mc@324 143 munmap(featureFileNameTable, fileTableLength);
mas01mc@324 144 if(timesFileNameTable)
mas01mc@324 145 munmap(timesFileNameTable, fileTableLength);
mas01mc@324 146 if(powerFileNameTable)
mas01mc@324 147 munmap(powerFileNameTable, fileTableLength);
mas01mc@292 148 if(reporter)
mas01mc@292 149 delete reporter;
mas01cr@284 150 if(rng)
mas01cr@284 151 gsl_rng_free(rng);
mas01cr@0 152 if(infid>0)
mas01cr@0 153 close(infid);
mas01cr@498 154 if(adb) {
mas01cr@498 155 audiodb_close(adb);
mas01cr@498 156 adb = NULL;
mas01cr@498 157 }
mas01cr@498 158 if(lsh)
mas01mc@308 159 delete lsh;
mas01cr@0 160 }
mas01cr@0 161
mas01cr@97 162 audioDB::~audioDB(){
mas01cr@97 163 cleanup();
mas01cr@97 164 }
mas01cr@97 165
mas01cr@370 166 int audioDB::processArgs(const unsigned argc, const char *argv[]){
mas01cr@0 167
mas01cr@0 168 if(argc<2){
mas01cr@0 169 cmdline_parser_print_version ();
mas01cr@0 170 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 171 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 172 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 173 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 174 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 175 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 176 exit(0);
mas01cr@0 177 }
mas01cr@0 178
mas01cr@345 179 /* KLUDGE: gengetopt generates a function which is not completely
mas01cr@345 180 const-clean in its declaration. We cast argv here to keep the
mas01cr@345 181 compiler happy. -- CSR, 2008-10-08 */
mas01cr@345 182 if (cmdline_parser (argc, (char *const *) argv, &args_info) != 0)
mas01cr@151 183 error("Error parsing command line");
mas01cr@0 184
mas01cr@0 185 if(args_info.help_given){
mas01cr@0 186 cmdline_parser_print_help();
mas01cr@0 187 exit(0);
mas01cr@0 188 }
mas01cr@0 189
mas01cr@0 190 if(args_info.verbosity_given){
mas01cr@239 191 verbosity = args_info.verbosity_arg;
mas01cr@239 192 if(verbosity < 0 || verbosity > 10){
mas01cr@239 193 std::cerr << "Warning: verbosity out of range, setting to 1" << std::endl;
mas01cr@239 194 verbosity = 1;
mas01cr@0 195 }
mas01cr@0 196 }
mas01cr@0 197
mas01cr@129 198 if(args_info.size_given) {
mas01cr@256 199 if(args_info.datasize_given) {
mas01cr@256 200 error("both --size and --datasize given", "");
mas01cr@256 201 }
mas01cr@256 202 if(args_info.ntracks_given) {
mas01cr@256 203 error("both --size and --ntracks given", "");
mas01cr@256 204 }
mas01cr@256 205 if(args_info.datadim_given) {
mas01cr@256 206 error("both --size and --datadim given", "");
mas01cr@256 207 }
mas01cr@196 208 if (args_info.size_arg < 50 || args_info.size_arg > 32000) {
mas01cr@129 209 error("Size out of range", "");
mas01cr@129 210 }
mas01cr@256 211 double ratio = (double) args_info.size_arg * 1000000 / ((double) O2_DEFAULTDBSIZE);
mas01cr@256 212 /* FIXME: what's the safe way of doing this? */
mas01cr@256 213 datasize = (unsigned int) ceil(datasize * ratio);
mas01cr@256 214 ntracks = (unsigned int) ceil(ntracks * ratio);
mas01cr@256 215 } else {
mas01cr@256 216 if(args_info.datasize_given) {
mas01cr@256 217 datasize = args_info.datasize_arg;
mas01cr@256 218 }
mas01cr@256 219 if(args_info.ntracks_given) {
mas01cr@256 220 ntracks = args_info.ntracks_arg;
mas01cr@256 221 }
mas01cr@256 222 if(args_info.datadim_given) {
mas01cr@256 223 datadim = args_info.datadim_arg;
mas01cr@256 224 }
mas01cr@129 225 }
mas01cr@129 226
mas01cr@239 227 if(args_info.radius_given) {
mas01cr@239 228 radius = args_info.radius_arg;
mas01mc@307 229 if(radius < 0 || radius > 1000000000) {
mas01cr@77 230 error("radius out of range");
mas01cr@239 231 } else {
mas01cr@239 232 VERB_LOG(3, "Setting radius to %f\n", radius);
mas01mc@17 233 }
mas01mc@17 234 }
mas01mc@17 235
mas01mc@292 236 sequenceLength = args_info.sequencelength_arg;
mas01mc@292 237 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01mc@292 238 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01mc@292 239 }
mas01mc@292 240 sequenceHop = args_info.sequencehop_arg;
mas01mc@292 241 if(sequenceHop < 1 || sequenceHop > 1000) {
mas01mc@292 242 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01mc@292 243 }
mas01mc@292 244
mas01mc@292 245 if (args_info.absolute_threshold_given) {
mas01mc@292 246 if (args_info.absolute_threshold_arg >= 0) {
mas01mc@292 247 error("absolute threshold out of range: should be negative");
mas01mc@292 248 }
mas01mc@292 249 use_absolute_threshold = true;
mas01mc@292 250 absolute_threshold = args_info.absolute_threshold_arg;
mas01mc@292 251 }
mas01mc@292 252 if (args_info.relative_threshold_given) {
mas01mc@292 253 use_relative_threshold = true;
mas01mc@292 254 relative_threshold = args_info.relative_threshold_arg;
mas01mc@292 255 }
mas01mc@292 256
mas01mc@324 257 if (args_info.adb_root_given){
mas01mc@324 258 adb_root = args_info.adb_root_arg;
mas01mc@324 259 }
mas01mc@324 260
mas01mc@324 261 if (args_info.adb_feature_root_given){
mas01mc@324 262 adb_feature_root = args_info.adb_feature_root_arg;
mas01mc@324 263 }
mas01mc@324 264
mas01mc@324 265 // perform dbName path prefix SERVER-side subsitution
mas01mc@324 266 if(SERVER_ADB_ROOT && !adb_root)
mas01mc@324 267 adb_root = SERVER_ADB_ROOT;
mas01mc@324 268 if(SERVER_ADB_FEATURE_ROOT && !adb_feature_root)
mas01mc@324 269 adb_feature_root = SERVER_ADB_FEATURE_ROOT;
mas01mc@339 270
mas01cr@0 271 if(args_info.SERVER_given){
mas01cr@0 272 command=COM_SERVER;
mas01cr@0 273 port=args_info.SERVER_arg;
mas01cr@0 274 if(port<100 || port > 100000)
mas01cr@0 275 error("port out of range");
mas01cr@105 276 #if defined(O2_DEBUG)
mas01cr@104 277 struct sigaction sa;
mas01cr@104 278 sa.sa_sigaction = sigterm_action;
mas01cr@104 279 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 280 sigaction(SIGTERM, &sa, NULL);
mas01cr@104 281 sa.sa_sigaction = sighup_action;
mas01cr@104 282 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 283 sigaction(SIGHUP, &sa, NULL);
mas01cr@105 284 #endif
mas01mc@308 285 if(args_info.load_index_given){
mas01mc@308 286 if(!args_info.database_given)
mas01mc@308 287 error("load_index requires a --database argument");
mas01mc@308 288 else
mas01mc@308 289 dbName=args_info.database_arg;
mas01mc@308 290 if(!args_info.radius_given)
mas01mc@308 291 error("load_index requires a --radius argument");
mas01mc@308 292 if(!args_info.sequencelength_given)
mas01mc@308 293 error("load_index requires a --sequenceLength argument");
mas01mc@308 294 WS_load_index = true;
mas01mc@308 295 }
mas01cr@0 296 return 0;
mas01cr@0 297 }
mas01cr@0 298
mas01cr@0 299 // No return on client command, find database command
mas01cr@105 300 if(args_info.client_given){
mas01cr@105 301 command=COM_CLIENT;
mas01cr@105 302 hostport=args_info.client_arg;
mas01cr@105 303 isClient=1;
mas01cr@105 304 }
mas01cr@0 305
mas01cr@105 306 if(args_info.NEW_given){
mas01cr@105 307 command=COM_CREATE;
mas01cr@105 308 dbName=args_info.database_arg;
mas01cr@105 309 return 0;
mas01cr@105 310 }
mas01cr@0 311
mas01cr@105 312 if(args_info.STATUS_given){
mas01cr@105 313 command=COM_STATUS;
mas01cr@105 314 dbName=args_info.database_arg;
mas01cr@105 315 return 0;
mas01cr@105 316 }
mas01cr@0 317
mas01cr@280 318 if(args_info.SAMPLE_given) {
mas01cr@280 319 command = COM_SAMPLE;
mas01cr@280 320 dbName = args_info.database_arg;
mas01cr@280 321 sequenceLength = args_info.sequencelength_arg;
mas01cr@280 322 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01cr@280 323 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@280 324 }
mas01cr@280 325 nsamples = args_info.nsamples_arg;
mas01cr@280 326 return 0;
mas01cr@280 327 }
mas01cr@280 328
mas01cr@105 329 if(args_info.DUMP_given){
mas01cr@105 330 command=COM_DUMP;
mas01cr@105 331 dbName=args_info.database_arg;
mas01cr@131 332 output = args_info.output_arg;
mas01cr@105 333 return 0;
mas01cr@105 334 }
mas01cr@0 335
mas01cr@105 336 if(args_info.L2NORM_given){
mas01cr@105 337 command=COM_L2NORM;
mas01cr@105 338 dbName=args_info.database_arg;
mas01cr@105 339 return 0;
mas01cr@105 340 }
mas01cr@0 341
mas01cr@193 342 if(args_info.POWER_given){
mas01cr@193 343 command=COM_POWER;
mas01cr@193 344 dbName=args_info.database_arg;
mas01cr@193 345 return 0;
mas01cr@193 346 }
mas01cr@193 347
mas01cr@370 348 if(args_info.INSERT_given) {
mas01cr@105 349 command=COM_INSERT;
mas01cr@105 350 dbName=args_info.database_arg;
mas01cr@105 351 inFile=args_info.features_arg;
mas01cr@370 352 if(args_info.key_given) {
mas01cr@370 353 if(!args_info.features_given) {
mas01mc@292 354 error("INSERT: '-k key' argument depends on '-f features'");
mas01cr@370 355 } else {
mas01mc@292 356 key=args_info.key_arg;
mas01cr@370 357 }
mas01cr@370 358 }
mas01cr@370 359 if(args_info.times_given) {
mas01cr@105 360 timesFileName=args_info.times_arg;
mas01cr@370 361 if(strlen(timesFileName)>0) {
mas01cr@370 362 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in))) {
mas01cr@105 363 error("Could not open times file for reading", timesFileName);
mas01cr@370 364 }
mas01cr@105 365 usingTimes=1;
mas01cr@105 366 }
mas01cr@105 367 }
mas01cr@193 368 if (args_info.power_given) {
mas01cr@193 369 powerFileName = args_info.power_arg;
mas01cr@193 370 if (strlen(powerFileName) > 0) {
mas01cr@193 371 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 372 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 373 }
mas01cr@193 374 usingPower = 1;
mas01cr@193 375 }
mas01cr@193 376 }
mas01cr@105 377 return 0;
mas01cr@105 378 }
mas01cr@105 379
mas01cr@370 380 if(args_info.BATCHINSERT_given) {
mas01cr@105 381 command=COM_BATCHINSERT;
mas01cr@105 382 dbName=args_info.database_arg;
mas01cr@105 383 inFile=args_info.featureList_arg;
mas01cr@370 384 if(args_info.keyList_given) {
mas01cr@370 385 if(!args_info.featureList_given) {
mas01tc@300 386 error("BATCHINSERT: '-K keyList' argument depends on '-F featureList'");
mas01cr@370 387 } else {
mas01cr@304 388 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@370 389 }
mas01cr@370 390 }
mas01cr@105 391 /* TO DO: REPLACE WITH
mas01cr@0 392 if(args_info.keyList_given){
mas01mc@18 393 trackFileName=args_info.keyList_arg;
mas01cr@239 394 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01mc@18 395 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 396 }
mas01cr@0 397 AND UPDATE BATCHINSERT()
mas01cr@105 398 */
mas01cr@105 399
mas01cr@370 400 if(args_info.timesList_given) {
mas01cr@105 401 timesFileName=args_info.timesList_arg;
mas01cr@370 402 if(strlen(timesFileName)>0) {
mas01cr@239 403 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 404 error("Could not open timesList file for reading", timesFileName);
mas01cr@105 405 usingTimes=1;
mas01cr@105 406 }
mas01cr@105 407 }
mas01cr@370 408 if(args_info.powerList_given) {
mas01cr@193 409 powerFileName=args_info.powerList_arg;
mas01cr@370 410 if(strlen(powerFileName)>0) {
mas01cr@239 411 if(!(powerFile = new std::ifstream(powerFileName,std::ios::in)))
mas01cr@193 412 error("Could not open powerList file for reading", powerFileName);
mas01cr@193 413 usingPower=1;
mas01cr@193 414 }
mas01cr@193 415 }
mas01cr@105 416 return 0;
mas01cr@105 417 }
mas01mc@292 418
mas01mc@292 419 // Set no_unit_norm flag
mas01mc@292 420 no_unit_norming = args_info.no_unit_norming_flag;
mas01mc@292 421 lsh_use_u_functions = args_info.lsh_use_u_functions_flag;
mas01mc@292 422
mas01mc@292 423 // LSH Index Command
mas01mc@292 424 if(args_info.INDEX_given){
mas01mc@292 425 if(radius <= 0 )
mas01mc@292 426 error("INDEXing requires a Radius argument");
mas01mc@292 427 if(!(sequenceLength>0 && sequenceLength <= O2_MAXSEQLEN))
mas01mc@292 428 error("INDEXing requires 1 <= sequenceLength <= 1000");
mas01mc@292 429 command=COM_INDEX;
mas01mc@337 430 if(!args_info.database_given)
mas01mc@337 431 error("INDEXing requires a database");
mas01mc@292 432 dbName=args_info.database_arg;
mas01mc@292 433
mas01mc@292 434 // Whether to store LSH hash tables for query in core (FORMAT2)
mas01mc@297 435 lsh_in_core = !args_info.lsh_on_disk_flag; // This flag is set to 0 if on_disk requested
mas01mc@292 436
mas01mc@292 437 lsh_param_w = args_info.lsh_w_arg;
mas01mc@292 438 if(!(lsh_param_w>0 && lsh_param_w<=O2_SERIAL_MAX_BINWIDTH))
mas01mc@292 439 error("Indexing parameter w out of range (0.0 < w <= 100.0)");
mas01mc@292 440
mas01mc@292 441 lsh_param_k = args_info.lsh_k_arg;
mas01mc@292 442 if(!(lsh_param_k>0 && lsh_param_k<=O2_SERIAL_MAX_FUNS))
mas01mc@292 443 error("Indexing parameter k out of range (1 <= k <= 100)");
mas01mc@292 444
mas01mc@292 445 lsh_param_m = args_info.lsh_m_arg;
mas01mc@292 446 if(!(lsh_param_m>0 && lsh_param_m<= (1 + (sqrt(1 + O2_SERIAL_MAX_TABLES*8.0)))/2.0))
mas01mc@292 447 error("Indexing parameter m out of range (1 <= m <= 20)");
mas01mc@292 448
mas01mc@292 449 lsh_param_N = args_info.lsh_N_arg;
mas01mc@292 450 if(!(lsh_param_N>0 && lsh_param_N<=O2_SERIAL_MAX_ROWS))
mas01mc@292 451 error("Indexing parameter N out of range (1 <= N <= 1000000)");
mas01mc@292 452
mas01mc@292 453 lsh_param_b = args_info.lsh_b_arg;
mas01mc@292 454 if(!(lsh_param_b>0 && lsh_param_b<=O2_SERIAL_MAX_TRACKBATCH))
mas01mc@292 455 error("Indexing parameter b out of range (1 <= b <= 10000)");
mas01mc@292 456
mas01mc@296 457 lsh_param_ncols = args_info.lsh_ncols_arg;
mas01mc@296 458 if(lsh_in_core) // We don't want to block rows with FORMAT2 indexing
mas01mc@296 459 lsh_param_ncols = O2_SERIAL_MAX_COLS;
mas01mc@292 460 if( !(lsh_param_ncols>0 && lsh_param_ncols<=O2_SERIAL_MAX_COLS))
mas01mc@292 461 error("Indexing parameter ncols out of range (1 <= ncols <= 1000");
mas01mc@292 462
mas01mc@292 463 return 0;
mas01mc@292 464 }
mas01mc@292 465
mas01cr@105 466 // Query command and arguments
mas01cr@105 467 if(args_info.QUERY_given){
mas01cr@105 468 command=COM_QUERY;
mas01cr@105 469 dbName=args_info.database_arg;
mas01mc@292 470 // XOR features and key search
mas01cr@370 471 if((!args_info.features_given && !args_info.key_given) || (args_info.features_given && args_info.key_given))
mas01mc@292 472 error("QUERY requires exactly one of either -f features or -k key");
mas01mc@292 473 if(args_info.features_given)
mas01mc@292 474 inFile=args_info.features_arg; // query from file
mas01mc@292 475 else{
mas01mc@292 476 query_from_key = true;
mas01mc@292 477 key=args_info.key_arg; // query from key
mas01mc@292 478 }
mas01mc@292 479
mas01cr@105 480 if(args_info.keyList_given){
mas01cr@105 481 trackFileName=args_info.keyList_arg;
mas01cr@239 482 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01cr@105 483 error("Could not open keyList file for reading",trackFileName);
mas01cr@105 484 }
mas01cr@105 485
mas01cr@105 486 if(args_info.times_given){
mas01cr@105 487 timesFileName=args_info.times_arg;
mas01cr@105 488 if(strlen(timesFileName)>0){
mas01cr@239 489 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 490 error("Could not open times file for reading", timesFileName);
mas01cr@105 491 usingTimes=1;
mas01cr@105 492 }
mas01cr@105 493 }
mas01cr@193 494
mas01cr@193 495 if(args_info.power_given){
mas01cr@193 496 powerFileName=args_info.power_arg;
mas01cr@193 497 if(strlen(powerFileName)>0){
mas01cr@193 498 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 499 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 500 }
mas01cr@193 501 usingPower = 1;
mas01cr@193 502 }
mas01cr@193 503 }
mas01cr@105 504
mas01cr@105 505 // query type
mas01cr@105 506 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01cr@105 507 queryType=O2_TRACK_QUERY;
mas01cr@105 508 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@105 509 queryType=O2_POINT_QUERY;
mas01cr@105 510 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@105 511 queryType=O2_SEQUENCE_QUERY;
mas01mc@248 512 else if(strncmp(args_info.QUERY_arg, "nsequence", MAXSTR)==0)
mas01mc@248 513 queryType=O2_N_SEQUENCE_QUERY;
mas01mc@263 514 else if(strncmp(args_info.QUERY_arg, "onetoonensequence", MAXSTR)==0)
mas01mc@263 515 queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
mas01cr@105 516 else
mas01cr@105 517 error("unsupported query type",args_info.QUERY_arg);
mas01cr@105 518
mas01cr@105 519 if(!args_info.exhaustive_flag){
mas01cr@105 520 queryPoint = args_info.qpoint_arg;
mas01cr@105 521 usingQueryPoint=1;
mas01mc@467 522 if(queryPoint<0 || queryPoint >O2_MAX_VECTORS)
mas01mc@467 523 error("queryPoint out of range: 0 <= queryPoint <= O2_MAX_VECTORS");
mas01cr@105 524 }
mas01mc@292 525
mas01mc@296 526 // Whether to pre-load LSH hash tables for query (default on, if flag set then off)
mas01mc@297 527 lsh_in_core = !args_info.lsh_on_disk_flag;
mas01mc@292 528
mas01mc@292 529 // Whether to perform exact evaluation of points returned by LSH
mas01mc@292 530 lsh_exact = args_info.lsh_exact_flag;
mas01mc@292 531
mas01cr@105 532 pointNN = args_info.pointnn_arg;
mas01mc@263 533 if(pointNN < 1 || pointNN > O2_MAXNN) {
mas01mc@263 534 error("pointNN out of range: 1 <= pointNN <= 1000000");
mas01cr@105 535 }
mas01cr@105 536 trackNN = args_info.resultlength_arg;
mas01mc@263 537 if(trackNN < 1 || trackNN > O2_MAXNN) {
mas01mc@263 538 error("resultlength out of range: 1 <= resultlength <= 1000000");
mas01cr@105 539 }
mas01cr@105 540 return 0;
mas01cr@105 541 }
mas01mc@334 542
mas01mc@334 543 if(args_info.LISZT_given){
mas01mc@334 544 command = COM_LISZT;
mas01mc@334 545 dbName=args_info.database_arg;
mas01mc@334 546 lisztOffset = args_info.lisztOffset_arg;
mas01mc@334 547 lisztLength = args_info.lisztLength_arg;
mas01mc@334 548 if(args_info.lisztOffset_arg<0) // check upper bound later when database is opened
mas01mc@334 549 error("lisztOffset cannot be negative");
mas01mc@334 550 if(args_info.lisztLength_arg<0)
mas01mc@334 551 error("lisztLength cannot be negative");
mas01mc@334 552 if(lisztLength >1000000)
mas01mc@334 553 error("lisztLength too large (>1000000)");
mas01mc@334 554 return 0;
mas01mc@334 555 }
mas01mc@334 556
mas01cr@105 557 return -1; // no command found
mas01cr@0 558 }
mas01cr@0 559
mas01cr@133 560 void audioDB::status(const char* dbName, adb__statusResponse *adbStatusResponse){
mas01cr@498 561 adb_status_t status;
mas01cr@498 562 if(!adb) {
mas01cr@498 563 if(!(adb = audiodb_open(dbName, O_RDONLY))) {
mas01cr@498 564 error("Failed to open database file", dbName);
mas01cr@0 565 }
mas01cr@0 566 }
mas01cr@498 567 if(audiodb_status(adb, &status)) {
mas01cr@498 568 error("Failed to retrieve database status", dbName);
mas01cr@498 569 }
mas01cr@76 570
mas01cr@133 571 if(adbStatusResponse == 0) {
mas01cr@498 572 std::cout << "num files:" << status.numFiles << std::endl;
mas01cr@498 573 std::cout << "data dim:" << status.dim <<std::endl;
mas01cr@498 574 if(status.dim > 0) {
mas01cr@498 575 size_t bytes_per_vector = sizeof(double) * status.dim;
mas01cr@498 576 off_t nvectors = status.length / bytes_per_vector;
mas01cr@498 577 off_t data_region_vectors = status.data_region_size / bytes_per_vector;
mas01cr@498 578 std::cout << "total vectors:" << nvectors << std::endl;
mas01cr@498 579 std::cout << "vectors available:";
mas01cr@498 580 if(status.flags & O2_FLAG_LARGE_ADB) {
mas01cr@498 581 std::cout << O2_MAX_VECTORS - nvectors << std::endl;
mas01cr@498 582 } else {
mas01cr@498 583 std::cout << data_region_vectors - nvectors << std::endl;
mas01cr@498 584 }
mas01cr@76 585 }
mas01cr@498 586 if(!(status.flags & O2_FLAG_LARGE_ADB)) {
mas01cr@498 587 double used_frac = ((double) status.length) / status.data_region_size;
mas01cr@498 588 std::cout << "total bytes:" << status.length <<
mas01cr@498 589 " (" << (100.0*used_frac) << "%)" << std::endl;
mas01cr@498 590 std::cout << "bytes available:" << status.data_region_size - status.length <<
mas01cr@498 591 " (" << (100.0*(1-used_frac)) << "%)" << std::endl;
mas01mc@324 592 }
mas01cr@498 593 std::cout << "flags:" << " l2norm[" << DISPLAY_FLAG(status.flags&O2_FLAG_L2NORM)
mas01cr@498 594 << "] minmax[" << DISPLAY_FLAG(status.flags&O2_FLAG_MINMAX)
mas01cr@498 595 << "] power[" << DISPLAY_FLAG(status.flags&O2_FLAG_POWER)
mas01cr@498 596 << "] times[" << DISPLAY_FLAG(status.flags&O2_FLAG_TIMES)
mas01cr@498 597 << "] largeADB[" << DISPLAY_FLAG(status.flags&O2_FLAG_LARGE_ADB)
mas01mc@324 598 << "]" << endl;
mas01mc@324 599
mas01cr@498 600 std::cout << "null count: " << status.nullCount << " small sequence count " << status.dudCount-status.nullCount << std::endl;
mas01cr@76 601 } else {
mas01cr@498 602 adbStatusResponse->result.numFiles = status.numFiles;
mas01cr@498 603 adbStatusResponse->result.dim = status.dim;
mas01cr@498 604 adbStatusResponse->result.length = status.length;
mas01cr@498 605 adbStatusResponse->result.dudCount = status.dudCount;
mas01cr@498 606 adbStatusResponse->result.nullCount = status.nullCount;
mas01cr@498 607 adbStatusResponse->result.flags = status.flags;
mas01cr@76 608 }
mas01cr@0 609 }
mas01cr@0 610
mas01cr@498 611 void audioDB::l2norm(const char* dbName) {
mas01cr@498 612 if(!adb) {
mas01cr@498 613 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@498 614 error("Failed to open database file", dbName);
mas01ik@355 615 }
mas01ik@355 616 }
mas01cr@498 617 if(audiodb_l2norm(adb)) {
mas01cr@498 618 error("failed to turn on l2norm flag for database", dbName);
mas01cr@0 619 }
mas01cr@0 620 }
mas01cr@193 621
mas01cr@193 622 void audioDB::power_flag(const char *dbName) {
mas01cr@498 623 if(!adb) {
mas01cr@498 624 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@498 625 error("Failed to open database file", dbName);
mas01cr@498 626 }
mas01cr@193 627 }
mas01cr@498 628 if(audiodb_power(adb)) {
mas01cr@498 629 error("can't turn on power flag for database", dbName);
mas01cr@498 630 }
mas01cr@193 631 }
mas01cr@193 632
mas01cr@498 633 void audioDB::create(const char *dbName) {
mas01cr@498 634 if(adb) {
mas01cr@498 635 error("Already have an adb in this object", "");
mas01cr@498 636 }
mas01cr@498 637 if(!(adb = audiodb_create(dbName, datasize, ntracks, datadim))) {
mas01cr@498 638 error("Failed to create database file", dbName);
mas01cr@498 639 }
mas01cr@498 640 }
mas01cr@0 641
mas01cr@498 642 void audioDB::dump(const char *dbName) {
mas01cr@498 643 if(!adb) {
mas01cr@498 644 if(!(adb = audiodb_open(dbName, O_RDONLY))) {
mas01cr@498 645 error("Failed to open database file", dbName);
mas01cr@498 646 }
mas01cr@498 647 }
mas01cr@498 648 if(audiodb_dump(adb, output)) {
mas01cr@498 649 error("Failed to dump database to ", output);
mas01cr@498 650 }
mas01cr@498 651 status(dbName);
mas01cr@498 652 }
mas01cr@0 653
mas01cr@498 654 void audioDB::insert(const char* dbName, const char* inFile) {
mas01cr@498 655 if(!adb) {
mas01cr@498 656 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@498 657 error("failed to open database", dbName);
mas01cr@498 658 }
mas01cr@498 659 }
mas01cr@0 660
mas01cr@498 661 /* at this point, we have powerfd (an fd), timesFile (a
mas01cr@498 662 * std::ifstream *) and inFile (a char *). Wacky, huh? Ignore
mas01cr@498 663 * the wackiness and just use the names. */
mas01cr@498 664 adb_insert_t insert;
mas01cr@498 665 insert.features = inFile;
mas01cr@498 666 insert.times = timesFileName;
mas01cr@498 667 insert.power = powerFileName;
mas01cr@498 668 insert.key = key;
mas01cr@0 669
mas01cr@498 670 if(audiodb_insert(adb, &insert)) {
mas01cr@498 671 error("insertion failure", inFile);
mas01cr@498 672 }
mas01cr@498 673 status(dbName);
mas01cr@498 674 }
mas01cr@0 675
mas01cr@498 676 void audioDB::batchinsert(const char* dbName, const char* inFile) {
mas01cr@498 677 if(!adb) {
mas01cr@498 678 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@498 679 error("failed to open database", dbName);
mas01cr@498 680 }
mas01cr@498 681 }
mas01cr@0 682
mas01cr@498 683 if(!key)
mas01cr@498 684 key=inFile;
mas01cr@498 685 std::ifstream *filesIn = 0;
mas01cr@498 686 std::ifstream *keysIn = 0;
mas01cr@498 687
mas01cr@498 688 if(!(filesIn = new std::ifstream(inFile)))
mas01cr@498 689 error("Could not open batch in file", inFile);
mas01cr@498 690 if(key && key!=inFile)
mas01cr@498 691 if(!(keysIn = new std::ifstream(key)))
mas01cr@498 692 error("Could not open batch key file",key);
mas01cr@498 693
mas01cr@498 694 unsigned totalVectors=0;
mas01cr@498 695 char *thisFile = new char[MAXSTR];
mas01cr@498 696 char *thisKey = 0;
mas01cr@498 697 if (key && (key != inFile)) {
mas01cr@498 698 thisKey = new char[MAXSTR];
mas01cr@498 699 }
mas01cr@498 700 char *thisTimesFileName = new char[MAXSTR];
mas01cr@498 701 char *thisPowerFileName = new char[MAXSTR];
mas01cr@498 702
mas01cr@498 703 do {
mas01cr@498 704 filesIn->getline(thisFile,MAXSTR);
mas01cr@498 705 if(key && key!=inFile) {
mas01cr@498 706 keysIn->getline(thisKey,MAXSTR);
mas01cr@498 707 } else {
mas01cr@498 708 thisKey = thisFile;
mas01cr@0 709 }
mas01cr@498 710 if(usingTimes) {
mas01cr@498 711 timesFile->getline(thisTimesFileName,MAXSTR);
mas01cr@498 712 }
mas01cr@498 713 if(usingPower) {
mas01cr@498 714 powerFile->getline(thisPowerFileName, MAXSTR);
mas01cr@498 715 }
mas01cr@498 716
mas01cr@498 717 if(filesIn->eof()) {
mas01cr@498 718 break;
mas01cr@498 719 }
mas01cr@498 720 if(usingTimes){
mas01cr@498 721 if(timesFile->eof()) {
mas01cr@498 722 error("not enough timestamp files in timesList", timesFileName);
mas01cr@498 723 }
mas01cr@498 724 }
mas01cr@498 725 if (usingPower) {
mas01cr@498 726 if(powerFile->eof()) {
mas01cr@498 727 error("not enough power files in powerList", powerFileName);
mas01cr@498 728 }
mas01cr@498 729 }
mas01cr@498 730 adb_insert_t insert;
mas01cr@498 731 insert.features = thisFile;
mas01cr@498 732 insert.times = usingTimes ? thisTimesFileName : NULL;
mas01cr@498 733 insert.power = usingPower ? thisPowerFileName : NULL;
mas01cr@498 734 insert.key = thisKey;
mas01cr@498 735 if(audiodb_insert(adb, &insert)) {
mas01cr@498 736 error("insertion failure", thisFile);
mas01cr@498 737 }
mas01cr@498 738 } while(!filesIn->eof());
mas01cr@498 739
mas01mc@537 740 VERB_LOG(0, "%s %s %u vectors %ju bytes.\n", COM_BATCHINSERT, dbName, totalVectors, (intmax_t) (totalVectors * adb->header->dim * sizeof(double)));
mas01cr@498 741
mas01cr@498 742 delete [] thisPowerFileName;
mas01cr@498 743 if(key && (key != inFile)) {
mas01cr@498 744 delete [] thisKey;
mas01cr@0 745 }
mas01cr@498 746 delete [] thisFile;
mas01cr@498 747 delete [] thisTimesFileName;
mas01cr@498 748
mas01cr@498 749 delete filesIn;
mas01cr@498 750 delete keysIn;
mas01cr@498 751
mas01cr@498 752 // Report status
mas01cr@498 753 status(dbName);
mas01cr@498 754 }
mas01cr@498 755
mas01cr@508 756 void audioDB::query(const char* dbName, const char* inFile, struct soap *soap, adb__queryResponse *adbQueryResponse) {
mas01cr@498 757
mas01cr@498 758 if(!adb) {
mas01cr@515 759 if(!(adb = audiodb_open(dbName, O_RDONLY))) {
mas01cr@498 760 error("failed to open database", dbName);
mas01cr@498 761 }
mas01cr@498 762 }
mas01cr@498 763
mas01cr@498 764 /* FIXME: we only need this for getting nfiles, which we only need
mas01cr@498 765 * because the reporters aren't desperately well implemented,
mas01cr@498 766 * relying on statically-sized vectors rather than adjustable data
mas01cr@498 767 * structures. Rework reporter.h to be less lame. */
mas01cr@498 768 adb_status_t status;
mas01cr@498 769 audiodb_status(adb, &status);
mas01cr@498 770 uint32_t nfiles = status.numFiles;
mas01cr@498 771
mas01cr@498 772 adb_query_spec_t qspec;
mas01cr@498 773 adb_datum_t datum = {0};
mas01cr@498 774
mas01cr@498 775 qspec.refine.flags = 0;
mas01cr@498 776 if(trackFile) {
mas01cr@498 777 qspec.refine.flags |= ADB_REFINE_INCLUDE_KEYLIST;
mas01cr@498 778 std::vector<const char *> v;
mas01cr@498 779 char *k = new char[MAXSTR];
mas01cr@498 780 trackFile->getline(k, MAXSTR);
mas01cr@498 781 while(!trackFile->eof()) {
mas01cr@498 782 v.push_back(k);
mas01cr@498 783 k = new char[MAXSTR];
mas01cr@498 784 trackFile->getline(k, MAXSTR);
mas01cr@498 785 }
mas01cr@498 786 delete [] k;
mas01cr@498 787 qspec.refine.include.nkeys = v.size();
mas01cr@498 788 qspec.refine.include.keys = new const char *[qspec.refine.include.nkeys];
mas01cr@498 789 for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) {
mas01cr@498 790 qspec.refine.include.keys[k] = v[k];
mas01cr@498 791 }
mas01cr@498 792 }
mas01cr@498 793 if(query_from_key) {
mas01cr@498 794 qspec.refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST;
mas01cr@498 795 qspec.refine.exclude.nkeys = 1;
mas01cr@498 796 qspec.refine.exclude.keys = &key;
mas01cr@498 797 }
mas01cr@498 798 if(radius) {
mas01cr@498 799 qspec.refine.flags |= ADB_REFINE_RADIUS;
mas01cr@498 800 qspec.refine.radius = radius;
mas01cr@498 801 }
mas01cr@498 802 if(use_absolute_threshold) {
mas01cr@498 803 qspec.refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD;
mas01cr@498 804 qspec.refine.absolute_threshold = absolute_threshold;
mas01cr@498 805 }
mas01cr@498 806 if(use_relative_threshold) {
mas01cr@498 807 qspec.refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD;
mas01cr@498 808 qspec.refine.relative_threshold = relative_threshold;
mas01cr@498 809 }
mas01cr@498 810 if(usingTimes) {
mas01cr@498 811 qspec.refine.flags |= ADB_REFINE_DURATION_RATIO;
mas01cr@498 812 qspec.refine.duration_ratio = timesTol;
mas01cr@498 813 }
mas01cr@498 814 /* FIXME: not sure about this any more; maybe it belongs in
mas01cr@498 815 query_id? Or maybe we just don't need a flag for it? */
mas01cr@498 816 qspec.refine.hopsize = sequenceHop;
mas01cr@498 817 if(sequenceHop != 1) {
mas01cr@498 818 qspec.refine.flags |= ADB_REFINE_HOP_SIZE;
mas01cr@498 819 }
mas01cr@498 820
mas01cr@498 821 if(query_from_key) {
mas01cr@498 822 datum.key = key;
mas01cr@84 823 } else {
mas01cr@498 824 int fd;
mas01cr@498 825 struct stat st;
mas01cr@498 826
mas01cr@498 827 /* FIXME: around here there are all sorts of hideous leaks. */
mas01cr@498 828 fd = open(inFile, O_RDONLY);
mas01cr@498 829 if(fd < 0) {
mas01cr@498 830 error("failed to open feature file", inFile);
mas01cr@498 831 }
mas01cr@498 832 fstat(fd, &st);
mas01cr@498 833 read(fd, &datum.dim, sizeof(uint32_t));
mas01cr@498 834 datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
mas01cr@498 835 datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
mas01cr@498 836 read(fd, datum.data, st.st_size - sizeof(uint32_t));
mas01cr@498 837 close(fd);
mas01cr@498 838 if(usingPower) {
mas01cr@498 839 uint32_t one;
mas01cr@498 840 fd = open(powerFileName, O_RDONLY);
mas01cr@498 841 if(fd < 0) {
mas01cr@498 842 error("failed to open power file", powerFileName);
mas01cr@498 843 }
mas01cr@498 844 read(fd, &one, sizeof(uint32_t));
mas01cr@498 845 if(one != 1) {
mas01cr@498 846 error("malformed power file dimensionality", powerFileName);
mas01cr@498 847 }
mas01cr@498 848 datum.power = (double *) malloc(datum.nvectors * sizeof(double));
mas01cr@498 849 if(read(fd, datum.power, datum.nvectors * sizeof(double)) != (ssize_t) (datum.nvectors * sizeof(double))) {
mas01cr@498 850 error("malformed power file", powerFileName);
mas01cr@498 851 }
mas01cr@498 852 close(fd);
mas01cr@498 853 }
mas01cr@498 854 if(usingTimes) {
mas01cr@498 855 datum.times = (double *) malloc(2 * datum.nvectors * sizeof(double));
mas01cr@498 856 insertTimeStamps(datum.nvectors, timesFile, datum.times);
mas01cr@498 857 }
mas01cr@84 858 }
mas01cr@498 859
mas01cr@498 860 qspec.qid.datum = &datum;
mas01cr@498 861 qspec.qid.sequence_length = sequenceLength;
mas01cr@498 862 qspec.qid.flags = 0;
mas01cr@498 863 qspec.qid.flags |= usingQueryPoint ? 0 : ADB_QID_FLAG_EXHAUSTIVE;
mas01cr@498 864 qspec.qid.flags |= lsh_exact ? 0 : ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
mas01cr@498 865 qspec.qid.sequence_start = queryPoint;
mas01cr@498 866
mas01cr@498 867 switch(queryType) {
mas01cr@498 868 case O2_POINT_QUERY:
mas01cr@498 869 qspec.qid.sequence_length = 1;
mas01cr@498 870 qspec.params.accumulation = ADB_ACCUMULATION_DB;
mas01cr@498 871 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@498 872 qspec.params.npoints = pointNN;
mas01cr@498 873 qspec.params.ntracks = 0;
mas01cr@498 874 reporter = new pointQueryReporter< std::greater < NNresult > >(pointNN);
mas01cr@498 875 break;
mas01cr@498 876 case O2_TRACK_QUERY:
mas01cr@498 877 qspec.qid.sequence_length = 1;
mas01cr@498 878 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@498 879 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@498 880 qspec.params.npoints = pointNN;
mas01cr@498 881 qspec.params.ntracks = trackNN;
mas01cr@498 882 reporter = new trackAveragingReporter< std::greater< NNresult > >(pointNN, trackNN, nfiles);
mas01cr@498 883 break;
mas01cr@498 884 case O2_SEQUENCE_QUERY:
mas01cr@498 885 case O2_N_SEQUENCE_QUERY:
mas01cr@498 886 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@498 887 qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@498 888 qspec.params.npoints = pointNN;
mas01cr@498 889 qspec.params.ntracks = trackNN;
mas01cr@498 890 switch(queryType) {
mas01cr@498 891 case O2_SEQUENCE_QUERY:
mas01cr@498 892 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@498 893 reporter = new trackAveragingReporter< std::less< NNresult > >(pointNN, trackNN, nfiles);
mas01cr@498 894 } else {
mas01cr@498 895 reporter = new trackSequenceQueryRadReporter(trackNN, nfiles);
mas01cr@498 896 }
mas01cr@498 897 break;
mas01cr@498 898 case O2_N_SEQUENCE_QUERY:
mas01cr@498 899 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@498 900 reporter = new trackSequenceQueryNNReporter< std::less < NNresult > >(pointNN, trackNN, nfiles);
mas01cr@498 901 } else {
mas01cr@498 902 reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, nfiles);
mas01cr@498 903 }
mas01cr@498 904 break;
mas01cr@498 905 }
mas01cr@498 906 break;
mas01cr@498 907 case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
mas01cr@498 908 qspec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
mas01cr@498 909 qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@498 910 qspec.params.npoints = 0;
mas01cr@498 911 qspec.params.ntracks = 0;
mas01cr@498 912 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@498 913 error("query-type not yet supported");
mas01cr@498 914 } else {
mas01mc@537 915 reporter = new trackSequenceQueryRadNNReporterOneToOne(pointNN,trackNN, adb->header->numFiles);
mas01cr@498 916 }
mas01cr@498 917 break;
mas01cr@498 918 default:
mas01cr@498 919 error("unrecognized queryType");
mas01cr@498 920 }
mas01cr@498 921
mas01cr@498 922 adb_query_results_t *rs = audiodb_query_spec(adb, &qspec);
mas01cr@498 923
mas01cr@507 924 // FIXME: we don't yet free everything up if there are error
mas01cr@507 925 // conditions during the construction of the query spec (including
mas01cr@507 926 // the datum itself).
mas01cr@507 927 if(datum.data) {
mas01cr@507 928 free(datum.data);
mas01cr@507 929 datum.data = NULL;
mas01cr@507 930 }
mas01cr@507 931 if(datum.power) {
mas01cr@507 932 free(datum.data);
mas01cr@507 933 datum.data = NULL;
mas01cr@507 934 }
mas01cr@507 935 if(datum.times) {
mas01cr@507 936 free(datum.data);
mas01cr@507 937 datum.data = NULL;
mas01cr@507 938 }
mas01cr@498 939
mas01cr@498 940 if(rs == NULL) {
mas01cr@498 941 error("audiodb_query_spec failed");
mas01cr@498 942 }
mas01cr@498 943
mas01cr@498 944 for(unsigned int k = 0; k < rs->nresults; k++) {
mas01cr@498 945 adb_result_t r = rs->results[k];
mas01cr@498 946 reporter->add_point(audiodb_key_index(adb, r.key), r.qpos, r.ipos, r.dist);
mas01cr@498 947 }
mas01cr@498 948 audiodb_query_free_results(adb, &qspec, rs);
mas01cr@498 949
mas01cr@508 950 reporter->report(adb, soap, adbQueryResponse);
mas01cr@193 951 }
mas01cr@193 952
mas01mc@308 953 // This entry point is visited once per instance
mas01mc@308 954 // so it is a good place to set any global state variables
mas01cr@370 955 int main(const int argc, const char* argv[]){
mas01mc@324 956 SERVER_ADB_ROOT = 0; // Server-side database root prefix
mas01mc@324 957 SERVER_ADB_FEATURE_ROOT = 0; // Server-side features root prefix
mas01cr@0 958 audioDB(argc, argv);
mas01cr@0 959 }