#include #include #include #include #include "MKRequest.h" #include "MKCommModel.h" using namespace std; unsigned char MKRequest::lastID = 0; MKRequest *MKRequest::reqCache[MKREQUEST_CACHE_SIZE] = {NULL}; MKRequest *MKRequest::lastLatency = NULL; MKRequest *MKRequest::lastTraceRoute = NULL; MKRequest::~MKRequest() { if(bData != NULL) { delete bData; } } MKRequest *MKRequest::latency(MKNode *from, MKNode *to) { mongo::BSONObjBuilder build; mongo::BSONObj *data; timeval now, diff; if(lastLatency != NULL && lastLatency->from == from && lastLatency->to == to) { gettimeofday(&now, NULL); timersub(&now, &lastLatency->time, &diff); if(diff.tv_sec == 0 && diff.tv_usec < MKREQUEST_TIMEOUT) { // just sent one, re-use the last request return lastLatency; } } data = new mongo::BSONObj(); return lastLatency = new MKRequest(kLatency, data, from, to); } MKRequest *MKRequest::route(MKNode *from, MKNode *to) { mongo::BSONObjBuilder build; mongo::BSONObj *data; timeval now, diff; if(lastTraceRoute != NULL && lastTraceRoute->from == from && lastTraceRoute->to == to) { gettimeofday(&now, NULL); timersub(&now, &lastTraceRoute->time, &diff); if(diff.tv_sec == 0 && diff.tv_usec < MKREQUEST_TIMEOUT) { // just sent one, re-use the last request return lastTraceRoute; } } data = new mongo::BSONObj(); return lastTraceRoute = new MKRequest(kTraceRoute, data, from, to); } MKRequest *MKRequest::cache(int id) { MKRequest *req; if(id < 0 || id >= MKREQUEST_CACHE_SIZE) { return NULL; } return reqCache[id]; } void MKRequest::reset() { for(int i = 0; i < MKREQUEST_CACHE_SIZE; i++) { if(reqCache[i] != NULL) { delete reqCache[i]; reqCache[i] = NULL; } } lastID = 0; lastLatency = NULL; lastTraceRoute = NULL; } MKRequest::MKRequest(int reqType, mongo::BSONObj *data, MKNode *fromNode, MKNode *toNode) : requestType(reqType), bData(data), from(fromNode), to(toNode), sent(false) { requestID = lastID++; gettimeofday(&time, NULL); if(reqCache[requestID] != NULL) { delete reqCache[requestID]; reqCache[requestID] = NULL; } reqCache[requestID] = this; } void MKRequest::send() { ostringstream text1; string text2, text3; int pipefd[2], status; pid_t pid; if(sent) return; sent = true; MKCommModel::log() << "Sending cc request..." << endl; errno = 0; if(pipe(pipefd) == -1) { perror("pipe sendccreq"); } errno = 0; pid = fork(); if(pid == 0) { text1 << requestID; text2 = MKLib::ip2string(from->getIP4()); text3 = MKLib::ip2string(to->getIP4()); dup2(pipefd[0], STDIN_FILENO); close(pipefd[1]); errno = 0; MKCommModel::log() << MK_PYTHON_BIN << " - " << text1.str().c_str() << " " << text2.c_str() << " " << text3.c_str() << endl; execlp(MK_PYTHON_BIN, MK_PYTHON_BIN, "-", text1.str().c_str(), text2.c_str(), text3.c_str(), (char *) 0); //execlp("cat", "cat", "-", (char *) 0); perror("fork sendccreq"); exit(EXIT_FAILURE); } else { #include "sendccreq.py.h" //char *code; // = "import sys\nprint sys.argv[1]\nwhile(1 == 1) :\n\tprint \"X\\n\"\n\nquit()\n"; close(pipefd[0]); // write to child stdin write(pipefd[1], pyCode, strlen(pyCode)); close(pipefd[1]); waitpid(pid, &status, 0); if(WEXITSTATUS(status) != 0) { perror("invoking sendccreq returned bad exit status"); MKCommModel::log() << "Error: sending cc request returned bad exit status " << WEXITSTATUS(status) << endl; } } MKCommModel::log() << "Done sending cc request." << endl; }