annotate soap.cpp @ 548:e18843dc0aea

Implement a rudimentary API for audioDB::liszt The API is rudimentary because we've dropped support for the incremental retrieval of tracks and their number of vectors (at the API level; the SOAP and command-line support is still there -- no changes should be visible). This is potentially bad for the large-scale databases, of course; one million tracks will take of the order of 16MB of RAM, more if I'm unlucky about how std::string.c_str() is implemented. Both this liszt operation and querying (and sampling, forthcoming...) would benefit from a `cursor-like' interface to retrieval results: for an API like that, instead of getting a struct with the data there, you get a cookie with which you can ask the database for successive results. This would be neat for all sorts of reasons. In the meantime, at least this change fixes SOAP memory leaks related to liszt. Make liszt.o part of LIBOBJS rather than ordinary OBJS, so that the liszt functionality is actually compiled into the library. Add a test for this library functionality; also modify the command-line test file to run the SOAP server on its own port.
author mas01cr
date Wed, 11 Feb 2009 12:38:03 +0000
parents cc2b97d020b1
children d5ada9532a40
rev   line source
mas01cr@239 1 #include "audioDB.h"
mas01cr@239 2 #include "adb.nsmap"
mas01cr@239 3
mas01cr@239 4 /* Command-line client definitions */
mas01cr@239 5
mas01cr@239 6 // FIXME: this can't propagate the sequence length argument (used for
mas01cr@239 7 // dudCount). See adb__status() definition for the other half of
mas01cr@239 8 // this. -- CSR, 2007-10-01
mas01cr@239 9 void audioDB::ws_status(const char*dbName, char* hostport){
mas01cr@239 10 struct soap soap;
mas01cr@239 11 adb__statusResponse adbStatusResponse;
mas01cr@239 12
mas01cr@239 13 // Query an existing adb database
mas01cr@239 14 soap_init(&soap);
mas01cr@239 15 if(soap_call_adb__status(&soap,hostport,NULL,(char*)dbName,adbStatusResponse)==SOAP_OK) {
mas01cr@239 16 std::cout << "numFiles = " << adbStatusResponse.result.numFiles << std::endl;
mas01cr@239 17 std::cout << "dim = " << adbStatusResponse.result.dim << std::endl;
mas01cr@239 18 std::cout << "length = " << adbStatusResponse.result.length << std::endl;
mas01cr@239 19 std::cout << "dudCount = " << adbStatusResponse.result.dudCount << std::endl;
mas01cr@239 20 std::cout << "nullCount = " << adbStatusResponse.result.nullCount << std::endl;
mas01mc@324 21 std::cout << "flags = " << (adbStatusResponse.result.flags & 0x00FFFFFF) << std::endl;
mas01cr@239 22 } else {
mas01cr@239 23 soap_print_fault(&soap,stderr);
mas01cr@239 24 }
mas01cr@239 25
mas01cr@239 26 soap_destroy(&soap);
mas01cr@239 27 soap_end(&soap);
mas01cr@239 28 soap_done(&soap);
mas01cr@239 29 }
mas01cr@239 30
mas01mc@334 31 void audioDB::ws_liszt(const char* dbName, char* Hostport){
mas01mc@334 32 struct soap soap;
mas01mc@334 33 adb__lisztResponse adbLisztResponse;
mas01mc@334 34
mas01mc@334 35 soap_init(&soap);
mas01mc@334 36 if(soap_call_adb__liszt(&soap, hostport, NULL, (char*)dbName, lisztOffset, lisztLength, adbLisztResponse)==SOAP_OK){
mas01mc@334 37 for(int i = 0; i < adbLisztResponse.result.__sizeRkey; i++) {
mas01mc@334 38 std::cout << "[" << i+lisztOffset << "] " << adbLisztResponse.result.Rkey[i] << " ("
mas01mc@334 39 << adbLisztResponse.result.Rlen[i] << ")" << std::endl;
mas01mc@334 40 }
mas01mc@334 41 } else {
mas01mc@334 42 soap_print_fault(&soap, stderr);
mas01mc@334 43 }
mas01mc@334 44 }
mas01mc@334 45
mas01mc@308 46 // WS_QUERY (CLIENT SIDE)
mas01mc@307 47 void audioDB::ws_query(const char*dbName, const char *featureFileName, const char* hostport){
mas01cr@239 48 struct soap soap;
mas01cr@239 49 adb__queryResponse adbQueryResponse;
mas01mc@329 50 VERB_LOG(1, "Calling fileName query on database %s with featureFile=%s\n", dbName, featureFileName);
mas01cr@333 51 soap_init(&soap);
mas01cr@333 52 if(soap_call_adb__query(&soap, hostport, NULL, (char *) dbName,
mas01cr@333 53 (char *)featureFileName, (char *)trackFileName,
mas01cr@333 54 (char *)timesFileName, (char *) powerFileName,
mas01cr@333 55 queryType, queryPoint,
mas01cr@333 56 pointNN, trackNN, sequenceLength,
mas01cr@333 57 radius, absolute_threshold, relative_threshold,
mas01mc@471 58 !usingQueryPoint, lsh_exact, no_unit_norming,
mas01cr@333 59 adbQueryResponse)
mas01cr@333 60 == SOAP_OK) {
mas01cr@333 61 if(radius == 0) {
mas01cr@333 62 for(int i=0; i<adbQueryResponse.result.__sizeRlist; i++) {
mas01cr@333 63 std::cout << adbQueryResponse.result.Rlist[i] << " "
mas01cr@333 64 << adbQueryResponse.result.Dist[i] << " "
mas01cr@333 65 << adbQueryResponse.result.Qpos[i] << " "
mas01cr@333 66 << adbQueryResponse.result.Spos[i] << std::endl;
mas01cr@333 67 }
mas01cr@333 68 } else {
mas01cr@333 69 for(int i = 0; i < adbQueryResponse.result.__sizeRlist; i++) {
mas01cr@333 70 std::cout << adbQueryResponse.result.Rlist[i] << " "
mas01cr@333 71 << adbQueryResponse.result.Spos[i] << std::endl;
mas01cr@333 72 }
mas01cr@333 73 }
mas01cr@333 74 } else {
mas01cr@333 75 soap_print_fault(&soap,stderr);
mas01cr@239 76 }
mas01cr@333 77
mas01cr@239 78 soap_destroy(&soap);
mas01cr@239 79 soap_end(&soap);
mas01cr@239 80 soap_done(&soap);
mas01cr@239 81 }
mas01mc@307 82
mas01mc@308 83 // WS_QUERY_BY_KEY (CLIENT SIDE)
mas01mc@328 84 void audioDB::ws_query_by_key(const char*dbName, const char *trackKey, const char* featureFileName, const char* hostport){
mas01mc@307 85 struct soap soap;
mas01mc@307 86 adb__queryResponse adbQueryResponse;
mas01mc@314 87 /* JUST TRY TO USE A DATA STRUCTURE WITH PHP
mas01mc@314 88 adb__sequenceQueryParms asqp;
mas01mc@314 89 asqp.keyList = (char*)trackFileName;
mas01mc@314 90 asqp.timesFileName = (char*)timesFileName;
mas01mc@314 91 asqp.queryPoint = queryPoint;
mas01mc@314 92 asqp.pointNN = pointNN;
mas01mc@314 93 asqp.trackNN = trackNN;
mas01mc@314 94 asqp.sequenceLength = sequenceLength;
mas01mc@314 95 asqp.radius = radius;
mas01mc@314 96 asqp.relative_threshold = relative_threshold;
mas01mc@314 97 asqp.absolute_threshold = absolute_threshold;
mas01mc@314 98 asqp.usingQueryPoint = usingQueryPoint;
mas01mc@314 99 asqp.lsh_exact = lsh_exact;
mas01mc@314 100 */
mas01mc@331 101 VERB_LOG(1, "Calling %s query on database %s with %s=%s\n", (trackKey&&strlen(trackKey))?"KEY":"FILENAME", dbName, (trackKey&&strlen(trackKey))?"KEY":"FILENAME",(trackKey&&strlen(trackKey))?trackKey:featureFileName);
mas01mc@307 102 soap_init(&soap);
mas01mc@307 103 if(queryType==O2_SEQUENCE_QUERY || queryType==O2_N_SEQUENCE_QUERY){
mas01mc@314 104 if(soap_call_adb__sequenceQueryByKey(&soap,hostport,NULL,
mas01mc@328 105 (char*)dbName,
mas01mc@328 106 (char*)trackKey,
mas01mc@328 107 (char*)featureFileName,
mas01mc@328 108 queryType,
mas01mc@328 109 (char*)trackFileName, // this means keyFileName
mas01mc@328 110 (char*)timesFileName,
mas01mc@314 111 queryPoint,
mas01mc@328 112 pointNN,
mas01mc@328 113 trackNN,
mas01mc@328 114 sequenceLength,
mas01mc@328 115 radius,
mas01mc@328 116 absolute_threshold,
mas01mc@328 117 usingQueryPoint,
mas01mc@471 118 lsh_exact,
mas01mc@471 119 no_unit_norming,
mas01mc@314 120 adbQueryResponse)==SOAP_OK){
mas01mc@307 121 //std::std::cerr << "result list length:" << adbQueryResponse.result.__sizeRlist << std::std::endl;
mas01mc@307 122 for(int i=0; i<adbQueryResponse.result.__sizeRlist; i++)
mas01mc@307 123 std::cout << adbQueryResponse.result.Rlist[i] << " " << adbQueryResponse.result.Dist[i]
mas01mc@307 124 << " " << adbQueryResponse.result.Qpos[i] << " " << adbQueryResponse.result.Spos[i] << std::endl;
mas01mc@307 125 }
mas01mc@307 126 else
mas01mc@307 127 soap_print_fault(&soap,stderr);
mas01mc@307 128 }else
mas01mc@307 129 ;// FIX ME: WRITE NON-SEQUENCE QUERY BY KEY ?
mas01mc@307 130
mas01mc@307 131 soap_destroy(&soap);
mas01mc@307 132 soap_end(&soap);
mas01mc@307 133 soap_done(&soap);
mas01mc@307 134 }
mas01mc@307 135
mas01cr@239 136
mas01cr@333 137 /* handy macros */
mas01cr@333 138 #define INTSTRINGIFY(val, str) \
mas01cr@333 139 char str[256]; \
mas01cr@333 140 snprintf(str, 256, "%d", val);
mas01cr@333 141 #define DOUBLESTRINGIFY(val, str) \
mas01cr@333 142 char str[256]; \
mas01cr@333 143 snprintf(str, 256, "%f", val);
mas01cr@333 144
mas01cr@239 145 /* Server definitions */
mas01cr@239 146 int adb__status(struct soap* soap, xsd__string dbName, adb__statusResponse &adbStatusResponse){
mas01cr@370 147 const char *argv[]={"./audioDB",COM_STATUS,"-d",dbName};
mas01cr@239 148 const unsigned argc = 4;
mas01cr@239 149 try {
mas01cr@239 150 audioDB(argc, argv, &adbStatusResponse);
mas01cr@239 151 return SOAP_OK;
mas01cr@239 152 } catch(char *err) {
mas01cr@239 153 soap_receiver_fault(soap, err, "");
mas01cr@239 154 return SOAP_FAULT;
mas01cr@239 155 }
mas01cr@239 156 }
mas01mc@334 157
mas01mc@334 158 int adb__liszt(struct soap* soap, xsd__string dbName, xsd__int lisztOffset, xsd__int lisztLength,
mas01mc@334 159 adb__lisztResponse& adbLisztResponse){
mas01mc@334 160
mas01mc@334 161 INTSTRINGIFY(lisztOffset, lisztOffsetStr);
mas01mc@334 162 INTSTRINGIFY(lisztLength, lisztLengthStr);
mas01mc@334 163
mas01cr@370 164 const char *argv[] = {"./audioDB", COM_LISZT, "-d",dbName, "--lisztOffset", lisztOffsetStr, "--lisztLength", lisztLengthStr};
mas01mc@334 165 const unsigned argc = 8;
mas01mc@334 166 try{
mas01cr@548 167 audioDB(argc, argv, soap, &adbLisztResponse);
mas01mc@334 168 return SOAP_OK;
mas01mc@334 169 } catch(char *err) {
mas01mc@334 170 soap_receiver_fault(soap, err, "");
mas01mc@334 171 return SOAP_FAULT;
mas01mc@334 172 }
mas01mc@334 173 }
mas01mc@334 174
mas01cr@239 175 // Literal translation of command line to web service
mas01cr@333 176 int adb__query(struct soap* soap, xsd__string dbName,
mas01cr@333 177 xsd__string qKey, xsd__string keyList,
mas01cr@333 178 xsd__string timesFileName, xsd__string powerFileName,
mas01cr@333 179 xsd__int qType,
mas01cr@333 180 xsd__int qPos, xsd__int pointNN, xsd__int trackNN,
mas01cr@333 181 xsd__int seqLen,
mas01cr@333 182 xsd__double radius,
mas01cr@333 183 xsd__double absolute_threshold, xsd__double relative_threshold,
mas01mc@471 184 xsd__int exhaustive, xsd__int lsh_exact, xsd__int no_unit_norming,
mas01cr@333 185 adb__queryResponse &adbQueryResponse){
mas01cr@239 186 char queryType[256];
mas01mc@329 187
mas01mc@329 188 fprintf(stderr,"Calling fileName query on database %s with featureFile=%s\n", dbName, qKey);
mas01mc@329 189
mas01cr@239 190 for(int k=0; k<256; k++)
mas01cr@239 191 queryType[k]='\0';
mas01cr@239 192 if(qType == O2_POINT_QUERY)
mas01cr@239 193 strncpy(queryType, "point", strlen("point"));
mas01cr@239 194 else if (qType == O2_SEQUENCE_QUERY)
mas01cr@239 195 strncpy(queryType, "sequence", strlen("sequence"));
mas01cr@239 196 else if(qType == O2_TRACK_QUERY)
mas01cr@239 197 strncpy(queryType,"track", strlen("track"));
mas01mc@324 198 else if(qType == O2_N_SEQUENCE_QUERY)
mas01mc@324 199 strncpy(queryType,"nsequence", strlen("nsequence"));
mas01cr@239 200
mas01cr@239 201 if(pointNN==0)
mas01cr@239 202 pointNN=10;
mas01cr@239 203 if(trackNN==0)
mas01cr@239 204 trackNN=10;
mas01cr@239 205 if(seqLen==0)
mas01cr@239 206 seqLen=16;
mas01cr@239 207
mas01cr@333 208 INTSTRINGIFY(qPos, qPosStr);
mas01cr@333 209 INTSTRINGIFY(pointNN, pointNNStr);
mas01cr@333 210 INTSTRINGIFY(trackNN, trackNNStr);
mas01cr@333 211 INTSTRINGIFY(seqLen, seqLenStr);
mas01cr@239 212
mas01cr@333 213 /* We don't necessarily use these, but because of scope we do this
mas01cr@333 214 anyway. We waste 756 bytes of stack this way. */
mas01cr@333 215 DOUBLESTRINGIFY(radius, radiusStr);
mas01cr@333 216 DOUBLESTRINGIFY(absolute_threshold, absolute_thresholdStr);
mas01cr@333 217 DOUBLESTRINGIFY(relative_threshold, relative_thresholdStr);
mas01cr@333 218
mas01cr@333 219 unsigned int argc = 19;
mas01cr@333 220 if (powerFileName) {
mas01cr@333 221 argc += 2;
mas01cr@333 222 }
mas01cr@333 223 if (radius != 0) {
mas01cr@333 224 argc += 2;
mas01cr@333 225 }
mas01cr@333 226 /* we can't use use_absolute_threshold and friends because we're not
mas01cr@333 227 in the audioDB class here. */
mas01cr@333 228 if (absolute_threshold != 0) {
mas01cr@333 229 argc += 2;
mas01cr@333 230 }
mas01cr@333 231 if (relative_threshold != 0) {
mas01cr@333 232 argc += 2;
mas01cr@333 233 }
mas01cr@333 234 if (exhaustive) {
mas01cr@333 235 argc++;
mas01cr@333 236 }
mas01cr@333 237 if (lsh_exact) {
mas01cr@333 238 argc++;
mas01cr@333 239 }
mas01cr@333 240
mas01mc@471 241 if(no_unit_norming){
mas01mc@471 242 argc++;
mas01mc@471 243 }
mas01mc@471 244
mas01cr@345 245 const char **argv = new const char*[argc+1];
mas01cr@333 246 argv[0] = "./audioDB";
mas01cr@333 247 argv[1] = COM_QUERY;
mas01cr@333 248 argv[2] = queryType;
mas01cr@333 249 argv[3] = COM_DATABASE;
mas01cr@333 250 argv[4] = (char *) (ENSURE_STRING(dbName));
mas01cr@333 251 argv[5] = COM_FEATURES;
mas01cr@333 252 argv[6] = (char *) (ENSURE_STRING(qKey));
mas01cr@333 253 argv[7] = COM_KEYLIST;
mas01cr@333 254 argv[8] = (char *) (ENSURE_STRING(keyList));
mas01cr@333 255 argv[9] = COM_TIMES;
mas01cr@333 256 argv[10] = (char *) (ENSURE_STRING(timesFileName));
mas01cr@333 257 argv[11] = COM_QPOINT;
mas01cr@333 258 argv[12] = qPosStr;
mas01cr@333 259 argv[13] = COM_POINTNN;
mas01cr@333 260 argv[14] = pointNNStr;
mas01cr@333 261 argv[15] = COM_TRACKNN;
mas01cr@333 262 argv[16] = trackNNStr;
mas01cr@333 263 argv[17] = COM_SEQLEN;
mas01cr@333 264 argv[18] = seqLenStr;
mas01cr@333 265 int argv_counter = 19;
mas01cr@333 266 if (powerFileName) {
mas01cr@333 267 argv[argv_counter++] = COM_QUERYPOWER;
mas01cr@333 268 argv[argv_counter++] = powerFileName;
mas01cr@333 269 }
mas01cr@333 270 if (radius != 0) {
mas01cr@333 271 argv[argv_counter++] = COM_RADIUS;
mas01cr@333 272 argv[argv_counter++] = radiusStr;
mas01cr@333 273 }
mas01cr@333 274 if (absolute_threshold != 0) {
mas01cr@333 275 argv[argv_counter++] = COM_ABSOLUTE_THRESH;
mas01cr@333 276 argv[argv_counter++] = absolute_thresholdStr;
mas01cr@333 277 }
mas01cr@333 278 if (relative_threshold != 0) {
mas01cr@333 279 argv[argv_counter++] = COM_RELATIVE_THRESH;
mas01cr@333 280 argv[argv_counter++] = relative_thresholdStr;
mas01cr@333 281 }
mas01cr@333 282 if (exhaustive) {
mas01cr@333 283 argv[argv_counter++] = COM_EXHAUSTIVE;
mas01cr@333 284 }
mas01cr@333 285 if (lsh_exact) {
mas01cr@333 286 argv[argv_counter++] = COM_LSH_EXACT;
mas01cr@333 287 }
mas01mc@471 288
mas01mc@471 289 if (no_unit_norming) {
mas01mc@471 290 argv[argv_counter++] = COM_NO_UNIT_NORMING;
mas01mc@471 291 }
mas01mc@471 292
mas01cr@333 293 argv[argv_counter] = NULL;
mas01cr@333 294
mas01cr@239 295 try {
mas01cr@508 296 audioDB(argc, argv, soap, &adbQueryResponse);
mas01cr@333 297 delete [] argv;
mas01cr@239 298 return SOAP_OK;
mas01cr@239 299 } catch (char *err) {
mas01cr@239 300 soap_receiver_fault(soap, err, "");
mas01cr@333 301 delete [] argv;
mas01cr@239 302 return SOAP_FAULT;
mas01cr@239 303 }
mas01cr@239 304 }
mas01cr@239 305
mas01mc@314 306 int adb__sequenceQueryByKey(struct soap* soap,xsd__string dbName,
mas01mc@314 307 xsd__string trackKey,
mas01mc@328 308 xsd__string featureFileName,
mas01mc@314 309 xsd__int queryType,
mas01mc@328 310 xsd__string keyFileName,
mas01mc@314 311 xsd__string timesFileName,
mas01mc@314 312 xsd__int queryPoint,
mas01mc@314 313 xsd__int pointNN,
mas01mc@314 314 xsd__int trackNN,
mas01mc@314 315 xsd__int sequenceLength,
mas01mc@314 316 xsd__double radius,
mas01mc@314 317 xsd__double absolute_threshold,
mas01mc@314 318 xsd__int usingQueryPoint,
mas01mc@471 319 xsd__int lsh_exact, xsd__int no_unit_norming,
mas01mc@314 320 struct adb__queryResponse& adbQueryResponse){
mas01mc@307 321 char qtypeStr[256];
mas01cr@239 322
mas01mc@471 323 fprintf(stderr, "Calling %s query on database %s with %s=%s, distFun:%s\n", (trackKey&&strlen(trackKey))?"KEY":"FILENAME", dbName, (trackKey&&strlen(trackKey))?"KEY":"FILENAME",(trackKey&&strlen(trackKey))?trackKey:featureFileName, no_unit_norming?"Euclidean":"Normed Euclidean");
mas01mc@329 324
mas01mc@314 325 INTSTRINGIFY(queryPoint, qPosStr);
mas01mc@314 326 INTSTRINGIFY(pointNN, pointNNStr);
mas01mc@314 327 INTSTRINGIFY(trackNN, trackNNStr);
mas01mc@314 328 INTSTRINGIFY(sequenceLength, seqLenStr);
mas01mc@314 329 DOUBLESTRINGIFY(absolute_threshold, absolute_thresholdStr);
mas01mc@314 330 DOUBLESTRINGIFY(radius, radiusStr);
mas01mc@307 331
mas01mc@307 332 snprintf(qtypeStr, 256, "nsequence");
mas01mc@310 333 const char *argv[]={
mas01cr@239 334 "./audioDB",
mas01cr@239 335 COM_QUERY,
mas01mc@307 336 qtypeStr,
mas01cr@239 337 COM_DATABASE,
mas01cr@239 338 dbName,
mas01mc@330 339 (trackKey&&strlen(trackKey))?COM_QUERYKEY:COM_FEATURES,
mas01mc@330 340 (trackKey&&strlen(trackKey))?ENSURE_STRING(trackKey):ENSURE_STRING(featureFileName),
mas01cr@239 341 COM_KEYLIST,
mas01mc@328 342 ENSURE_STRING(keyFileName),
mas01mc@314 343 usingQueryPoint?COM_QPOINT:COM_EXHAUSTIVE,
mas01mc@314 344 usingQueryPoint?qPosStr:"",
mas01cr@239 345 COM_POINTNN,
mas01cr@239 346 pointNNStr,
mas01cr@239 347 COM_TRACKNN,
mas01cr@239 348 trackNNStr,
mas01mc@307 349 COM_RADIUS,
mas01mc@307 350 radiusStr,
mas01cr@239 351 COM_SEQLEN,
mas01cr@239 352 seqLenStr,
mas01cr@239 353 COM_ABSOLUTE_THRESH,
mas01mc@310 354 absolute_thresholdStr,
mas01mc@471 355 lsh_exact?COM_LSH_EXACT:"",
mas01mc@471 356 no_unit_norming?COM_NO_UNIT_NORMING:"",
mas01cr@239 357 };
mas01cr@239 358
mas01mc@471 359 const unsigned argc = 23;
mas01mc@310 360
mas01mc@310 361
mas01cr@239 362 try {
mas01cr@508 363 audioDB(argc, argv, soap, &adbQueryResponse);
mas01cr@239 364 return SOAP_OK;
mas01cr@239 365 } catch (char *err) {
mas01cr@239 366 soap_receiver_fault(soap, err, "");
mas01cr@239 367 return SOAP_FAULT;
mas01cr@239 368 }
mas01cr@239 369 }
mas01mc@354 370
mas01mc@354 371 // Query an audioDB database by vector (serialized)
mas01mc@471 372 int adb__shingleQuery(struct soap* soap, xsd__string dbName, struct adb__queryVector qVector, xsd__string keyList, xsd__string timesFileName, xsd__int queryType, xsd__int queryPos, xsd__int pointNN, xsd__int trackNN, xsd__int sequenceLength, xsd__double radius, xsd__double absolute_threshold, xsd__double relative_threshold, xsd__int exhaustive, xsd__int lsh_exact, xsd__int no_unit_norming, struct adb__queryResponse &adbQueryResponse){
mas01mc@354 373
mas01mc@354 374 // open a tmp file on the server, write shingle, query as a file with query point 0
mas01mc@354 375 // and shingle length l/dim
mas01mc@354 376 char tmpFileName[] = "/tmp/adb_XXXXXX";
mas01mc@354 377 int tmpFid = mkstemp(tmpFileName);
mas01mc@354 378 if(tmpFid==-1){
mas01mc@354 379 cerr << "Cannot make tmpfile <" << tmpFileName << "> on server" << endl;
mas01mc@354 380 return SOAP_FAULT;
mas01mc@354 381 }
mas01mc@354 382
mas01mc@354 383 FILE* tmpFile = fdopen(tmpFid, "r+b");
mas01mc@354 384 if(!tmpFile){
mas01mc@354 385 cerr << "error opening <" << tmpFileName << "> for write" << endl;
mas01mc@354 386 return SOAP_FAULT;
mas01mc@354 387 }
mas01mc@354 388
mas01mc@354 389 if(fwrite(&qVector.dim, sizeof(int), 1, tmpFile)!=1){
mas01mc@354 390 cerr << "error writing tmp file dim <"<< tmpFileName << ">" << endl;
mas01mc@354 391 return SOAP_FAULT;
mas01mc@354 392 }
mas01mc@354 393
mas01mc@354 394 if(fwrite(qVector.v, sizeof(double), qVector.__sizev, tmpFile)!=(size_t)qVector.__sizev){
mas01mc@354 395 cerr << "error writing tmp file doubles <" << tmpFileName << ">" << endl;
mas01mc@354 396 return SOAP_FAULT;
mas01mc@354 397 }
mas01mc@354 398
mas01mc@354 399 // Close the file so that a new FD can be opened
mas01mc@354 400 fclose(tmpFile);
mas01mc@354 401
mas01mc@354 402 char tmpFileName2[] = "/tmp/adbP_XXXXXX";
mas01mc@354 403 int tmpFid2 = 0;
mas01mc@354 404 FILE* tmpFile2 = NULL;
mas01mc@354 405
mas01mc@354 406 // Check if powers have been passed and write accordingly
mas01mc@354 407 if(qVector.__sizep){
mas01mc@354 408 tmpFid2 = mkstemp(tmpFileName2);
mas01mc@354 409 tmpFile2 = fdopen(tmpFid2, "r+b");
mas01mc@354 410 if(!tmpFile2){
mas01mc@354 411 cerr << "error opening power file <" << tmpFileName2 << "> for write" << endl;
mas01mc@354 412 return SOAP_FAULT;
mas01mc@354 413 }
mas01mc@354 414 int pSize=1;
mas01mc@354 415 if(fwrite(&pSize, sizeof(int), 1, tmpFile2)!=1){
mas01mc@354 416 cerr << "error writing tmp power file dim <"<< tmpFileName2 << ">" << endl;
mas01mc@354 417 return SOAP_FAULT;
mas01mc@354 418 }
mas01mc@354 419
mas01mc@354 420 if(fwrite(qVector.p, sizeof(double), qVector.__sizep, tmpFile2)!=(size_t)qVector.__sizep){
mas01mc@354 421 cerr << "error writing tmp power file doubles <" << tmpFileName2 << ">" << endl;
mas01mc@354 422 return SOAP_FAULT;
mas01mc@354 423 }
mas01mc@354 424 fclose(tmpFile2);
mas01mc@354 425 }
mas01mc@354 426
mas01mc@354 427 // fix up sequenceLength if it isn't provided, we know what the caller wants by the size of the shingle
mas01mc@354 428 // and the feature dimensionality
mas01mc@354 429 if(!sequenceLength)
mas01mc@354 430 sequenceLength = qVector.__sizev/qVector.dim;
mas01mc@354 431
mas01mc@354 432 int retVal = adb__query(soap, dbName, tmpFileName, keyList, timesFileName, qVector.__sizep?tmpFileName2:0,
mas01mc@354 433 queryType, queryPos, pointNN, trackNN, sequenceLength, radius,
mas01mc@471 434 absolute_threshold, relative_threshold, exhaustive, lsh_exact, no_unit_norming, adbQueryResponse);
mas01mc@354 435
mas01mc@354 436 return retVal;
mas01mc@354 437 }
mas01mc@354 438
mas01cr@239 439 /* Server loop */
mas01cr@239 440 void audioDB::startServer(){
mas01cr@239 441 struct soap soap;
mas01cr@239 442 int m, s; // master and slave sockets
mas01cr@239 443 soap_init(&soap);
mas01cr@239 444 // FIXME: largely this use of SO_REUSEADDR is to make writing (and
mas01cr@239 445 // running) test cases more convenient, so that multiple test runs
mas01cr@239 446 // in close succession don't fail because of a bin() error.
mas01cr@239 447 // Investigate whether there are any potential drawbacks in this,
mas01cr@239 448 // and also whether there's a better way to write the tests. --
mas01cr@239 449 // CSR, 2007-10-03
mas01cr@239 450 soap.bind_flags |= SO_REUSEADDR;
mas01cr@239 451 m = soap_bind(&soap, NULL, port, 100);
mas01cr@239 452 if (m < 0)
mas01cr@239 453 soap_print_fault(&soap, stderr);
mas01cr@239 454 else
mas01cr@239 455 {
mas01cr@239 456 fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
mas01cr@498 457 /* FIXME: we used to have a global cache of a single LSH index
mas01cr@498 458 * here. CSR removed it because it interacted badly with
mas01cr@498 459 * APIification of querying, replacing it with a per-open-adb
mas01cr@498 460 * cache; we should try to take advantage of that instead.
mas01cr@498 461 */
mas01cr@498 462
mas01mc@324 463 // Server-side path prefix to databases and features
mas01mc@324 464 if(adb_root)
mas01mc@324 465 SERVER_ADB_ROOT = (char*)adb_root; // Server-side database root
mas01mc@324 466 if(adb_feature_root)
mas01mc@324 467 SERVER_ADB_FEATURE_ROOT = (char*)adb_feature_root; // Server-side features root
mas01mc@338 468
mas01mc@338 469 isServer = 1; // From this point, errors are reported via SOAP to the client
mas01cr@239 470 for (int i = 1; ; i++)
mas01cr@239 471 {
mas01cr@239 472 s = soap_accept(&soap);
mas01cr@239 473 if (s < 0)
mas01cr@239 474 {
mas01cr@239 475 soap_print_fault(&soap, stderr);
mas01cr@239 476 break;
mas01cr@239 477 }
mas01cr@239 478 /* FIXME: find a way to play nice with logging when run from
mas01cr@239 479 /etc/init.d scripts: at present this just goes nowhere */
mas01cr@239 480 fprintf(stderr, "%d: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d\n", i,
mas01cr@239 481 (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
mas01cr@239 482 if (soap_serve(&soap) != SOAP_OK) // process RPC request
mas01cr@239 483 soap_print_fault(&soap, stderr); // print error
mas01cr@239 484 fprintf(stderr, "request served\n");
mas01cr@239 485 soap_destroy(&soap); // clean up class instances
mas01cr@239 486 soap_end(&soap); // clean up everything and close socket
mas01cr@239 487 }
mas01cr@239 488 }
mas01cr@239 489 soap_done(&soap); // close master socket and detach environment
mas01cr@239 490 }