- Timestamp:
- Jul 30, 2009 4:27:15 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/SSM-new.cpp
r21895 r21897 465 465 uint8_t abDataBuffer[4096]; 466 466 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. */ 469 468 uint8_t abComprBuffer[4096]; 470 469 } Read; … … 750 749 static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version); 751 750 static int ssmR3Register(PVM pVM, const char *pszName, uint32_t u32Instance, uint32_t u32Version, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit); 751 static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm); 752 752 static int ssmR3CalcChecksum(RTFILE File, uint64_t cbFile, uint32_t *pu32CRC); 753 753 static void ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance); … … 1556 1556 if (RT_FAILURE(pStrm->rc)) 1557 1557 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 } 1558 1565 int rc = RTSemEventWaitNoResume(pStrm->hEvtFree, 30000); 1559 1566 if ( rc == VERR_SEM_DESTROYED … … 1825 1832 /* 1826 1833 * 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.1828 1834 */ 1829 1835 ssmR3StrmFlushCurBuf(pStrm); 1830 if (pStrm->hIoThread == NIL_RTTHREAD)1831 {1832 int rc = ssmR3StrmWriteBuffers(pStrm);1833 if (RT_FAILURE(rc))1834 return rc;1835 }1836 1836 pBuf = ssmR3StrmGetFreeBuf(pStrm); 1837 1837 if (!pBuf) … … 1856 1856 1857 1857 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 */ 1867 static 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 */ 1912 static 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 1858 1920 1859 1921 /** … … 1961 2023 * Get more buffers from the stream. 1962 2024 */ 1963 int rc ;2025 int rc = VINF_SUCCESS; 1964 2026 do 1965 2027 { … … 2010 2072 2011 2073 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 */ 2091 static 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; 2012 2114 } 2013 2115 … … 4116 4218 static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM) 4117 4219 { 4220 /* 4221 * Check how much there current is in the buffer. 4222 */ 4118 4223 uint32_t cb = pSSM->u.Write.offDataBuffer; 4119 4224 if (!cb) 4120 4225 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 else4179 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);4189 4226 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); 4190 4236 return rc; 4191 4237 } … … 4212 4258 if (cbBuf >= SSM_ZIP_BLOCK_SIZE) 4213 4259 { 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); 4222 4266 rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/, 4223 4267 pvBuf, SSM_ZIP_BLOCK_SIZE, 4224 &s.abCompr[0], sizeof(s.abCompr), &cbCompr);4268 pb + 1 + 3 + 1, cbRec, &cbRec); 4225 4269 if (RT_SUCCESS(rc)) 4226 4270 { 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; 4235 4274 } 4236 4275 else 4237 4276 { 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; 4245 4280 } 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 */ 4246 4293 if (cbBuf == SSM_ZIP_BLOCK_SIZE) 4247 4294 return VINF_SUCCESS; … … 4251 4298 else 4252 4299 { 4253 /* Less than one page, just store it. */ 4300 /* 4301 * Less than one block left, store it the simple way. 4302 */ 4254 4303 rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW); 4255 4304 if (RT_SUCCESS(rc)) 4256 4305 rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf); 4257 return rc;4306 break; 4258 4307 } 4259 4308 } … … 4911 4960 DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead) 4912 4961 { 4913 /** @todo buffered reads! (at some level or another) */4914 4962 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead); 4915 4963 if (RT_SUCCESS(rc)) … … 4972 5020 static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr) 4973 5021 { 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; 4976 5024 pSSM->u.Read.cbRecLeft = 0; 4977 5025 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); 4979 5050 if (RT_SUCCESS(rc)) 4980 5051 { 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; 4990 5054 } 4991 5055 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.