VirtualBox

Changeset 37485 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 16, 2011 8:37:49 AM (14 years ago)
Author:
vboxsync
Message:

Main-CloneVM: add save state file support; multi result errors

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/MachineImpl.h

    r37449 r37485  
    841841
    842842    struct CloneVMTask;
    843     HRESULT cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const;
     843    HRESULT cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const;
    844844    settings::Snapshot cloneFindSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const;
    845845    void cloneUpdateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
    846846    void cloneUpdateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
     847    void cloneUpdateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const;
     848    static int cloneCopyStateFileProgress(unsigned uPercentage, void *pvUser);
    847849
    848850    static DECLCALLBACK(int) cloneVMThread(RTTHREAD Thread, void *pvUser);
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r37449 r37485  
    60936093    }MediumTaskChain;
    60946094    RTCList<MediumTaskChain>    llMedias;
    6095     RTCList< std::pair<Utf8Str, Utf8Str> > llSaveStateFiles; /* Snapshot UUID -> File path */
     6095    typedef struct
     6096    {
     6097        Guid                    snapshotUuid;
     6098        Utf8Str                 strSaveStateFile;
     6099        uint64_t                cbSize;
     6100    }SaveStateTask;
     6101    RTCList<SaveStateTask> llSaveStateFiles; /* Snapshot UUID -> File path */
    60966102};
    60976103
     
    61236129
    61246130        if (pTask->pSrcMachine->isSnapshotMachine())
    6125             pTask->snapshotId  = static_cast<SnapshotMachine*>((Machine*)pTask->pSrcMachine)->getSnapshotId();
     6131            pTask->snapshotId = pTask->pSrcMachine->getSnapshotId();
    61266132
    61276133        /* Add the current machine and all snapshot machines below this machine
    61286134         * in a list for further processing. */
    6129         RTCList< ComPtr<IMachine> > machineList;
     6135        RTCList< ComObjPtr<Machine> > machineList;
    61306136
    61316137        /* Include current state? */
    6132         if (   pTask->mode == CloneMode_MachineState
    6133             || pTask->mode == CloneMode_AllStates)
    6134             machineList.append(static_cast< ComPtr<IMachine> >(pTask->pSrcMachine));
     6138        if (   pTask->mode == CloneMode_MachineState)
     6139//            || pTask->mode == CloneMode_AllStates)
     6140            machineList.append(pTask->pSrcMachine);
    61356141        /* Should be done a depth copy with all child snapshots? */
    61366142        if (   pTask->mode == CloneMode_MachineAndChildStates
     
    61616167        for (size_t i = 0; i < machineList.size(); ++i)
    61626168        {
     6169            ComObjPtr<Machine> machine = machineList.at(i);
    61636170            /* If this is the Snapshot Machine we want to clone, we need to
    61646171             * create a new diff file for the new "current state". */
    61656172            bool fCreateDiffs = false;
    6166             if (machineList.at(i) == pTask->pOldMachineState)
     6173            if (machine == pTask->pOldMachineState)
    61676174                fCreateDiffs = true;
    61686175            SafeIfaceArray<IMediumAttachment> sfaAttachments;
    6169             rc = machineList.at(i)->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
     6176            rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
    61706177            if (FAILED(rc)) throw rc;
    61716178            /* Add all attachments (and there parents) of the different
     
    62206227                pTask->llMedias.append(mtc);
    62216228            }
    6222             /* Todo: If this machine has save state files, they have to be copied as well. */
    6223 //            Bstr bstrSrcSaveStatePath;
    6224 //            rc = machineList.at(i)->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam());
    6225 //            if (FAILED(rc)) throw rc;
    6226 //            if (!bstrSrcSaveStatePath.isEmpty())
    6227 //                pTask->llSaveStates.append(bstrSrcSaveStatePath);
     6229            Bstr bstrSrcSaveStatePath;
     6230            rc = machine->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam());
     6231            if (FAILED(rc)) throw rc;
     6232            if (!bstrSrcSaveStatePath.isEmpty())
     6233            {
     6234                Machine::CloneVMTask::SaveStateTask sst;
     6235                sst.snapshotUuid     = machine->getSnapshotId();
     6236                sst.strSaveStateFile = bstrSrcSaveStatePath;
     6237                int vrc = RTFileQuerySize(sst.strSaveStateFile.c_str(), &sst.cbSize);
     6238                if (RT_FAILURE(vrc))
     6239                    throw setError(VBOX_E_IPRT_ERROR, tr("Could not query file size of '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), vrc);
     6240                pTask->llSaveStateFiles.append(sst);
     6241                ++uCount;
     6242                uTotalWeight += sst.cbSize;
     6243            }
    62286244        }
    62296245
     
    62486264                                 "MachineClone");
    62496265        if (RT_FAILURE(vrc))
    6250             throw setError(E_FAIL, "Could not create Machine clone thread (%Rrc)", vrc);
     6266            throw setError(VBOX_E_IPRT_ERROR, "Could not create machine clone thread (%Rrc)", vrc);
    62516267    }
    62526268    catch (HRESULT rc2)
     
    62936309}
    62946310
    6295 HRESULT Machine::cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const
     6311HRESULT Machine::cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const
    62966312{
    62976313    HRESULT rc = S_OK;
     
    63036319    rc = pSnapshot->COMGETTER(Machine)(pMachine.asOutParam());
    63046320    if (FAILED(rc)) return rc;
    6305     machineList.append(pMachine);
     6321    machineList.append((Machine*)(IMachine*)pMachine);
    63066322
    63076323    SafeIfaceArray<ISnapshot> sfaChilds;
     
    63636379            cloneUpdateSnapshotStorageLists(it->llChildSnapshots, bstrOldId, bstrNewId);
    63646380    }
     6381}
     6382
     6383void Machine::cloneUpdateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const
     6384{
     6385    settings::SnapshotsList::iterator it;
     6386    for (it = snl.begin(); it != snl.end(); ++it)
     6387    {
     6388        if (it->uuid == id)
     6389            it->strStateFile = strFile;
     6390        else if (!it->llChildSnapshots.empty())
     6391            cloneUpdateStateFile(it->llChildSnapshots, id, strFile);
     6392    }
     6393}
     6394
     6395/* static */
     6396int Machine::cloneCopyStateFileProgress(unsigned uPercentage, void *pvUser)
     6397{
     6398    ComObjPtr<Progress> pProgress = *static_cast< ComObjPtr<Progress>* >(pvUser);
     6399
     6400    BOOL fCanceled = false;
     6401    HRESULT rc = pProgress->COMGETTER(Canceled)(&fCanceled);
     6402    if (FAILED(rc)) return VERR_GENERAL_FAILURE;
     6403    /* If canceled by the user tell it to the copy operation. */
     6404    if (fCanceled) return VERR_CANCELLED;
     6405    /* Set the new process. */
     6406    RTPrintf("stat %d %%\n", uPercentage);
     6407    rc = pProgress->SetCurrentOperationProgress(uPercentage);
     6408    if (FAILED(rc)) return VERR_GENERAL_FAILURE;
     6409
     6410    return VINF_SUCCESS;
    63656411}
    63666412
     
    63786424    AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS);
    63796425
    6380     HRESULT rc = S_OK;
     6426    MultiResult rc = S_OK;
    63816427
    63826428    /*
     
    63966442
    63976443    RTCList< ComObjPtr<Medium> > newMedias; /* All created images */
     6444    RTCList<Utf8Str> newFiles;              /* All extra created files (save states, ...) */
    63986445    try
    63996446    {
     
    64366483        }
    64376484
    6438         /* Reset the snapshot folder to 'Snapshots' within the target directory.
    6439          * Todo: Not sure if this is what we want. */
    6440         pTrgMCF->machineUserData.strSnapshotFolder = "Snapshots";
     6485        /* When the current snapshot folder is absolute we reset it to the
     6486         * default relative folder. */
     6487        if (RTPathStartsWithRoot(pTrgMCF->machineUserData.strSnapshotFolder.c_str()))
     6488            pTrgMCF->machineUserData.strSnapshotFolder = "Snapshots";
    64416489        pTrgMCF->strStateFile = "";
    64426490        /* Force writing of setting file. */
     
    64466494        pTrgMCF->uuid = pTask->pTrgMachine->mData->mUuid;
    64476495
     6496        Bstr bstrSrcSnapshotFolder;
     6497        rc = pTask->pSrcMachine->COMGETTER(SnapshotFolder)(bstrSrcSnapshotFolder.asOutParam());
     6498        if (FAILED(rc)) throw rc;
    64486499        /* The absolute name of the snapshot folder. */
    64496500        Utf8Str strTrgSnapshotFolder = Utf8StrFmt("%s%c%s%c", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, pTrgMCF->machineUserData.strSnapshotFolder.c_str(), RTPATH_DELIMITER);
     
    65936644            cloneUpdateSnapshotStorageLists(pTrgMCF->llFirstSnapshot, bstrSrcId, bstrTrgId);
    65946645        }
    6595         /* Todo: Clone all save state files. */
    6596 //        for (size_t i = 0; i < pTask->llSaveStates.size(); ++i)
    6597 //        {
    6598 //            RTPrintf("save state: %s\n", pTask->llSaveStates.at(i).c_str());
    6599 //            RTFileCopy(llSaveStates.at(i).c_str(),);
    6600 //        }
     6646        /* Clone all save state files. */
     6647        for (size_t i = 0; i < pTask->llSaveStateFiles.size(); ++i)
     6648        {
     6649            Machine::CloneVMTask::SaveStateTask sst = pTask->llSaveStateFiles.at(i);
     6650            const Utf8Str &strTrgSaveState = Utf8StrFmt("%s%s", strTrgSnapshotFolder.c_str(), RTPathFilename(sst.strSaveStateFile.c_str()));
     6651
     6652            /* Move to next sub-operation. */
     6653            rc = pTask->pProgress->SetNextOperation(BstrFmt(tr("Copy save state file '%s' ..."), RTPathFilename(sst.strSaveStateFile.c_str())).raw(), sst.cbSize);
     6654            if (FAILED(rc)) throw rc;
     6655            /* Copy the file only if it was not copied already. */
     6656            if (!newFiles.contains(strTrgSaveState.c_str()))
     6657            {
     6658                int vrc = RTFileCopyEx(sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), 0, cloneCopyStateFileProgress, &pTask->pProgress);
     6659                if (RT_FAILURE(vrc))
     6660                    throw setError(VBOX_E_IPRT_ERROR,
     6661                                   tr("Could not copy state file '%s' to '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), vrc);
     6662                newFiles.append(strTrgSaveState);
     6663            }
     6664            /* Update the path in the configuration either for the current
     6665             * machine state or the snapshots. */
     6666            if (sst.snapshotUuid.isEmpty())
     6667                pTrgMCF->strStateFile = strTrgSaveState;
     6668            else
     6669                cloneUpdateStateFile(pTrgMCF->llFirstSnapshot, sst.snapshotUuid, strTrgSaveState);
     6670        }
    66016671
    66026672        if (false)
     
    66916761    if (FAILED(rc))
    66926762    {
     6763        int vrc = VINF_SUCCESS;
     6764        /* Delete all created files. */
     6765        for (size_t i = 0; i < newFiles.size(); ++i)
     6766        {
     6767            vrc = RTFileDelete(newFiles.at(i).c_str());
     6768            if (RT_FAILURE(vrc))
     6769                rc = setError(VBOX_E_IPRT_ERROR, tr("Could not delete file '%s' (%Rrc)"), newFiles.at(i).c_str(), vrc);
     6770        }
    66936771        /* Delete all already created medias. (Reverse, cause there could be
    66946772         * parent->child relations.) */
     
    66976775            ComObjPtr<Medium> &pMedium = newMedias.at(i - 1);
    66986776            AutoCaller mac(pMedium);
    6699             if (FAILED(mac.rc())) return mac.rc();
     6777            if (FAILED(mac.rc())) { continue; rc = mac.rc(); }
    67006778            AutoReadLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
    67016779            bool fFile = pMedium->isMediumFormatFile();
     
    67046782            /* Close the medium. If this succeed, delete it finally from the
    67056783             * disk. */
    6706             HRESULT rc1 = pMedium->close(NULL, mac);
    6707             if (   SUCCEEDED(rc1)
    6708                 && fFile)
    6709                 RTFileDelete(strLoc.c_str());
     6784            rc = pMedium->close(NULL, mac);
     6785            if (FAILED(rc)) continue;
     6786            if (fFile)
     6787            {
     6788                vrc = RTFileDelete(strLoc.c_str());
     6789                if (RT_FAILURE(vrc))
     6790                    rc = setError(VBOX_E_IPRT_ERROR, tr("Could not delete file '%s' (%Rrc)"), strLoc.c_str(), vrc);
     6791            }
    67106792        }
    67116793        /* Delete the machine folder when not empty. */
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