annotate audioDB.cpp @ 314:b671a46873c2

working SIIGRAPH08 version. Fixed powerTable mmap memory leak in WS calls (only showed up in big databases). Implements radius queries over WS with new wsdl file
author mas01mc
date Tue, 12 Aug 2008 01:21:44 +0000
parents f9dde18f556a
children ab411674dad4 c93be2f3a674
rev   line source
mas01cr@0 1 #include "audioDB.h"
mas01cr@0 2
mas01mc@308 3 LSH* SERVER_LSH_INDEX_SINGLETON;
mas01mc@308 4
mas01mc@292 5 PointPair::PointPair(Uns32T a, Uns32T b, Uns32T c):trackID(a),qpos(b),spos(c){};
mas01mc@292 6
mas01mc@292 7 bool operator<(const PointPair& a, const PointPair& b){
mas01mc@292 8 return ( (a.qpos<b.qpos) ||
mas01mc@292 9 ((a.qpos==b.qpos) &&
mas01mc@292 10 ( (a.trackID<b.trackID)) || ((a.trackID==b.trackID)&&(a.spos<b.spos)) ) );
mas01mc@292 11 }
mas01mc@292 12
mas01mc@292 13 bool operator>(const PointPair& a, const PointPair& b){
mas01mc@292 14 return ( (a.qpos>b.qpos) ||
mas01mc@292 15 ((a.qpos==b.qpos) &&
mas01mc@292 16 ( (a.trackID>b.trackID)) || ((a.trackID==b.trackID)&&(a.spos>b.spos)) ) );
mas01mc@292 17 }
mas01mc@292 18
mas01mc@292 19 bool operator==(const PointPair& a, const PointPair& b){
mas01mc@292 20 return ( (a.trackID==b.trackID) && (a.qpos==b.qpos) && (a.spos==b.spos) );
mas01mc@292 21 }
mas01mc@292 22
mas01cr@76 23 audioDB::audioDB(const unsigned argc, char* const argv[]): O2_AUDIODB_INITIALIZERS
mas01cr@76 24 {
mas01cr@0 25 if(processArgs(argc, argv)<0){
mas01cr@0 26 printf("No command found.\n");
mas01cr@0 27 cmdline_parser_print_version ();
mas01cr@0 28 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 29 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 30 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 31 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 32 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 33 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@151 34 error("No command found");
mas01cr@0 35 }
mas01cr@77 36
mas01cr@0 37 if(O2_ACTION(COM_SERVER))
mas01cr@0 38 startServer();
mas01cr@0 39
mas01cr@0 40 else if(O2_ACTION(COM_CREATE))
mas01cr@0 41 create(dbName);
mas01cr@0 42
mas01cr@0 43 else if(O2_ACTION(COM_INSERT))
mas01cr@0 44 insert(dbName, inFile);
mas01cr@0 45
mas01cr@0 46 else if(O2_ACTION(COM_BATCHINSERT))
mas01cr@0 47 batchinsert(dbName, inFile);
mas01cr@0 48
mas01cr@0 49 else if(O2_ACTION(COM_QUERY))
mas01mc@307 50 if(isClient){
mas01mc@307 51 if(query_from_key)
mas01mc@307 52 ws_query_by_key(dbName, key, (char*)hostport);
mas01mc@307 53 else
mas01mc@307 54 ws_query(dbName, inFile, (char*)hostport);
mas01mc@307 55 }
mas01cr@0 56 else
mas01cr@76 57 query(dbName, inFile);
mas01cr@0 58
mas01cr@0 59 else if(O2_ACTION(COM_STATUS))
mas01cr@0 60 if(isClient)
mas01cr@0 61 ws_status(dbName,(char*)hostport);
mas01cr@0 62 else
mas01cr@0 63 status(dbName);
mas01cr@280 64
mas01cr@280 65 else if(O2_ACTION(COM_SAMPLE))
mas01cr@280 66 sample(dbName);
mas01cr@0 67
mas01cr@0 68 else if(O2_ACTION(COM_L2NORM))
mas01cr@0 69 l2norm(dbName);
mas01cr@0 70
mas01cr@193 71 else if(O2_ACTION(COM_POWER))
mas01cr@193 72 power_flag(dbName);
mas01cr@193 73
mas01cr@0 74 else if(O2_ACTION(COM_DUMP))
mas01cr@0 75 dump(dbName);
mas01mc@292 76
mas01mc@292 77 else if(O2_ACTION(COM_INDEX))
mas01mc@292 78 index_index_db(dbName);
mas01cr@0 79
mas01cr@0 80 else
mas01cr@0 81 error("Unrecognized command",command);
mas01cr@0 82 }
mas01cr@0 83
mas01cr@133 84 audioDB::audioDB(const unsigned argc, char* const argv[], adb__queryResponse *adbQueryResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 85 {
mas01cr@97 86 try {
mas01cr@151 87 isServer = 1; // FIXME: Hack
mas01cr@97 88 processArgs(argc, argv);
mas01cr@97 89 assert(O2_ACTION(COM_QUERY));
mas01cr@133 90 query(dbName, inFile, adbQueryResponse);
mas01cr@97 91 } catch(char *err) {
mas01cr@97 92 cleanup();
mas01cr@97 93 throw(err);
mas01cr@97 94 }
mas01cr@76 95 }
mas01cr@76 96
mas01cr@133 97 audioDB::audioDB(const unsigned argc, char* const argv[], adb__statusResponse *adbStatusResponse): O2_AUDIODB_INITIALIZERS
mas01cr@76 98 {
mas01cr@97 99 try {
mas01cr@151 100 isServer = 1; // FIXME: Hack
mas01cr@97 101 processArgs(argc, argv);
mas01cr@97 102 assert(O2_ACTION(COM_STATUS));
mas01cr@133 103 status(dbName, adbStatusResponse);
mas01cr@97 104 } catch(char *err) {
mas01cr@97 105 cleanup();
mas01cr@97 106 throw(err);
mas01cr@97 107 }
mas01cr@76 108 }
mas01cr@76 109
mas01cr@97 110 void audioDB::cleanup() {
mas01cr@122 111 cmdline_parser_free(&args_info);
mas01cr@0 112 if(indata)
mas01cr@0 113 munmap(indata,statbuf.st_size);
mas01cr@0 114 if(db)
mas01cr@196 115 munmap(db,getpagesize());
mas01cr@196 116 if(fileTable)
mas01cr@196 117 munmap(fileTable, fileTableLength);
mas01cr@196 118 if(trackTable)
mas01cr@196 119 munmap(trackTable, trackTableLength);
mas01cr@196 120 if(dataBuf)
mas01cr@196 121 munmap(dataBuf, dataBufLength);
mas01cr@196 122 if(timesTable)
mas01cr@196 123 munmap(timesTable, timesTableLength);
mas01mc@314 124 if(powerTable)
mas01mc@314 125 munmap(powerTable, powerTableLength);
mas01cr@196 126 if(l2normTable)
mas01cr@196 127 munmap(l2normTable, l2normTableLength);
mas01mc@292 128 if(trackOffsetTable)
mas01mc@292 129 delete trackOffsetTable;
mas01mc@292 130 if(reporter)
mas01mc@292 131 delete reporter;
mas01mc@292 132 if(exact_evaluation_queue)
mas01mc@292 133 delete exact_evaluation_queue;
mas01cr@284 134 if(rng)
mas01cr@284 135 gsl_rng_free(rng);
mas01mc@292 136 if(vv)
mas01mc@292 137 delete vv;
mas01cr@0 138 if(dbfid>0)
mas01cr@0 139 close(dbfid);
mas01cr@0 140 if(infid>0)
mas01cr@0 141 close(infid);
mas01cr@0 142 if(dbH)
mas01cr@0 143 delete dbH;
mas01mc@308 144 if(lsh!=SERVER_LSH_INDEX_SINGLETON)
mas01mc@308 145 delete lsh;
mas01cr@0 146 }
mas01cr@0 147
mas01cr@97 148 audioDB::~audioDB(){
mas01cr@97 149 cleanup();
mas01cr@97 150 }
mas01cr@97 151
mas01cr@0 152 int audioDB::processArgs(const unsigned argc, char* const argv[]){
mas01cr@0 153
mas01cr@0 154 if(argc<2){
mas01cr@0 155 cmdline_parser_print_version ();
mas01cr@0 156 if (strlen(gengetopt_args_info_purpose) > 0)
mas01cr@0 157 printf("%s\n", gengetopt_args_info_purpose);
mas01cr@0 158 printf("%s\n", gengetopt_args_info_usage);
mas01cr@0 159 printf("%s\n", gengetopt_args_info_help[1]);
mas01cr@0 160 printf("%s\n", gengetopt_args_info_help[2]);
mas01cr@0 161 printf("%s\n", gengetopt_args_info_help[0]);
mas01cr@0 162 exit(0);
mas01cr@0 163 }
mas01cr@0 164
mas01cr@0 165 if (cmdline_parser (argc, argv, &args_info) != 0)
mas01cr@151 166 error("Error parsing command line");
mas01cr@0 167
mas01cr@0 168 if(args_info.help_given){
mas01cr@0 169 cmdline_parser_print_help();
mas01cr@0 170 exit(0);
mas01cr@0 171 }
mas01cr@0 172
mas01cr@0 173 if(args_info.verbosity_given){
mas01cr@239 174 verbosity = args_info.verbosity_arg;
mas01cr@239 175 if(verbosity < 0 || verbosity > 10){
mas01cr@239 176 std::cerr << "Warning: verbosity out of range, setting to 1" << std::endl;
mas01cr@239 177 verbosity = 1;
mas01cr@0 178 }
mas01cr@0 179 }
mas01cr@0 180
mas01cr@129 181 if(args_info.size_given) {
mas01cr@256 182 if(args_info.datasize_given) {
mas01cr@256 183 error("both --size and --datasize given", "");
mas01cr@256 184 }
mas01cr@256 185 if(args_info.ntracks_given) {
mas01cr@256 186 error("both --size and --ntracks given", "");
mas01cr@256 187 }
mas01cr@256 188 if(args_info.datadim_given) {
mas01cr@256 189 error("both --size and --datadim given", "");
mas01cr@256 190 }
mas01cr@196 191 if (args_info.size_arg < 50 || args_info.size_arg > 32000) {
mas01cr@129 192 error("Size out of range", "");
mas01cr@129 193 }
mas01cr@256 194 double ratio = (double) args_info.size_arg * 1000000 / ((double) O2_DEFAULTDBSIZE);
mas01cr@256 195 /* FIXME: what's the safe way of doing this? */
mas01cr@256 196 datasize = (unsigned int) ceil(datasize * ratio);
mas01cr@256 197 ntracks = (unsigned int) ceil(ntracks * ratio);
mas01cr@256 198 } else {
mas01cr@256 199 if(args_info.datasize_given) {
mas01cr@256 200 datasize = args_info.datasize_arg;
mas01cr@256 201 }
mas01cr@256 202 if(args_info.ntracks_given) {
mas01cr@256 203 ntracks = args_info.ntracks_arg;
mas01cr@256 204 }
mas01cr@256 205 if(args_info.datadim_given) {
mas01cr@256 206 datadim = args_info.datadim_arg;
mas01cr@256 207 }
mas01cr@129 208 }
mas01cr@129 209
mas01cr@239 210 if(args_info.radius_given) {
mas01cr@239 211 radius = args_info.radius_arg;
mas01mc@307 212 if(radius < 0 || radius > 1000000000) {
mas01cr@77 213 error("radius out of range");
mas01cr@239 214 } else {
mas01cr@239 215 VERB_LOG(3, "Setting radius to %f\n", radius);
mas01mc@17 216 }
mas01mc@17 217 }
mas01mc@17 218
mas01mc@292 219 sequenceLength = args_info.sequencelength_arg;
mas01mc@292 220 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01mc@292 221 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01mc@292 222 }
mas01mc@292 223 sequenceHop = args_info.sequencehop_arg;
mas01mc@292 224 if(sequenceHop < 1 || sequenceHop > 1000) {
mas01mc@292 225 error("seqhop out of range: 1 <= seqhop <= 1000");
mas01mc@292 226 }
mas01mc@292 227
mas01mc@292 228 if (args_info.absolute_threshold_given) {
mas01mc@292 229 if (args_info.absolute_threshold_arg >= 0) {
mas01mc@292 230 error("absolute threshold out of range: should be negative");
mas01mc@292 231 }
mas01mc@292 232 use_absolute_threshold = true;
mas01mc@292 233 absolute_threshold = args_info.absolute_threshold_arg;
mas01mc@292 234 }
mas01mc@292 235 if (args_info.relative_threshold_given) {
mas01mc@292 236 use_relative_threshold = true;
mas01mc@292 237 relative_threshold = args_info.relative_threshold_arg;
mas01mc@292 238 }
mas01mc@292 239
mas01cr@0 240 if(args_info.SERVER_given){
mas01cr@0 241 command=COM_SERVER;
mas01cr@0 242 port=args_info.SERVER_arg;
mas01cr@0 243 if(port<100 || port > 100000)
mas01cr@0 244 error("port out of range");
mas01cr@151 245 isServer = 1;
mas01cr@105 246 #if defined(O2_DEBUG)
mas01cr@104 247 struct sigaction sa;
mas01cr@104 248 sa.sa_sigaction = sigterm_action;
mas01cr@104 249 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 250 sigaction(SIGTERM, &sa, NULL);
mas01cr@104 251 sa.sa_sigaction = sighup_action;
mas01cr@104 252 sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
mas01cr@104 253 sigaction(SIGHUP, &sa, NULL);
mas01cr@105 254 #endif
mas01mc@308 255 if(args_info.load_index_given){
mas01mc@308 256 if(!args_info.database_given)
mas01mc@308 257 error("load_index requires a --database argument");
mas01mc@308 258 else
mas01mc@308 259 dbName=args_info.database_arg;
mas01mc@308 260 if(!args_info.radius_given)
mas01mc@308 261 error("load_index requires a --radius argument");
mas01mc@308 262 if(!args_info.sequencelength_given)
mas01mc@308 263 error("load_index requires a --sequenceLength argument");
mas01mc@308 264 WS_load_index = true;
mas01mc@308 265 }
mas01cr@0 266 return 0;
mas01cr@0 267 }
mas01cr@0 268
mas01cr@0 269 // No return on client command, find database command
mas01cr@105 270 if(args_info.client_given){
mas01cr@105 271 command=COM_CLIENT;
mas01cr@105 272 hostport=args_info.client_arg;
mas01cr@105 273 isClient=1;
mas01cr@105 274 }
mas01cr@0 275
mas01cr@105 276 if(args_info.NEW_given){
mas01cr@105 277 command=COM_CREATE;
mas01cr@105 278 dbName=args_info.database_arg;
mas01cr@105 279 return 0;
mas01cr@105 280 }
mas01cr@0 281
mas01cr@105 282 if(args_info.STATUS_given){
mas01cr@105 283 command=COM_STATUS;
mas01cr@105 284 dbName=args_info.database_arg;
mas01cr@105 285 return 0;
mas01cr@105 286 }
mas01cr@0 287
mas01cr@280 288 if(args_info.SAMPLE_given) {
mas01cr@280 289 command = COM_SAMPLE;
mas01cr@280 290 dbName = args_info.database_arg;
mas01cr@280 291 sequenceLength = args_info.sequencelength_arg;
mas01cr@280 292 if(sequenceLength < 1 || sequenceLength > 1000) {
mas01cr@280 293 error("seqlen out of range: 1 <= seqlen <= 1000");
mas01cr@280 294 }
mas01cr@280 295 nsamples = args_info.nsamples_arg;
mas01cr@280 296 return 0;
mas01cr@280 297 }
mas01cr@280 298
mas01cr@105 299 if(args_info.DUMP_given){
mas01cr@105 300 command=COM_DUMP;
mas01cr@105 301 dbName=args_info.database_arg;
mas01cr@131 302 output = args_info.output_arg;
mas01cr@105 303 return 0;
mas01cr@105 304 }
mas01cr@0 305
mas01cr@105 306 if(args_info.L2NORM_given){
mas01cr@105 307 command=COM_L2NORM;
mas01cr@105 308 dbName=args_info.database_arg;
mas01cr@105 309 return 0;
mas01cr@105 310 }
mas01cr@0 311
mas01cr@193 312 if(args_info.POWER_given){
mas01cr@193 313 command=COM_POWER;
mas01cr@193 314 dbName=args_info.database_arg;
mas01cr@193 315 return 0;
mas01cr@193 316 }
mas01cr@193 317
mas01cr@105 318 if(args_info.INSERT_given){
mas01cr@105 319 command=COM_INSERT;
mas01cr@105 320 dbName=args_info.database_arg;
mas01cr@105 321 inFile=args_info.features_arg;
mas01cr@105 322 if(args_info.key_given)
mas01mc@292 323 if(!args_info.features_given)
mas01mc@292 324 error("INSERT: '-k key' argument depends on '-f features'");
mas01mc@292 325 else
mas01mc@292 326 key=args_info.key_arg;
mas01cr@105 327 if(args_info.times_given){
mas01cr@105 328 timesFileName=args_info.times_arg;
mas01cr@105 329 if(strlen(timesFileName)>0){
mas01cr@239 330 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 331 error("Could not open times file for reading", timesFileName);
mas01cr@105 332 usingTimes=1;
mas01cr@105 333 }
mas01cr@105 334 }
mas01cr@193 335 if (args_info.power_given) {
mas01cr@193 336 powerFileName = args_info.power_arg;
mas01cr@193 337 if (strlen(powerFileName) > 0) {
mas01cr@193 338 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 339 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 340 }
mas01cr@193 341 usingPower = 1;
mas01cr@193 342 }
mas01cr@193 343 }
mas01cr@105 344 return 0;
mas01cr@105 345 }
mas01cr@105 346
mas01cr@105 347 if(args_info.BATCHINSERT_given){
mas01cr@105 348 command=COM_BATCHINSERT;
mas01cr@105 349 dbName=args_info.database_arg;
mas01cr@105 350 inFile=args_info.featureList_arg;
mas01cr@105 351 if(args_info.keyList_given)
mas01tc@298 352 if(!args_info.featureList_given)
mas01tc@300 353 error("BATCHINSERT: '-K keyList' argument depends on '-F featureList'");
mas01mc@292 354 else
mas01cr@304 355 key=args_info.keyList_arg; // INCONSISTENT NO CHECK
mas01cr@0 356
mas01cr@105 357 /* TO DO: REPLACE WITH
mas01cr@0 358 if(args_info.keyList_given){
mas01mc@18 359 trackFileName=args_info.keyList_arg;
mas01cr@239 360 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01mc@18 361 error("Could not open keyList file for reading",trackFileName);
mas01cr@0 362 }
mas01cr@0 363 AND UPDATE BATCHINSERT()
mas01cr@105 364 */
mas01cr@105 365
mas01cr@105 366 if(args_info.timesList_given){
mas01cr@105 367 timesFileName=args_info.timesList_arg;
mas01cr@105 368 if(strlen(timesFileName)>0){
mas01cr@239 369 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 370 error("Could not open timesList file for reading", timesFileName);
mas01cr@105 371 usingTimes=1;
mas01cr@105 372 }
mas01cr@105 373 }
mas01cr@193 374 if(args_info.powerList_given){
mas01cr@193 375 powerFileName=args_info.powerList_arg;
mas01cr@193 376 if(strlen(powerFileName)>0){
mas01cr@239 377 if(!(powerFile = new std::ifstream(powerFileName,std::ios::in)))
mas01cr@193 378 error("Could not open powerList file for reading", powerFileName);
mas01cr@193 379 usingPower=1;
mas01cr@193 380 }
mas01cr@193 381 }
mas01cr@105 382 return 0;
mas01cr@105 383 }
mas01mc@292 384
mas01mc@292 385 // Set no_unit_norm flag
mas01mc@292 386 no_unit_norming = args_info.no_unit_norming_flag;
mas01mc@292 387 lsh_use_u_functions = args_info.lsh_use_u_functions_flag;
mas01mc@292 388
mas01mc@292 389 // LSH Index Command
mas01mc@292 390 if(args_info.INDEX_given){
mas01mc@292 391 if(radius <= 0 )
mas01mc@292 392 error("INDEXing requires a Radius argument");
mas01mc@292 393 if(!(sequenceLength>0 && sequenceLength <= O2_MAXSEQLEN))
mas01mc@292 394 error("INDEXing requires 1 <= sequenceLength <= 1000");
mas01mc@292 395 command=COM_INDEX;
mas01mc@292 396 dbName=args_info.database_arg;
mas01mc@292 397
mas01mc@292 398 // Whether to store LSH hash tables for query in core (FORMAT2)
mas01mc@297 399 lsh_in_core = !args_info.lsh_on_disk_flag; // This flag is set to 0 if on_disk requested
mas01mc@292 400
mas01mc@292 401 lsh_param_w = args_info.lsh_w_arg;
mas01mc@292 402 if(!(lsh_param_w>0 && lsh_param_w<=O2_SERIAL_MAX_BINWIDTH))
mas01mc@292 403 error("Indexing parameter w out of range (0.0 < w <= 100.0)");
mas01mc@292 404
mas01mc@292 405 lsh_param_k = args_info.lsh_k_arg;
mas01mc@292 406 if(!(lsh_param_k>0 && lsh_param_k<=O2_SERIAL_MAX_FUNS))
mas01mc@292 407 error("Indexing parameter k out of range (1 <= k <= 100)");
mas01mc@292 408
mas01mc@292 409 lsh_param_m = args_info.lsh_m_arg;
mas01mc@292 410 if(!(lsh_param_m>0 && lsh_param_m<= (1 + (sqrt(1 + O2_SERIAL_MAX_TABLES*8.0)))/2.0))
mas01mc@292 411 error("Indexing parameter m out of range (1 <= m <= 20)");
mas01mc@292 412
mas01mc@292 413 lsh_param_N = args_info.lsh_N_arg;
mas01mc@292 414 if(!(lsh_param_N>0 && lsh_param_N<=O2_SERIAL_MAX_ROWS))
mas01mc@292 415 error("Indexing parameter N out of range (1 <= N <= 1000000)");
mas01mc@292 416
mas01mc@292 417 lsh_param_b = args_info.lsh_b_arg;
mas01mc@292 418 if(!(lsh_param_b>0 && lsh_param_b<=O2_SERIAL_MAX_TRACKBATCH))
mas01mc@292 419 error("Indexing parameter b out of range (1 <= b <= 10000)");
mas01mc@292 420
mas01mc@296 421 lsh_param_ncols = args_info.lsh_ncols_arg;
mas01mc@296 422 if(lsh_in_core) // We don't want to block rows with FORMAT2 indexing
mas01mc@296 423 lsh_param_ncols = O2_SERIAL_MAX_COLS;
mas01mc@292 424 if( !(lsh_param_ncols>0 && lsh_param_ncols<=O2_SERIAL_MAX_COLS))
mas01mc@292 425 error("Indexing parameter ncols out of range (1 <= ncols <= 1000");
mas01mc@292 426
mas01mc@292 427 return 0;
mas01mc@292 428 }
mas01mc@292 429
mas01cr@105 430 // Query command and arguments
mas01cr@105 431 if(args_info.QUERY_given){
mas01cr@105 432 command=COM_QUERY;
mas01cr@105 433 dbName=args_info.database_arg;
mas01mc@292 434 // XOR features and key search
mas01mc@292 435 if(!args_info.features_given && !args_info.key_given || (args_info.features_given && args_info.key_given))
mas01mc@292 436 error("QUERY requires exactly one of either -f features or -k key");
mas01mc@292 437 if(args_info.features_given)
mas01mc@292 438 inFile=args_info.features_arg; // query from file
mas01mc@292 439 else{
mas01mc@292 440 query_from_key = true;
mas01mc@292 441 key=args_info.key_arg; // query from key
mas01mc@292 442 }
mas01mc@292 443
mas01cr@105 444 if(args_info.keyList_given){
mas01cr@105 445 trackFileName=args_info.keyList_arg;
mas01cr@239 446 if(strlen(trackFileName)>0 && !(trackFile = new std::ifstream(trackFileName,std::ios::in)))
mas01cr@105 447 error("Could not open keyList file for reading",trackFileName);
mas01cr@105 448 }
mas01cr@105 449
mas01cr@105 450 if(args_info.times_given){
mas01cr@105 451 timesFileName=args_info.times_arg;
mas01cr@105 452 if(strlen(timesFileName)>0){
mas01cr@239 453 if(!(timesFile = new std::ifstream(timesFileName,std::ios::in)))
mas01cr@105 454 error("Could not open times file for reading", timesFileName);
mas01cr@105 455 usingTimes=1;
mas01cr@105 456 }
mas01cr@105 457 }
mas01cr@193 458
mas01cr@193 459 if(args_info.power_given){
mas01cr@193 460 powerFileName=args_info.power_arg;
mas01cr@193 461 if(strlen(powerFileName)>0){
mas01cr@193 462 if (!(powerfd = open(powerFileName, O_RDONLY))) {
mas01cr@193 463 error("Could not open power file for reading", powerFileName, "open");
mas01cr@193 464 }
mas01cr@193 465 usingPower = 1;
mas01cr@193 466 }
mas01cr@193 467 }
mas01cr@105 468
mas01cr@105 469 // query type
mas01cr@105 470 if(strncmp(args_info.QUERY_arg, "track", MAXSTR)==0)
mas01cr@105 471 queryType=O2_TRACK_QUERY;
mas01cr@105 472 else if(strncmp(args_info.QUERY_arg, "point", MAXSTR)==0)
mas01cr@105 473 queryType=O2_POINT_QUERY;
mas01cr@105 474 else if(strncmp(args_info.QUERY_arg, "sequence", MAXSTR)==0)
mas01cr@105 475 queryType=O2_SEQUENCE_QUERY;
mas01mc@248 476 else if(strncmp(args_info.QUERY_arg, "nsequence", MAXSTR)==0)
mas01mc@248 477 queryType=O2_N_SEQUENCE_QUERY;
mas01mc@263 478 else if(strncmp(args_info.QUERY_arg, "onetoonensequence", MAXSTR)==0)
mas01mc@263 479 queryType=O2_ONE_TO_ONE_N_SEQUENCE_QUERY;
mas01cr@105 480 else
mas01cr@105 481 error("unsupported query type",args_info.QUERY_arg);
mas01cr@105 482
mas01cr@105 483 if(!args_info.exhaustive_flag){
mas01cr@105 484 queryPoint = args_info.qpoint_arg;
mas01cr@105 485 usingQueryPoint=1;
mas01cr@105 486 if(queryPoint<0 || queryPoint >10000)
mas01cr@105 487 error("queryPoint out of range: 0 <= queryPoint <= 10000");
mas01cr@105 488 }
mas01mc@292 489
mas01mc@296 490 // Whether to pre-load LSH hash tables for query (default on, if flag set then off)
mas01mc@297 491 lsh_in_core = !args_info.lsh_on_disk_flag;
mas01mc@292 492
mas01mc@292 493 // Whether to perform exact evaluation of points returned by LSH
mas01mc@292 494 lsh_exact = args_info.lsh_exact_flag;
mas01mc@292 495
mas01cr@105 496 pointNN = args_info.pointnn_arg;
mas01mc@263 497 if(pointNN < 1 || pointNN > O2_MAXNN) {
mas01mc@263 498 error("pointNN out of range: 1 <= pointNN <= 1000000");
mas01cr@105 499 }
mas01cr@105 500 trackNN = args_info.resultlength_arg;
mas01mc@263 501 if(trackNN < 1 || trackNN > O2_MAXNN) {
mas01mc@263 502 error("resultlength out of range: 1 <= resultlength <= 1000000");
mas01cr@105 503 }
mas01cr@105 504 return 0;
mas01cr@105 505 }
mas01cr@105 506 return -1; // no command found
mas01cr@0 507 }
mas01cr@0 508
mas01cr@133 509 void audioDB::status(const char* dbName, adb__statusResponse *adbStatusResponse){
mas01cr@0 510 if(!dbH)
mas01cr@196 511 initTables(dbName, 0);
mas01cr@0 512
mas01cr@0 513 unsigned dudCount=0;
mas01cr@0 514 unsigned nullCount=0;
mas01cr@0 515 for(unsigned k=0; k<dbH->numFiles; k++){
mas01mc@18 516 if(trackTable[k]<sequenceLength){
mas01cr@0 517 dudCount++;
mas01mc@18 518 if(!trackTable[k])
mas01cr@76 519 nullCount++;
mas01cr@0 520 }
mas01cr@0 521 }
mas01cr@76 522
mas01cr@133 523 if(adbStatusResponse == 0) {
mas01cr@76 524
mas01cr@76 525 // Update Header information
mas01cr@239 526 std::cout << "num files:" << dbH->numFiles << std::endl;
mas01cr@239 527 std::cout << "data dim:" << dbH->dim <<std::endl;
mas01cr@76 528 if(dbH->dim>0){
mas01cr@239 529 std::cout << "total vectors:" << dbH->length/(sizeof(double)*dbH->dim)<<std::endl;
mas01cr@239 530 std::cout << "vectors available:" << (dbH->timesTableOffset-(dbH->dataOffset+dbH->length))/(sizeof(double)*dbH->dim) << std::endl;
mas01cr@76 531 }
mas01cr@239 532 std::cout << "total bytes:" << dbH->length << " (" << (100.0*dbH->length)/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01cr@239 533 std::cout << "bytes available:" << dbH->timesTableOffset-(dbH->dataOffset+dbH->length) << " (" <<
mas01cr@239 534 (100.0*(dbH->timesTableOffset-(dbH->dataOffset+dbH->length)))/(dbH->timesTableOffset-dbH->dataOffset) << "%)" << std::endl;
mas01mc@301 535 std::cout << "flags:" << " l2norm[" << DISPLAY_FLAG(dbH->flags&O2_FLAG_L2NORM)
mas01mc@301 536 << "] minmax[" << DISPLAY_FLAG(dbH->flags&O2_FLAG_MINMAX)
mas01mc@301 537 << "] power[" << DISPLAY_FLAG(dbH->flags&O2_FLAG_POWER)
mas01mc@301 538 << "] times[" << DISPLAY_FLAG(dbH->flags&O2_FLAG_TIMES) << "]" << endl;
mas01cr@239 539 std::cout << "null count: " << nullCount << " small sequence count " << dudCount-nullCount << std::endl;
mas01cr@76 540 } else {
mas01cr@133 541 adbStatusResponse->result.numFiles = dbH->numFiles;
mas01cr@133 542 adbStatusResponse->result.dim = dbH->dim;
mas01cr@133 543 adbStatusResponse->result.length = dbH->length;
mas01cr@133 544 adbStatusResponse->result.dudCount = dudCount;
mas01cr@133 545 adbStatusResponse->result.nullCount = nullCount;
mas01cr@133 546 adbStatusResponse->result.flags = dbH->flags;
mas01cr@76 547 }
mas01cr@0 548 }
mas01cr@0 549
mas01cr@196 550 void audioDB::l2norm(const char* dbName) {
mas01cr@196 551 forWrite = true;
mas01cr@196 552 initTables(dbName, 0);
mas01cr@0 553 if(dbH->length>0){
mas01cr@196 554 /* FIXME: should probably be uint64_t */
mas01cr@0 555 unsigned numVectors = dbH->length/(sizeof(double)*dbH->dim);
mas01cr@196 556 CHECKED_MMAP(double *, dataBuf, dbH->dataOffset, dataBufLength);
mas01cr@0 557 unitNormAndInsertL2(dataBuf, dbH->dim, numVectors, 0); // No append
mas01cr@0 558 }
mas01cr@0 559 // Update database flags
mas01cr@0 560 dbH->flags = dbH->flags|O2_FLAG_L2NORM;
mas01cr@0 561 memcpy (db, dbH, O2_HEADERSIZE);
mas01cr@0 562 }
mas01cr@193 563
mas01cr@193 564 void audioDB::power_flag(const char *dbName) {
mas01cr@196 565 forWrite = true;
mas01cr@196 566 initTables(dbName, 0);
mas01cr@193 567 if (dbH->length > 0) {
mas01cr@193 568 error("cannot turn on power storage for non-empty database", dbName);
mas01cr@193 569 }
mas01cr@193 570 dbH->flags |= O2_FLAG_POWER;
mas01cr@193 571 memcpy(db, dbH, O2_HEADERSIZE);
mas01cr@193 572 }
mas01cr@193 573
mas01cr@239 574 // Unit norm block of features
mas01cr@0 575
mas01cr@239 576 /* FIXME: in fact this does not unit norm a block of features, it just
mas01cr@239 577 records the L2 norms somewhere. unitNorm() does in fact unit norm
mas01cr@239 578 a block of features. */
mas01cr@0 579 void audioDB::unitNormAndInsertL2(double* X, unsigned dim, unsigned n, unsigned append=0){
mas01cr@0 580 unsigned d;
mas01cr@59 581 double *p;
mas01cr@0 582 unsigned nn = n;
mas01cr@0 583
mas01cr@0 584 assert(l2normTable);
mas01cr@0 585
mas01cr@0 586 if( !append && (dbH->flags & O2_FLAG_L2NORM) )
mas01cr@0 587 error("Database is already L2 normed", "automatic norm on insert is enabled");
mas01cr@0 588
mas01cr@239 589 VERB_LOG(2, "norming %u vectors...", n);
mas01cr@0 590
mas01cr@0 591 double* l2buf = new double[n];
mas01cr@0 592 double* l2ptr = l2buf;
mas01cr@0 593 assert(l2buf);
mas01cr@0 594 assert(X);
mas01cr@0 595
mas01cr@0 596 while(nn--){
mas01cr@0 597 p=X;
mas01cr@0 598 *l2ptr=0.0;
mas01cr@0 599 d=dim;
mas01cr@0 600 while(d--){
mas01cr@0 601 *l2ptr+=*p**p;
mas01cr@0 602 p++;
mas01cr@0 603 }
mas01mc@17 604 l2ptr++;
mas01mc@17 605 X+=dim;
mas01cr@0 606 }
mas01cr@0 607 unsigned offset;
mas01cr@84 608 if(append) {
mas01cr@84 609 // FIXME: a hack, a very palpable hack: the vectors have already
mas01cr@84 610 // been inserted, and dbH->length has already been updated. We
mas01cr@84 611 // need to subtract off again the number of vectors that we've
mas01cr@84 612 // inserted this time...
mas01cr@84 613 offset=(dbH->length/(dbH->dim*sizeof(double)))-n; // number of vectors
mas01cr@84 614 } else {
mas01cr@0 615 offset=0;
mas01cr@84 616 }
mas01cr@0 617 memcpy(l2normTable+offset, l2buf, n*sizeof(double));
mas01cr@0 618 if(l2buf)
mas01mc@17 619 delete[] l2buf;
mas01cr@239 620 VERB_LOG(2, " done.");
mas01cr@193 621 }
mas01cr@193 622
mas01mc@308 623 // This entry point is visited once per instance
mas01mc@308 624 // so it is a good place to set any global state variables
mas01cr@0 625 int main(const unsigned argc, char* const argv[]){
mas01mc@308 626 SERVER_LSH_INDEX_SINGLETON = 0; // Initialize global variables
mas01cr@0 627 audioDB(argc, argv);
mas01cr@0 628 }