Changeset 30396 in vbox
- Timestamp:
- Jun 23, 2010 3:26:41 PM (14 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/ssm.h
r28800 r30396 1165 1165 VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM); 1166 1166 VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM); 1167 VMMR3_INT_DECL(int) SSMR3SetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr); 1167 VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr); 1168 VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent); 1168 1169 VMMR3DECL(int) SSMR3Cancel(PVM pVM); 1169 1170 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r29979 r30396 822 822 static const RTGETOPTDEF s_aTeleportOptions[] = 823 823 { 824 { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */ 825 { "--hostname", 'h', RTGETOPT_REQ_STRING }, /** @todo remove this */ 826 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 }, 827 { "--port", 'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */ 828 { "--password", 'P', RTGETOPT_REQ_STRING }, 829 { "--timeout", 't', RTGETOPT_REQ_UINT32 } 824 { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */ 825 { "--hostname", 'h', RTGETOPT_REQ_STRING }, /** @todo remove this */ 826 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 }, 827 { "--port", 'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */ 828 { "--password", 'P', RTGETOPT_REQ_STRING }, 829 { "--timeout", 't', RTGETOPT_REQ_UINT32 }, 830 { "--detailed-progress", 'D', RTGETOPT_REQ_NOTHING } 830 831 }; 831 832 RTGETOPTSTATE GetOptState; … … 840 841 case 'h': bstrHostname = Value.psz; break; 841 842 case 'd': uMaxDowntime = Value.u32; break; 843 case 'D': g_fDetailedProgress = true; break; 842 844 case 'p': uPort = Value.u32; break; 843 845 case 'P': bstrPassword = Value.psz; break; -
trunk/src/VBox/Main/ProgressImpl.cpp
r29989 r30396 977 977 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 978 978 979 Assert Return(aPercent <= 100, E_INVALIDARG);979 AssertMsgReturn(aPercent <= 100, ("%u\n", aPercent), E_INVALIDARG); 980 980 981 981 checkForAutomaticTimeout(); -
trunk/src/VBox/VMM/CPUM.cpp
r30316 r30396 2085 2085 */ 2086 2086 if (uVersion == CPUM_SAVED_STATE_VERSION_VER1_6) 2087 SSMR3 SetGCPtrSize(pSSM, sizeof(RTGCPTR32));2087 SSMR3HandleSetGCPtrSize(pSSM, sizeof(RTGCPTR32)); 2088 2088 else if (uVersion <= CPUM_SAVED_STATE_VERSION_VER3_0) 2089 SSMR3 SetGCPtrSize(pSSM, HC_ARCH_BITS == 32 ? sizeof(RTGCPTR32) : sizeof(RTGCPTR));2089 SSMR3HandleSetGCPtrSize(pSSM, HC_ARCH_BITS == 32 ? sizeof(RTGCPTR32) : sizeof(RTGCPTR)); 2090 2090 2091 2091 /* -
trunk/src/VBox/VMM/PGMSavedState.cpp
r30326 r30396 1890 1890 } 1891 1891 } 1892 1893 /* 1894 * Come up with a completion percentage. Currently this is a simple 1895 * dirty page (long term) vs. total pages ratio + some pass trickery. 1896 */ 1897 unsigned uPctDirty = cDirtyPagesLong 1898 / (long double)(pVM->pgm.s.cAllPages - pVM->pgm.s.LiveSave.cIgnoredPages - pVM->pgm.s.cZeroPages); 1899 if (uPctDirty <= 100) 1900 SSMR3HandleReportLivePercent(pSSM, RT_MIN(100 - uPctDirty, uPass * 2)); 1901 else 1902 AssertMsgFailed(("uPctDirty=%u cDirtyPagesLong=%#x cAllPages=%#x cIgnoredPages=%#x cZeroPages=%#x\n", 1903 uPctDirty, cDirtyPagesLong, pVM->pgm.s.cAllPages, pVM->pgm.s.LiveSave.cIgnoredPages, pVM->pgm.s.cZeroPages)); 1904 1892 1905 return VINF_SSM_VOTE_FOR_ANOTHER_PASS; 1893 1906 } -
trunk/src/VBox/VMM/SSM.cpp
r30111 r30396 5 5 6 6 /* 7 * Copyright (C) 2006-20 09Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 485 485 /** End of current unit in the estimated file. */ 486 486 uint64_t offEstUnitEnd; 487 /** the amount of % we reserve for the 'prepare' phase */ 487 /** The amount of % we reserve for the 'live' stage */ 488 unsigned uPercentLive; 489 /** The amount of % we reserve for the 'prepare' phase */ 488 490 unsigned uPercentPrepare; 489 /** the amount of % we reserve for the 'done' stage */491 /** The amount of % we reserve for the 'done' stage */ 490 492 unsigned uPercentDone; 493 /** The lowest value reported via SSMR3HandleReportLivePercent during one 494 * vote run. */ 495 unsigned uReportedLivePercent; 491 496 /** The filename, NULL if remote stream. */ 492 497 const char *pszFilename; … … 872 877 static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM); 873 878 static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); 879 static DECLCALLBACK(int) ssmR3LiveControlLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass); 874 880 static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit); 881 static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass); 875 882 #endif 876 883 … … 916 923 NULL /*pfnSavePrep*/, ssmR3SelfSaveExec, NULL /*pfnSaveDone*/, 917 924 NULL /*pfnSavePrep*/, ssmR3SelfLoadExec, NULL /*pfnSaveDone*/); 925 if (RT_SUCCESS(rc)) 926 rc = SSMR3RegisterInternal(pVM, "SSMLiveControl", 0 /*uInstance*/, 1 /*uVersion*/, 1 /*cbGuess*/, 927 NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/, 928 NULL /*pfnSavePrep*/, NULL /*pfnSaveExec*/, NULL /*pfnSaveDone*/, 929 NULL /*pfnSavePrep*/, ssmR3LiveControlLoadExec, NULL /*pfnSaveDone*/); 918 930 919 931 /* … … 1040 1052 } 1041 1053 return VINF_SUCCESS; 1054 } 1055 1056 1057 /** 1058 * Load exec callback for the special live save state unit that tracks the 1059 * progress of a live save. 1060 * 1061 * This is saved by ssmR3LiveControlEmit(). 1062 * 1063 * @returns VBox status code. 1064 * @param pVM Pointer to the shared VM structure. 1065 * @param pSSM The SSM handle. 1066 * @param uVersion The version (1). 1067 * @param uPass The pass. 1068 */ 1069 static DECLCALLBACK(int) ssmR3LiveControlLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1070 { 1071 AssertLogRelMsgReturn(uVersion == 1, ("%d", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION); 1072 1073 uint16_t uPartsPerTenThousand; 1074 int rc = SSMR3GetU16(pSSM, &uPartsPerTenThousand); 1075 if (RT_SUCCESS(rc)) 1076 { 1077 /* Scale it down to fit in our exec range. */ 1078 unsigned uPct = (unsigned)( (long double)uPartsPerTenThousand / 100 1079 * (100 - pSSM->uPercentPrepare - pSSM->uPercentDone) / 100) 1080 + pSSM->uPercentPrepare; 1081 if (uPct != pSSM->uPercent) 1082 { 1083 AssertMsg(uPct < 100, ("uPct=%d uPartsPerTenThousand=%d uPercentPrepare=%d uPercentDone=%d\n", uPct, uPartsPerTenThousand, pSSM->uPercentPrepare, pSSM->uPercentDone)); 1084 pSSM->uPercent = uPct; 1085 if (pSSM->pfnProgress) 1086 pSSM->pfnProgress(pVM, RT_MIN(uPct, 100 - pSSM->uPercentDone), pSSM->pvUser); 1087 } 1088 } 1089 return rc; 1042 1090 } 1043 1091 … … 2892 2940 2893 2941 /** 2894 * Works the progress calculation .2942 * Works the progress calculation for non-live saves and restores. 2895 2943 * 2896 2944 * @param pSSM The SSM handle. 2897 * @param cbAdvance Number of bytes to advance 2898 */ 2899 static void ssmR3Progress(PSSMHANDLE pSSM, uint64_t cbAdvance) 2900 { 2901 /* Can't advance it beyond the estimated end of the unit. */ 2902 uint64_t cbLeft = pSSM->offEstUnitEnd - pSSM->offEst; 2903 if (cbAdvance > cbLeft) 2904 cbAdvance = cbLeft; 2905 pSSM->offEst += cbAdvance; 2906 2907 /* uPercentPrepare% prepare, xx% exec, uPercentDone% done+crc */ 2908 while ( pSSM->offEst >= pSSM->offEstProgress 2909 && pSSM->uPercent <= 100-pSSM->uPercentDone) 2910 { 2911 if (pSSM->pfnProgress) 2912 pSSM->pfnProgress(pSSM->pVM, pSSM->uPercent, pSSM->pvUser); 2913 pSSM->uPercent++; 2914 pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare) * pSSM->cbEstTotal 2915 / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare); 2945 * @param cbAdvance Number of bytes to advance (with in the current unit). 2946 */ 2947 static void ssmR3ProgressByByte(PSSMHANDLE pSSM, uint64_t cbAdvance) 2948 { 2949 if (!pSSM->fLiveSave) 2950 { 2951 /* Can't advance it beyond the estimated end of the unit. */ 2952 uint64_t cbLeft = pSSM->offEstUnitEnd - pSSM->offEst; 2953 if (cbAdvance > cbLeft) 2954 cbAdvance = cbLeft; 2955 pSSM->offEst += cbAdvance; 2956 2957 /* uPercentPrepare% prepare, xx% exec, uPercentDone% done+crc. This is not 2958 quite right for live save, but the non-live stage there is very short. */ 2959 while ( pSSM->offEst >= pSSM->offEstProgress 2960 && pSSM->uPercent <= 100 - pSSM->uPercentDone) 2961 { 2962 if (pSSM->pfnProgress) 2963 pSSM->pfnProgress(pSSM->pVM, pSSM->uPercent, pSSM->pvUser); 2964 pSSM->uPercent++; 2965 pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare - pSSM->uPercentLive) * pSSM->cbEstTotal 2966 / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive); 2967 } 2916 2968 } 2917 2969 } … … 3151 3203 if (RT_SUCCESS(rc)) 3152 3204 rc = ssmR3DataWriteRaw(pSSM, pSSM->u.Write.abDataBuffer, cb); 3153 ssmR3Progress (pSSM, cb);3205 ssmR3ProgressByByte(pSSM, cb); 3154 3206 return rc; 3155 3207 } … … 3213 3265 3214 3266 pSSM->offUnit += cbRec; 3215 ssmR3Progress (pSSM, SSM_ZIP_BLOCK_SIZE);3267 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE); 3216 3268 3217 3269 /* advance */ … … 3236 3288 3237 3289 /* advance */ 3238 ssmR3Progress (pSSM, SSM_ZIP_BLOCK_SIZE);3290 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE); 3239 3291 if (cbBuf == SSM_ZIP_BLOCK_SIZE) 3240 3292 return VINF_SUCCESS; … … 3250 3302 if (RT_SUCCESS(rc)) 3251 3303 rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf); 3252 ssmR3Progress (pSSM, cbBuf);3304 ssmR3ProgressByByte(pSSM, cbBuf); 3253 3305 break; 3254 3306 } … … 4061 4113 4062 4114 /** 4115 * Emits a SSMLiveControl unit with a new progress report. 4116 * 4117 * @returns VBox status code. 4118 * @param pSSM The saved state handle. 4119 * @param lrdPct The progress of the the live save. 4120 * @param uPass The current pass. 4121 */ 4122 static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass) 4123 { 4124 AssertMsg(lrdPct <= 100.0, ("%u\n", lrdPct * 100)); 4125 4126 /* 4127 * Make sure we're in one of the two EXEC states or we may fail. 4128 */ 4129 SSMSTATE enmSavedState = pSSM->enmOp; 4130 if (enmSavedState == SSMSTATE_LIVE_VOTE) 4131 pSSM->enmOp = SSMSTATE_LIVE_EXEC; 4132 else if (enmSavedState == SSMSTATE_SAVE_DONE) 4133 pSSM->enmOp = SSMSTATE_SAVE_EXEC; 4134 4135 /* 4136 * Write the unit header. 4137 */ 4138 SSMFILEUNITHDRV2 UnitHdr; 4139 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic)); 4140 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm); 4141 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm); 4142 UnitHdr.u32CRC = 0; 4143 UnitHdr.u32Version = 1; 4144 UnitHdr.u32Instance = 0; 4145 UnitHdr.u32Pass = uPass; 4146 UnitHdr.fFlags = 0; 4147 UnitHdr.cbName = sizeof("SSMLiveControl"); 4148 memcpy(&UnitHdr.szName[0], "SSMLiveControl", UnitHdr.cbName); 4149 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName])); 4150 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n", 4151 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version)); 4152 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName])); 4153 if (RT_SUCCESS(rc)) 4154 { 4155 /* 4156 * Write the payload. 4157 */ 4158 ssmR3DataWriteBegin(pSSM); 4159 4160 uint16_t u16PartsPerTenThousand = (uint16_t)(lrdPct * (100 - pSSM->uPercentDone)); 4161 AssertMsg(u16PartsPerTenThousand <= 10000, ("%u\n", u16PartsPerTenThousand)); 4162 ssmR3DataWrite(pSSM, &u16PartsPerTenThousand, sizeof(u16PartsPerTenThousand)); 4163 4164 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */ 4165 if (RT_SUCCESS(rc)) 4166 { 4167 /* 4168 * Write the termination record and flush the compression stream. 4169 */ 4170 SSMRECTERM TermRec; 4171 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM; 4172 TermRec.cbRec = sizeof(TermRec) - 2; 4173 if (pSSM->Strm.fChecksummed) 4174 { 4175 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32; 4176 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2)); 4177 } 4178 else 4179 { 4180 TermRec.fFlags = 0; 4181 TermRec.u32StreamCRC = 0; 4182 } 4183 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec); 4184 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec)); 4185 if (RT_SUCCESS(rc)) 4186 rc = ssmR3DataWriteFinish(pSSM); 4187 if (RT_SUCCESS(rc)) 4188 { 4189 pSSM->enmOp = enmSavedState; 4190 return rc; 4191 } 4192 } 4193 } 4194 4195 LogRel(("SSM: Failed to write live control unit. rc=%Rrc\n", rc)); 4196 if (RT_SUCCESS_NP(pSSM->rc)) 4197 pSSM->rc = rc; 4198 pSSM->enmOp = enmSavedState; 4199 return rc; 4200 } 4201 4202 4203 /** 4063 4204 * Do the pfnSaveDone run. 4064 4205 * … … 4338 4479 4339 4480 /** 4481 * Works the progress calculation during the exec part of a live save. 4482 * 4483 * @param pSSM The SSM handle. 4484 * @param iUnit The current unit number. 4485 */ 4486 static void ssmR3ProgressByUnit(PSSMHANDLE pSSM, uint32_t iUnit) 4487 { 4488 if (pSSM->fLiveSave) 4489 { 4490 unsigned uPctExec = iUnit * 100 / pSSM->pVM->ssm.s.cUnits; 4491 unsigned cPctExec = 100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive; 4492 long double lrdPct = (long double)uPctExec * cPctExec / 100 + pSSM->uPercentPrepare + pSSM->uPercentLive; 4493 unsigned uPct = (unsigned)lrdPct; 4494 if (uPct != pSSM->uPercent) 4495 { 4496 ssmR3LiveControlEmit(pSSM, lrdPct, SSM_PASS_FINAL); 4497 pSSM->uPercent = uPct; 4498 pSSM->pfnProgress(pSSM->pVM, uPct, pSSM->pvUser); 4499 } 4500 } 4501 } 4502 4503 4504 /** 4340 4505 * Do the pfnSaveExec run. 4341 4506 * … … 4350 4515 pSSM->rc = VINF_SUCCESS; 4351 4516 pSSM->enmOp = SSMSTATE_SAVE_EXEC; 4352 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext) 4517 unsigned iUnit = 0; 4518 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext, iUnit++) 4353 4519 { 4354 4520 /* … … 4356 4522 * make sure to keep the progress indicator up to date. 4357 4523 */ 4524 ssmR3ProgressByUnit(pSSM, iUnit); 4358 4525 pSSM->offEstUnitEnd += pUnit->cbGuess; 4359 4526 if (!pUnit->u.Common.pfnSaveExec) … … 4361 4528 pUnit->fCalled = true; 4362 4529 if (pUnit->cbGuess) 4363 ssmR3Progress (pSSM, pSSM->offEstUnitEnd - pSSM->offEst);4530 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst); 4364 4531 continue; 4365 4532 } … … 4463 4630 * Advance the progress indicator to the end of the current unit. 4464 4631 */ 4465 ssmR3Progress (pSSM, pSSM->offEstUnitEnd - pSSM->offEst);4632 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst); 4466 4633 } /* for each unit */ 4467 4634 ssmR3ProgressByUnit(pSSM, pVM->ssm.s.cUnits); 4468 4635 4469 4636 /* (progress should be pending 99% now) */ 4470 AssertMsg( pSSM->uPercent == (101 - pSSM->uPercentDone) 4471 || pSSM->fLiveSave, ("%d\n", pSSM->uPercent)); 4637 AssertMsg( pSSM->uPercent == 101 - pSSM->uPercentDone 4638 || pSSM->uPercent == 100 - pSSM->uPercentDone, 4639 ("%d\n", pSSM->uPercent)); 4472 4640 return VINF_SUCCESS; 4473 4641 } … … 4528 4696 */ 4529 4697 if (pSSM->pfnProgress) 4530 pSSM->pfnProgress(pVM, pSSM->uPercentPrepare -1, pSSM->pvUser);4531 pSSM->uPercent = pSSM->uPercentPrepare ;4698 pSSM->pfnProgress(pVM, pSSM->uPercentPrepare + pSSM->uPercentLive - 1, pSSM->pvUser); 4699 pSSM->uPercent = pSSM->uPercentPrepare + pSSM->uPercentLive; 4532 4700 4533 4701 return VINF_SUCCESS; … … 4687 4855 pSSM->offEst = 0; 4688 4856 pSSM->offEstUnitEnd = 0; 4857 pSSM->uPercentLive = 0; 4689 4858 pSSM->uPercentPrepare = 0; 4690 4859 pSSM->uPercentDone = 0; 4860 pSSM->uReportedLivePercent = 0; 4691 4861 pSSM->pszFilename = pszFilename; 4692 4862 pSSM->u.Write.offDataBuffer = 0; … … 4747 4917 if (RT_FAILURE(rc)) 4748 4918 return rc; 4919 pSSM->uPercentLive = 0; 4749 4920 pSSM->uPercentPrepare = 20; 4750 4921 pSSM->uPercentDone = 2; … … 4768 4939 4769 4940 /** 4941 * Used by PGM to report the completion percentage of the live stage during the 4942 * vote run. 4943 * 4944 * @param pSSM The saved state handle. 4945 * @param uPercent The completion percentage. 4946 */ 4947 VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent) 4948 { 4949 AssertMsgReturnVoid(pSSM->enmOp == SSMSTATE_LIVE_VOTE, ("%d\n", pSSM->enmOp)); 4950 AssertReturnVoid(uPercent <= 100); 4951 if (uPercent < pSSM->uReportedLivePercent) 4952 pSSM->uReportedLivePercent = uPercent; 4953 } 4954 4955 4956 /** 4770 4957 * Calls pfnLiveVote for all units. 4771 4958 * … … 4784 4971 pSSM->rc = VINF_SUCCESS; 4785 4972 pSSM->enmOp = SSMSTATE_LIVE_VOTE; 4973 4974 unsigned uPrevPrecent = pSSM->uReportedLivePercent; 4975 pSSM->uReportedLivePercent = 101; 4976 4786 4977 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext) 4787 4978 { … … 4837 5028 } 4838 5029 if (rcRet == VINF_SUCCESS) 5030 { 4839 5031 LogRel(("SSM: Step 1 completed after pass %u.\n", uPass)); 5032 pSSM->uReportedLivePercent = 100; 5033 } 5034 else 5035 { 5036 /* 5037 * Work the progress callback. 5038 */ 5039 if (pSSM->uReportedLivePercent > 100) 5040 pSSM->uReportedLivePercent = 0; 5041 if ( pSSM->uReportedLivePercent != uPrevPrecent 5042 && pSSM->pfnProgress 5043 && pSSM->uPercentLive) 5044 { 5045 long double lrdPct = (long double)pSSM->uReportedLivePercent * pSSM->uPercentLive / 100; 5046 unsigned uPct = (unsigned)lrdPct; 5047 if (uPct != pSSM->uPercent) 5048 { 5049 ssmR3LiveControlEmit(pSSM, lrdPct, uPass); 5050 pSSM->uPercent = uPct; 5051 pSSM->pfnProgress(pVM, uPct, pSSM->pvUser); 5052 } 5053 } 5054 } 4840 5055 return rcRet; 4841 5056 } … … 5207 5422 if (RT_FAILURE(rc)) 5208 5423 return rc; 5209 pSSM->uPercentPrepare = 20; /** @todo fix these. */ 5424 pSSM->uPercentLive = 93; 5425 pSSM->uPercentPrepare = 2; 5210 5426 pSSM->uPercentDone = 2; 5211 5427 pSSM->fLiveSave = true; … … 5302 5518 if (pcbRead) 5303 5519 *pcbRead = cbRead; 5304 ssmR3Progress (pSSM, cbRead);5520 ssmR3ProgressByByte(pSSM, cbRead); 5305 5521 return VINF_SUCCESS; 5306 5522 } … … 5415 5631 { 5416 5632 pSSM->offUnit += cbToRead; 5417 ssmR3Progress (pSSM, cbToRead);5633 ssmR3ProgressByByte(pSSM, cbToRead); 5418 5634 return VINF_SUCCESS; 5419 5635 } … … 5482 5698 { 5483 5699 pSSM->offUnit += cbCompr; 5484 ssmR3Progress (pSSM, cbCompr);5700 ssmR3ProgressByByte(pSSM, cbCompr); 5485 5701 } 5486 5702 else … … 6670 6886 * format isn't 1.1 the call will be ignored. 6671 6887 */ 6672 VMMR3_INT_DECL(int) SSMR3 SetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr)6888 VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr) 6673 6889 { 6674 6890 Assert(cbGCPtr == sizeof(RTGCPTR32) || cbGCPtr == sizeof(RTGCPTR64)); … … 7398 7614 * Initialize the handle. 7399 7615 */ 7400 pSSM->pVM = pVM; 7401 pSSM->enmOp = SSMSTATE_INVALID; 7402 pSSM->enmAfter = SSMAFTER_INVALID; 7403 pSSM->fCancelled = SSMHANDLE_OK; 7404 pSSM->rc = VINF_SUCCESS; 7405 pSSM->cbUnitLeftV1 = 0; 7406 pSSM->offUnit = UINT64_MAX; 7407 pSSM->fLiveSave = false; 7408 pSSM->pfnProgress = NULL; 7409 pSSM->pvUser = NULL; 7410 pSSM->uPercent = 0; 7411 pSSM->offEstProgress = 0; 7412 pSSM->cbEstTotal = 0; 7413 pSSM->offEst = 0; 7414 pSSM->offEstUnitEnd = 0; 7415 pSSM->uPercentPrepare = 5; 7416 pSSM->uPercentDone = 2; 7417 pSSM->pszFilename = pszFilename; 7616 pSSM->pVM = pVM; 7617 pSSM->enmOp = SSMSTATE_INVALID; 7618 pSSM->enmAfter = SSMAFTER_INVALID; 7619 pSSM->fCancelled = SSMHANDLE_OK; 7620 pSSM->rc = VINF_SUCCESS; 7621 pSSM->cbUnitLeftV1 = 0; 7622 pSSM->offUnit = UINT64_MAX; 7623 pSSM->fLiveSave = false; 7624 pSSM->pfnProgress = NULL; 7625 pSSM->pvUser = NULL; 7626 pSSM->uPercent = 0; 7627 pSSM->offEstProgress = 0; 7628 pSSM->cbEstTotal = 0; 7629 pSSM->offEst = 0; 7630 pSSM->offEstUnitEnd = 0; 7631 pSSM->uPercentLive = 0; 7632 pSSM->uPercentPrepare = 5; 7633 pSSM->uPercentDone = 2; 7634 pSSM->uReportedLivePercent = 0; 7635 pSSM->pszFilename = pszFilename; 7418 7636 7419 7637 pSSM->u.Read.pZipDecompV1 = NULL; … … 7558 7776 Log(("SSM: EndOfFile: offset %#9llx size %9d\n", offUnit, UnitHdr.cbUnit)); 7559 7777 /* Complete the progress bar (pending 99% afterwards). */ 7560 ssmR3Progress (pSSM, pSSM->cbEstTotal - pSSM->offEst);7778 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst); 7561 7779 break; 7562 7780 } … … 7652 7870 Log(("SSM: Unit '%s' left %lld bytes unread!\n", pszName, -i64Diff)); 7653 7871 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit); 7654 ssmR3Progress (pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst);7872 ssmR3ProgressByByte(pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst); 7655 7873 } 7656 7874 else if (i64Diff > 0) … … 7849 8067 */ 7850 8068 Log(("SSM: Unit at %#9llx: END UNIT\n", offUnit)); 7851 ssmR3Progress(pSSM, pSSM->cbEstTotal - pSSM->offEst); 7852 8069 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst); 7853 8070 return ssmR3LoadDirectoryAndFooter(pSSM); 7854 8071 } … … 8003 8220 ssmR3SetCancellable(pVM, &Handle, true); 8004 8221 8005 Handle.enmAfter = enmAfter; 8006 Handle.pfnProgress = pfnProgress; 8007 Handle.pvUser = pvProgressUser; 8222 Handle.enmAfter = enmAfter; 8223 Handle.pfnProgress = pfnProgress; 8224 Handle.pvUser = pvProgressUser; 8225 Handle.uPercentLive = 0; 8226 Handle.uPercentPrepare = 2; 8227 Handle.uPercentDone = 2; 8008 8228 8009 8229 if (Handle.u.Read.u16VerMajor) … … 8069 8289 } 8070 8290 8071 /* pending 2% */8291 /* end of prepare % */ 8072 8292 if (pfnProgress) 8073 pfnProgress(pVM, Handle.uPercentPrepare -1, pvProgressUser);8293 pfnProgress(pVM, Handle.uPercentPrepare - 1, pvProgressUser); 8074 8294 Handle.uPercent = Handle.uPercentPrepare; 8075 8295 Handle.cbEstTotal = Handle.u.Read.cbLoadFile; … … 8092 8312 AssertMsg( Handle.fLiveSave 8093 8313 || RT_FAILURE(rc) 8094 || Handle.uPercent == (101-Handle.uPercentDone), ("%d\n", Handle.uPercent));8314 || Handle.uPercent == 101 - Handle.uPercentDone, ("%d\n", Handle.uPercent)); 8095 8315 } 8096 8316
Note:
See TracChangeset
for help on using the changeset viewer.