annotate audioDB.cpp @ 601:82d23418d867

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