// Actually only used for movie requests vector<pair<char, string> > KeyValueStore::forwardLongRequest(Protocol::KEYVALUE_STORE type, const string& req, Config::ThreadControl& control) { vector<pair<char, string> > ret; Mutex& outMutex = control.getOutMutex(); Condition& cond = control.getOutCondition(); procForward.lock(); pair<char, string> freq(type, req); forwardQueue.enqueue(freq); outMutex.lock(); cond.signal(); outMutex.unlock(); forwardCond.wait(procForward); while(true) { pair<char, string> resp(respBuffer.dequeue()); ret.push_back(resp); if(resp.first == Protocol::MLOOKUP_DONE || resp.first == Protocol::LOOKUP_NO) { procForward.unlock(); break; } } printKv("Done serving movie list"); return ret; }
pair<char, string> KeyValueStore::forwardRequest(Protocol::KEYVALUE_STORE type, const string& req, Config::ThreadControl& control) { Mutex& outMutex = control.getOutMutex(); Condition& cond = control.getOutCondition(); procForward.lock(); pair<char, string> freq(type, req); forwardQueue.enqueue(freq); outMutex.lock(); cond.signal(); outMutex.unlock(); forwardCond.wait(procForward); pair<char, string> resp(respBuffer.dequeue()); procForward.unlock(); return resp; }
void KeyValueStore::InternalThread::outgoingRoutine() { unsigned currId = -1; const Config::ServerInformation& info = config.getServerInformation(); Config::ThreadControl& control = config.getThreadControl(); Mutex& outMutex = control.getOutMutex(); Condition& cond = control.getOutCondition(); Timespan timeout(3, 0); // 3 seconds to receive response bool connected = false; unsigned contentLength = 0; char* buf = NULL; while(control.isLive()) { outMutex.lock(); cond.wait(outMutex); // Check if server changed if(control.getReconnectedTo()) { printKv("Reconnecting"); currId = control.getConnectedToId(); const Config::ServerInformation& nextInfo = config.getServerInformation(currId); try { if(connected) sock.close(); sock.connect(SocketAddress(nextInfo.address, nextInfo.internalPort), Timespan(5, 0)); connected = true; printKv("Connected to outgoing server: "<< nextInfo.id); //sock.setReceiveTimeout(timeout); KeyValueStore::replicateDB(sock, control.getMachineCount()); } catch(Exception& e) { printKv("Could not connect to next key-value internal server ("<< e.displayText() <<")" << endl << "System may be inconsistent until next reconnect."); connected = false; } } while(!forwardQueue.isEmpty()) { pair<char, string> req(forwardQueue.dequeue()); if(req.first == Protocol::REPL_INS || req.first == Protocol::REPL_REM) { try { KeyValueStore::sendRequest(sock, req); } catch(Exception& e) { printKv("Could not replicate: "<< e.displayText()); } } else if(req.first == Protocol::INS_MOVIE) { // Requests without responses KeyValueStore::sendRequest(sock, req); // Not waiting for a response } else if(req.first == Protocol::LUP_MOVIE && false) { // This returns many responses need to get all printKv("Received movie lookup forward"); KeyValueStore::sendRequest(sock, req); pair<char, string> resp(KeyValueStore::rcvResponse(sock, buf)); while(resp.first != Protocol::MLOOKUP_DONE && resp.first != Protocol::LOOKUP_NO) { resp = KeyValueStore::rcvResponse(sock, buf); respBuffer.enqueue(resp); // replyForward(); // Send as we get them } respBuffer.enqueue(resp); // Make sure we also send our done response printKv("Served movies"); replyForward(); } else { // Forward and wait for response. try { KeyValueStore::sendRequest(sock, req); pair<char, string> resp(KeyValueStore::rcvResponse(sock, buf)); respBuffer.enqueue(resp); replyForward(); } catch(Exception& e) { // If we timeout or anything, treat request as failed printKv("Exception while forwarding: "<< e.displayText()); respBuffer.enqueue(pair<char, string>(Protocol::REQ_FAIL, "")); replyForward(); } } } // if(!respBuffer.isEmpty()) // replyForward(); outMutex.unlock(); } }