bool gotReplyWrapperxd ( void *state ) { // grab it XmlDoc *xd = (XmlDoc *)state; // get it UdpSlot *slot = (UdpSlot *)xd->m_slot; // parse the request Msg20Request *req = (Msg20Request *)slot->m_readBuf; // print time long long took = gettimeofdayInMilliseconds() - xd->m_setTime; // if there is a baclkog of msg20 summary generation requests this // is really not the cpu it took to make the smmary, but how long it // took to get the reply. this request might have had to wait for the // other summaries to finish computing before it got its turn, // meanwhile its clock was ticking. TODO: make this better? // only do for niceness 0 otherwise it gets interrupted by quickpoll // and can take a long time. if ( (req->m_isDebug || took > 100) && req->m_niceness == 0 ) log("query: Took %lli ms to compute summary for d=%lli u=%s " "niceness=%li", took, xd->m_docId,xd->m_firstUrl.m_url, xd->m_niceness ); // error? if ( g_errno ) { xd->m_reply.sendReply ( xd ); return true; } // this should not block now Msg20Reply *reply = xd->getMsg20Reply ( ); // sanity check, should not block here now if ( reply == (void *)-1 ) { char *xx=NULL;*xx=0; } // NULL means error, -1 means blocked. on error g_errno should be set if ( ! reply && ! g_errno ) { char *xx=NULL;*xx=0;} // send it off. will send an error reply if g_errno is set return reply->sendReply ( xd ); }
// . this is called // . destroys the UdpSlot if false is returned void handleRequest20 ( UdpSlot *slot , long netnice ) { // . check g_errno // . before, we were not sending a reply back here and we continued // to process the request, even though it was empty. the slot // had a NULL m_readBuf because it could not alloc mem for the read // buf i'm assuming. and the slot was saved in a line below here... // state20->m_msg22.m_parent = slot; if ( g_errno ) { log("net: Msg20 handler got error: %s.",mstrerror(g_errno)); g_udpServer.sendErrorReply ( slot , g_errno ); return; } // ensure request is big enough if ( slot->m_readBufSize < (long)sizeof(Msg20Request) ) { g_udpServer.sendErrorReply ( slot , EBADREQUESTSIZE ); return; } // parse the request Msg20Request *req = (Msg20Request *)slot->m_readBuf; // . turn the string offsets into ptrs in the request // . this is "destructive" on "request" long nb = req->deserialize(); // sanity check if ( nb != slot->m_readBufSize ) { char *xx = NULL; *xx = 0; } // sanity check, the size include the \0 if ( req->size_coll <= 1 || *req->ptr_coll == '\0' ) { log("query: Got empty collection in msg20 handler. FIX!"); char *xx =NULL; *xx = 0; } // if it's not stored locally that's an error if ( req->m_docId >= 0 && ! g_titledb.isLocal ( req->m_docId ) ) { log("query: Got msg20 request for non-local docId %lli", req->m_docId); g_udpServer.sendErrorReply ( slot , ENOTLOCAL ); return; } // sanity if ( req->m_docId == 0 && ! req->ptr_ubuf ) { char *xx=NULL;*xx=0; } long long startTime = gettimeofdayInMilliseconds(); // alloc a new state to get the titlerec XmlDoc *xd; try { xd = new (XmlDoc); } catch ( ... ) { g_errno = ENOMEM; log("query: msg20 new(%i): %s", sizeof(XmlDoc), mstrerror(g_errno)); g_udpServer.sendErrorReply ( slot, g_errno ); return; } mnew ( xd , sizeof(XmlDoc) , "xd20" ); // ok, let's use the new XmlDoc.cpp class now! xd->set20 ( req ); // encode slot xd->m_slot = slot; // set the callback xd->setCallback ( xd , gotReplyWrapperxd ); // set set time xd->m_setTime = startTime; xd->m_cpuSummaryStartTime = 0; // . now as for the msg20 reply! // . TODO: move the parse state cache into just a cache of the // XmlDoc itself, and put that cache logic into XmlDoc.cpp so // it can be used more generally. Msg20Reply *reply = xd->getMsg20Reply ( ); // this is just blocked if ( reply == (void *)-1 ) return; // got it? gotReplyWrapperxd ( xd ); }