VirtualBox

Changeset 31809 in vbox for trunk/src


Ignore:
Timestamp:
Aug 20, 2010 10:04:47 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

    r31807 r31809  
    3636#include <iprt/tcp.h>
    3737#include <iprt/semaphore.h>
     38#include <iprt/asm.h>
     39
     40/*******************************************************************************
     41 * Structures and Typedefs                                                     *
     42 *******************************************************************************/
     43
     44/**
     45 * TCP stream header.
     46 *
     47 * This is an extra layer for fixing the problem with figuring out when the SSM
     48 * stream ends.
     49 */
     50typedef struct FTMTCPHDR
     51{
     52    /** Magic value. */
     53    uint32_t    u32Magic;
     54    /** The size of the data block following this header.
     55     * 0 indicates the end of the stream, while UINT32_MAX indicates
     56     * cancelation. */
     57    uint32_t    cb;
     58} FTMTCPHDR;
     59/** Magic value for TELEPORTERTCPHDR::u32Magic. (Egberto Gismonti Amin) */
     60#define FTMTCPHDR_MAGIC       UINT32_C(0x19471205)
     61/** The max block size. */
     62#define FTMTCPHDR_MAX_SIZE    UINT32_C(0x00fffff8)
    3863
    3964/*******************************************************************************
     
    232257    return VERR_INTERNAL_ERROR_3;
    233258}
     259
     260/**
     261 * @copydoc SSMSTRMOPS::pfnWrite
     262 */
     263static DECLCALLBACK(int) ftmR3TcpOpWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
     264{
     265    PVM pVM = (PVM)pvUser;
     266
     267    AssertReturn(cbToWrite > 0, VINF_SUCCESS);
     268    AssertReturn(cbToWrite < UINT32_MAX, VERR_OUT_OF_RANGE);
     269    AssertReturn(pVM->fFaultTolerantMaster, VERR_INVALID_HANDLE);
     270
     271    for (;;)
     272    {
     273        FTMTCPHDR Hdr;
     274        Hdr.u32Magic = FTMTCPHDR_MAGIC;
     275        Hdr.cb       = RT_MIN((uint32_t)cbToWrite, FTMTCPHDR_MAX_SIZE);
     276        int rc = RTTcpSgWriteL(pVM->ftm.s.hSocket, 2, &Hdr, sizeof(Hdr), pvBuf, (size_t)Hdr.cb);
     277        if (RT_FAILURE(rc))
     278        {
     279            LogRel(("FTSync/TCP: Write error: %Rrc (cb=%#x)\n", rc, Hdr.cb));
     280            return rc;
     281        }
     282        pVM->ftm.s.syncstate.uOffStream += Hdr.cb;
     283        if (Hdr.cb == cbToWrite)
     284            return VINF_SUCCESS;
     285
     286        /* advance */
     287        cbToWrite -= Hdr.cb;
     288        pvBuf = (uint8_t const *)pvBuf + Hdr.cb;
     289    }
     290}
     291
     292
     293/**
     294 * Selects and poll for close condition.
     295 *
     296 * We can use a relatively high poll timeout here since it's only used to get
     297 * us out of error paths.  In the normal cause of events, we'll get a
     298 * end-of-stream header.
     299 *
     300 * @returns VBox status code.
     301 *
     302 * @param   pState          The teleporter state data.
     303 */
     304static int ftmR3TcpReadSelect(PVM pVM)
     305{
     306    int rc;
     307    do
     308    {
     309        rc = RTTcpSelectOne(pVM->ftm.s.hSocket, 1000);
     310        if (RT_FAILURE(rc) && rc != VERR_TIMEOUT)
     311        {
     312            pVM->ftm.s.syncstate.fIOError = true;
     313            LogRel(("FTSync/TCP: Header select error: %Rrc\n", rc));
     314            break;
     315        }
     316        if (pVM->ftm.s.syncstate.fStopReading)
     317        {
     318            rc = VERR_EOF;
     319            break;
     320        }
     321    } while (rc == VERR_TIMEOUT);
     322    return rc;
     323}
     324
     325
     326/**
     327 * @copydoc SSMSTRMOPS::pfnRead
     328 */
     329static DECLCALLBACK(int) ftmR3TcpOpRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead)
     330{
     331    PVM pVM = (PVM)pvUser;
     332    AssertReturn(!pVM->fFaultTolerantMaster, VERR_INVALID_HANDLE);
     333
     334    for (;;)
     335    {
     336        int rc;
     337
     338        /*
     339         * Check for various conditions and may have been signalled.
     340         */
     341        if (pVM->ftm.s.syncstate.fEndOfStream)
     342            return VERR_EOF;
     343        if (pVM->ftm.s.syncstate.fStopReading)
     344            return VERR_EOF;
     345        if (pVM->ftm.s.syncstate.fIOError)
     346            return VERR_IO_GEN_FAILURE;
     347
     348        /*
     349         * If there is no more data in the current block, read the next
     350         * block header.
     351         */
     352        if (!pVM->ftm.s.syncstate.cbReadBlock)
     353        {
     354            rc = ftmR3TcpReadSelect(pVM);
     355            if (RT_FAILURE(rc))
     356                return rc;
     357            FTMTCPHDR Hdr;
     358            rc = RTTcpRead(pVM->ftm.s.hSocket, &Hdr, sizeof(Hdr), NULL);
     359            if (RT_FAILURE(rc))
     360            {
     361                pVM->ftm.s.syncstate.fIOError = true;
     362                LogRel(("FTSync/TCP: Header read error: %Rrc\n", rc));
     363                return rc;
     364            }
     365
     366            if (RT_UNLIKELY(   Hdr.u32Magic != FTMTCPHDR_MAGIC
     367                            || Hdr.cb > FTMTCPHDR_MAX_SIZE
     368                            || Hdr.cb == 0))
     369            {
     370                if (    Hdr.u32Magic == FTMTCPHDR_MAGIC
     371                    &&  (   Hdr.cb == 0
     372                         || Hdr.cb == UINT32_MAX)
     373                   )
     374                {
     375                    pVM->ftm.s.syncstate.fEndOfStream = true;
     376                    pVM->ftm.s.syncstate.cbReadBlock  = 0;
     377                    return Hdr.cb ? VERR_SSM_CANCELLED : VERR_EOF;
     378                }
     379                pVM->ftm.s.syncstate.fIOError = true;
     380                LogRel(("FTSync/TCP: Invalid block: u32Magic=%#x cb=%#x\n", Hdr.u32Magic, Hdr.cb));
     381                return VERR_IO_GEN_FAILURE;
     382            }
     383
     384            pVM->ftm.s.syncstate.cbReadBlock = Hdr.cb;
     385            if (pVM->ftm.s.syncstate.fStopReading)
     386                return VERR_EOF;
     387        }
     388
     389        /*
     390         * Read more data.
     391         */
     392        rc = ftmR3TcpReadSelect(pVM);
     393        if (RT_FAILURE(rc))
     394            return rc;
     395        uint32_t cb = (uint32_t)RT_MIN(pVM->ftm.s.syncstate.cbReadBlock, cbToRead);
     396        rc = RTTcpRead(pVM->ftm.s.hSocket, pvBuf, cb, pcbRead);
     397        if (RT_FAILURE(rc))
     398        {
     399            pVM->ftm.s.syncstate.fIOError = true;
     400            LogRel(("FTSync/TCP: Data read error: %Rrc (cb=%#x)\n", rc, cb));
     401            return rc;
     402        }
     403        if (pcbRead)
     404        {
     405            cb = (uint32_t)*pcbRead;
     406            pVM->ftm.s.syncstate.uOffStream   += cb;
     407            pVM->ftm.s.syncstate.cbReadBlock -= cb;
     408            return VINF_SUCCESS;
     409        }
     410        pVM->ftm.s.syncstate.uOffStream   += cb;
     411        pVM->ftm.s.syncstate.cbReadBlock -= cb;
     412        if (cbToRead == cb)
     413            return VINF_SUCCESS;
     414
     415        /* Advance to the next block. */
     416        cbToRead -= cb;
     417        pvBuf = (uint8_t *)pvBuf + cb;
     418    }
     419}
     420
     421
     422/**
     423 * @copydoc SSMSTRMOPS::pfnSeek
     424 */
     425static DECLCALLBACK(int) ftmR3TcpOpSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
     426{
     427    return VERR_NOT_SUPPORTED;
     428}
     429
     430
     431/**
     432 * @copydoc SSMSTRMOPS::pfnTell
     433 */
     434static DECLCALLBACK(uint64_t) ftmR3TcpOpTell(void *pvUser)
     435{
     436    PVM pVM = (PVM)pvUser;
     437    return pVM->ftm.s.syncstate.uOffStream;
     438}
     439
     440
     441/**
     442 * @copydoc SSMSTRMOPS::pfnSize
     443 */
     444static DECLCALLBACK(int) ftmR3TcpOpSize(void *pvUser, uint64_t *pcb)
     445{
     446    return VERR_NOT_SUPPORTED;
     447}
     448
     449
     450/**
     451 * @copydoc SSMSTRMOPS::pfnIsOk
     452 */
     453static DECLCALLBACK(int) ftmR3TcpOpIsOk(void *pvUser)
     454{
     455    PVM pVM = (PVM)pvUser;
     456
     457    if (pVM->fFaultTolerantMaster)
     458    {
     459        /* Poll for incoming NACKs and errors from the other side */
     460        int rc = RTTcpSelectOne(pVM->ftm.s.hSocket, 0);
     461        if (rc != VERR_TIMEOUT)
     462        {
     463            if (RT_SUCCESS(rc))
     464            {
     465                LogRel(("FTSync/TCP: Incoming data detect by IsOk, assuming it is a cancellation NACK.\n"));
     466                rc = VERR_SSM_CANCELLED;
     467            }
     468            else
     469                LogRel(("FTSync/TCP: RTTcpSelectOne -> %Rrc (IsOk).\n", rc));
     470            return rc;
     471        }
     472    }
     473
     474    return VINF_SUCCESS;
     475}
     476
     477
     478/**
     479 * @copydoc SSMSTRMOPS::pfnClose
     480 */
     481static DECLCALLBACK(int) ftmR3TcpOpClose(void *pvUser, bool fCanceled)
     482{
     483    PVM pVM = (PVM)pvUser;
     484
     485    if (pVM->fFaultTolerantMaster)
     486    {
     487        FTMTCPHDR EofHdr;
     488        EofHdr.u32Magic = FTMTCPHDR_MAGIC;
     489        EofHdr.cb       = fCanceled ? UINT32_MAX : 0;
     490        int rc = RTTcpWrite(pVM->ftm.s.hSocket, &EofHdr, sizeof(EofHdr));
     491        if (RT_FAILURE(rc))
     492        {
     493            LogRel(("FTSync/TCP: EOF Header write error: %Rrc\n", rc));
     494            return rc;
     495        }
     496    }
     497    else
     498    {
     499        ASMAtomicWriteBool(&pVM->ftm.s.syncstate.fStopReading, true);
     500    }
     501
     502    return VINF_SUCCESS;
     503}
     504
     505
     506/**
     507 * Method table for a TCP based stream.
     508 */
     509static SSMSTRMOPS const g_ftmR3TcpOps =
     510{
     511    SSMSTRMOPS_VERSION,
     512    ftmR3TcpOpWrite,
     513    ftmR3TcpOpRead,
     514    ftmR3TcpOpSeek,
     515    ftmR3TcpOpTell,
     516    ftmR3TcpOpSize,
     517    ftmR3TcpOpIsOk,
     518    ftmR3TcpOpClose,
     519    SSMSTRMOPS_VERSION
     520};
    234521
    235522/**
     
    507794    AssertMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
    508795
     796    /* Reset the sync state. */
     797    pVM->ftm.s.syncstate.uOffStream   = 0;
     798    pVM->ftm.s.syncstate.cbReadBlock  = 0;
     799    pVM->ftm.s.syncstate.fStopReading = false;
     800    pVM->ftm.s.syncstate.fIOError     = false;
     801    pVM->ftm.s.syncstate.fEndOfStream = false;
     802
     803    /** @todo sync state + changed memory. */
     804
    509805    PDMCritSectLeave(&pVM->ftm.s.CritSect);
    510806    pVM->ftm.s.fCheckpointingActive = false;
  • trunk/src/VBox/VMM/FTMInternal.h

    r31789 r31809  
    5555    RTSOCKET            hSocket;
    5656
     57    /** State sync. */
     58    struct
     59    {
     60        unsigned            uOffStream;
     61        unsigned            cbReadBlock;
     62        bool                fStopReading;
     63        bool                fIOError;
     64        bool                fEndOfStream;
     65        bool                fAlignment[5];
     66    } syncstate;
     67
    5768    struct
    5869    {
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