annotate audioDB.cpp @ 507:e7fd50483311

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