VirtualBox

Changeset 14272 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Nov 18, 2008 12:22:15 AM (16 years ago)
Author:
vboxsync
Message:

Main: HardDisk2: Fixed opening VMDK images for the first time. Made the implicit diff creatoin routine use the default backend extension. Improved setLocation() to distinguish between file and non-file locations according to the backend capability.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/HardDisk2Impl.cpp

    r14225 r14272  
    2222#include "HardDisk2Impl.h"
    2323
    24 #include "VirtualBoxImpl.h"
    2524#include "ProgressImpl.h"
    2625#include "SystemPropertiesImpl.h"
     
    492491    m.state = MediaState_NotCreated;
    493492
     493    /* No storage unit is created yet, no need to queryInfo() */
     494
     495    rc = setFormat (aFormat);
     496    CheckComRCReturnRC (rc);
     497
    494498    rc = setLocation (aLocation);
    495499    CheckComRCReturnRC (rc);
    496 
    497     /* No storage unit is created yet, no need to queryInfo() */
    498 
    499     /// @todo NEWMEDIA check the format ID is valid
    500     unconst (mm.format) = aFormat;
    501500
    502501    /* Confirm a successful initialization when it's the case */
     
    553552            rc = setError (E_FAIL, Utf8Str (m.lastAccessError));
    554553        }
    555     }
    556 
    557     /* storage format must be detected by queryInfo() if the medium is
    558      * accessible */
    559     AssertReturn (m.state == MediaState_Inaccessible ||
    560                   (!m.id.isEmpty() && !mm.format.isNull()),
    561                   E_FAIL);
     554
     555        /* storage format must be detected by queryInfo() if the medium is
     556         * accessible */
     557        AssertReturn (!m.id.isEmpty() && !mm.format.isNull(), E_FAIL);
     558    }
    562559
    563560    /* Confirm a successful initialization when it's the case */
     
    613610    /* required */
    614611    unconst (m.id) = aNode.value <Guid> ("uuid");
     612
     613    /* optional */
     614    {
     615        settings::Key descNode = aNode.findKey ("Description");
     616        if (!descNode.isNull())
     617            m.description = descNode.keyStringValue();
     618    }
     619
     620    /* required */
     621    Bstr format = aNode.stringValue ("format");
     622    AssertReturn (!format.isNull(), E_FAIL);
     623    rc = setFormat (format);
     624    CheckComRCReturnRC (rc);
     625
    615626    /* required */
    616627    Bstr location = aNode.stringValue ("location");
    617628    rc = setLocation (location);
    618629    CheckComRCReturnRC (rc);
    619     /* optional */
    620     {
    621         settings::Key descNode = aNode.findKey ("Description");
    622         if (!descNode.isNull())
    623             m.description = descNode.keyStringValue();
    624     }
    625 
    626     /* required */
    627     unconst (mm.format) = aNode.stringValue ("format");
    628     AssertReturn (!mm.format.isNull(), E_FAIL);
    629 
    630     /* only for base hard disks */
     630
     631    /* type is only for base hard disks */
    631632    if (mParent.isNull())
    632633    {
     
    691692        return;
    692693
     694    if (!mm.formatObj.isNull())
     695    {
     696        /* remove the caller reference we added in setFormat() */
     697        mm.formatObj->releaseCaller();
     698        mm.formatObj.setNull();
     699    }
     700
    693701    if (m.state == MediaState_Deleting)
    694702    {
     
    13111319    /// @todo NEWMEDIA delegate the comparison to the backend?
    13121320
    1313     if (isFileLocation (locationFull))
     1321    if (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File)
    13141322    {
    13151323        Utf8Str location (aLocation);
     
    13561364    return name;
    13571365}
     1366
     1367/// @todo NEWMEDIA remove, should not need anymore
     1368#if 0
    13581369
    13591370/**
     
    13981409    return true;
    13991410}
     1411
     1412#endif /* if 0 */
    14001413
    14011414/**
     
    16691682
    16701683    /* check that our own format supports diffs */
    1671 
    1672     /* lock system properties now to make the format check atomic with
    1673      * defaultHardDiskFormat() */
    1674     AutoReadLock propsLock (mVirtualBox->systemProperties());
    1675 
    1676     ComObjPtr <HardDiskFormat> formatObj =
    1677         mVirtualBox->systemProperties()->hardDiskFormat (format);
    1678     AssertReturn (!formatObj.isNull(), format);
    1679 
    1680     if (!(formatObj->capabilities() & HardDiskFormatCapabilities_Differencing))
     1684    if (!(mm.formatObj->capabilities() & HardDiskFormatCapabilities_Differencing))
     1685    {
     1686        /* use the default format if not */
     1687        AutoReadLock propsLock (mVirtualBox->systemProperties());
    16811688        format = mVirtualBox->systemProperties()->defaultHardDiskFormat();
     1689    }
    16821690
    16831691    return format;
     
    22432251        return E_INVALIDARG;
    22442252
    2245     /// @todo NEWMEDIA treat non-FS-paths specially! (may require to request
    2246     /// this information from the VD backend)
    2247 
    2248     Utf8Str location (aLocation);
    2249 
    2250     Guid id;
    2251 
    2252     if (RTPathFilename (location) == NULL)
    2253     {
    2254         /* no file name is given (either an empty string or ends with a slash),
    2255          * generate a new UUID + file name if the state allows this */
     2253    AutoCaller autoCaller (this);
     2254    AssertComRCReturnRC (autoCaller.rc());
     2255
     2256    /* formatObj may be null only when initializing from an existing path and
     2257     * no format is known yet */
     2258    AssertReturn ((!mm.format.isNull() && !mm.formatObj.isNull()) ||
     2259                  (autoCaller.state() == InInit &&
     2260                   m.state != MediaState_NotCreated && m.id.isEmpty() &&
     2261                   mm.format.isNull() && mm.formatObj.isNull()),
     2262                  E_FAIL);
     2263
     2264    /* are we dealing with a hard disk opened from the existing path? */
     2265    bool isNew = mm.format.isNull();
     2266
     2267    if (isNew ||
     2268        (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File))
     2269    {
     2270        Guid id;
     2271
     2272        Utf8Str location (aLocation);
    22562273
    22572274        if (m.state == MediaState_NotCreated)
    22582275        {
    2259             id.create();
    2260 
    2261             /// @todo NEWMEDIA use the default extension for the given VD backend
    2262             location = Utf8StrFmt ("%s{%RTuuid}.vdi", location.raw(), id.raw());
     2276            /* must be a file (formatObj must be already known) */
     2277            Assert (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File);
     2278
     2279            if (RTPathFilename (location) == NULL)
     2280            {
     2281                /* no file name is given (either an empty string or ends with a
     2282                 * slash), generate a new UUID + file name if the state allows
     2283                 * this */
     2284
     2285                ComAssertMsgRet (!mm.formatObj->fileExtensions().empty(),
     2286                                 ("Must be at least one extension if it is "
     2287                                  "HardDiskFormatCapabilities_File\n"),
     2288                                 E_FAIL);
     2289
     2290                Bstr ext = mm.formatObj->fileExtensions().front();
     2291                ComAssertMsgRet (!ext.isEmpty(),
     2292                                 ("Default extension must not be empty\n"),
     2293                                 E_FAIL);
     2294
     2295                id.create();
     2296
     2297                location = Utf8StrFmt ("%s{%RTuuid}.%ls",
     2298                                       location.raw(), id.raw(), ext.raw());
     2299            }
     2300        }
     2301
     2302        /* append the default folder if no path is given */
     2303        if (!RTPathHavePath (location))
     2304        {
     2305            AutoReadLock propsLock (mVirtualBox->systemProperties());
     2306            location = Utf8StrFmt ("%ls%c%s",
     2307                mVirtualBox->systemProperties()->defaultHardDiskFolder().raw(),
     2308                RTPATH_DELIMITER,
     2309                location.raw());
     2310        }
     2311
     2312        /* get the full file name */
     2313        Utf8Str locationFull;
     2314        int vrc = mVirtualBox->calculateFullPath (location, locationFull);
     2315        if (RT_FAILURE (vrc))
     2316            return setError (E_FAIL,
     2317                tr ("Invalid hard disk storage file location '%s' (%Rrc)"),
     2318                location.raw(), vrc);
     2319
     2320        /* detect the backend from the storage unit if new */
     2321        if (isNew)
     2322        {
     2323            char *backendName = NULL;
     2324
     2325            /* is it a file? */
     2326            {
     2327                RTFILE file;
     2328                vrc = RTFileOpen (&file, locationFull, RTFILE_O_READ);
     2329                if (RT_SUCCESS (vrc))
     2330                    RTFileClose (file);
     2331            }
     2332            if (RT_SUCCESS (vrc))
     2333            {
     2334                vrc = VDGetFormat (locationFull, &backendName);
     2335            }
     2336            else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND)
     2337            {
     2338                /* assume it's not a file, restore the original location */
     2339                location = locationFull = aLocation;
     2340                vrc = VDGetFormat (locationFull, &backendName);
     2341            }
     2342
     2343            if (RT_FAILURE (vrc))
     2344                return setError (E_FAIL,
     2345                    tr ("Could not get the storage format of the hard disk "
     2346                        "'%s' (%Rrc)"), locationFull.raw(), vrc);
     2347
     2348            ComAssertRet (backendName != NULL && *backendName != '\0', E_FAIL);
     2349
     2350            HRESULT rc = setFormat (Bstr (backendName));
     2351            RTStrFree (backendName);
     2352
     2353            /* setFormat() must not fail since we've just used the backend so
     2354             * the format object must be there */
     2355            AssertComRCReturnRC (rc);
     2356        }
     2357
     2358        /* is it still a file? */
     2359        if (mm.formatObj->capabilities() & HardDiskFormatCapabilities_File)
     2360        {
     2361            m.location = location;
     2362            m.locationFull = locationFull;
     2363
     2364            /* assign a new UUID if we generated it */
     2365            if (!id.isEmpty())
     2366                unconst (m.id) = id;
    22632367        }
    22642368        else
    22652369        {
    2266             /* it's an error to not have a file name :) */
     2370            m.location = locationFull;
     2371            m.locationFull = locationFull;
     2372        }
     2373    }
     2374    else
     2375    {
     2376        m.location = aLocation;
     2377        m.locationFull = aLocation;
     2378    }
     2379
     2380    return S_OK;
     2381}
     2382
     2383/**
     2384 * Checks that the format ID is valid and sets it on success.
     2385 *
     2386 * Note that this method will caller-reference the format object on success!
     2387 * This reference must be released somewhere to let the HardDiskFormat object be
     2388 * uninitialized.
     2389 *
     2390 * @note Must be called from under this object's write lock.
     2391 */
     2392HRESULT HardDisk2::setFormat (const BSTR aFormat)
     2393{
     2394    /* get the format object first */
     2395    {
     2396        AutoReadLock propsLock (mVirtualBox->systemProperties());
     2397
     2398        unconst (mm.formatObj)
     2399            = mVirtualBox->systemProperties()->hardDiskFormat (aFormat);
     2400        if (mm.formatObj.isNull())
    22672401            return setError (E_FAIL,
    2268                 tr ("Hard disk storage file location '%s' does not contain "
    2269                     "a file name"),
    2270                 location.raw());
    2271         }
    2272     }
    2273 
    2274     /* append the default folder if no path is given */
    2275     if (!RTPathHavePath (location))
    2276     {
    2277         AutoReadLock propsLock (mVirtualBox->systemProperties());
    2278         location = Utf8StrFmt ("%ls%c%s",
    2279             mVirtualBox->systemProperties()->defaultHardDiskFolder().raw(),
    2280             RTPATH_DELIMITER,
    2281             location.raw());
    2282     }
    2283 
    2284     /* get the full file name */
    2285     Utf8Str locationFull;
    2286     int vrc = mVirtualBox->calculateFullPath (location, locationFull);
    2287     if (RT_FAILURE (vrc))
    2288         return setError (E_FAIL,
    2289             tr ("Invalid hard disk storage file location '%s' (%Rrc)"),
    2290             location.raw(), vrc);
    2291 
    2292     m.location = location;
    2293     m.locationFull = locationFull;
    2294 
    2295     /* assign a new UUID if we generated it */
    2296     if (!id.isEmpty())
    2297         unconst (m.id) = id;
     2402                tr ("Invalid hard disk storage format '%ls'"), aFormat);
     2403
     2404        /* reference the format permanently to prevent its unexpected
     2405         * uninitialization */
     2406        HRESULT rc = mm.formatObj->addCaller();
     2407        AssertComRCReturnRC (rc);
     2408    }
     2409
     2410    unconst (mm.format) = aFormat;
    22982411
    22992412    return S_OK;
    23002413}
     2414
    23012415/**
    23022416 * Queries information from the image file.
     
    23812495        Utf8Str location (m.locationFull);
    23822496
    2383         /* are we dealing with an unknown (just opened) image? */
    2384         bool isNew = mm.format.isNull();
    2385 
    2386         if (isNew)
    2387         {
    2388             /* detect the backend from the storage unit */
    2389             char *backendName = NULL;
    2390             vrc = VDGetFormat (location, &backendName);
    2391             if (RT_FAILURE (vrc))
    2392             {
    2393                 lastAccessError = Utf8StrFmt (
    2394                     tr ("Could not get the storage format of the hard disk "
    2395                         "'%ls'%s"), m.locationFull.raw(), vdError (vrc).raw());
    2396                 throw S_OK;
    2397             }
    2398 
    2399             ComAssertThrow (backendName != NULL, E_FAIL);
    2400 
    2401             unconst (mm.format) = backendName;
    2402             RTStrFree (backendName);
    2403         }
     2497        /* are we dealing with a hard disk opened from the existing path? */
     2498        bool isNew = m.id.isEmpty();
    24042499
    24052500        PVBOXHDD hdd;
     
    24092504        try
    24102505        {
    2411             vrc = VDOpen (hdd, Utf8Str (mm.format), location,
    2412                           VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO,
    2413                           NULL);
     2506            unsigned flags = VD_OPEN_FLAGS_INFO;
     2507
     2508            /* Note that we don't use VD_OPEN_FLAGS_READONLY when opening new
     2509             * hard disks because that would prevent necessary modifications
     2510             * when opening hard disks of some third-party formats for the first
     2511             * time in VirtualBox (such as VMDK for which VDOpen() needs to
     2512             * generate an UUID if it is missing) */
     2513            if (!isNew)
     2514                flags |= VD_OPEN_FLAGS_READONLY;
     2515
     2516            vrc = VDOpen (hdd, Utf8Str (mm.format), location, flags, NULL);
    24142517            if (RT_FAILURE (vrc))
    24152518            {
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r14224 r14272  
    247247            CheckComRCThrowRC (rc);
    248248
    249             /* create the system properties object */
     249            /* create the system properties object, someone may need it too */
    250250            unconst (mData.mSystemProperties).createObject();
    251251            rc = mData.mSystemProperties->init (this);
     
    375375    }
    376376
    377     if (mData.mSystemProperties)
    378     {
    379         mData.mSystemProperties->uninit();
    380         unconst (mData.mSystemProperties).setNull();
    381     }
    382 
    383     if (mData.mHost)
    384     {
    385         mData.mHost->uninit();
    386         unconst (mData.mHost).setNull();
    387     }
    388 
    389 #ifdef VBOX_WITH_RESOURCE_USAGE_API
    390     if (mData.mPerformanceCollector)
    391     {
    392         mData.mPerformanceCollector->uninit();
    393         unconst (mData.mPerformanceCollector).setNull();
    394     }
    395 #endif /* VBOX_WITH_RESOURCE_USAGE_API */
    396 
    397377    /* Uninit all other children still referenced by clients (unregistered
    398378     * machines, hard disks, DVD/floppy images, server-side progress
     
    409389
    410390    mData.mGuestOSTypes.clear();
     391
     392    /* Note that we release singleton children after we've all other children.
     393     * In some cases this is important because these other children may use
     394     * some resources of the singletons which would prevent them from
     395     * uninitializing (as for example, mSystemProperties which owns
     396     * HardDiskFormat objects which HardDisk2 objects refer to) */
     397    if (mData.mSystemProperties)
     398    {
     399        mData.mSystemProperties->uninit();
     400        unconst (mData.mSystemProperties).setNull();
     401    }
     402
     403    if (mData.mHost)
     404    {
     405        mData.mHost->uninit();
     406        unconst (mData.mHost).setNull();
     407    }
     408
     409#ifdef VBOX_WITH_RESOURCE_USAGE_API
     410    if (mData.mPerformanceCollector)
     411    {
     412        mData.mPerformanceCollector->uninit();
     413        unconst (mData.mPerformanceCollector).setNull();
     414    }
     415#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    411416
    412417    /* unlock the config file */
  • trunk/src/VBox/Main/include/HardDisk2Impl.h

    r14225 r14272  
    2828
    2929#include "VirtualBoxImpl.h"
     30#include "HardDiskFormatImpl.h"
    3031#include "MediumImpl.h"
    3132
     
    174175    Utf8Str name();
    175176
    176     static bool isFileLocation (const char *aLocation);
    177 
    178177    HRESULT prepareDiscard (MergeChain * &aChain);
    179178    HRESULT discard (ComObjPtr <Progress> &aProgress, MergeChain *aChain);
     
    225224
    226225    HRESULT setLocation (const BSTR aLocation);
     226    HRESULT setFormat (const BSTR aFormat);
     227
    227228    HRESULT queryInfo();
    228229
     
    256257
    257258        const Bstr format;
     259        ComObjPtr <HardDiskFormat> formatObj;
    258260
    259261        HardDiskType_T type;
  • trunk/src/VBox/Main/include/HardDiskFormatImpl.h

    r14225 r14272  
    3333struct VDBACKENDINFO;
    3434
     35/**
     36 * The HardDiskFormat class represents the backend used to store hard disk data
     37 * (IHardDiskFormat interface).
     38 *
     39 * @note Instances of this class are permanently caller-referenced by HardDisk2
     40 * objects (through addCaller()) so that an attempt to uninitialize or delete
     41 * them before all HardDisk2 objects are uninitialized will produce an endless
     42 * wait!
     43 */
    3544class ATL_NO_VTABLE HardDiskFormat :
    3645    public VirtualBoxBaseNEXT,
     
    4049{
    4150public:
     51
     52    struct Property
     53    {
     54        Bstr name;
     55        Bstr description;
     56        DataType_T type;
     57        ULONG flags;
     58        Bstr defaultValue;
     59    };
     60
     61    typedef std::list <Bstr> BstrList;
     62    typedef std::list <Property> PropertyList;
     63
     64    struct Data
     65    {
     66        Data() : capabilities (0) {}
     67
     68        const Bstr id;
     69        const Bstr name;
     70        const BstrList fileExtensions;
     71        const uint64_t capabilities;
     72        const PropertyList properties;
     73    };
    4274
    4375    VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (HardDiskFormat)
     
    84116    const Bstr &id() { return m.id; }
    85117    /** Const, no need to lock */
     118    const BstrList &fileExtensions() { return m.fileExtensions; }
     119    /** Const, no need to lock */
    86120    uint64_t capabilities() { return m.capabilities; }
    87121
     
    91125private:
    92126
    93     typedef std::list <Bstr> BstrList;
    94 
    95     struct Property
    96     {
    97         Bstr name;
    98         Bstr description;
    99         DataType_T type;
    100         ULONG flags;
    101         Bstr defaultValue;
    102     };
    103     typedef std::list <Property> PropertyList;
    104 
    105     struct Data
    106     {
    107         Data() : capabilities (0) {}
    108 
    109         const Bstr id;
    110         const Bstr name;
    111         const BstrList fileExtensions;
    112         const uint64_t capabilities;
    113         const PropertyList properties;
    114     };
    115 
    116127    Data m;
    117128};
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