VirtualBox

Changeset 21897 in vbox for trunk


Ignore:
Timestamp:
Jul 30, 2009 4:27:15 PM (15 years ago)
Author:
vboxsync
Message:

SSM: some direct stream buffer access.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/SSM-new.cpp

    r21895 r21897  
    465465            uint8_t         abDataBuffer[4096];
    466466
    467             /** V2: Decompression buffer.
    468              * @todo removed this when we start buffering the stream. */
     467            /** V2: Decompression buffer for when we cannot use the stream buffer. */
    469468            uint8_t         abComprBuffer[4096];
    470469        } Read;
     
    750749static DECLCALLBACK(int)    ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
    751750static int                  ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit);
     751static int                  ssmR3StrmWriteBuffers(PSSMSTRM pStrm);
    752752static int                  ssmR3CalcChecksum(RTFILE File, uint64_t cbFile, uint32_t *pu32CRC);
    753753static void                 ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance);
     
    15561556            if (RT_FAILURE(pStrm->rc))
    15571557                return NULL;
     1558            if (    pStrm->fWrite
     1559                &&  pStrm->hIoThread == NIL_RTTHREAD)
     1560            {
     1561                int rc = ssmR3StrmWriteBuffers(pStrm);
     1562                if (RT_FAILURE(rc))
     1563                    return NULL;
     1564            }
    15581565            int rc = RTSemEventWaitNoResume(pStrm->hEvtFree, 30000);
    15591566            if (    rc == VERR_SEM_DESTROYED
     
    18251832        /*
    18261833         * Flush the current buffer and replace it with a new one.
    1827          * Write the bits to the disk if we haven't got any helper yet.
    18281834         */
    18291835        ssmR3StrmFlushCurBuf(pStrm);
    1830         if (pStrm->hIoThread == NIL_RTTHREAD)
    1831         {
    1832             int rc = ssmR3StrmWriteBuffers(pStrm);
    1833             if (RT_FAILURE(rc))
    1834                 return rc;
    1835         }
    18361836        pBuf = ssmR3StrmGetFreeBuf(pStrm);
    18371837        if (!pBuf)
     
    18561856
    18571857
     1858/**
     1859 * Reserves space in the current buffer so the caller can write directly to the
     1860 * buffer instead of doing double buffering.
     1861 *
     1862 * @returns VBox status code
     1863 * @param   pStrm       The stream handle.
     1864 * @param   cb          The amount of buffer space to reserve.
     1865 * @param   ppb         Where to return the pointer.
     1866 */
     1867static int ssmR3StrmReserveWriteBufferSpace(PSSMSTRM pStrm, size_t cb, uint8_t **ppb)
     1868{
     1869    Assert(pStrm->fWrite);
     1870    Assert(RT_SIZEOFMEMB(SSMSTRMBUF, abData) / 4 >= cb);
     1871
     1872    /*
     1873     * Check if there is room in the current buffer, it not flush it.
     1874     */
     1875    PSSMSTRMBUF pBuf = pStrm->pCur;
     1876    if (pBuf)
     1877    {
     1878        uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
     1879        if (cbLeft >= cb)
     1880        {
     1881            *ppb = &pBuf->abData[pStrm->off];
     1882            return VINF_SUCCESS;
     1883        }
     1884
     1885        ssmR3StrmFlushCurBuf(pStrm);
     1886    }
     1887
     1888    /*
     1889     * Get a fresh buffer and return a pointer into it.
     1890     */
     1891    pBuf = ssmR3StrmGetFreeBuf(pStrm);
     1892    if (pBuf)
     1893    {
     1894        pStrm->pCur = pBuf;
     1895        Assert(pStrm->off == 0);
     1896        *ppb = &pBuf->abData[0];
     1897    }
     1898    else
     1899        *ppb = NULL; /* make gcc happy. */
     1900    return pStrm->rc;
     1901}
     1902
     1903
     1904/**
     1905 * Commits buffer space reserved by ssmR3StrmReserveWriteBufferSpace.
     1906 *
     1907 * @returns VBox status code.
     1908 * @param   pStrm       The stream handle.
     1909 * @param   cb          The amount of buffer space to commit.  This can be less
     1910 *                      that what was reserved initially.
     1911 */
     1912static int ssmR3StrmCommitWriteBufferSpace(PSSMSTRM pStrm, size_t cb)
     1913{
     1914    Assert(pStrm->pCur);
     1915    Assert(pStrm->off + cb <= RT_SIZEOFMEMB(SSMSTRMBUF, abData));
     1916    pStrm->off += cb;
     1917    return VINF_SUCCESS;
     1918}
     1919
    18581920
    18591921/**
     
    19612023     * Get more buffers from the stream.
    19622024     */
    1963     int rc;
     2025    int rc = VINF_SUCCESS;
    19642026    do
    19652027    {
     
    20102072
    20112073    return rc;
     2074}
     2075
     2076
     2077/**
     2078 * Reads data from the stream but instead of copying it to some output buffer
     2079 * the caller gets a pointer to into the current stream buffer.
     2080 *
     2081 * The returned pointer becomes invalid after the next stream operation!
     2082 *
     2083 * @returns Pointer to the read data residing in the stream buffer.  NULL is
     2084 *          returned if the request amount of data isn't available in the
     2085 *          buffer.  The caller must fall back on ssmR3StrmRead when this
     2086 *          happens.
     2087 *
     2088 * @param   pStrm       The stream handle.
     2089 * @param   cbToRead    The number of bytes to tread.
     2090 */
     2091static uint8_t const *ssmR3StrmReadDirect(PSSMSTRM pStrm, size_t cbToRead)
     2092{
     2093    AssertReturn(cbToRead > 0, VINF_SUCCESS);
     2094    Assert(!pStrm->fWrite);
     2095
     2096    /*
     2097     * Too lazy to fetch more data for the odd case that we're
     2098     * exactly at the boundrary between two buffers.
     2099     */
     2100    PSSMSTRMBUF pBuf = pStrm->pCur;
     2101    if (RT_LIKELY(pBuf))
     2102    {
     2103        Assert(pStrm->off <= pBuf->cb);
     2104        uint32_t cbLeft = pBuf->cb - pStrm->off;
     2105        if (cbLeft >= cbToRead)
     2106        {
     2107            uint8_t const *pb = &pBuf->abData[pStrm->off];
     2108            pStrm->off += (uint32_t)cbToRead;
     2109            Assert(pStrm->off <= pBuf->cb);
     2110            return pb;
     2111        }
     2112    }
     2113    return NULL;
    20122114}
    20132115
     
    41164218static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM)
    41174219{
     4220    /*
     4221     * Check how much there current is in the buffer.
     4222     */
    41184223    uint32_t cb = pSSM->u.Write.offDataBuffer;
    41194224    if (!cb)
    41204225        return pSSM->rc;
    4121 
    4122     /*
    4123      * Create a record header.
    4124      */
    4125     uint32_t    cbTotal = cb + 1;
    4126     uint8_t    *pbHdr   = &pSSM->u.Write.abRecHdr[sizeof(pSSM->u.Write.abRecHdr) - 1];
    4127     if (cb < 0x80)
    4128     {
    4129         cbTotal += 1;
    4130         pbHdr   -= 1;
    4131         pbHdr[1] = cb;
    4132     }
    4133     else if (cb < 0x00000800)
    4134     {
    4135         cbTotal += 2;
    4136         pbHdr   -= 2;
    4137         pbHdr[1] = 0xc0 | (cb >> 6);
    4138         pbHdr[2] = 0x80 | (cb & 0x3f);
    4139     }
    4140     else if (cb < 0x00010000)
    4141     {
    4142         cbTotal += 3;
    4143         pbHdr   -= 3;
    4144         pbHdr[1] = 0xe0 | (cb >> 12);
    4145         pbHdr[2] = 0x80 | ((cb >> 6) & 0x3f);
    4146         pbHdr[3] = 0x80 | (cb & 0x3f);
    4147     }
    4148     else if (cb < 0x00200000)
    4149     {
    4150         cbTotal += 4;
    4151         pbHdr   -= 4;
    4152         pbHdr[1] = 0xf0 | (cb >> 18);
    4153         pbHdr[2] = 0x80 | ((cb >> 12) & 0x3f);
    4154         pbHdr[3] = 0x80 | ((cb >> 6) & 0x3f);
    4155         pbHdr[4] = 0x80 | (cb & 0x3f);
    4156     }
    4157     else if (cb < 0x04000000)
    4158     {
    4159         cbTotal += 5;
    4160         pbHdr   -= 5;
    4161         pbHdr[1] = 0xf8 | (cb >> 24);
    4162         pbHdr[2] = 0x80 | ((cb >> 18) & 0x3f);
    4163         pbHdr[3] = 0x80 | ((cb >> 12) & 0x3f);
    4164         pbHdr[4] = 0x80 | ((cb >> 6) & 0x3f);
    4165         pbHdr[5] = 0x80 | (cb & 0x3f);
    4166     }
    4167     else if (cb <= 0x7fffffff)
    4168     {
    4169         cbTotal += 6;
    4170         pbHdr   -= 6;
    4171         pbHdr[1] = 0xfc | (cb >> 30);
    4172         pbHdr[2] = 0x80 | ((cb >> 24) & 0x3f);
    4173         pbHdr[3] = 0x80 | ((cb >> 18) & 0x3f);
    4174         pbHdr[4] = 0x80 | ((cb >> 12) & 0x3f);
    4175         pbHdr[5] = 0x80 | ((cb >> 6) & 0x3f);
    4176         pbHdr[6] = 0x80 | (cb & 0x3f);
    4177     }
    4178     else
    4179         AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), VERR_INTERNAL_ERROR);
    4180     pbHdr[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
    4181 
    4182     Log3(("ssmR3DataFlushBuffer: %08llx|%08llx/%08x: Type=RAW fImportant=true cbHdr=%u\n",
    4183           ssmR3StrmTell(&pSSM->Strm) + (cbTotal - cb), pSSM->offUnit + (cbTotal - cb), cb, (cbTotal - cb) ));
    4184 
    4185     /*
    4186      * Write it and reset the buffer.
    4187      */
    4188     int rc = ssmR3DataWriteRaw(pSSM, pbHdr, cbTotal);
    41894226    pSSM->u.Write.offDataBuffer = 0;
     4227
     4228    /*
     4229     * Write a record header and then the data.
     4230     * (No need for fancy optimizations here any longer since the stream is
     4231     * fully buffered.)
     4232     */
     4233    int rc = ssmR3DataWriteRecHdr(pSSM, cb, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
     4234    if (RT_SUCCESS(rc))
     4235        rc = ssmR3DataWriteRaw(pSSM, pSSM->u.Write.abDataBuffer, cb);
    41904236    return rc;
    41914237}
     
    42124258            if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
    42134259            {
    4214                 struct
    4215                 {
    4216                     uint8_t     cKB;
    4217                     uint8_t     abCompr[SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16)];
    4218                 } s;
    4219                 AssertCompile(sizeof(s) == SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16) + sizeof(uint8_t));
    4220 
    4221                 size_t cbCompr;
     4260                AssertCompile(1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE < 0x00010000);
     4261                uint8_t *pb;
     4262                rc = ssmR3StrmReserveWriteBufferSpace(&pSSM->Strm, 1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE, &pb);
     4263                if (RT_FAILURE(rc))
     4264                    break;
     4265                size_t cbRec = SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16);
    42224266                rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
    42234267                                        pvBuf, SSM_ZIP_BLOCK_SIZE,
    4224                                         &s.abCompr[0], sizeof(s.abCompr), &cbCompr);
     4268                                        pb + 1 + 3 + 1, cbRec, &cbRec);
    42254269                if (RT_SUCCESS(rc))
    42264270                {
    4227                     cbCompr += sizeof(s.cKB);
    4228                     s.cKB = SSM_ZIP_BLOCK_SIZE / _1K;
    4229                     rc = ssmR3DataWriteRecHdr(pSSM, cbCompr, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF);
    4230                     if (RT_FAILURE(rc))
    4231                         return rc;
    4232                     rc = ssmR3DataWriteRaw(pSSM, &s, cbCompr);
    4233                     if (RT_FAILURE(rc))
    4234                         return rc;
     4271                    pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF;
     4272                    pb[4] = SSM_ZIP_BLOCK_SIZE / _1K;
     4273                    cbRec += 1;
    42354274                }
    42364275                else
    42374276                {
    4238                     /* Didn't compress very well, store it. */
    4239                     rc = ssmR3DataWriteRecHdr(pSSM, SSM_ZIP_BLOCK_SIZE, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
    4240                     if (RT_FAILURE(rc))
    4241                         return rc;
    4242                     rc = ssmR3DataWriteRaw(pSSM, pvBuf, SSM_ZIP_BLOCK_SIZE);
    4243                     if (RT_FAILURE(rc))
    4244                         return rc;
     4277                    pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
     4278                    memcpy(&pb[4], pvBuf, SSM_ZIP_BLOCK_SIZE);
     4279                    cbRec = SSM_ZIP_BLOCK_SIZE;
    42454280                }
     4281                pb[1] = (uint8_t)(0xe0 | ( cbRec >> 12));
     4282                pb[2] = (uint8_t)(0x80 | ((cbRec >>  6) & 0x3f));
     4283                pb[3] = (uint8_t)(0x80 | ( cbRec        & 0x3f));
     4284                cbRec += 1 + 3;
     4285                rc = ssmR3StrmCommitWriteBufferSpace(&pSSM->Strm, cbRec);
     4286                if (RT_FAILURE(rc))
     4287                    break;
     4288
     4289                pSSM->offUnit += cbRec;
     4290                ssmR3Progress(pSSM, SSM_ZIP_BLOCK_SIZE);
     4291
     4292                /* advance */
    42464293                if (cbBuf == SSM_ZIP_BLOCK_SIZE)
    42474294                    return VINF_SUCCESS;
     
    42514298            else
    42524299            {
    4253                 /* Less than one page, just store it. */
     4300                /*
     4301                 * Less than one block left, store it the simple way.
     4302                 */
    42544303                rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
    42554304                if (RT_SUCCESS(rc))
    42564305                    rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
    4257                 return rc;
     4306                break;
    42584307            }
    42594308        }
     
    49114960DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
    49124961{
    4913     /** @todo buffered reads! (at some level or another) */
    49144962    int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead);
    49154963    if (RT_SUCCESS(rc))
     
    49725020static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr)
    49735021{
    4974     /** @todo optimize this wrt to stream buffering when that is added. */
    4975     uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
     5022    int         rc;
     5023    uint32_t    cbCompr    = pSSM->u.Read.cbRecLeft;
    49765024    pSSM->u.Read.cbRecLeft = 0;
    49775025
    4978     int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
     5026    /*
     5027     * Try use the stream buffer directly to avoid copying things around.
     5028     */
     5029    uint8_t const *pb = ssmR3StrmReadDirect(&pSSM->Strm, cbCompr);
     5030    if (pb)
     5031    {
     5032        pSSM->offUnit += cbCompr;
     5033        ssmR3Progress(pSSM, cbCompr);
     5034    }
     5035    else
     5036    {
     5037        rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
     5038        if (RT_FAILURE(rc))
     5039            return rc;
     5040        pb = &pSSM->u.Read.abComprBuffer[0];
     5041    }
     5042
     5043    /*
     5044     * Decompress it.
     5045     */
     5046    size_t cbDstActual;
     5047    rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
     5048                              pb, cbCompr, NULL /*pcbSrcActual*/,
     5049                              pvDst, cbDecompr, &cbDstActual);
    49795050    if (RT_SUCCESS(rc))
    49805051    {
    4981         size_t cbDstActual;
    4982         rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
    4983                                   &pSSM->u.Read.abComprBuffer[0], cbCompr, NULL /*pcbSrcActual*/,
    4984                                   pvDst, cbDecompr, &cbDstActual);
    4985         if (RT_SUCCESS(rc))
    4986         {
    4987             AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), VERR_SSM_INTEGRITY);
    4988             return VINF_SUCCESS;
    4989         }
     5052        AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), VERR_SSM_INTEGRITY);
     5053        return VINF_SUCCESS;
    49905054    }
    49915055    return rc;
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