annotate audioDB.cpp @ 496:8fb85fbcaba6 api-inversion

Mostly disentangle API from command-line binary. Now audioDB.cpp doesn't need to be included in the library, because nothing the library does creates an audioDB instance. Hooray. We can't disentangle the other way, because there's still plenty in the command-line binary that isn't implemented in terms of the API, so the audioDB binary code needs to know naughty stuff about the library's internals (e.g. what the file header looks like). Remove liszt.o and sample.o from the library, even though they'll probably make a reapparance soon (for scare-quoted values of "soon") Remove cmdline.o and common.o from the library, not scheduled to make a reapparence ever (hooray!). Separate out the bits that are used in the library -- locks and PointPairs -- into their own files.
author mas01cr
date Sat, 10 Jan 2009 15:33:25 +0000
parents d3afc91d205d
children
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@385 2 extern "C" {
mas01cr@385 3 #include "audioDB_API.h"
mas01cr@402 4 #include "audioDB-internals.h"
mas01cr@385 5 }
mas01cr@469 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
mas01cr@0 29 if(O2_ACTION(COM_SERVER))
mas01cr@0 30 startServer();
mas01cr@0 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@496 158 if(adb) {
mas01cr@392 159 audiodb_close(adb);
mas01cr@392 160 adb = NULL;
mas01cr@392 161 }
mas01cr@465 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;
mas01cr@105 526 if(queryPoint<0 || queryPoint >10000)
mas01cr@105 527 error("queryPoint out of range: 0 <= queryPoint <= 10000");
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@395 565 adb_status_t status;
mas01cr@399 566 if(!adb) {
mas01cr@399 567 if(!(adb = audiodb_open(dbName, O_RDONLY))) {
mas01cr@399 568 error("Failed to open database file", dbName);
mas01cr@399 569 }
mas01cr@0 570 }
mas01cr@395 571 if(audiodb_status(adb, &status)) {
mas01cr@395 572 error("Failed to retrieve database status", dbName);
mas01cr@395 573 }
mas01cr@76 574
mas01cr@133 575 if(adbStatusResponse == 0) {
mas01cr@395 576 std::cout << "num files:" << status.numFiles << std::endl;
mas01cr@395 577 std::cout << "data dim:" << status.dim <<std::endl;
mas01cr@395 578 if(status.dim > 0) {
mas01cr@397 579 size_t bytes_per_vector = sizeof(double) * status.dim;
mas01cr@397 580 off_t nvectors = status.length / bytes_per_vector;
mas01cr@397 581 off_t data_region_vectors = status.data_region_size / bytes_per_vector;
mas01cr@395 582 std::cout << "total vectors:" << nvectors << std::endl;
mas01cr@395 583 std::cout << "vectors available:";
mas01cr@395 584 if(status.flags & O2_FLAG_LARGE_ADB) {
mas01cr@395 585 std::cout << O2_MAX_VECTORS - nvectors << std::endl;
mas01cr@395 586 } else {
mas01cr@395 587 std::cout << data_region_vectors - nvectors << std::endl;
mas01cr@395 588 }
mas01cr@76 589 }
mas01cr@395 590 if(!(status.flags & O2_FLAG_LARGE_ADB)) {
mas01cr@395 591 double used_frac = ((double) status.length) / status.data_region_size;
mas01cr@395 592 std::cout << "total bytes:" << status.length <<
mas01cr@395 593 " (" << (100.0*used_frac) << "%)" << std::endl;
mas01cr@395 594 std::cout << "bytes available:" << status.data_region_size - status.length <<
mas01cr@395 595 " (" << (100.0*(1-used_frac)) << "%)" << std::endl;
mas01mc@324 596 }
mas01cr@395 597 std::cout << "flags:" << " l2norm[" << DISPLAY_FLAG(status.flags&O2_FLAG_L2NORM)
mas01cr@395 598 << "] minmax[" << DISPLAY_FLAG(status.flags&O2_FLAG_MINMAX)
mas01cr@395 599 << "] power[" << DISPLAY_FLAG(status.flags&O2_FLAG_POWER)
mas01cr@395 600 << "] times[" << DISPLAY_FLAG(status.flags&O2_FLAG_TIMES)
mas01cr@395 601 << "] largeADB[" << DISPLAY_FLAG(status.flags&O2_FLAG_LARGE_ADB)
mas01mc@324 602 << "]" << endl;
mas01mc@324 603
mas01cr@395 604 std::cout << "null count: " << status.nullCount << " small sequence count " << status.dudCount-status.nullCount << std::endl;
mas01cr@76 605 } else {
mas01cr@395 606 adbStatusResponse->result.numFiles = status.numFiles;
mas01cr@395 607 adbStatusResponse->result.dim = status.dim;
mas01cr@395 608 adbStatusResponse->result.length = status.length;
mas01cr@395 609 adbStatusResponse->result.dudCount = status.dudCount;
mas01cr@395 610 adbStatusResponse->result.nullCount = status.nullCount;
mas01cr@395 611 adbStatusResponse->result.flags = status.flags;
mas01cr@76 612 }
mas01cr@0 613 }
mas01cr@0 614
mas01cr@196 615 void audioDB::l2norm(const char* dbName) {
mas01cr@401 616 if(!adb) {
mas01cr@401 617 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@401 618 error("Failed to open database file", dbName);
mas01cr@401 619 }
mas01cr@0 620 }
mas01cr@401 621 if(audiodb_l2norm(adb)) {
mas01cr@401 622 error("failed to turn on l2norm flag for database", dbName);
mas01cr@401 623 }
mas01cr@0 624 }
mas01cr@193 625
mas01cr@193 626 void audioDB::power_flag(const char *dbName) {
mas01cr@400 627 if(!adb) {
mas01cr@400 628 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@400 629 error("Failed to open database file", dbName);
mas01cr@400 630 }
mas01cr@193 631 }
mas01cr@400 632 if(audiodb_power(adb)) {
mas01cr@400 633 error("can't turn on power flag for database", dbName);
mas01cr@400 634 }
mas01cr@193 635 }
mas01cr@193 636
mas01cr@385 637 void audioDB::create(const char *dbName) {
mas01cr@399 638 if(adb) {
mas01cr@399 639 error("Already have an adb in this object", "");
mas01cr@399 640 }
mas01cr@391 641 if(!(adb = audiodb_create(dbName, datasize, ntracks, datadim))) {
mas01cr@392 642 error("Failed to create database file", dbName);
mas01cr@385 643 }
mas01cr@385 644 }
mas01cr@385 645
mas01cr@399 646 void audioDB::dump(const char *dbName) {
mas01cr@399 647 if(!adb) {
mas01cr@399 648 if(!(adb = audiodb_open(dbName, O_RDONLY))) {
mas01cr@399 649 error("Failed to open database file", dbName);
mas01cr@399 650 }
mas01cr@399 651 }
mas01cr@399 652 if(audiodb_dump(adb, output)) {
mas01cr@399 653 error("Failed to dump database to ", output);
mas01cr@399 654 }
mas01cr@399 655 status(dbName);
mas01cr@399 656 }
mas01cr@193 657
mas01cr@409 658 void audioDB::insert(const char* dbName, const char* inFile) {
mas01cr@409 659 if(!adb) {
mas01cr@409 660 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@409 661 error("failed to open database", dbName);
mas01cr@409 662 }
mas01cr@409 663 }
mas01cr@409 664
mas01cr@409 665 /* at this point, we have powerfd (an fd), timesFile (a
mas01cr@409 666 * std::ifstream *) and inFile (a char *). Wacky, huh? Ignore
mas01cr@409 667 * the wackiness and just use the names. */
mas01cr@409 668 adb_insert_t insert;
mas01cr@409 669 insert.features = inFile;
mas01cr@409 670 insert.times = timesFileName;
mas01cr@409 671 insert.power = powerFileName;
mas01cr@409 672 insert.key = key;
mas01cr@409 673
mas01cr@409 674 if(audiodb_insert(adb, &insert)) {
mas01cr@409 675 error("insertion failure", inFile);
mas01cr@409 676 }
mas01cr@409 677 status(dbName);
mas01cr@409 678 }
mas01cr@409 679
mas01cr@409 680 void audioDB::batchinsert(const char* dbName, const char* inFile) {
mas01cr@409 681 if(!adb) {
mas01cr@409 682 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@409 683 error("failed to open database", dbName);
mas01cr@409 684 }
mas01cr@409 685 }
mas01cr@409 686
mas01cr@409 687 if(!key)
mas01cr@409 688 key=inFile;
mas01cr@409 689 std::ifstream *filesIn = 0;
mas01cr@409 690 std::ifstream *keysIn = 0;
mas01cr@409 691
mas01cr@409 692 if(!(filesIn = new std::ifstream(inFile)))
mas01cr@409 693 error("Could not open batch in file", inFile);
mas01cr@409 694 if(key && key!=inFile)
mas01cr@409 695 if(!(keysIn = new std::ifstream(key)))
mas01cr@409 696 error("Could not open batch key file",key);
mas01cr@409 697
mas01cr@409 698 unsigned totalVectors=0;
mas01cr@409 699 char *thisFile = new char[MAXSTR];
mas01cr@409 700 char *thisKey = 0;
mas01cr@409 701 if (key && (key != inFile)) {
mas01cr@409 702 thisKey = new char[MAXSTR];
mas01cr@409 703 }
mas01cr@409 704 char *thisTimesFileName = new char[MAXSTR];
mas01cr@409 705 char *thisPowerFileName = new char[MAXSTR];
mas01cr@409 706
mas01cr@409 707 do {
mas01cr@409 708 filesIn->getline(thisFile,MAXSTR);
mas01cr@409 709 if(key && key!=inFile) {
mas01cr@409 710 keysIn->getline(thisKey,MAXSTR);
mas01cr@409 711 } else {
mas01cr@409 712 thisKey = thisFile;
mas01cr@409 713 }
mas01cr@409 714 if(usingTimes) {
mas01cr@409 715 timesFile->getline(thisTimesFileName,MAXSTR);
mas01cr@409 716 }
mas01cr@409 717 if(usingPower) {
mas01cr@409 718 powerFile->getline(thisPowerFileName, MAXSTR);
mas01cr@409 719 }
mas01cr@409 720
mas01cr@409 721 if(filesIn->eof()) {
mas01cr@409 722 break;
mas01cr@409 723 }
mas01cr@409 724 if(usingTimes){
mas01cr@409 725 if(timesFile->eof()) {
mas01cr@409 726 error("not enough timestamp files in timesList", timesFileName);
mas01cr@409 727 }
mas01cr@409 728 }
mas01cr@409 729 if (usingPower) {
mas01cr@409 730 if(powerFile->eof()) {
mas01cr@409 731 error("not enough power files in powerList", powerFileName);
mas01cr@409 732 }
mas01cr@409 733 }
mas01cr@409 734 adb_insert_t insert;
mas01cr@409 735 insert.features = thisFile;
mas01cr@409 736 insert.times = usingTimes ? thisTimesFileName : NULL;
mas01cr@409 737 insert.power = usingPower ? thisPowerFileName : NULL;
mas01cr@409 738 insert.key = thisKey;
mas01cr@409 739 if(audiodb_insert(adb, &insert)) {
mas01cr@409 740 error("insertion failure", thisFile);
mas01cr@409 741 }
mas01cr@409 742 } while(!filesIn->eof());
mas01cr@409 743
mas01cr@409 744 VERB_LOG(0, "%s %s %u vectors %ju bytes.\n", COM_BATCHINSERT, dbName, totalVectors, (intmax_t) (totalVectors * dbH->dim * sizeof(double)));
mas01cr@409 745
mas01cr@409 746 delete [] thisPowerFileName;
mas01cr@409 747 if(key && (key != inFile)) {
mas01cr@409 748 delete [] thisKey;
mas01cr@409 749 }
mas01cr@409 750 delete [] thisFile;
mas01cr@409 751 delete [] thisTimesFileName;
mas01cr@409 752
mas01cr@409 753 delete filesIn;
mas01cr@409 754 delete keysIn;
mas01cr@409 755
mas01cr@409 756 // Report status
mas01cr@409 757 status(dbName);
mas01cr@409 758 }
mas01cr@409 759
mas01cr@469 760 void audioDB::query(const char* dbName, const char* inFile, adb__queryResponse *adbQueryResponse) {
mas01cr@469 761
mas01cr@469 762 if(!adb) {
mas01cr@469 763 if(!(adb = audiodb_open(dbName, O_RDWR))) {
mas01cr@469 764 error("failed to open database", dbName);
mas01cr@469 765 }
mas01cr@469 766 }
mas01cr@469 767
mas01cr@469 768 /* FIXME: we only need this for getting nfiles, which we only need
mas01cr@469 769 * because the reporters aren't desperately well implemented,
mas01cr@469 770 * relying on statically-sized vectors rather than adjustable data
mas01cr@469 771 * structures. Rework reporter.h to be less lame. */
mas01cr@469 772 adb_status_t status;
mas01cr@469 773 audiodb_status(adb, &status);
mas01cr@469 774 uint32_t nfiles = status.numFiles;
mas01cr@469 775
mas01cr@469 776 adb_query_spec_t qspec;
mas01cr@469 777 adb_datum_t datum = {0};
mas01cr@469 778
mas01cr@469 779 qspec.refine.flags = 0;
mas01cr@469 780 if(trackFile) {
mas01cr@469 781 qspec.refine.flags |= ADB_REFINE_INCLUDE_KEYLIST;
mas01cr@469 782 std::vector<const char *> v;
mas01cr@469 783 char *k = new char[MAXSTR];
mas01cr@469 784 trackFile->getline(k, MAXSTR);
mas01cr@469 785 while(!trackFile->eof()) {
mas01cr@469 786 v.push_back(k);
mas01cr@469 787 k = new char[MAXSTR];
mas01cr@469 788 trackFile->getline(k, MAXSTR);
mas01cr@469 789 }
mas01cr@469 790 delete [] k;
mas01cr@469 791 qspec.refine.include.nkeys = v.size();
mas01cr@469 792 qspec.refine.include.keys = new const char *[qspec.refine.include.nkeys];
mas01cr@469 793 for(unsigned int k = 0; k < qspec.refine.include.nkeys; k++) {
mas01cr@469 794 qspec.refine.include.keys[k] = v[k];
mas01cr@469 795 }
mas01cr@469 796 }
mas01cr@469 797 if(query_from_key) {
mas01cr@469 798 qspec.refine.flags |= ADB_REFINE_EXCLUDE_KEYLIST;
mas01cr@469 799 qspec.refine.exclude.nkeys = 1;
mas01cr@469 800 qspec.refine.exclude.keys = &key;
mas01cr@469 801 }
mas01cr@469 802 if(radius) {
mas01cr@469 803 qspec.refine.flags |= ADB_REFINE_RADIUS;
mas01cr@469 804 qspec.refine.radius = radius;
mas01cr@469 805 }
mas01cr@469 806 if(use_absolute_threshold) {
mas01cr@469 807 qspec.refine.flags |= ADB_REFINE_ABSOLUTE_THRESHOLD;
mas01cr@469 808 qspec.refine.absolute_threshold = absolute_threshold;
mas01cr@469 809 }
mas01cr@469 810 if(use_relative_threshold) {
mas01cr@469 811 qspec.refine.flags |= ADB_REFINE_RELATIVE_THRESHOLD;
mas01cr@469 812 qspec.refine.relative_threshold = relative_threshold;
mas01cr@469 813 }
mas01cr@469 814 if(usingTimes) {
mas01cr@469 815 qspec.refine.flags |= ADB_REFINE_DURATION_RATIO;
mas01cr@469 816 qspec.refine.duration_ratio = timesTol;
mas01cr@469 817 }
mas01cr@469 818 /* FIXME: not sure about this any more; maybe it belongs in
mas01cr@469 819 query_id? Or maybe we just don't need a flag for it? */
mas01cr@469 820 qspec.refine.hopsize = sequenceHop;
mas01cr@469 821 if(sequenceHop != 1) {
mas01cr@469 822 qspec.refine.flags |= ADB_REFINE_HOP_SIZE;
mas01cr@469 823 }
mas01cr@469 824
mas01cr@469 825 if(query_from_key) {
mas01cr@469 826 datum.key = key;
mas01cr@469 827 } else {
mas01cr@469 828 int fd;
mas01cr@469 829 struct stat st;
mas01cr@469 830
mas01cr@469 831 /* FIXME: around here there are all sorts of hideous leaks. */
mas01cr@469 832 fd = open(inFile, O_RDONLY);
mas01cr@469 833 if(fd < 0) {
mas01cr@469 834 error("failed to open feature file", inFile);
mas01cr@469 835 }
mas01cr@469 836 fstat(fd, &st);
mas01cr@469 837 read(fd, &datum.dim, sizeof(uint32_t));
mas01cr@469 838 datum.nvectors = (st.st_size - sizeof(uint32_t)) / (datum.dim * sizeof(double));
mas01cr@469 839 datum.data = (double *) malloc(st.st_size - sizeof(uint32_t));
mas01cr@469 840 read(fd, datum.data, st.st_size - sizeof(uint32_t));
mas01cr@469 841 close(fd);
mas01cr@469 842 if(usingPower) {
mas01cr@469 843 uint32_t one;
mas01cr@469 844 fd = open(powerFileName, O_RDONLY);
mas01cr@469 845 if(fd < 0) {
mas01cr@469 846 error("failed to open power file", powerFileName);
mas01cr@469 847 }
mas01cr@469 848 read(fd, &one, sizeof(uint32_t));
mas01cr@469 849 if(one != 1) {
mas01cr@469 850 error("malformed power file dimensionality", powerFileName);
mas01cr@469 851 }
mas01cr@469 852 datum.power = (double *) malloc(datum.nvectors * sizeof(double));
mas01cr@469 853 if(read(fd, datum.power, datum.nvectors * sizeof(double)) != (ssize_t) (datum.nvectors * sizeof(double))) {
mas01cr@469 854 error("malformed power file", powerFileName);
mas01cr@469 855 }
mas01cr@469 856 close(fd);
mas01cr@469 857 }
mas01cr@469 858 if(usingTimes) {
mas01cr@469 859 datum.times = (double *) malloc(2 * datum.nvectors * sizeof(double));
mas01cr@469 860 insertTimeStamps(datum.nvectors, timesFile, datum.times);
mas01cr@469 861 }
mas01cr@469 862 }
mas01cr@469 863
mas01cr@469 864 qspec.qid.datum = &datum;
mas01cr@469 865 qspec.qid.sequence_length = sequenceLength;
mas01cr@469 866 qspec.qid.flags = 0;
mas01cr@469 867 qspec.qid.flags |= usingQueryPoint ? 0 : ADB_QID_FLAG_EXHAUSTIVE;
mas01cr@469 868 qspec.qid.flags |= lsh_exact ? 0 : ADB_QID_FLAG_ALLOW_FALSE_POSITIVES;
mas01cr@469 869 qspec.qid.sequence_start = queryPoint;
mas01cr@469 870
mas01cr@469 871 switch(queryType) {
mas01cr@469 872 case O2_POINT_QUERY:
mas01cr@469 873 qspec.qid.sequence_length = 1;
mas01cr@469 874 qspec.params.accumulation = ADB_ACCUMULATION_DB;
mas01cr@469 875 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@469 876 qspec.params.npoints = pointNN;
mas01cr@469 877 qspec.params.ntracks = 0;
mas01cr@469 878 reporter = new pointQueryReporter< std::greater < NNresult > >(pointNN);
mas01cr@469 879 break;
mas01cr@469 880 case O2_TRACK_QUERY:
mas01cr@469 881 qspec.qid.sequence_length = 1;
mas01cr@469 882 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@469 883 qspec.params.distance = ADB_DISTANCE_DOT_PRODUCT;
mas01cr@469 884 qspec.params.npoints = pointNN;
mas01cr@469 885 qspec.params.ntracks = trackNN;
mas01cr@469 886 reporter = new trackAveragingReporter< std::greater< NNresult > >(pointNN, trackNN, nfiles);
mas01cr@469 887 break;
mas01cr@469 888 case O2_SEQUENCE_QUERY:
mas01cr@469 889 case O2_N_SEQUENCE_QUERY:
mas01cr@469 890 qspec.params.accumulation = ADB_ACCUMULATION_PER_TRACK;
mas01cr@469 891 qspec.params.distance = no_unit_norming ? ADB_DISTANCE_EUCLIDEAN : ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@469 892 qspec.params.npoints = pointNN;
mas01cr@469 893 qspec.params.ntracks = trackNN;
mas01cr@469 894 switch(queryType) {
mas01cr@469 895 case O2_SEQUENCE_QUERY:
mas01cr@469 896 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@469 897 reporter = new trackAveragingReporter< std::less< NNresult > >(pointNN, trackNN, nfiles);
mas01cr@469 898 } else {
mas01cr@469 899 reporter = new trackSequenceQueryRadReporter(trackNN, nfiles);
mas01cr@469 900 }
mas01cr@469 901 break;
mas01cr@469 902 case O2_N_SEQUENCE_QUERY:
mas01cr@469 903 if(!(qspec.refine.flags & ADB_REFINE_RADIUS)) {
mas01cr@469 904 reporter = new trackSequenceQueryNNReporter< std::less < NNresult > >(pointNN, trackNN, nfiles);
mas01cr@469 905 } else {
mas01cr@469 906 reporter = new trackSequenceQueryRadNNReporter(pointNN, trackNN, nfiles);
mas01cr@469 907 }
mas01cr@469 908 break;
mas01cr@469 909 }
mas01cr@469 910 break;
mas01cr@469 911 case O2_ONE_TO_ONE_N_SEQUENCE_QUERY:
mas01cr@469 912 qspec.params.accumulation = ADB_ACCUMULATION_ONE_TO_ONE;
mas01cr@469 913 qspec.params.distance = ADB_DISTANCE_EUCLIDEAN_NORMED;
mas01cr@469 914 qspec.params.npoints = 0;
mas01cr@469 915 qspec.params.ntracks = 0;
mas01cr@469 916 break;
mas01cr@469 917 default:
mas01cr@469 918 error("unrecognized queryType");
mas01cr@469 919 }
mas01cr@469 920
mas01cr@469 921 adb_query_results_t *rs = audiodb_query_spec(adb, &qspec);
mas01cr@469 922
mas01cr@469 923 // FIXME: free bits of datum if !query_from_key
mas01cr@469 924
mas01cr@469 925 if(rs == NULL) {
mas01cr@469 926 error("audiodb_query_spec failed");
mas01cr@469 927 }
mas01cr@469 928
mas01cr@469 929 for(unsigned int k = 0; k < rs->nresults; k++) {
mas01cr@469 930 adb_result_t r = rs->results[k];
mas01cr@469 931 reporter->add_point(audiodb_key_index(adb, r.key), r.qpos, r.ipos, r.dist);
mas01cr@469 932 }
mas01cr@469 933 audiodb_query_free_results(adb, &qspec, rs);
mas01cr@469 934
mas01cr@469 935 reporter->report(adb, adbQueryResponse);
mas01cr@469 936 }
mas01cr@469 937
mas01mc@308 938 // This entry point is visited once per instance
mas01mc@308 939 // so it is a good place to set any global state variables
mas01cr@370 940 int main(const int argc, const char* argv[]){
mas01mc@324 941 SERVER_ADB_ROOT = 0; // Server-side database root prefix
mas01mc@324 942 SERVER_ADB_FEATURE_ROOT = 0; // Server-side features root prefix
mas01cr@0 943 audioDB(argc, argv);
mas01cr@0 944 }