VirtualBox

Changeset 26375 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 9, 2010 2:24:56 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
57468
Message:

Webservice: use AutoLock.h for locking; more fine-grained locking in preparation for multithreading

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/webservice/vboxweb.cpp

    r26089 r26375  
    3232#include <VBox/version.h>
    3333
    34 #include <iprt/cpp/lock.h>
     34#include <iprt/thread.h>
    3535#include <iprt/rand.h>
    3636#include <iprt/initterm.h>
     
    114114 ****************************************************************************/
    115115
    116 RTLockMtx           g_mutexAuthLib;
     116// this mutex protects the auth lib and authentication
     117util::RWLockHandle  *g_pAuthLibLockHandle;
    117118
    118119// this mutex protects all of the below
    119 RTLockMtx           g_mutexSessions;
     120util::RWLockHandle  *g_pSessionsLockHandle;
    120121
    121122SessionsMap         g_mapSessions;
     
    247248}
    248249
     250/**
     251 * Called from main(). This implements the loop that takes SOAP calls
     252 * from HTTP and serves them, calling the COM method implementations
     253 * in the generated methodmaps.cpp code.
     254 */
     255void beginProcessing()
     256{
     257    // set up gSOAP
     258    struct soap soap;
     259    soap_init(&soap);
     260
     261    soap.bind_flags |= SO_REUSEADDR;
     262            // avoid EADDRINUSE on bind()
     263
     264    int m, s; // master and slave sockets
     265    m = soap_bind(&soap,
     266                  g_pcszBindToHost,     // host: current machine
     267                  g_uBindToPort,     // port
     268                  g_uBacklog);     // backlog = max queue size for requests
     269    if (m < 0)
     270        WebLogSoapError(&soap);
     271    else
     272    {
     273        WebLog("Socket connection successful: host = %s, port = %u, master socket = %d\n",
     274               (g_pcszBindToHost) ? g_pcszBindToHost : "default (localhost)",
     275               g_uBindToPort,
     276               m);
     277
     278        for (uint64_t i = 1;
     279             ;
     280             i++)
     281        {
     282            // call gSOAP to handle incoming SOAP connection
     283            s = soap_accept(&soap);
     284            if (s < 0)
     285            {
     286                WebLogSoapError(&soap);
     287                break;
     288            }
     289
     290            WebLog("%llu: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d... ",
     291                   i,
     292                   (soap.ip>>24)&0xFF,
     293                   (soap.ip>>16)&0xFF,
     294                   (soap.ip>>8)&0xFF,
     295                   soap.ip&0xFF,
     296                   s);
     297
     298            // now process the RPC request (this goes into the
     299            // generated code in methodmaps.cpp with all the COM calls)
     300            if (soap_serve(&soap) != SOAP_OK)
     301            {
     302                WebLogSoapError(&soap);
     303            }
     304
     305            WebLog("Request served\n");
     306
     307            soap_destroy(&soap); // clean up class instances
     308            soap_end(&soap); // clean up everything and close socket
     309
     310            // we have to process main event queue
     311            int vrc = com::EventQueue::getMainEventQueue()->processEventQueue(0);
     312        }
     313    }
     314    soap_done(&soap); // close master socket and detach environment
     315}
    249316
    250317/**
     
    390457    }
    391458
     459    // create the global mutexes
     460    g_pAuthLibLockHandle = new util::RWLockHandle(util::LOCKCLASS_OBJECTSTATE);
     461    g_pSessionsLockHandle = new util::RWLockHandle(util::LOCKCLASS_OBJECTSTATE);
     462
    392463    if (g_iWatchdogTimeoutSecs > 0)
    393464    {
     
    407478    }
    408479
    409     // set up gSOAP
    410     struct soap soap;
    411     soap_init(&soap);
    412 
    413     soap.bind_flags |= SO_REUSEADDR;
    414             // avoid EADDRINUSE on bind()
    415 
    416     int m, s; // master and slave sockets
    417     m = soap_bind(&soap,
    418                   g_pcszBindToHost,     // host: current machine
    419                   g_uBindToPort,     // port
    420                   g_uBacklog);     // backlog = max queue size for requests
    421     if (m < 0)
    422         WebLogSoapError(&soap);
    423     else
    424     {
    425         WebLog("Socket connection successful: host = %s, port = %u, master socket = %d\n",
    426                (g_pcszBindToHost) ? g_pcszBindToHost : "default (localhost)",
    427                g_uBindToPort,
    428                m);
    429 
    430         for (uint64_t i = 1;
    431              ;
    432              i++)
    433         {
    434             // call gSOAP to handle incoming SOAP connection
    435             s = soap_accept(&soap);
    436             if (s < 0)
    437             {
    438                 WebLogSoapError(&soap);
    439                 break;
    440             }
    441 
    442             WebLog("%llu: accepted connection from IP=%lu.%lu.%lu.%lu socket=%d... ",
    443                    i,
    444                    (soap.ip>>24)&0xFF,
    445                    (soap.ip>>16)&0xFF,
    446                    (soap.ip>>8)&0xFF,
    447                    soap.ip&0xFF,
    448                    s);
    449 
    450             // enclose the entire RPC call in the sessions lock
    451             // so that the watchdog cannot destroy COM objects
    452             // while the RPC is ongoing
    453             RTLock lock(g_mutexSessions);
    454             // now process the RPC request (this goes into the
    455             // generated code in methodmaps.cpp with all the COM calls)
    456             if (soap_serve(&soap) != SOAP_OK)
    457             {
    458                 WebLogSoapError(&soap);
    459             }
    460             lock.release();
    461 
    462             WebLog("Request served\n");
    463 
    464             soap_destroy(&soap); // clean up class instances
    465             soap_end(&soap); // clean up everything and close socket
    466 
    467             // we have to process main event queue
    468             int vrc = com::EventQueue::getMainEventQueue()->processEventQueue(0);
    469         }
    470     }
    471     soap_done(&soap); // close master socket and detach environment
     480    beginProcessing();
    472481
    473482    com::Shutdown();
     
    499508        time(&tNow);
    500509
    501         RTLock lock(g_mutexSessions);
     510        // lock the sessions while we're iterating; this blocks
     511        // out the COM code from messing with it
     512        util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
    502513        WEBDEBUG(("Watchdog: checking %d sessions\n", g_mapSessions.size()));
    503514
    504         SessionsMap::iterator
    505             it = g_mapSessions.begin(),
    506             itEnd = g_mapSessions.end();
     515        SessionsMap::iterator it = g_mapSessions.begin(),
     516                              itEnd = g_mapSessions.end();
    507517        while (it != itEnd)
    508518        {
     
    520530                ++it;
    521531        }
    522         lock.release();
    523532    }
    524533
     
    617626std::string ConvertComString(const com::Guid &uuid)
    618627{
    619     com::Bstr bstr(uuid);
    620     com::Utf8Str ustr(bstr);
     628    com::Utf8Str ustr(uuid.toString());
    621629    const char *pcsz;
    622630    if ((pcsz = ustr.raw()))
     
    739747 * Constructor for the session object.
    740748 *
    741  * Preconditions: Caller must have locked g_mutexSessions.
     749 * Preconditions: Caller must have locked g_pSessionsLockHandle in write mode.
    742750 *
    743751 * @param username
     
    753761
    754762    // register this session globally
     763    Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread());
    755764    g_mapSessions[_uSessionID] = this;
    756765}
     
    759768 * Destructor. Cleans up and destroys all contained managed object references on the way.
    760769 *
    761  * Preconditions: Caller must have locked g_mutexSessions.
     770 * Preconditions: Caller must have locked g_pSessionsLockHandle in write mode.
    762771 */
    763772WebServiceSession::~WebServiceSession()
     
    765774    // delete us from global map first so we can't be found
    766775    // any more while we're cleaning up
     776    Assert(g_pSessionsLockHandle->isWriteLockOnCurrentThread());
    767777    g_mapSessions.erase(_uSessionID);
    768778
     
    778788    // }
    779789
    780     ManagedObjectsMapById::iterator
    781         it,
    782         end = _pp->_mapManagedObjectsById.end();
     790    ManagedObjectsMapById::iterator it,
     791                                    end = _pp->_mapManagedObjectsById.end();
    783792    for (it = _pp->_mapManagedObjectsById.begin();
    784793         it != end;
     
    804813    int rc = VERR_WEB_NOT_AUTHENTICATED;
    805814
    806     RTLock lock(g_mutexAuthLib);
     815    util::AutoReadLock lock(g_pAuthLibLockHandle COMMA_LOCKVAL_SRC_POS);
    807816
    808817    static bool fAuthLibLoaded = false;
     
    875884    }
    876885
     886    lock.release();
     887
    877888    if (!rc)
    878889    {
     
    912923 *  our private hash table, we must search for one too.
    913924 *
    914  *  Preconditions: Caller must have locked g_mutexSessions.
     925 * Preconditions: Caller must have locked g_pSessionsLockHandle in read mode.
    915926 *
    916927 * @param pcu pointer to a COM object.
     
    919930ManagedObjectRef* WebServiceSession::findRefFromPtr(const ComPtr<IUnknown> &pcu)
    920931{
     932    // Assert(g_pSessionsLockHandle->isReadLockOnCurrentThread());      // @todo
     933
    921934    IUnknown *p = pcu;
    922935    uintptr_t ulp = (uintptr_t)p;
     
    940953 * object IDs and then looking up the session object for that session ID.
    941954 *
    942  * Preconditions: Caller must have locked g_mutexSessions.
     955 * Preconditions: Caller must have locked g_pSessionsLockHandle in read mode.
    943956 *
    944957 * @param id Managed object reference (with combined session and object IDs).
     
    947960WebServiceSession* WebServiceSession::findSessionFromRef(const WSDLT_ID &id)
    948961{
     962    // Assert(g_pSessionsLockHandle->isReadLockOnCurrentThread()); // @todo
     963
    949964    WebServiceSession *pSession = NULL;
    950965    uint64_t sessid;
     
    10101025/**
    10111026 *  Constructor, which assigns a unique ID to this managed object
    1012  *  reference and stores it two global hashs:
     1027 *  reference and stores it two global hashes:
    10131028 *
    10141029 *   a) G_mapManagedObjectsById, which maps ManagedObjectID's to
     
    12941309
    12951310    do {
     1311        // WebServiceSession constructor tinkers with global MOR map and requires a write lock
     1312        util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
     1313
    12961314        // create new session; the constructor stores the new session
    12971315        // in the global map automatically
  • trunk/src/VBox/Main/webservice/vboxweb.h

    r22708 r26375  
    33 *      header file for "real" web server code.
    44 *
    5  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     5 * Copyright (C) 2006-2010 Sun Microsystems, Inc.
    66 *
    77 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3333#include <VBox/com/VirtualBox.h>
    3434#include <VBox/com/Guid.h>
     35#include <VBox/com/AutoLock.h>
    3536
    3637#include <VBox/err.h>
     
    3940
    4041#include <string>
    41 
    4242
    4343/****************************************************************************
     
    5151
    5252extern PRTSTREAM g_pstrLog;
     53
     54extern util::RWLockHandle  *g_pAuthLibLockHandle;
     55
     56extern util::RWLockHandle  *g_pSessionsLockHandle;
    5357
    5458/****************************************************************************
     
    224228                     bool fNullAllowed)
    225229{
     230    // we're only reading the MOR maps, not modifying them, so a readlock is good enough
     231    // (allow concurrency, this code gets called from everywhere in methodmaps.cpp)
     232    util::AutoReadLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
     233
    226234    int rc;
    227235    ManagedObjectRef *pRef;
     
    270278    }
    271279
     280    // we might be modifying the MOR maps below, so request write lock now
     281    util::AutoWriteLock lock(g_pSessionsLockHandle COMMA_LOCKVAL_SRC_POS);
    272282    WebServiceSession *pSession;
    273283    if ((pSession = WebServiceSession::findSessionFromRef(idParent)))
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