Exemple #1
0
void SNetStorageObjectRPC::Close()
{
    if (m_State == eReady)
        return;

    CNetServerConnection conn_copy(m_Connection);
    m_Connection = NULL;

    if (m_State == eReading) {
        m_State = eReady;

        if (!m_EOF) {
            m_UTTPReader.Reset();
            conn_copy->Close();
        }
    } else { /* m_State == eWriting */
        m_State = eReady;

        CSocket& sock = conn_copy->m_Socket;

        s_SendEndOfData(sock);

        CReadJsonFromSocket message_reader;

        s_TrapErrors(m_OriginalRequest,
                message_reader.ReadMessage(sock), sock,
                m_NetStorageRPC->m_Config.err_mode);
    }
}
Exemple #2
0
void SNetStorageObjectRPC::ReadConfirmation()
{
    CSocket& sock = m_Connection->m_Socket;

    CJsonOverUTTPReader json_reader;
    try {
        size_t bytes_read;

        while (!json_reader.ReadMessage(m_UTTPReader)) {
            s_ReadSocket(sock, m_ReadBuffer,
                    READ_BUFFER_SIZE, &bytes_read);

            m_UTTPReader.SetNewBuffer(m_ReadBuffer, bytes_read);
        }

        if (m_UTTPReader.GetNextEvent() != CUTTPReader::eEndOfBuffer) {
            NCBI_THROW_FMT(CNetStorageException, eIOError,
                    "Extra bytes past confirmation message "
                    "while reading " << m_Locator << " from " <<
                    sock.GetPeerAddress() << '.');
        }
    }
    catch (...) {
        m_UTTPReader.Reset();
        m_Connection->Close();
        throw;
    }

    s_TrapErrors(m_OriginalRequest, json_reader.GetMessage(), sock,
            m_NetStorageRPC->m_Config.err_mode);
}
Exemple #3
0
ERW_Result SNetStorageObjectRPC::Read(void* buffer, size_t buf_size,
        size_t* bytes_read)
{
    if (m_State == eWriting) {
        NCBI_THROW_FMT(CNetStorageException, eInvalidArg,
                "Cannot read a NetStorage file while writing to it");
    }

    size_t bytes_read_local;

    if (m_State == eReady) {
        m_OriginalRequest = x_MkRequest("READ");

        if (m_ReadBuffer == NULL)
            m_ReadBuffer = new char[READ_BUFFER_SIZE];

        CNetServer server(*m_OwnService.Iterate(CNetService::eRandomize));

        CJsonOverUTTPExecHandler json_over_uttp_sender(m_OriginalRequest);

        server->TryExec(json_over_uttp_sender);

        CSocket& sock = json_over_uttp_sender.GetConnection()->m_Socket;

        CJsonOverUTTPReader json_reader;

        try {
            do {
                s_ReadSocket(sock, m_ReadBuffer, READ_BUFFER_SIZE,
                        &bytes_read_local);

                m_UTTPReader.SetNewBuffer(m_ReadBuffer, bytes_read_local);

            } while (!json_reader.ReadMessage(m_UTTPReader));
        }
        catch (...) {
            m_UTTPReader.Reset();
            sock.Close();
            throw;
        }

        s_TrapErrors(m_OriginalRequest, json_reader.GetMessage(), sock,
            m_NetStorageRPC->m_Config.err_mode);

        m_Connection = json_over_uttp_sender.GetConnection();

        m_CurrentChunkSize = 0;

        m_State = eReading;
        m_EOF = false;
    }

    char* buf_pos = reinterpret_cast<char*>(buffer);

    if (m_CurrentChunkSize >= buf_size) {
        if (buf_size > 0) {
            memcpy(buf_pos, m_CurrentChunk, buf_size);
            m_CurrentChunk += buf_size;
            m_CurrentChunkSize -= buf_size;
        }
        if (bytes_read != NULL)
            *bytes_read = buf_size;
        return eRW_Success;
    }

    if (m_CurrentChunkSize > 0) {
        memcpy(buf_pos, m_CurrentChunk, m_CurrentChunkSize);
        buf_pos += m_CurrentChunkSize;
        buf_size -= m_CurrentChunkSize;
    }

    size_t bytes_copied = m_CurrentChunkSize;

    m_CurrentChunkSize = 0;

    if (m_EOF) {
        if (bytes_read != NULL)
            *bytes_read = bytes_copied;
        return bytes_copied ? eRW_Success : eRW_Eof;
    }

    try {
        while (buf_size > 0) {
            switch (m_UTTPReader.GetNextEvent()) {
            case CUTTPReader::eChunkPart:
            case CUTTPReader::eChunk:
                m_CurrentChunk = m_UTTPReader.GetChunkPart();
                m_CurrentChunkSize = m_UTTPReader.GetChunkPartSize();

                if (m_CurrentChunkSize >= buf_size) {
                    memcpy(buf_pos, m_CurrentChunk, buf_size);
                    m_CurrentChunk += buf_size;
                    m_CurrentChunkSize -= buf_size;
                    if (bytes_read != NULL)
                        *bytes_read = bytes_copied + buf_size;
                    return eRW_Success;
                }

                memcpy(buf_pos, m_CurrentChunk, m_CurrentChunkSize);
                buf_pos += m_CurrentChunkSize;
                buf_size -= m_CurrentChunkSize;
                bytes_copied += m_CurrentChunkSize;
                m_CurrentChunkSize = 0;
                break;

            case CUTTPReader::eControlSymbol:
                if (m_UTTPReader.GetControlSymbol() != END_OF_DATA_MARKER) {
                    NCBI_THROW_FMT(CNetStorageException, eIOError,
                            "NetStorage API: invalid end-of-data-stream "
                            "terminator: " <<
                                    (int) m_UTTPReader.GetControlSymbol());
                }
                m_EOF = true;
                ReadConfirmation();
                if (bytes_read != NULL)
                    *bytes_read = bytes_copied;
                return bytes_copied ? eRW_Success : eRW_Eof;

            case CUTTPReader::eEndOfBuffer:
                s_ReadSocket(m_Connection->m_Socket, m_ReadBuffer,
                        READ_BUFFER_SIZE, &bytes_read_local);

                m_UTTPReader.SetNewBuffer(m_ReadBuffer, bytes_read_local);
                break;

            default:
                NCBI_THROW_FMT(CNetStorageException, eIOError,
                        "NetStorage API: invalid UTTP status "
                        "while reading " << m_Locator);
            }
        }

        if (bytes_read != NULL)
            *bytes_read = bytes_copied;
        return eRW_Success;
    }
    catch (...) {
        m_State = eReady;
        m_UTTPReader.Reset();
        m_Connection->Close();
        m_Connection = NULL;
        throw;
    }
}