VirtualBox

Changeset 47335 in vbox


Ignore:
Timestamp:
Jul 23, 2013 10:53:37 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
87480
Message:

VBoxService/VMInfo: Added internal state tracking for idle user detection, made idle threshold configurable through guest properties and command line (default is 5000ms).

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r46506 r47335  
    174174#endif
    175175
    176 extern RTEXITCODE   VBoxServiceSyntax(const char *pszFormat, ...);
    177 extern RTEXITCODE   VBoxServiceError(const char *pszFormat, ...);
    178 extern void         VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
    179 extern int          VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32,
    180                                          uint32_t u32Min, uint32_t u32Max);
    181 extern int          VBoxServiceStartServices(void);
    182 extern int          VBoxServiceStopServices(void);
    183 extern void         VBoxServiceMainWait(void);
    184 extern int          VBoxServiceReportStatus(VBoxGuestFacilityStatus enmStatus);
    185 #ifdef RT_OS_WINDOWS
    186 extern RTEXITCODE   VBoxServiceWinInstall(void);
    187 extern RTEXITCODE   VBoxServiceWinUninstall(void);
    188 extern RTEXITCODE   VBoxServiceWinEnterCtrlDispatcher(void);
    189 extern void         VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint);
     176extern RTEXITCODE               VBoxServiceSyntax(const char *pszFormat, ...);
     177extern RTEXITCODE               VBoxServiceError(const char *pszFormat, ...);
     178extern void                     VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
     179extern int                      VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32,
     180                                                     uint32_t u32Min, uint32_t u32Max);
     181extern int                      VBoxServiceStartServices(void);
     182extern int                      VBoxServiceStopServices(void);
     183extern void                     VBoxServiceMainWait(void);
     184extern int                      VBoxServiceReportStatus(VBoxGuestFacilityStatus enmStatus);
     185#ifdef RT_OS_WINDOWS
     186extern RTEXITCODE               VBoxServiceWinInstall(void);
     187extern RTEXITCODE               VBoxServiceWinUninstall(void);
     188extern RTEXITCODE               VBoxServiceWinEnterCtrlDispatcher(void);
     189extern void                     VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint);
    190190#endif
    191191
    192192#ifdef VBOXSERVICE_TOOLBOX
    193 extern bool         VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
     193extern bool                     VBoxServiceToolboxMain(int argc, char **argv, RTEXITCODE *prcExit);
    194194#endif
    195195
    196196#ifdef RT_OS_WINDOWS
    197197# ifdef VBOX_WITH_GUEST_PROPS
    198 extern int          VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList);
    199 extern int          VBoxServiceWinGetComponentVersions(uint32_t uiClientID);
     198extern int                      VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache, char **ppszUserList, uint32_t *pcUsersInList);
     199extern int                      VBoxServiceWinGetComponentVersions(uint32_t uiClientID);
    200200# endif /* VBOX_WITH_GUEST_PROPS */
    201201#endif /* RT_OS_WINDOWS */
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceUtils.cpp

    r44570 r47335  
    152152 * Reads a guest property from the host side.
    153153 *
    154  * @returns VBox status code, fully bitched.
    155  *
     154 * @returns IPRT status code, fully bitched.
    156155 * @param   u32ClientId         The HGCM client ID for the guest property session.
    157156 * @param   pszPropName         The property name.
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp

    r47294 r47335  
    2525#endif
    2626#include <Windows.h>
    27 #include <wtsapi32.h>       /* For WTS* calls. */
    28 #include <psapi.h>          /* EnumProcesses. */
    29 #include <Ntsecapi.h>       /* Needed for process security information. */
     27#include <wtsapi32.h>        /* For WTS* calls. */
     28#include <psapi.h>           /* EnumProcesses. */
     29#include <Ntsecapi.h>        /* Needed for process security information. */
    3030
    3131#include <iprt/assert.h>
     
    4141#include "VBoxServiceInternal.h"
    4242#include "VBoxServiceUtils.h"
     43#include "VBoxServiceVMInfo.h"
    4344#include "../../WINNT/VBoxTray/VBoxTrayMsg.h" /* For IPC. */
    4445
     
    9293int  VBoxServiceVMInfoWinProcessesEnumerate(PVBOXSERVICEVMINFOPROC *ppProc, DWORD *pdwCount);
    9394void VBoxServiceVMInfoWinProcessesFree(DWORD cProcs, PVBOXSERVICEVMINFOPROC paProcs);
    94 int vboxServiceVMInfoWinWriteLastInput(const char *pszUser, const char *pszDomain);
     95int vboxServiceVMInfoWinWriteLastInput(PVBOXSERVICEVEPROPCACHE pCache, const char *pszUser, const char *pszDomain);
    9596
    9697typedef BOOL WINAPI FNQUERYFULLPROCESSIMAGENAME(HANDLE,  DWORD, LPTSTR, PDWORD);
     
    808809
    809810
    810 static int vboxServiceVMInfoWinWriteLastInput(const char *pszUser, const char *pszDomain)
    811 {
     811static int vboxServiceVMInfoWinWriteLastInput(PVBOXSERVICEVEPROPCACHE pCache,
     812                                              const char *pszUser, const char *pszDomain)
     813{
     814    AssertPtrReturn(pCache, VERR_INVALID_POINTER);
    812815    AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
    813816
     
    833836            if (RT_SUCCESS(rc))
    834837            {
    835                 VBoxGuestUserState userState = ipcRes.uLastInputMs < 5000 /** @todo Make this configurable. */
     838                VBoxGuestUserState userState = ipcRes.uLastInputMs < g_uVMInfoUserIdleThreshold
    836839                                             ? VBoxGuestUserState_InUse
    837840                                             : VBoxGuestUserState_Idle;
    838                 if (ipcRes.uLastInputMs)
     841
     842                rc = vboxServiceUserUpdateF(pCache, pszUser, pszDomain, "UsageState",
     843                                              userState == VBoxGuestUserState_InUse
     844                                            ? "InUse" : "Idle");
     845
     846                /*
     847                 * Note: vboxServiceUserUpdateF can return VINF_NO_CHANGE in case there wasn't anything
     848                 *       to update. So only report the user's status to host when we really got something
     849                 *       new.
     850                 */
     851                if (rc == VINF_SUCCESS)
    839852                {
    840853                    VBoxServiceVerbose(4, "User \"%s\" (domain \"%s\") is idle for %RU32ms\n",
    841854                                       pszUser, pszDomain ? pszDomain : "<None>", ipcRes.uLastInputMs);
    842855
    843                     rc = VbglR3GuestUserReportState(pszUser, pszDomain, userState,
    844                                                     NULL /* No details */, 0);
     856#if 0 /* Do we want to write the idle time as well? */
     857                    /* Also write the user's current idle time, if there is any. */
     858                    if (userState == VBoxGuestUserState_Idle)
     859                        rc = vboxServiceUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs",
     860                                                    "%RU32", ipcRes.uLastInputMs);
     861                    else
     862                        rc = vboxServiceUserUpdateF(pCache, pszUser, pszDomain, "IdleTimeMs",
     863                                                    NULL /* Delete property */);
     864
     865                    if (RT_SUCCESS(rc))
     866#endif
     867                        rc = VbglR3GuestUserReportState(pszUser, pszDomain, userState,
     868                                                        NULL /* No details */, 0);
    845869                }
    846870            }
     
    883907 *
    884908 * @returns VBox status code.
     909 * @param   pCachce         Property cache to use for storing some of the lookup
     910 *                          data in between calls.
    885911 * @param   ppszUserList    Where to store the user list (separated by commas).
    886912 *                          Must be freed with RTStrFree().
    887913 * @param   pcUsersInList   Where to store the number of users in the list.
    888914 */
    889 int VBoxServiceVMInfoWinWriteUsers(char **ppszUserList, uint32_t *pcUsersInList)
    890 {
     915int VBoxServiceVMInfoWinWriteUsers(PVBOXSERVICEVEPROPCACHE pCache,
     916                                   char **ppszUserList, uint32_t *pcUsersInList)
     917{
     918    AssertPtrReturn(pCache, VERR_INVALID_POINTER);
    891919    AssertPtrReturn(ppszUserList, VERR_INVALID_POINTER);
    892920    AssertPtrReturn(pcUsersInList, VERR_INVALID_POINTER);
     
    10811109                        /* Do idle detection. */
    10821110                        if (RT_SUCCESS(rc))
    1083                             rc = vboxServiceVMInfoWinWriteLastInput(pszUser, pszDomain);
     1111                            rc = vboxServiceVMInfoWinWriteLastInput(pCache, pszUser, pszDomain);
    10841112                    }
    10851113                    else
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo.cpp

    r45874 r47335  
    103103static const char              *g_pszPropCacheValNoLoggedInUsers = "/VirtualBox/GuestInfo/OS/NoLoggedInUsers";
    104104static const char              *g_pszPropCacheValNetCount = "/VirtualBox/GuestInfo/Net/Count";
     105/** A guest user's guest property root key. */
     106static const char              *g_pszPropCacheValUser = "/VirtualBox/GuestInfo/User/";
    105107/** The VM session ID. Changes whenever the VM is restored or reset. */
    106108static uint64_t                 g_idVMInfoSession;
     
    109111/** The current LA client info. */
    110112static VBOXSERVICELACLIENTINFO  g_LAClientInfo;
     113/** User idle threshold. This specifies the minimum time a user is considered
     114 *  being idle and then will be reported to the host. Default is 5s. */
     115uint32_t                        g_uVMInfoUserIdleThreshold = 5 * 1000;
    111116
    112117
     
    157162static DECLCALLBACK(int) VBoxServiceVMInfoOption(const char **ppszShort, int argc, char **argv, int *pi)
    158163{
     164    /** @todo Use RTGetOpt here. */
     165
    159166    int rc = -1;
    160167    if (ppszShort)
     
    163170        rc = VBoxServiceArgUInt32(argc, argv, "", pi,
    164171                                  &g_cMsVMInfoInterval, 1, UINT32_MAX - 1);
     172    else if (!strcmp(argv[*pi], "--vminfo-user-idle-threshold"))
     173        rc = VBoxServiceArgUInt32(argc, argv, "", pi,
     174                                  &g_uVMInfoUserIdleThreshold, 1, UINT32_MAX - 1);
    165175    return rc;
    166176}
     
    235245        if (RT_FAILURE(rc2))
    236246            VBoxServiceError("Failed to init property cache value \"%s\", rc=%Rrc\n", g_pszPropCacheValNetCount, rc2);
     247
     248        /*
     249         * Get configuration guest properties from the host.
     250         * Note: All properties should have sensible defaults in case the lookup here fails.
     251         */
     252        char *pszValue;
     253        rc2 = VBoxServiceReadHostProp(g_uVMInfoGuestPropSvcClientID, "/VirtualBox/GuestAdd/VBoxService/--vminfo-user-idle-threshold", true /* Read only */,
     254                                      &pszValue, NULL /* Flags */, NULL /* Timestamp */);
     255        if (RT_SUCCESS(rc2))
     256        {
     257            AssertPtr(pszValue);
     258            g_uVMInfoUserIdleThreshold = RT_CLAMP(RTStrToInt32(pszValue), 1000, UINT32_MAX - 1);
     259        }
    237260    }
    238261    return rc;
     
    337360        }
    338361    }
     362}
     363
     364
     365/**
     366 * Updates a per-guest user guest property inside the given property cache.
     367 *
     368 * @return  IPRT status code.
     369 * @param   pCache                  Pointer to guest property cache to update user in.
     370 * @param   pszUser                 Name of guest user to update.
     371 * @param   pszDomain               Domain of guest user to update. Optional.
     372 * @param   pszKey                  Key name of guest property to update.
     373 * @param   pszValueFormat          Guest property value to set. Pass NULL for deleting
     374 *                                  the property.
     375 */
     376int vboxServiceUserUpdateF(PVBOXSERVICEVEPROPCACHE pCache, const char *pszUser, const char *pszDomain,
     377                           const char *pszKey, const char *pszValueFormat, ...)
     378{
     379    AssertPtrReturn(pCache, VERR_INVALID_POINTER);
     380    AssertPtrReturn(pszUser, VERR_INVALID_POINTER);
     381    /* pszDomain is optional. */
     382    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     383    /* pszValueFormat is optional. */
     384
     385    int rc = VINF_SUCCESS;
     386
     387    char *pszName;
     388    if (pszDomain)
     389        if (!RTStrAPrintf(&pszName, "%s%s@%s/%s", g_pszPropCacheValUser, pszUser, pszDomain, pszKey))
     390            rc = VERR_NO_MEMORY;
     391    else
     392        if (!RTStrAPrintf(&pszName, "%s%s/%s", g_pszPropCacheValUser, pszUser, pszKey))
     393            rc = VERR_NO_MEMORY;
     394
     395    char *pszValue = NULL;
     396    if (   RT_SUCCESS(rc)
     397        && pszValueFormat)
     398    {
     399        va_list va;
     400        va_start(va, pszValueFormat);
     401        if (RTStrAPrintfV(&pszValue, pszValueFormat, va) < 0)
     402            rc = VERR_NO_MEMORY;
     403        va_end(va);
     404        if (   RT_SUCCESS(rc)
     405            && !pszValue)
     406            rc = VERR_NO_STR_MEMORY;
     407    }
     408
     409    if (RT_SUCCESS(rc))
     410        rc = VBoxServicePropCacheUpdate(pCache, pszName, pszValue);
     411    if (rc == VINF_SUCCESS) /* VBoxServicePropCacheUpdate will also return VINF_NO_CHANGE. */
     412    {
     413        /** @todo Combine updating flags w/ updating the actual value. */
     414        rc = VBoxServicePropCacheUpdateEntry(pCache, pszName,
     415                                             VBOXSERVICEPROPCACHEFLAG_TEMPORARY | VBOXSERVICEPROPCACHEFLAG_TRANSIENT,
     416                                             NULL /* Delete on exit */);
     417    }
     418
     419    RTStrFree(pszValue);
     420    RTStrFree(pszName);
     421    return rc;
    339422}
    340423
     
    431514#ifdef RT_OS_WINDOWS
    432515# ifndef TARGET_NT4
    433     rc = VBoxServiceVMInfoWinWriteUsers(&pszUserList, &cUsersInList);
     516    rc = VBoxServiceVMInfoWinWriteUsers(&g_VMInfoPropCache,
     517                                        &pszUserList, &cUsersInList);
    434518# else
    435519    rc = VERR_NOT_IMPLEMENTED;
     
    13911475    "Virtual Machine Information",
    13921476    /* pszUsage. */
    1393     "              [--vminfo-interval <ms>]"
     1477    "              [--vminfo-interval <ms>] [--vminfo-user-idle-threshold <ms>]"
    13941478    ,
    13951479    /* pszOptions. */
    13961480    "    --vminfo-interval       Specifies the interval at which to retrieve the\n"
    13971481    "                            VM information. The default is 10000 ms.\n"
     1482    "    --vminfo-user-idle-threshold <ms>\n"
     1483    "                            Specifies the user idle threshold (in ms) for\n"
     1484    "                            considering a guest user being as idle. The default\n"
     1485    "                            is 5000 (5 seconds).\n"
    13981486    ,
    13991487    /* methods */
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