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;
}
//-----------------------------------------------------------------------------
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;
}