Пример #1
0
void ContextTransport::OnMessage(uint64_t nodeID, ReadBuffer msg)
{
    int         nread;
    char        proto;
    
    Log_Trace("%R", &msg);
    
    if (msg.GetLength() < 2)
        ASSERT_FAIL();

    nread = msg.Readf("%c:", &proto);
    if (nread < 2)
        ASSERT_FAIL();

    msg.Advance(2);
    
    switch (proto)
    {
        case PROTOCOL_CLUSTER:
            OnClusterMessage(nodeID, msg);
            break;
        case PROTOCOL_QUORUM:
            OnQuorumMessage(nodeID, msg);
            break;
        default:
            ASSERT_FAIL();
            break;
    }
}
Пример #2
0
void ContextTransport::OnQuorumMessage(uint64_t nodeID, ReadBuffer& msg)
{
    int             nread;
    uint64_t        quorumID;
    QuorumContext*  quorumContext;

    nread = msg.Readf("%U:", &quorumID);
    if (nread < 2)
        ASSERT_FAIL();
    
    msg.Advance(nread);

    quorumContext = GetQuorumContext(quorumID);
    
    if (quorumContext)
        GetQuorumContext(quorumID)->OnMessage(nodeID, msg);
}
Пример #3
0
bool ClusterConnection::OnMessage(ReadBuffer& msg)
{
    uint64_t            otherNodeID;
    uint64_t            otherClusterID;
    ReadBuffer          buffer;
    ClusterConnection*  dup;
    int                 read;

    //Log_Debug("ClusterConnection::OnMessage");

    if (progress == ClusterConnection::INCOMING)
    {
        // we have no incoming connections if we don't have a nodeID
        ASSERT(transport->IsAwaitingNodeID() == false);

        // the node at the other end is awaiting its nodeID
        if (msg.GetCharAt(0) == '*')
        {
            read = msg.Readf("*:%#R", &buffer);
            if (read != (int) msg.GetLength())
            {
                // protocol error
                GetSocket().GetEndpoint(endpoint);
                Log_Message("[%s] Cluster protocol error, disconnecting...", endpoint.ToString());
                transport->DeleteConnection(this);
                return true;
            }
            
            if (!endpoint.Set(buffer, true))
            {
                Log_Message("[%R] Cluster invalid network address", &buffer);
                transport->DeleteConnection(this);
                return true;                
            }
            
            progress = ClusterConnection::AWAITING_NODEID;
            Log_Trace("Conn is awaiting nodeID at %s", endpoint.ToString());

            transport->AddConnection(this);
            if (transport->OnAwaitingNodeID(endpoint))
            {
                Log_Trace();
                transport->DeleteConnection(this);
                return true;
            }
            if (nodeID == UNDEFINED_NODEID)
                Log_Message("[%s] Cluster unknown node connected <=", endpoint.ToString());
            else
                Log_Message("[%s] Cluster node %U connected <=", endpoint.ToString(), nodeID);
            return false;
        }
        
        // both ends have nodeIDs
        read = msg.Readf("%U:%U:%#R", &otherClusterID, &otherNodeID, &buffer);
        if (read != (int) msg.GetLength())
        {
            // protocol error
            GetSocket().GetEndpoint(endpoint);
            Log_Message("[%s] Cluster protocol error, disconnecting...", endpoint.ToString());
            transport->DeleteConnection(this);
            return true;
        }
        
        if (otherClusterID > 0)
        {
            if (transport->GetClusterID() == 0)
            {
                // the other side has a clusterID, I don't, so set mine
                // if I'm a config server:
                //   the clusterID also needs to be set in REPLICATON_CONFIG,
                //   this is set in ConfigServer::OnConnectionReady()
                // if I'm a shard server:
                //   the controllers will send a SetNodeID message, which
                //   contains the clusterID, so I'll be fine
                transport->SetClusterID(otherClusterID);
            }
            else
            {
                if (otherClusterID != transport->GetClusterID())
                {
                    Log_Message("[%R] Cluster invalid configuration, disconnecting...", &buffer);
                    Log_Debug("mine: %U != controller %U", transport->GetClusterID(), otherClusterID);
            
                    transport->DeleteConnection(this);          // drop this
                    return true;
                }
            }
        }
        
        dup = transport->GetConnection(otherNodeID);
        if (dup)
        {
            // if the other connections isn't ready yet, drop it
            // OR
            // the other connection is ready
            // in this case, kill the connection that was initiated by higher nodeID
            // in other words, since this is an incoming connection:
            // if nodeID[of initiator] > transport->GetSelfNodeID(): drop

            if (dup->progress != READY || otherNodeID > transport->GetSelfNodeID())
            {
                Log_Trace("delete dup");
                transport->DeleteConnection(dup);       // drop dup
            }
            else if (otherNodeID != transport->GetSelfNodeID())
            {
                Log_Trace("delete this");
                transport->DeleteConnection(this);      // drop this
                return true;
            }
        }
        progress = ClusterConnection::READY;
        SetNodeID(otherNodeID);
        if (!endpoint.Set(buffer, true))
        {
            Log_Message("[%R] Cluster invalid network address", &buffer);
            transport->DeleteConnection(this);
            return true;                
        }

        // check if the other side is not sending its localhost address, when they are on 
        // different nodes
        if (endpoint.GetAddress() == Endpoint::GetLoopbackAddress() && 
         transport->GetSelfEndpoint().GetAddress() != Endpoint::GetLoopbackAddress())
        {
            Log_Message("[%R] Cluster invalid network address", &buffer);
            transport->DeleteConnection(this);
            return true;
        }
        
        Log_Trace("Conn READY to node %U at %s", nodeID, endpoint.ToString());
        if (nodeID != transport->GetSelfNodeID())
        {
            if (nodeID == UNDEFINED_NODEID)
                Log_Message("[%s] Cluster unknown node connected <=", endpoint.ToString());
            else
                Log_Message("[%s] Cluster node %U connected <=", endpoint.ToString(), nodeID);
        }
        
        transport->AddConnection(this);
        transport->OnWriteReadyness(this);
        transport->OnConnectionReady(nodeID, endpoint);
    }
    else if (progress == ClusterConnection::OUTGOING)
        ASSERT_FAIL();
    else
        transport->OnMessage(nodeID, msg); // pass msg to upper layer
    
    return false;
}
Пример #4
0
bool ConfigMessage::Read(ReadBuffer& buffer)
{
    int         read;
    unsigned    numNodes, i;
    uint64_t    nodeID_;
    ReadBuffer  rb;
        
    if (buffer.GetLength() < 1)
        return false;
    
    switch (buffer.GetCharAt(0))
    {
        // Cluster management
        case CONFIGMESSAGE_SET_CLUSTER_ID:
            read = buffer.Readf("%c:%U",
             &type, &clusterID);
             break;
        case CONFIGMESSAGE_REGISTER_SHARDSERVER:
            read = buffer.Readf("%c:%U:%#R",
             &type, &nodeID, &rb);
            endpoint.Set(rb);
            break;
        case CONFIGMESSAGE_UNREGISTER_SHARDSERVER:
            read = buffer.Readf("%c:%U",
             &type, &nodeID);
            break;
        case CONFIGMESSAGE_CREATE_QUORUM:
            read = buffer.Readf("%c:%#R:%u",
             &type, &name, &numNodes);
             if (read < 0 || read == (signed)buffer.GetLength())
                return false;
            buffer.Advance(read);
            for (i = 0; i < numNodes; i++)
            {
                read = buffer.Readf(":%U", &nodeID_);
                if (read < 0)
                    return false;
                buffer.Advance(read);
                nodes.Append(nodeID_);
            }
            if (buffer.GetLength() == 0)
                return true;
            else
                return false;
            break;
        case CONFIGMESSAGE_RENAME_QUORUM:
            read = buffer.Readf("%c:%U:%#R",
             &type, &quorumID, &name);
            break;
        case CONFIGMESSAGE_DELETE_QUORUM:
            read = buffer.Readf("%c:%U",
             &type, &quorumID);
            break;
        case CONFIGMESSAGE_ADD_SHARDSERVER_TO_QUORUM:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &nodeID);
            break;
        case CONFIGMESSAGE_REMOVE_SHARDSERVER_FROM_QUORUM:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &nodeID);
            break;
        case CONFIGMESSAGE_ACTIVATE_SHARDSERVER:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &nodeID);
            break;
        case CONFIGMESSAGE_DEACTIVATE_SHARDSERVER:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &nodeID);
            break;

        // Database management
        case CONFIGMESSAGE_CREATE_DATABASE:
            read = buffer.Readf("%c:%#R",
             &type, &name);
            break;
        case CONFIGMESSAGE_RENAME_DATABASE:
            read = buffer.Readf("%c:%U:%#R",
             &type, &databaseID, &name);
            break;
        case CONFIGMESSAGE_DELETE_DATABASE:
            read = buffer.Readf("%c:%U", 
            &type, &databaseID);
            break;

        // Table management
        case CONFIGMESSAGE_CREATE_TABLE:
            read = buffer.Readf("%c:%U:%U:%#R",
             &type, &databaseID, &quorumID, &name);
            break;
        case CONFIGMESSAGE_RENAME_TABLE:
            read = buffer.Readf("%c:%U:%#R",
             &type, &tableID, &name);
            break;
        case CONFIGMESSAGE_DELETE_TABLE:
            read = buffer.Readf("%c:%U",
             &type, &tableID);
            break;
        case CONFIGMESSAGE_TRUNCATE_TABLE_BEGIN:
            read = buffer.Readf("%c:%U",
             &type, &tableID);
            break;
        case CONFIGMESSAGE_TRUNCATE_TABLE_COMPLETE:
            read = buffer.Readf("%c:%U",
             &type, &tableID);
            break;
        case CONFIGMESSAGE_FREEZE_TABLE:
            read = buffer.Readf("%c:%U",
             &type, &tableID);
            break;
        case CONFIGMESSAGE_UNFREEZE_TABLE:
            read = buffer.Readf("%c:%U",
             &type, &tableID);
            break;

        // Shard management
        case CONFIGMESSAGE_SPLIT_SHARD_BEGIN:
            read = buffer.Readf("%c:%U:%#B",
             &type, &shardID, &splitKey);
            break;
        case CONFIGMESSAGE_SPLIT_SHARD_COMPLETE:
            read = buffer.Readf("%c:%U",
             &type, &shardID);
            break;
        case CONFIGMESSAGE_SHARD_MIGRATION_BEGIN:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &shardID);
            break;
        case CONFIGMESSAGE_SHARD_MIGRATION_COMPLETE:
            read = buffer.Readf("%c:%U:%U:%U",
             &type, &quorumID, &srcShardID, &dstShardID);
            break;

        default:
            return false;
    }
    
    return (read == (signed)buffer.GetLength() ? true : false);
}
Пример #5
0
bool PaxosMessage::Read(ReadBuffer& buffer)
{
    int     read;
    char    proto;
    
    if (buffer.GetLength() < 3)
        return false;

    switch (buffer.GetCharAt(2))
    {
        case PAXOS_PREPARE_REQUEST:
            read = buffer.Readf("%c:%c:%U:%U:%U", 
             &proto, &type, &paxosID, &nodeID, &proposalID);
            break;
        case PAXOS_PREPARE_REJECTED:
            read = buffer.Readf("%c:%c:%U:%U:%U:%U",
             &proto, &type, &paxosID, &nodeID, &proposalID, &promisedProposalID);
            break;
        case PAXOS_PREPARE_PREVIOUSLY_ACCEPTED:
            read = buffer.Readf("%c:%c:%U:%U:%U:%U:%U:%#R",
             &proto, &type, &paxosID, &nodeID, &proposalID, &acceptedProposalID, &runID, &value);
            break;
        case PAXOS_PREPARE_CURRENTLY_OPEN:
            read = buffer.Readf("%c:%c:%U:%U:%U",
             &proto, &type, &paxosID, &nodeID, &proposalID);
            break;
        case PAXOS_PROPOSE_REQUEST:
            read = buffer.Readf("%c:%c:%U:%U:%U:%U:%#R",
             &proto, &type, &paxosID, &nodeID, &proposalID, &runID, &value);
            break;
        case PAXOS_PROPOSE_REJECTED:
            read = buffer.Readf("%c:%c:%U:%U:%U",
             &proto, &type, &paxosID, &nodeID, &proposalID);
            break;
        case PAXOS_PROPOSE_ACCEPTED:
            read = buffer.Readf("%c:%c:%U:%U:%U",
             &proto, &type, &paxosID, &nodeID, &proposalID);
            break;
        case PAXOS_LEARN_PROPOSAL:
            read = buffer.Readf("%c:%c:%U:%U:%U",
             &proto, &type, &paxosID, &nodeID, &proposalID);
            break;
        case PAXOS_LEARN_VALUE:
            read = buffer.Readf("%c:%c:%U:%U:%U:%#R",
             &proto, &type, &paxosID, &nodeID, &runID, &value);
            break;
        case PAXOS_REQUEST_CHOSEN:
            read = buffer.Readf("%c:%c:%U:%U",
             &proto, &type, &paxosID, &nodeID);
            break;
        case PAXOS_START_CATCHUP:
            read = buffer.Readf("%c:%c:%U:%U",
             &proto, &type, &paxosID, &nodeID);
            break;
        default:
            return false;
    }
    
    ASSERT(proto == PAXOS_PROTOCOL_ID);
    
    return (read == (signed)buffer.GetLength());

}
Пример #6
0
bool SDBPRequestMessage::Read(ReadBuffer& buffer)
{
    int         read;
    unsigned    i, numNodes;
    uint64_t    nodeID;
    ReadBuffer  optional;

    if (buffer.GetLength() < 1)
        return false;

    switch (buffer.GetCharAt(0))
    {
    /* Master query */
    case CLIENTREQUEST_GET_MASTER:
        read = buffer.Readf("%c:%U",
                            &request->type, &request->commandID);
        break;

    /* Get config state: databases, tables, shards, quora */
    case CLIENTREQUEST_GET_CONFIG_STATE:
        read = buffer.Readf("%c:%U",
                            &request->type, &request->commandID);
        break;

    /* Quorum management */
    case CLIENTREQUEST_CREATE_QUORUM:
        read = buffer.Readf("%c:%U:%u",
                            &request->type, &request->commandID, &numNodes);
        if (read < 0 || read == (signed)buffer.GetLength())
            return false;
        buffer.Advance(read);
        for (i = 0; i < numNodes; i++)
        {
            read = buffer.Readf(":%U", &nodeID);
            if (read < 0)
                return false;
            buffer.Advance(read);
            request->nodes.Append(nodeID);
        }
        if (buffer.GetLength() == 0)
            return true;
        else
            return false;
        break;
    case CLIENTREQUEST_DELETE_QUORUM:
        read = buffer.Readf("%c:%U:%U",
                            &request->type, &request->commandID, &request->quorumID);
        break;
    case CLIENTREQUEST_ADD_NODE:
        read = buffer.Readf("%c:%U:%U:%U",
                            &request->type, &request->commandID, &request->quorumID, &request->nodeID);
        break;
    case CLIENTREQUEST_REMOVE_NODE:
        read = buffer.Readf("%c:%U:%U:%U",
                            &request->type, &request->commandID, &request->quorumID, &request->nodeID);
        break;
    case CLIENTREQUEST_ACTIVATE_NODE:
        read = buffer.Readf("%c:%U:%U",
                            &request->type, &request->commandID, &request->nodeID);
        break;

    /* Database management */
    case CLIENTREQUEST_CREATE_DATABASE:
        read = buffer.Readf("%c:%U:%#B",
                            &request->type, &request->commandID, &request->name);
        break;
    case CLIENTREQUEST_RENAME_DATABASE:
        read = buffer.Readf("%c:%U:%U:%#B",
                            &request->type, &request->commandID, &request->databaseID,
                            &request->name);
        break;
    case CLIENTREQUEST_DELETE_DATABASE:
        read = buffer.Readf("%c:%U:%U",
                            &request->type, &request->commandID, &request->databaseID);
        break;
    case CLIENTREQUEST_SPLIT_SHARD:
        read = buffer.Readf("%c:%U:%U:%#B",
                            &request->type, &request->commandID,
                            &request->shardID, &request->key);
        break;
    case CLIENTREQUEST_MIGRATE_SHARD:
        read = buffer.Readf("%c:%U:%U:%U",
                            &request->type, &request->commandID, &request->shardID, &request->quorumID);
        return true;

    /* Table management */
    case CLIENTREQUEST_CREATE_TABLE:
        read = buffer.Readf("%c:%U:%U:%U:%#B",
                            &request->type, &request->commandID, &request->databaseID,
                            &request->quorumID, &request->name);
        break;
    case CLIENTREQUEST_RENAME_TABLE:
        read = buffer.Readf("%c:%U:%U:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->name);
        break;
    case CLIENTREQUEST_DELETE_TABLE:
        read = buffer.Readf("%c:%U:%U",
                            &request->type, &request->commandID,
                            &request->tableID);
        break;
    case CLIENTREQUEST_TRUNCATE_TABLE:
        read = buffer.Readf("%c:%U:%U",
                            &request->type, &request->commandID,
                            &request->tableID);
        break;

    /* Data operations */
    case CLIENTREQUEST_GET:
        read = buffer.Readf("%c:%U:%U:%U:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->paxosID,
                            &request->key);
        break;
    case CLIENTREQUEST_SET:
    case CLIENTREQUEST_SET_IF_NOT_EXISTS:
    case CLIENTREQUEST_GET_AND_SET:
        read = buffer.Readf("%c:%U:%U:%#B:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->value);
        break;
    case CLIENTREQUEST_TEST_AND_SET:
        read = buffer.Readf("%c:%U:%U:%#B:%#B:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->test, &request->value);
        break;
    case CLIENTREQUEST_TEST_AND_DELETE:
        read = buffer.Readf("%c:%U:%U:%#B:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->test);
        break;
    case CLIENTREQUEST_ADD:
        read = buffer.Readf("%c:%U:%U:%#B:%I",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->number);
        break;
    case CLIENTREQUEST_APPEND:
        read = buffer.Readf("%c:%U:%U:%#B:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->value);
        break;
    case CLIENTREQUEST_DELETE:
    case CLIENTREQUEST_REMOVE:
        read = buffer.Readf("%c:%U:%U:%#B",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key);
        break;

    case CLIENTREQUEST_LIST_KEYS:
    case CLIENTREQUEST_LIST_KEYVALUES:
    case CLIENTREQUEST_COUNT:
        read = buffer.Readf("%c:%U:%U:%#B:%#B:%#B:%U:%U",
                            &request->type, &request->commandID,
                            &request->tableID, &request->key, &request->endKey, &request->prefix,
                            &request->count, &request->offset);
        break;

    case CLIENTREQUEST_SUBMIT:
        read = buffer.Readf("%c:%U",
                            &request->type, &request->quorumID);
        break;

    case CLIENTREQUEST_BULK_LOADING:
        read = buffer.Readf("%c:%U",
                            &request->type, &request->commandID);
        break;

    default:
        return false;
    }

    return (read == (signed)buffer.GetLength() ? true : false);
}
Пример #7
0
bool ClusterMessage::Read(ReadBuffer& buffer)
{
#define READ_SEPARATOR() \
    read = buffer.Readf(":"); \
    if (read != 1) \
        return false; \
    buffer.Advance(read); \

    int             read;
    ReadBuffer      tempBuffer;
        
    if (buffer.GetLength() < 1)
        return false;
    
    switch (buffer.GetCharAt(0))
    {
        case CLUSTERMESSAGE_SET_NODEID:
            read = buffer.Readf("%c:%U:%U",
             &type, &clusterID, &nodeID);
            break;
        case CLUSTERMESSAGE_UNREGISTER_STOP:
            read = buffer.Readf("%c",
             &type);
            break;
        case CLUSTERMESSAGE_HEARTBEAT:
            read = buffer.Readf("%c:%U:%u:%u",
             &type, &nodeID, &httpPort, &sdbpPort);
            if (read < 3)
                return false;
            buffer.Advance(read);
            READ_SEPARATOR();
            if (!QuorumInfo::ReadList(buffer, quorumInfos))
                return false;
            READ_SEPARATOR();
            if (!QuorumShardInfo::ReadList(buffer, quorumShardInfos))
                return false;
            return true;
            break;
        case CLUSTERMESSAGE_SET_CONFIG_STATE:
            type = CLUSTERMESSAGE_SET_CONFIG_STATE;
            return configState.Read(buffer, true);
        case CLUSTERMESSAGE_REQUEST_LEASE:
            read = buffer.Readf("%c:%U:%U:%U:%U:%U:%u",
             &type, &nodeID, &quorumID, &proposalID, &paxosID, &configID, &duration);
            break;
        case CLUSTERMESSAGE_RECEIVE_LEASE:
            read = buffer.Readf("%c:%U:%U:%U:%U:%u:%b",
             &type, &nodeID, &quorumID, &proposalID, &configID, &duration, &watchingPaxosID);
             if (read < 9)
                return false;
            buffer.Advance(read);
            READ_SEPARATOR();
            if (!MessageUtil::ReadIDList(activeNodes, buffer))
                return false;
            READ_SEPARATOR();
            if (!MessageUtil::ReadIDList(shards, buffer))
                return false;
            return true;
        case CLUSTERMESSAGE_SHARDMIGRATION_INITIATE:
            read = buffer.Readf("%c:%U:%U:%U:%U",
             &type, &nodeID, &quorumID, &srcShardID, &dstShardID);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_BEGIN:
            read = buffer.Readf("%c:%U:%U:%U",
             &type, &quorumID, &srcShardID, &dstShardID);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_SET:
            read = buffer.Readf("%c:%U:%U:%#R:%#R",
             &type, &quorumID, &shardID, &key, &value);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_DELETE:
            read = buffer.Readf("%c:%U:%U:%#R",
             &type, &quorumID, &shardID, &key);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_COMMIT:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &shardID);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_COMPLETE:
            read = buffer.Readf("%c:%U:%U",
             &type, &quorumID, &shardID);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_PAUSE:
            read = buffer.Readf("%c",
             &type);
            break;
        case CLUSTERMESSAGE_SHARDMIGRATION_RESUME:
            read = buffer.Readf("%c",
             &type);
            break;
        case CLUSTERMESSAGE_HELLO:
            read = buffer.Readf("%c:%U:%#R",
             &type, &clusterID, &value);
            break;
        case CLUSTERMESSAGE_HTTP_ENDPOINT:
            read = buffer.Readf("%c:%U:%#R",
             &type, &nodeID, &endpoint);
            break;
        default:
            return false;
    }
    
    return (read == (signed)buffer.GetLength());
    
#undef READ_SEPARATOR
}