VirtualBox

Changeset 13713 in vbox


Ignore:
Timestamp:
Oct 31, 2008 1:35:03 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38680
Message:

Main: #3276: Simplified suspend/resume event handling in VBoxSVC.

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

Legend:

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

    r13706 r13713  
    2929#include "Logging.h"
    3030
    31 HostPowerService::HostPowerService(VirtualBox *aVirtualBox) : aMachineSuspended(NULL), cbMachineSuspended(0)
     31HostPowerService::HostPowerService (VirtualBox *aVirtualBox)
    3232{
     33    Assert (aVirtualBox != NULL);
    3334    mVirtualBox = aVirtualBox;
    3435}
     
    3839}
    3940
    40 
    41 void HostPowerService::notify(HostPowerEvent event)
     41void HostPowerService::notify (HostPowerEvent aEvent)
    4242{
    4343    VirtualBox::SessionMachineVector machines;
    44     mVirtualBox->getOpenedMachines (machines);
     44    VirtualBox::InternalControlVector controls;
    4545
    46     switch (event)
     46    HRESULT rc = S_OK;
     47
     48    switch (aEvent)
    4749    {
    48     case HostPowerEvent_Suspend:
    49         if (machines.size())
    50             aMachineSuspended = (BOOL *)RTMemAllocZ(sizeof(BOOL) * machines.size());
     50        case HostPowerEvent_Suspend:
     51        {
     52            LogFunc (("SUSPEND\n"));
    5153
    52         cbMachineSuspended = machines.size();
     54            mVirtualBox->getOpenedMachinesAndControls (machines, controls);
    5355
    54         for (size_t i = 0; i < machines.size(); i++)
    55             processEvent(machines[i], HostPowerEvent_Suspend, (aMachineSuspended) ? &aMachineSuspended[i] : NULL);
     56            /* pause running VMs */
     57            for (size_t i = 0; i < controls.size(); ++ i)
     58            {
     59                /* get the remote console */
     60                ComPtr <IConsole> console;
     61                rc = controls [i]->GetRemoteConsole (console.asOutParam());
     62                /* the VM could have been powered down and closed or whatever */
     63                if (FAILED (rc))
     64                    continue;
    5665
    57         Log(("HostPowerService::notify SUSPEND\n"));
    58         break;
     66                /* note that Pause() will simply return a failure if the VM is
     67                 * in an inappropriate state */
     68                rc = console->Pause();
     69                if (FAILED (rc))
     70                    continue;
    5971
    60     case HostPowerEvent_Resume:
    61         Log(("HostPowerService::notify RESUME\n"));
     72                /* save the control to un-pause the VM later */
     73                mConsoles.push_back (console);
     74            }
    6275
    63         if (aMachineSuspended)
    64         {
    65             /* It's possible (in theory) that machines are created or destroyed between the suspend notification and the actual host suspend.
    66              * Ignore this edge case and just make sure not to access invalid data.
    67              */
    68             cbMachineSuspended = RT_MIN(machines.size(), cbMachineSuspended);
     76            LogFunc (("Suspended %d VMs\n", mConsoles.size()));
    6977
    70             for (size_t i = 0; i < cbMachineSuspended; i++)
    71                 processEvent(machines[i], HostPowerEvent_Resume, &aMachineSuspended[i]);
    72 
    73             RTMemFree(aMachineSuspended);
    74             cbMachineSuspended = 0;
    75             aMachineSuspended  = NULL;
    76         }
    77         break;
    78 
    79     case HostPowerEvent_BatteryLow:
    80         Log(("HostPowerService::notify BATTERY LOW\n"));
    81         for (size_t i = 0; i < machines.size(); i++)
    82             processEvent(machines[i], HostPowerEvent_BatteryLow, NULL);
    83         break;
    84     }
    85 
    86     machines.clear();
    87 }
    88 
    89 HRESULT HostPowerService::processEvent(SessionMachine *machine, HostPowerEvent event, BOOL *pMachineSuspended)
    90 {
    91     MachineState_T state;
    92     HRESULT        rc;
    93 
    94     rc = machine->COMGETTER(State)(&state);
    95     CheckComRCReturnRC (rc);
    96 
    97     /* Power event handling:
    98      * - pause running machines for HostPowerEvent_Suspend
    99      * - resume paused machines for HostPowerEvent_Resume
    100      * - save the state of running and paused machine for HostPowerEvent_BatteryLow
    101      */
    102     if (    (state == MachineState_Running && event != HostPowerEvent_Resume)
    103         ||  (state == MachineState_Paused  && event != HostPowerEvent_Suspend))
    104     {
    105         ComPtr <ISession> session;
    106 
    107         rc = session.createInprocObject (CLSID_Session);
    108         if (FAILED (rc))
    109             return rc;
    110 
    111         /* get the IInternalSessionControl interface */
    112         ComPtr <IInternalSessionControl> control = session;
    113         if (!control)
    114         {
    115             rc = E_INVALIDARG;
    116             goto fail;
     78            break;
    11779        }
    11880
    119         rc = machine->openExistingSession (control);
    120         if (SUCCEEDED (rc))
     81        case HostPowerEvent_Resume:
    12182        {
    122             /* get the associated console */
    123             ComPtr<IConsole> console;
    124             rc = session->COMGETTER(Console)(console.asOutParam());
    125             if (SUCCEEDED (rc))
     83            LogFunc (("RESUME\n"));
     84
     85            size_t resumed = 0;
     86
     87            /* go through VMs we paused on Suspend */
     88            for (size_t i = 0; i < mConsoles.size(); ++ i)
    12689            {
    127                 switch (event)
    128                 {
    129                 case HostPowerEvent_Suspend:
    130                     rc = console->Pause();
    131                     if (    SUCCEEDED(rc)
    132                         &&  pMachineSuspended)
    133                         *pMachineSuspended = TRUE;
    134                     break;
     90                /* note that Resume() will simply return a failure if the VM is
     91                 * in an inappropriate state (it will also fail if the VM has
     92                 * been somehow closed by this time already so that the
     93                 * console reference we have is dead) */
     94                rc = mConsoles [i]->Resume();
     95                if (FAILED (rc))
     96                    continue;
    13597
    136                 case HostPowerEvent_Resume:
    137                     Assert(pMachineSuspended);
    138                     if (*pMachineSuspended == TRUE)
    139                         rc = console->Resume();
    140                     break;
     98                ++ resumed;
     99            }
    141100
    142                 case HostPowerEvent_BatteryLow:
    143                 {
    144                     ComPtr<IProgress> progress;
     101            LogFunc (("Resumed %d VMs\n", resumed));
    145102
    146                     rc = console->SaveState(progress.asOutParam());
    147                     if (SUCCEEDED(rc))
    148                     {
    149                         /* Wait until the operation has been completed. */
    150                         progress->WaitForCompletion(-1);
     103            mConsoles.clear();
    151104
    152                         progress->COMGETTER(ResultCode)(&rc);
    153                         AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %x\n", rc));
    154                     }
     105            break;
     106        }
    155107
    156                     break;
    157                 }
     108        case HostPowerEvent_BatteryLow:
     109        {
     110            LogFunc (("BATTERY LOW\n"));
    158111
    159                 } /* switch (event) */
     112            mVirtualBox->getOpenedMachinesAndControls (machines, controls);
     113
     114            size_t saved = 0;
     115
     116            /* save running VMs */
     117            for (size_t i = 0; i < controls.size(); ++ i)
     118            {
     119                /* get the remote console */
     120                ComPtr <IConsole> console;
     121                rc = controls [i]->GetRemoteConsole (console.asOutParam());
     122                /* the VM could have been powered down and closed or whatever */
     123                if (FAILED (rc))
     124                    continue;
     125
     126                ComPtr<IProgress> progress;
     127
     128                /* note that SaveState() will simply return a failure if the VM
     129                 * is in an inappropriate state */
     130                rc = console->SaveState (progress.asOutParam());
     131                if (FAILED (rc))
     132                    continue;
     133
     134                /* Wait until the operation has been completed. */
     135                rc = progress->WaitForCompletion(-1);
     136                if (SUCCEEDED (rc))
     137                    progress->COMGETTER(ResultCode) (&rc);
     138
     139                AssertMsg (SUCCEEDED (rc), ("SaveState WaitForCompletion "
     140                                            "failed with %Rhrc (%#08X)\n", rc, rc));
     141
     142                if (SUCCEEDED (rc))
     143                    ++ saved;
    160144            }
     145
     146            LogFunc (("Saved %d VMs\n", saved));
     147
     148            break;
    161149        }
    162 fail:
    163         session->Close();
    164150    }
    165     return rc;
    166151}
  • trunk/src/VBox/Main/MachineImpl.cpp

    r13696 r13713  
    38283828 *
    38293829 * @param aMachine  Session machine object.
    3830  * @param aIPCSem   Mutex IPC semaphore handle for this machine.
     3830 * @param aControl  Direct session control object (optional).
     3831 * @param aIPCSem   Mutex IPC semaphore handle for this machine (optional).
    38313832 *
    38323833 * @note locks this object for reading.
     
    38343835#if defined (RT_OS_WINDOWS)
    38353836bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     3837                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
    38363838                             HANDLE *aIPCSem /*= NULL*/,
    38373839                             bool aAllowClosing /*= false*/)
    38383840#elif defined (RT_OS_OS2)
    38393841bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     3842                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
    38403843                             HMTX *aIPCSem /*= NULL*/,
    38413844                             bool aAllowClosing /*= false*/);
    38423845#else
    38433846bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     3847                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
    38443848                             bool aAllowClosing /*= false*/)
    38453849#endif
     
    38603864
    38613865        aMachine = mData->mSession.mMachine;
     3866
     3867        if (aControl != NULL)
     3868            *aControl = mData->mSession.mDirectControl;
    38623869
    38633870#if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r13696 r13713  
    24992499
    25002500/**
    2501  * Returns the list of opened machines (machines having direct sessionsopened by
    2502  * client processes).
    2503  *
    2504  * @note The returned list contains smart pointers. So, clear it as soon as
     2501 * Returns the list of opened machines (machines having direct sessions opened
     2502 * by client processes) and optionally the list of direct session controls.
     2503 *
     2504 * @param aMachines     Where to put opened machines (will be empty if none).
     2505 * @param aControls     Where to put direct session controls (optional).
     2506 *
     2507 * @note The returned lists contain smart pointers. So, clear it as soon as
    25052508 * it becomes no more necessary to release instances.
    25062509 *
     
    25112514 * @note Locks objects for reading.
    25122515 */
    2513 void VirtualBox::getOpenedMachines (SessionMachineVector &aVector)
     2516void VirtualBox::getOpenedMachines (SessionMachineVector &aMachines,
     2517                                    InternalControlVector *aControls /*= NULL*/)
    25142518{
    25152519    AutoCaller autoCaller (this);
    25162520    AssertComRCReturnVoid (autoCaller.rc());
    25172521
    2518     aVector.clear();
     2522    aMachines.clear();
     2523    if (aControls)
     2524        aControls->clear();
    25192525
    25202526    AutoReadLock alock (this);
     
    25252531    {
    25262532        ComObjPtr <SessionMachine> sm;
    2527         if ((*it)->isSessionOpen (sm))
    2528             aVector.push_back (sm);
     2533        ComPtr <IInternalSessionControl> ctl;
     2534        if ((*it)->isSessionOpen (sm, &ctl))
     2535        {
     2536            aMachines.push_back (sm);
     2537            if (aControls)
     2538                aControls->push_back (ctl);
     2539        }
    25292540    }
    25302541}
     
    40714082                    ComObjPtr <SessionMachine> sm;
    40724083                    HANDLE ipcSem;
    4073                     if ((*it)->isSessionOpenOrClosing (sm, &ipcSem))
     4084                    if ((*it)->isSessionOpenOrClosing (sm, NULL, &ipcSem))
    40744085                    {
    40754086                        machines.push_back (sm);
     
    42634274                        ComObjPtr <SessionMachine> sm;
    42644275                        HMTX ipcSem;
    4265                         if ((*it)->isSessionOpenOrClosing (sm, &ipcSem))
     4276                        if ((*it)->isSessionOpenOrClosing (sm, NULL, &ipcSem))
    42664277                        {
    42674278                            machines.push_back (sm);
  • trunk/src/VBox/Main/include/HostImpl.h

    r13655 r13713  
    126126#endif
    127127
    128     HostPowerService *mHostPowerService;
    129 
    130128    // for VirtualBoxSupportErrorInfoImpl
    131129    static const wchar_t *getComponentName() { return L"Host"; }
     
    179177#endif /* VBOX_WITH_USB */
    180178
     179    HostPowerService *mHostPowerService;
    181180};
    182181
  • trunk/src/VBox/Main/include/HostPower.h

    r13705 r13713  
    2626#include "MachineImpl.h"
    2727
     28#include <vector>
     29
    2830class VirtualBox;
    2931
     
    3840{
    3941public:
    40     HostPowerService(VirtualBox *aVirtualBox);
     42
     43    HostPowerService (VirtualBox *aVirtualBox);
    4144    virtual ~HostPowerService();
    4245
    43     void    notify(HostPowerEvent event);
    44     HRESULT processEvent(SessionMachine *machine, HostPowerEvent event, BOOL *paMachineSuspended);
     46    void    notify (HostPowerEvent aEvent);
    4547
    4648protected:
     49
    4750    ComObjPtr <VirtualBox, ComWeakRef> mVirtualBox;
    4851
    49     BOOL    *aMachineSuspended;
    50     size_t   cbMachineSuspended;
     52    std::vector <ComPtr <IConsole> > mConsoles;
    5153};
    5254
     
    5860{
    5961public:
     62
    6063    HostPowerServiceWin(VirtualBox *aVirtualBox);
    6164    virtual ~HostPowerServiceWin();
    6265
    6366private:
     67
    6468    static DECLCALLBACK(int) NotificationThread (RTTHREAD ThreadSelf, void *pInstance);
    6569    static LRESULT CALLBACK  WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  • trunk/src/VBox/Main/include/MachineImpl.h

    r13696 r13713  
    636636
    637637    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     638                        ComPtr <IInternalSessionControl> *aControl = NULL,
    638639                        HANDLE *aIPCSem = NULL, bool aAllowClosing = false);
    639640    bool isSessionSpawning (RTPROCESS *aPID = NULL);
    640641
    641642    bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
     643                                 ComPtr <IInternalSessionControl> *aControl = NULL,
    642644                                 HANDLE *aIPCSem = NULL)
    643     { return isSessionOpen (aMachine, aIPCSem, true /* aAllowClosing */); }
     645    { return isSessionOpen (aMachine, aControl, aIPCSem, true /* aAllowClosing */); }
    644646
    645647#elif defined (RT_OS_OS2)
    646648
    647649    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     650                        ComPtr <IInternalSessionControl> *aControl = NULL,
    648651                        HMTX *aIPCSem = NULL, bool aAllowClosing = false);
    649652
     
    651654
    652655    bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
     656                                 ComPtr <IInternalSessionControl> *aControl = NULL,
    653657                                 HMTX *aIPCSem = NULL)
    654     { return isSessionOpen (aMachine, aIPCSem, true /* aAllowClosing */); }
     658    { return isSessionOpen (aMachine, aControl, aIPCSem, true /* aAllowClosing */); }
    655659
    656660#else
    657661
    658662    bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     663                        ComPtr <IInternalSessionControl> *aControl = NULL,
    659664                        bool aAllowClosing = false);
    660665    bool isSessionSpawning();
    661666
    662     bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine)
    663     { return isSessionOpen (aMachine, true /* aAllowClosing */); }
     667    bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
     668                                 ComPtr <IInternalSessionControl> *aControl = NULL)
     669    { return isSessionOpen (aMachine, aControl, true /* aAllowClosing */); }
    664670
    665671#endif
     
    961967    Bstr mIPCSemName;
    962968    friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     969                                        ComPtr <IInternalSessionControl> *aControl,
    963970                                        HANDLE *aIPCSem, bool aAllowClosing);
    964971#elif defined (RT_OS_OS2)
     
    966973    Bstr mIPCSemName;
    967974    friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
     975                                        ComPtr <IInternalSessionControl> *aControl,
    968976                                        HMTX *aIPCSem, bool aAllowClosing);
    969977#elif defined (VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r13580 r13713  
    8282    typedef std::vector <ComObjPtr <SessionMachine> > SessionMachineVector;
    8383    typedef std::vector <ComObjPtr <Machine> > MachineVector;
     84
     85    typedef std::vector <ComPtr <IInternalSessionControl> > InternalControlVector;
    8486
    8587    class CallbackEvent;
     
    216218    ComObjPtr <GuestOSType> getUnknownOSType();
    217219
    218     void getOpenedMachines (SessionMachineVector &aVector);
     220    void getOpenedMachines (SessionMachineVector &aMachines,
     221                            InternalControlVector *aControls = NULL);
     222
     223    /** Shortcut to #getOpenedMachines (aMachines, &aControls). */
     224    void getOpenedMachinesAndControls (SessionMachineVector &aMachines,
     225                                       InternalControlVector &aControls)
     226    { getOpenedMachines (aMachines, &aControls); }
    219227
    220228    bool isMachineIdValid (const Guid &aId)
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette