annotate audioDB.cpp @ 469:d3afc91d205d api-inversion

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