annotate soap.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 25572f1bd37f c93be2f3a674
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;
mas01cr@239 21 std::cout << "flags = " << adbStatusResponse.result.flags << 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@308 31 // WS_QUERY (CLIENT SIDE)
mas01mc@307 32 void audioDB::ws_query(const char*dbName, const char *featureFileName, const char* hostport){
mas01cr@239 33 struct soap soap;
mas01cr@239 34 adb__queryResponse adbQueryResponse;
mas01cr@239 35
mas01cr@239 36 soap_init(&soap);
mas01cr@239 37 if(soap_call_adb__query(&soap,hostport,NULL,
mas01mc@307 38 (char*)dbName,(char*)featureFileName,(char*)trackFileName,(char*)timesFileName,
mas01cr@239 39 queryType, queryPoint, pointNN, trackNN, sequenceLength, adbQueryResponse)==SOAP_OK){
mas01cr@239 40 //std::std::cerr << "result list length:" << adbQueryResponse.result.__sizeRlist << std::std::endl;
mas01cr@239 41 for(int i=0; i<adbQueryResponse.result.__sizeRlist; i++)
mas01cr@239 42 std::cout << adbQueryResponse.result.Rlist[i] << " " << adbQueryResponse.result.Dist[i]
mas01cr@239 43 << " " << adbQueryResponse.result.Qpos[i] << " " << adbQueryResponse.result.Spos[i] << std::endl;
mas01cr@239 44 }
mas01cr@239 45 else
mas01cr@239 46 soap_print_fault(&soap,stderr);
mas01cr@239 47
mas01cr@239 48 soap_destroy(&soap);
mas01cr@239 49 soap_end(&soap);
mas01cr@239 50 soap_done(&soap);
mas01cr@239 51 }
mas01mc@307 52
mas01mc@308 53 // WS_QUERY_BY_KEY (CLIENT SIDE)
mas01mc@307 54 void audioDB::ws_query_by_key(const char*dbName, const char *trackKey, const char* hostport){
mas01mc@307 55 struct soap soap;
mas01mc@307 56 adb__queryResponse adbQueryResponse;
mas01mc@314 57 /* JUST TRY TO USE A DATA STRUCTURE WITH PHP
mas01mc@314 58 adb__sequenceQueryParms asqp;
mas01mc@314 59 asqp.keyList = (char*)trackFileName;
mas01mc@314 60 asqp.timesFileName = (char*)timesFileName;
mas01mc@314 61 asqp.queryPoint = queryPoint;
mas01mc@314 62 asqp.pointNN = pointNN;
mas01mc@314 63 asqp.trackNN = trackNN;
mas01mc@314 64 asqp.sequenceLength = sequenceLength;
mas01mc@314 65 asqp.radius = radius;
mas01mc@314 66 asqp.relative_threshold = relative_threshold;
mas01mc@314 67 asqp.absolute_threshold = absolute_threshold;
mas01mc@314 68 asqp.usingQueryPoint = usingQueryPoint;
mas01mc@314 69 asqp.lsh_exact = lsh_exact;
mas01mc@314 70 */
mas01mc@307 71
mas01mc@307 72 soap_init(&soap);
mas01mc@307 73 if(queryType==O2_SEQUENCE_QUERY || queryType==O2_N_SEQUENCE_QUERY){
mas01mc@314 74 if(soap_call_adb__sequenceQueryByKey(&soap,hostport,NULL,
mas01mc@314 75 (char*)dbName,
mas01mc@314 76 (char*)trackKey,
mas01mc@314 77 queryType,
mas01mc@314 78 (char*)trackFileName,
mas01mc@314 79 (char*)timesFileName,
mas01mc@314 80 queryPoint,
mas01mc@314 81 pointNN,
mas01mc@314 82 trackNN,
mas01mc@314 83 sequenceLength,
mas01mc@314 84 radius,
mas01mc@314 85 absolute_threshold,
mas01mc@314 86 usingQueryPoint,
mas01mc@314 87 lsh_exact,
mas01mc@314 88 adbQueryResponse)==SOAP_OK){
mas01mc@307 89 //std::std::cerr << "result list length:" << adbQueryResponse.result.__sizeRlist << std::std::endl;
mas01mc@307 90 for(int i=0; i<adbQueryResponse.result.__sizeRlist; i++)
mas01mc@307 91 std::cout << adbQueryResponse.result.Rlist[i] << " " << adbQueryResponse.result.Dist[i]
mas01mc@307 92 << " " << adbQueryResponse.result.Qpos[i] << " " << adbQueryResponse.result.Spos[i] << std::endl;
mas01mc@307 93 }
mas01mc@307 94 else
mas01mc@307 95 soap_print_fault(&soap,stderr);
mas01mc@307 96 }else
mas01mc@307 97 ;// FIX ME: WRITE NON-SEQUENCE QUERY BY KEY ?
mas01mc@307 98
mas01mc@307 99 soap_destroy(&soap);
mas01mc@307 100 soap_end(&soap);
mas01mc@307 101 soap_done(&soap);
mas01mc@307 102 }
mas01mc@307 103
mas01cr@239 104
mas01cr@239 105 /* Server definitions */
mas01cr@239 106 int adb__status(struct soap* soap, xsd__string dbName, adb__statusResponse &adbStatusResponse){
mas01mc@307 107 char* const argv[]={"./audioDB",COM_STATUS,"-d",dbName};
mas01cr@239 108 const unsigned argc = 4;
mas01cr@239 109 try {
mas01cr@239 110 audioDB(argc, argv, &adbStatusResponse);
mas01cr@239 111 return SOAP_OK;
mas01cr@239 112 } catch(char *err) {
mas01cr@239 113 soap_receiver_fault(soap, err, "");
mas01cr@239 114 return SOAP_FAULT;
mas01cr@239 115 }
mas01cr@239 116 }
mas01mc@308 117
mas01cr@239 118 // Literal translation of command line to web service
mas01cr@239 119 int adb__query(struct soap* soap, xsd__string dbName, xsd__string qKey, xsd__string keyList, xsd__string timesFileName, xsd__int qType, xsd__int qPos, xsd__int pointNN, xsd__int trackNN, xsd__int seqLen, adb__queryResponse &adbQueryResponse){
mas01cr@239 120 char queryType[256];
mas01cr@239 121 for(int k=0; k<256; k++)
mas01cr@239 122 queryType[k]='\0';
mas01cr@239 123 if(qType == O2_POINT_QUERY)
mas01cr@239 124 strncpy(queryType, "point", strlen("point"));
mas01cr@239 125 else if (qType == O2_SEQUENCE_QUERY)
mas01cr@239 126 strncpy(queryType, "sequence", strlen("sequence"));
mas01cr@239 127 else if(qType == O2_TRACK_QUERY)
mas01cr@239 128 strncpy(queryType,"track", strlen("track"));
mas01cr@239 129 else
mas01cr@239 130 strncpy(queryType, "", strlen(""));
mas01cr@239 131
mas01cr@239 132 if(pointNN==0)
mas01cr@239 133 pointNN=10;
mas01cr@239 134 if(trackNN==0)
mas01cr@239 135 trackNN=10;
mas01cr@239 136 if(seqLen==0)
mas01cr@239 137 seqLen=16;
mas01cr@239 138
mas01cr@239 139 char qPosStr[256];
mas01cr@239 140 sprintf(qPosStr, "%d", qPos);
mas01cr@239 141 char pointNNStr[256];
mas01cr@239 142 sprintf(pointNNStr,"%d",pointNN);
mas01cr@239 143 char trackNNStr[256];
mas01cr@239 144 sprintf(trackNNStr,"%d",trackNN);
mas01cr@239 145 char seqLenStr[256];
mas01cr@239 146 sprintf(seqLenStr,"%d",seqLen);
mas01cr@239 147
mas01cr@239 148 const char* argv[] ={
mas01cr@239 149 "./audioDB",
mas01cr@239 150 COM_QUERY,
mas01cr@239 151 queryType, // Need to pass a parameter
mas01cr@239 152 COM_DATABASE,
mas01cr@239 153 ENSURE_STRING(dbName),
mas01cr@239 154 COM_FEATURES,
mas01cr@239 155 ENSURE_STRING(qKey),
mas01cr@239 156 COM_KEYLIST,
mas01cr@239 157 ENSURE_STRING(keyList),
mas01cr@239 158 COM_TIMES,
mas01cr@239 159 ENSURE_STRING(timesFileName),
mas01cr@239 160 COM_QPOINT,
mas01cr@239 161 qPosStr,
mas01cr@239 162 COM_POINTNN,
mas01cr@239 163 pointNNStr,
mas01cr@239 164 COM_TRACKNN,
mas01cr@239 165 trackNNStr, // Need to pass a parameter
mas01cr@239 166 COM_SEQLEN,
mas01cr@239 167 seqLenStr
mas01cr@239 168 };
mas01cr@239 169
mas01cr@239 170 const unsigned argc = 19;
mas01cr@239 171 try {
mas01cr@239 172 audioDB(argc, (char* const*)argv, &adbQueryResponse);
mas01cr@239 173 return SOAP_OK;
mas01cr@239 174 } catch (char *err) {
mas01cr@239 175 soap_receiver_fault(soap, err, "");
mas01cr@239 176 return SOAP_FAULT;
mas01cr@239 177 }
mas01cr@239 178 }
mas01cr@239 179
mas01mc@314 180 int adb__sequenceQueryByKey(struct soap* soap,xsd__string dbName,
mas01mc@314 181 xsd__string trackKey,
mas01mc@314 182 xsd__int queryType,
mas01mc@314 183 xsd__string trackFileName,
mas01mc@314 184 xsd__string timesFileName,
mas01mc@314 185 xsd__int queryPoint,
mas01mc@314 186 xsd__int pointNN,
mas01mc@314 187 xsd__int trackNN,
mas01mc@314 188 xsd__int sequenceLength,
mas01mc@314 189 xsd__double radius,
mas01mc@314 190 xsd__double absolute_threshold,
mas01mc@314 191 xsd__int usingQueryPoint,
mas01mc@314 192 xsd__int lsh_exact,
mas01mc@314 193 struct adb__queryResponse& adbQueryResponse){
mas01mc@307 194 char radiusStr[256];
mas01cr@239 195 char qPosStr[256];
mas01cr@239 196 char pointNNStr[256];
mas01cr@239 197 char trackNNStr[256];
mas01cr@239 198 char seqLenStr[256];
mas01cr@239 199 char absolute_thresholdStr[256];
mas01mc@307 200 char qtypeStr[256];
mas01cr@239 201
mas01cr@239 202 /* When the branch is merged, move this to a header and use it
mas01cr@239 203 elsewhere */
mas01cr@239 204 #define INTSTRINGIFY(val, str) \
mas01cr@239 205 snprintf(str, 256, "%d", val);
mas01cr@239 206 #define DOUBLESTRINGIFY(val, str) \
mas01cr@239 207 snprintf(str, 256, "%f", val);
mas01cr@239 208
mas01mc@314 209 INTSTRINGIFY(queryPoint, qPosStr);
mas01mc@314 210 INTSTRINGIFY(pointNN, pointNNStr);
mas01mc@314 211 INTSTRINGIFY(trackNN, trackNNStr);
mas01mc@314 212 INTSTRINGIFY(sequenceLength, seqLenStr);
mas01mc@314 213 DOUBLESTRINGIFY(absolute_threshold, absolute_thresholdStr);
mas01mc@314 214 DOUBLESTRINGIFY(radius, radiusStr);
mas01mc@307 215
mas01mc@307 216 // WS queries only support 1-nearest neighbour point reporting
mas01mc@307 217 // at the moment, until we figure out how to better serve results
mas01mc@307 218 snprintf(qtypeStr, 256, "nsequence");
mas01mc@310 219 const char *argv[]={
mas01cr@239 220 "./audioDB",
mas01cr@239 221 COM_QUERY,
mas01mc@307 222 qtypeStr,
mas01cr@239 223 COM_DATABASE,
mas01cr@239 224 dbName,
mas01mc@307 225 COM_QUERYKEY,
mas01mc@314 226 ENSURE_STRING(trackKey),
mas01cr@239 227 COM_KEYLIST,
mas01mc@314 228 ENSURE_STRING(trackFileName),
mas01mc@314 229 usingQueryPoint?COM_QPOINT:COM_EXHAUSTIVE,
mas01mc@314 230 usingQueryPoint?qPosStr:"",
mas01cr@239 231 COM_POINTNN,
mas01cr@239 232 pointNNStr,
mas01cr@239 233 COM_TRACKNN,
mas01cr@239 234 trackNNStr,
mas01mc@307 235 COM_RADIUS,
mas01mc@307 236 radiusStr,
mas01cr@239 237 COM_SEQLEN,
mas01cr@239 238 seqLenStr,
mas01cr@239 239 COM_ABSOLUTE_THRESH,
mas01mc@310 240 absolute_thresholdStr,
mas01mc@314 241 lsh_exact?COM_LSH_EXACT:""
mas01cr@239 242 };
mas01cr@239 243
mas01mc@310 244 const unsigned argc = 22;
mas01mc@310 245
mas01mc@310 246
mas01cr@239 247 try {
mas01cr@239 248 audioDB(argc, (char* const*)argv, &adbQueryResponse);
mas01cr@239 249 return SOAP_OK;
mas01cr@239 250 } catch (char *err) {
mas01cr@239 251 soap_receiver_fault(soap, err, "");
mas01cr@239 252 return SOAP_FAULT;
mas01cr@239 253 }
mas01cr@239 254 }
mas01cr@239 255
mas01cr@239 256 /* Server loop */
mas01cr@239 257 void audioDB::startServer(){
mas01cr@239 258 struct soap soap;
mas01cr@239 259 int m, s; // master and slave sockets
mas01cr@239 260 soap_init(&soap);
mas01cr@239 261 // FIXME: largely this use of SO_REUSEADDR is to make writing (and
mas01cr@239 262 // running) test cases more convenient, so that multiple test runs
mas01cr@239 263 // in close succession don't fail because of a bin() error.
mas01cr@239 264 // Investigate whether there are any potential drawbacks in this,
mas01cr@239 265 // and also whether there's a better way to write the tests. --
mas01cr@239 266 // CSR, 2007-10-03
mas01cr@239 267 soap.bind_flags |= SO_REUSEADDR;
mas01cr@239 268 m = soap_bind(&soap, NULL, port, 100);
mas01cr@239 269 if (m < 0)
mas01cr@239 270 soap_print_fault(&soap, stderr);
mas01cr@239 271 else
mas01cr@239 272 {
mas01cr@239 273 fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
mas01mc@308 274 // Make a global Web Services LSH Index (SINGLETON)
mas01mc@313 275 if(WS_load_index && dbName && !index_exists(dbName, radius, sequenceLength)){
mas01mc@313 276 error("Can't find requested index file:", index_get_name(dbName,radius,sequenceLength));
mas01mc@313 277 }
mas01mc@308 278 if(WS_load_index && dbName && index_exists(dbName, radius, sequenceLength)){
mas01mc@308 279 char* indexName = index_get_name(dbName, radius, sequenceLength);
mas01mc@308 280 fprintf(stderr, "Loading LSH hashtables: %s...\n", indexName);
mas01mc@308 281 lsh = new LSH(indexName, true);
mas01mc@308 282 assert(lsh);
mas01mc@308 283 SERVER_LSH_INDEX_SINGLETON = lsh;
mas01mc@308 284 fprintf(stderr, "LSH INDEX READY\n");
mas01mc@308 285 fflush(stderr);
mas01mc@308 286 delete[] indexName;
mas01mc@308 287 }
mas01mc@308 288
mas01cr@239 289 for (int i = 1; ; i++)
mas01cr@239 290 {
mas01cr@239 291 s = soap_accept(&soap);
mas01cr@239 292 if (s < 0)
mas01cr@239 293 {
mas01cr@239 294 soap_print_fault(&soap, stderr);
mas01cr@239 295 break;
mas01cr@239 296 }
mas01cr@239 297 /* FIXME: find a way to play nice with logging when run from
mas01cr@239 298 /etc/init.d scripts: at present this just goes nowhere */
mas01cr@239 299 fprintf(stderr, "%d: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d\n", i,
mas01cr@239 300 (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
mas01cr@239 301 if (soap_serve(&soap) != SOAP_OK) // process RPC request
mas01cr@239 302 soap_print_fault(&soap, stderr); // print error
mas01cr@239 303 fprintf(stderr, "request served\n");
mas01cr@239 304 soap_destroy(&soap); // clean up class instances
mas01cr@239 305 soap_end(&soap); // clean up everything and close socket
mas01cr@239 306 }
mas01cr@239 307 }
mas01cr@239 308 soap_done(&soap); // close master socket and detach environment
mas01cr@239 309 }