void DestroyResponse(CommunicationID& rRequestID, Response** ppResponse) { PsAssert(ppResponse != NULL); if (*ppResponse == NULL) { return; } // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); // remove from streaming map if ((*ppResponse)->m_bStreamingEnabled) { ResponseMap::iterator iter = g_streamingResponseMap.find(rRequestID); if (iter != g_streamingResponseMap.end()) { g_streamingResponseMap.erase(iter); } } SAFE_DELETE(*ppResponse); rRequestID = 0; }
bool MultipleRequestHandler::get_result_response(const ResponseMap& responses, const std::string& index, ResultResponse** response) { ResponseMap::const_iterator it = responses.find(index); if (it == responses.end() || it->second->opcode() != CQL_OPCODE_RESULT) { return false; } *response = static_cast<ResultResponse*>(it->second.get()); return true; }
//----------------------------------------------------------------------------- /// ShouldResponseBeSent /// /// indicates whether a response should be sent to the specified request based /// on whether or not the request is streaming and is rate limited. If the /// request is rate limited, but a response can be sent, the "last sent time" /// will be updated if bUpdateTime is true /// /// \param requestID id of the request that may or may not be rate limited /// \param bUpdateTime indicates whether or not the "last sent time" will be /// updated if the response is rate limited, but allowed to be sent /// /// \return true if a response should NOT be sent; false otherwise //----------------------------------------------------------------------------- bool ShouldResponseBeSent(CommunicationID requestID, bool bUpdateTime) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); ResponseMap::iterator iterResponse = g_streamingResponseMap.find(requestID); if (iterResponse == g_streamingResponseMap.end()) { // don't limit the send because we don't even know it is streaming return false; } Response* pResponse = iterResponse->second; PsAssert(pResponse != NULL); // if this is a streaming request, only send if rate allows if (pResponse->m_bStreamingEnabled == true) { if (pResponse->m_dwMaxStreamsPerSecond == COMM_MAX_STREAM_RATE || pResponse->m_dwMaxStreamsPerSecond == 0) { return false; } DWORD dwCurrTime = g_streamTimer.GetAbsolute(); if (dwCurrTime - pResponse->m_dwLastSent >= 1000 / pResponse->m_dwMaxStreamsPerSecond) { if (bUpdateTime) { pResponse->m_dwLastSent = dwCurrTime; } return false; } else { return true; } } return false; }
void SchemaChangeHandler::on_set(const ResponseMap& responses) { elapsed_ms_ += get_time_since_epoch_ms() - start_ms_; bool has_error = false; for (MultipleRequestHandler::ResponseMap::const_iterator it = responses.begin(), end = responses.end(); it != end; ++it) { if (check_error_or_invalid_response("SchemaChangeHandler", CQL_OPCODE_RESULT, it->second.get())) { has_error = true; } } if (!has_error && has_schema_agreement(responses)) { LOG_DEBUG("Found schema agreement in %llu ms", static_cast<unsigned long long>(elapsed_ms_)); request_handler_->set_response(request_response_); return; } else if (elapsed_ms_ >= MAX_SCHEMA_AGREEMENT_WAIT_MS) { LOG_WARN("No schema agreement on live nodes after %llu ms. " "Schema may not be up-to-date on some nodes.", static_cast<unsigned long long>(elapsed_ms_)); request_handler_->set_response(request_response_); return; } LOG_DEBUG("Schema still not up-to-date on some live nodes. " "Trying again in %d ms", RETRY_SCHEMA_AGREEMENT_WAIT_MS); // Try again SharedRefPtr<SchemaChangeHandler> handler( new SchemaChangeHandler(connection(), request_handler_.get(), request_response_, elapsed_ms_)); connection()->schedule_schema_agreement(handler, RETRY_SCHEMA_AGREEMENT_WAIT_MS); }
//----------------------------------------------------------------------------- bool MakeResponse(CommunicationID requestID, Response** ppResponse) { // protect the maps from being changed by other threads using the mutex ScopeLock lock(s_mutex); PsAssert(ppResponse != NULL); // first see if we already have this ID as a streaming response ResponseMap::iterator iterResponse = g_streamingResponseMap.find(requestID); if (iterResponse != g_streamingResponseMap.end()) { *ppResponse = iterResponse->second; return true; } // otherwise we need to create a new response based on the original request // so get the request RequestMap::iterator iterRequest = g_requestMap.find(requestID); if (iterRequest == g_requestMap.end()) { // the original request couldn't be found, so return failure return false; } // need to create a new response if (PsNew(*ppResponse) == false) { return false; } HTTPRequestHeader* pRequest = iterRequest->second; PsAssert(pRequest != NULL); if (pRequest->GetReceivedOverSocket() == true) { (*ppResponse)->client_socket = pRequest->GetClientSocket(); } else { #if defined (_WIN32) (*ppResponse)->client_socket = NetSocket::CreateFromDuplicate(pRequest->GetProtoInfo()); #else // create a new socket and connect to the streamSocket on the server (*ppResponse)->client_socket = NetSocket::Create(); if ((*ppResponse)->client_socket != NULL) { osPortAddress portAddress((unsigned short)pRequest->GetPort()); (*ppResponse)->client_socket->Connect(portAddress); } #endif } if ((*ppResponse)->client_socket == NULL) { int Err = NetSocket::LastError(); Log(logERROR, "Could not create socket: NetSocket failed with error: %ld\n", Err); return false; } // see if this should be added as a streaming response gtASCIIString strUrl(pRequest->GetUrl()); int32 iStream = strUrl.find(STR_STREAM_TOKEN); if (iStream >= 0) { const char* pBuf = strUrl.asCharArray(); const char* pRate = &pBuf[ iStream + strlen(STR_STREAM_TOKEN)]; unsigned int uRate = 0; // try to get the rate from the command; if (sscanf_s(pRate, "%u", &uRate) < 1) { // default to max rate uRate = COMM_MAX_STREAM_RATE; } // set the response as streaming with the specified rate (*ppResponse)->m_bStreamingEnabled = true; (*ppResponse)->m_dwMaxStreamsPerSecond = uRate; g_streamingResponseMap[ requestID ] = *ppResponse; } else { // streaming requests need to be kept around so that // additional responses can be directed to the right place, // HOWEVER, non-streaming requests only get a single response // and we just created the response for it, so it is safe // to remove the request from the requestMap. This will // help keep communication quick as the number of incoming // requests grows. RemoveRequest(requestID); } return true; }