VirtualBox

Changeset 31770 in vbox


Ignore:
Timestamp:
Aug 19, 2010 8:53:41 AM (14 years ago)
Author:
vboxsync
Message:

FT updates

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/FTM.cpp

    r31766 r31770  
    3535#include <iprt/tcp.h>
    3636
     37/*******************************************************************************
     38*   Global Variables                                                           *
     39*******************************************************************************/
     40static const char g_szWelcome[] = "VirtualBox-Fault-Tolerance-Sync-1.0\n";
     41
    3742/**
    3843 * Initializes the FTM.
     
    4449{
    4550    /** @todo saved state for master nodes! */
    46     pVM->ftm.s.pszAddress       = NULL;
    47     pVM->ftm.s.pszPassword      = NULL;
    48     pVM->fFaultTolerantMaster   = false;
    49     pVM->ftm.s.fIsStandbyNode   = false;
    50     pVM->ftm.s.standby.hServer  = NULL;
     51    pVM->ftm.s.pszAddress               = NULL;
     52    pVM->ftm.s.pszPassword              = NULL;
     53    pVM->fFaultTolerantMaster           = false;
     54    pVM->ftm.s.fIsStandbyNode           = false;
     55    pVM->ftm.s.standby.hServer          = NULL;
     56    pVM->ftm.s.master.hShutdownEvent    = NIL_RTSEMEVENT;
     57    pVM->ftm.s.hSocket                  = NIL_RTSOCKET;
    5158    return VINF_SUCCESS;
    5259}
     
    5663 *
    5764 * Termination means cleaning up and freeing all resources,
    58  * the VM it self is at this point powered off or suspended.
     65 * the VM itself is at this point powered off or suspended.
    5966 *
    6067 * @returns VBox status code.
     
    6774    if (pVM->ftm.s.pszPassword)
    6875        RTMemFree(pVM->ftm.s.pszPassword);
     76    if (pVM->ftm.s.hSocket != NIL_RTSOCKET)
     77        RTTcpClientClose(pVM->ftm.s.hSocket);
    6978    if (pVM->ftm.s.standby.hServer)
    7079        RTTcpServerDestroy(pVM->ftm.s.standby.hServer);
     80    if (pVM->ftm.s.master.hShutdownEvent != NIL_RTSEMEVENT)
     81        RTSemEventDestroy(pVM->ftm.s.master.hShutdownEvent);
    7182
    7283    return VINF_SUCCESS;
     84}
     85
     86
     87static int ftmR3TcpWriteACK(PVM pVM)
     88{
     89    int rc = RTTcpWrite(pVM->ftm.s.hSocket, "ACK\n", sizeof("ACK\n") - 1);
     90    if (RT_FAILURE(rc))
     91    {
     92        LogRel(("FTSync: RTTcpWrite(,ACK,) -> %Rrc\n", rc));
     93    }
     94    return rc;
     95}
     96
     97
     98static int ftmR3TcpWriteNACK(PVM pVM, int32_t rc2, const char *pszMsgText = NULL)
     99{
     100    char    szMsg[256];
     101    size_t  cch;
     102    if (pszMsgText && *pszMsgText)
     103    {
     104        cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d;%s\n", rc2, pszMsgText);
     105        for (size_t off = 6; off + 1 < cch; off++)
     106            if (szMsg[off] == '\n')
     107                szMsg[off] = '\r';
     108    }
     109    else
     110        cch = RTStrPrintf(szMsg, sizeof(szMsg), "NACK=%d\n", rc2);
     111    int rc = RTTcpWrite(pVM->ftm.s.hSocket, szMsg, cch);
     112    if (RT_FAILURE(rc))
     113        LogRel(("FTSync: RTTcpWrite(,%s,%zu) -> %Rrc\n", szMsg, cch, rc));
     114    return rc;
     115}
     116
     117/**
     118 * Reads a string from the socket.
     119 *
     120 * @returns VBox status code.
     121 *
     122 * @param   pState      The teleporter state structure.
     123 * @param   pszBuf      The output buffer.
     124 * @param   cchBuf      The size of the output buffer.
     125 *
     126 */
     127static int ftmR3TcpReadLine(PVM pVM, char *pszBuf, size_t cchBuf)
     128{
     129    char       *pszStart = pszBuf;
     130    RTSOCKET    Sock     = pVM->ftm.s.hSocket;
     131
     132    AssertReturn(cchBuf > 1, VERR_INTERNAL_ERROR);
     133    *pszBuf = '\0';
     134
     135    /* dead simple approach. */
     136    for (;;)
     137    {
     138        char ch;
     139        int rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL);
     140        if (RT_FAILURE(rc))
     141        {
     142            LogRel(("FTSync: RTTcpRead -> %Rrc while reading string ('%s')\n", rc, pszStart));
     143            return rc;
     144        }
     145        if (    ch == '\n'
     146            ||  ch == '\0')
     147            return VINF_SUCCESS;
     148        if (cchBuf <= 1)
     149        {
     150            LogRel(("FTSync: String buffer overflow: '%s'\n", pszStart));
     151            return VERR_BUFFER_OVERFLOW;
     152        }
     153        *pszBuf++ = ch;
     154        *pszBuf = '\0';
     155        cchBuf--;
     156    }
     157}
     158
     159/**
     160 * Reads an ACK or NACK.
     161 *
     162 * @returns VBox status code.
     163 * @param   pVM                 The VM to operate on.
     164 * @param   pszWhich            Which ACK is this this?
     165 * @param   pszNAckMsg          Optional NACK message.
     166 */
     167static int ftmR3TcpReadACK(PVM pVM, const char *pszWhich, const char *pszNAckMsg /*= NULL*/)
     168{
     169    char szMsg[256];
     170    int rc = ftmR3TcpReadLine(pVM, szMsg, sizeof(szMsg));
     171    if (RT_FAILURE(rc))
     172        return rc;
     173
     174    if (!strcmp(szMsg, "ACK"))
     175        return VINF_SUCCESS;
     176
     177    if (!strncmp(szMsg, "NACK=", sizeof("NACK=") - 1))
     178    {
     179        char *pszMsgText = strchr(szMsg, ';');
     180        if (pszMsgText)
     181            *pszMsgText++ = '\0';
     182
     183        int32_t vrc2;
     184        rc = RTStrToInt32Full(&szMsg[sizeof("NACK=") - 1], 10, &vrc2);
     185        if (rc == VINF_SUCCESS)
     186        {
     187            /*
     188             * Well formed NACK, transform it into an error.
     189             */
     190            if (pszNAckMsg)
     191            {
     192                LogRel(("FTSync: %s: NACK=%Rrc (%d)\n", pszWhich, vrc2, vrc2));
     193                return VERR_INTERNAL_ERROR;
     194            }
     195
     196            if (pszMsgText)
     197            {
     198                pszMsgText = RTStrStrip(pszMsgText);
     199                for (size_t off = 0; pszMsgText[off]; off++)
     200                    if (pszMsgText[off] == '\r')
     201                        pszMsgText[off] = '\n';
     202
     203                LogRel(("FTSync: %s: NACK=%Rrc (%d) - '%s'\n", pszWhich, vrc2, vrc2, pszMsgText));
     204            }
     205            return VERR_INTERNAL_ERROR_2;
     206        }
     207
     208        if (pszMsgText)
     209            pszMsgText[-1] = ';';
     210    }
     211    return VERR_INTERNAL_ERROR_3;
    73212}
    74213
     
    84223static DECLCALLBACK(int) ftmR3MasterThread(RTTHREAD Thread, void *pvUser)
    85224{
    86     return VINF_SUCCESS;
     225    int rc  = VINF_SUCCESS;
     226    PVM pVM = (PVM)pvUser;
     227
     228    for (;;)
     229    {
     230        /*
     231         * Try connect to the standby machine.
     232         */
     233        rc = RTTcpClientConnect(pVM->ftm.s.pszAddress, pVM->ftm.s.uPort, &pVM->ftm.s.hSocket);
     234        if (RT_SUCCESS(rc))
     235        {
     236            /* Disable Nagle. */
     237            rc = RTTcpSetSendCoalescing(pVM->ftm.s.hSocket, false /*fEnable*/);
     238            AssertRC(rc);
     239
     240            /* Read and check the welcome message. */
     241            char szLine[RT_MAX(128, sizeof(g_szWelcome))];
     242            RT_ZERO(szLine);
     243            rc = RTTcpRead(pVM->ftm.s.hSocket, szLine, sizeof(g_szWelcome) - 1, NULL);
     244            if (    RT_SUCCESS(rc)
     245                &&  !strcmp(szLine, g_szWelcome))
     246            {
     247                /* password */
     248                rc = RTTcpWrite(pVM->ftm.s.hSocket, pVM->ftm.s.pszPassword, strlen(pVM->ftm.s.pszPassword));
     249                if (RT_SUCCESS(rc))
     250                {
     251                    /* ACK */
     252                    rc = ftmR3TcpReadACK(pVM, "password", "Invalid password");
     253                    if (RT_SUCCESS(rc))
     254                        break;
     255                }
     256            }
     257            rc = RTTcpClientClose(pVM->ftm.s.hSocket);
     258            AssertRC(rc);
     259            pVM->ftm.s.hSocket = NIL_RTSOCKET;
     260        }
     261        rc = RTSemEventWait(pVM->ftm.s.master.hShutdownEvent, 1000 /* 1 second */);
     262        if (rc != VERR_TIMEOUT)
     263            return VINF_SUCCESS;    /* told to quit */           
     264    }
     265
     266    /* Successfully initialized the connection to the standby node.
     267     * Start the sync process.
     268     */
     269
     270    return rc;
    87271}
    88272
     
    97281{
    98282    PVM pVM = (PVM)pvUser;
     283
     284    pVM->ftm.s.hSocket = Sock;
    99285
    100286    /*
     
    104290    AssertRC(rc);
    105291
    106     return VINF_SUCCESS;
     292    /* Send the welcome message to the master node. */
     293    rc = RTTcpWrite(Sock, g_szWelcome, sizeof(g_szWelcome) - 1);
     294    if (RT_FAILURE(rc))
     295    {
     296        LogRel(("Teleporter: Failed to write welcome message: %Rrc\n", rc));
     297        return VINF_SUCCESS;
     298    }
     299
     300    /*
     301     * Password.
     302     */
     303    const char *pszPassword = pVM->ftm.s.pszPassword;
     304    unsigned    off = 0;
     305    while (pszPassword[off])
     306    {
     307        char ch;
     308        rc = RTTcpRead(Sock, &ch, sizeof(ch), NULL);
     309        if (    RT_FAILURE(rc)
     310            ||  pszPassword[off] != ch)
     311        {
     312            if (RT_FAILURE(rc))
     313                LogRel(("FTSync: Password read failure (off=%u): %Rrc\n", off, rc));
     314            else
     315                LogRel(("FTSync: Invalid password (off=%u)\n", off));
     316            ftmR3TcpWriteNACK(pVM, VERR_AUTHENTICATION_FAILURE);
     317            return VINF_SUCCESS;
     318        }
     319        off++;
     320    }
     321    rc = ftmR3TcpWriteACK(pVM);
     322    if (RT_FAILURE(rc))
     323        return VINF_SUCCESS;
     324
     325    /*
     326     * Stop the server.
     327     *
     328     * Note! After this point we must return VERR_TCP_SERVER_STOP, while prior
     329     *       to it we must not return that value!
     330     */
     331    RTTcpServerShutdown(pVM->ftm.s.standby.hServer);
     332
     333    /*
     334     * Command processing loop.
     335     */
     336    bool fDone = false;
     337    for (;;)
     338    {
     339        char szCmd[128];
     340        rc = ftmR3TcpReadLine(pVM, szCmd, sizeof(szCmd));
     341        if (RT_FAILURE(rc))
     342            break;
     343
     344        if (!strcmp(szCmd, "mem-sync"))
     345        {
     346        }
     347        else
     348        if (!strcmp(szCmd, "heartbeat"))
     349        {
     350        }
     351        else
     352        if (!strcmp(szCmd, "checkpoint"))
     353        {
     354        }
     355        if (RT_FAILURE(rc))
     356            break;
     357    }
     358    LogFlowFunc(("returns mRc=%Rrc\n", rc));
     359    return VERR_TCP_SERVER_STOP;
    107360}
    108361
     
    140393    if (fMaster)
    141394    {
    142         rc = RTThreadCreate(NULL, ftmR3MasterThread, NULL,
     395        rc = RTSemEventCreate(&pVM->ftm.s.master.hShutdownEvent);
     396        if (RT_FAILURE(rc))
     397            return rc;
     398
     399        rc = RTThreadCreate(NULL, ftmR3MasterThread, pVM,
    143400                            0, RTTHREADTYPE_IO /* higher than normal priority */, 0, "ftmR3MasterThread");
    144401        if (RT_FAILURE(rc))
  • trunk/src/VBox/VMM/FTMInternal.h

    r31754 r31770  
    2323#include <VBox/ftm.h>
    2424#include <iprt/tcp.h>
    25 
     25#include <iprt/semaphore.h>
    2626
    2727/** @defgroup grp_ftm_int Internals.
     
    4949    bool                fIsStandbyNode;
    5050
     51    /** Current active socket. */
     52    RTSOCKET            hSocket;
     53
    5154    struct
    5255    {
    5356        PRTTCPSERVER    hServer;
    5457    } standby;
     58
     59    struct
     60    {
     61        RTSEMEVENT      hShutdownEvent;
     62    } master;
    5563
    5664} FTM;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette