(file) Return to CIMListener.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Listener

Diff for /pegasus/src/Pegasus/Listener/CIMListener.cpp between version 1.6 and 1.40.2.1

version 1.6, 2002/10/17 17:56:23 version 1.40.2.1, 2006/09/19 18:29:19
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // The Open Group, Tivoli Systems  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec Corporation; The Open Group.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 21 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // Modified By:  
 //         Mike Day (mdday@us.ibm.com)s  
 //         Nitin Upasani, Hewlett-Packard Company (Nitin_Upasani@hp.com)  
 //         Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)  
 //         Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)  
 //         Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include <Pegasus/Common/Config.h>  #include "CIMListener.h"
  
 #include <iostream>  #include <Pegasus/Common/Exception.h>
 #include <cstdio>  #include <Pegasus/Common/SSLContext.h>
 #include <cctype>  #include <Pegasus/Common/Monitor.h>
 #include <ctime>  
 #include <Pegasus/Common/FileSystem.h>  
 #include <Pegasus/Common/HTTPAcceptor.h> #include <Pegasus/Common/HTTPAcceptor.h>
 #include <Pegasus/Common/Tracer.h>  
 #include <Pegasus/Common/PegasusVersion.h> #include <Pegasus/Common/PegasusVersion.h>
   #include <Pegasus/Common/MessageLoader.h>
  
 #include <Pegasus/Repository/CIMRepository.h>  
 #include <Pegasus/ExportServer/CIMExportRequestDispatcher.h>  
 #include <Pegasus/ExportServer/CIMExportResponseEncoder.h> #include <Pegasus/ExportServer/CIMExportResponseEncoder.h>
 #include <Pegasus/ExportServer/CIMExportRequestDecoder.h> #include <Pegasus/ExportServer/CIMExportRequestDecoder.h>
  
 #include "CIMListener.h"  #include <Pegasus/Consumer/CIMIndicationConsumer.h>
   #include <Pegasus/Listener/CIMListenerIndicationDispatcher.h>
  
 #define DDD(X) // X  PEGASUS_NAMESPACE_BEGIN
   /////////////////////////////////////////////////////////////////////////////
   // CIMListenerService
   /////////////////////////////////////////////////////////////////////////////
   class CIMListenerService
   {
   public:
           CIMListenerService(Uint32 portNumber, SSLContext* sslContext=NULL);
           CIMListenerService(CIMListenerService& svc);
     ~CIMListenerService();
   
           void                            init();
           /** bind to the port
           */
           void                            bind();
           /** runForever Main runloop for the server.
           */
           void runForever();
   
           /** Call to gracefully shutdown the server.  The server connection socket
           will be closed to disable new connections from clients.
           */
           void stopClientConnection();
   
           /** Call to gracefully shutdown the server.  It is called when the server
           has been stopped and is ready to be shutdown.  Next time runForever()
           is called, the server shuts down.
           */
           void shutdown();
   
           /** Return true if the server has shutdown, false otherwise.
           */
           Boolean terminated() const { return _dieNow; };
   
           /** Call to resume the sever.
           */
           void resume();
   
           /** Call to set the CIMServer state.  Also inform the appropriate
           message queues about the current state of the CIMServer.
           */
           void setState(Uint32 state);
   
           Uint32 getOutstandingRequestCount();
   
           /** Returns the indication listener dispatcher
            */
           CIMListenerIndicationDispatcher* getIndicationDispatcher() const;
   
           /** Returns the indication listener dispatcher
            */
           void setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher);
   
           /** Returns the port number being used.
            */
           Uint32 getPortNumber() const;
   
           static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _listener_routine(void *param);
   
   private:
           Uint32 _portNumber;
           SSLContext* _sslContext;
           Monitor* _monitor;
           HTTPAcceptor* _acceptor;
   
     Boolean                                       _dieNow;
   
     CIMListenerIndicationDispatcher* _dispatcher;
   
     CIMExportResponseEncoder* _responseEncoder;
     CIMExportRequestDecoder*  _requestDecoder;
   
   };
   
   CIMListenerService::CIMListenerService(Uint32 portNumber, SSLContext* sslContext)
   :_portNumber(portNumber)
   ,_sslContext(sslContext)
   ,_monitor(NULL)
   ,_acceptor(NULL)
   ,_dieNow(false)
   ,_dispatcher(NULL)
   ,_responseEncoder(NULL)
   ,_requestDecoder(NULL)
   {
   }
  
 PEGASUS_USING_STD;  CIMListenerService::CIMListenerService(CIMListenerService& svc)
   :_portNumber(svc._portNumber)
   ,_sslContext(svc._sslContext)
   ,_monitor(NULL)
   ,_acceptor(NULL)
   ,_dieNow(svc._dieNow)
   ,_dispatcher(NULL)
   ,_responseEncoder(NULL)
   ,_requestDecoder(NULL)
   {
   }
   CIMListenerService::~CIMListenerService()
   {
       // if port is alive, clean up the port
       //delete _sslContext;
  
 PEGASUS_NAMESPACE_BEGIN      delete _responseEncoder;
   
       delete _requestDecoder;
   
       //delete _dispatcher;
  
 CIMListener::CIMListener(      delete _acceptor;
     Monitor* monitor,  
     const String& rootPath,      delete _monitor;
     Boolean dynamicReg,  }
     Boolean staticConsumers,  
     Boolean persistence)  void CIMListenerService::init()
     : _dieNow(false), _rootPath(rootPath),  
     _dynamicReg(dynamicReg),  
     _staticConsumers(staticConsumers),  
     _persistence(persistence)  
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::CIMListener()");          PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::init");
   
     if(NULL == _monitor) _monitor = new Monitor();
  
     // -- Save the monitor or create a new one:          //_dispatcher = new CIMListenerIndicationDispatcher();
  
     _monitor = monitor;    if(NULL == _responseEncoder) _responseEncoder = new CIMExportResponseEncoder();
     if(NULL == _requestDecoder) _requestDecoder = new CIMExportRequestDecoder(
                                         _dispatcher,_responseEncoder->getQueueId());
  
     // -- Create a CIMListenerState object:    if(NULL == _acceptor) _acceptor = new HTTPAcceptor(
                    _monitor,
                    _requestDecoder,
                    false,
                    _portNumber,
                    _sslContext,
                    false);
  
     _cimExportRequestDispatcher    bind();
         = new CIMExportRequestDispatcher(dynamicReg, staticConsumers, persistence);  
  
     _cimExportResponseEncoder    PEG_METHOD_EXIT();
         = new CIMExportResponseEncoder;  }
  
     _cimExportRequestDecoder = new CIMExportRequestDecoder(  void CIMListenerService::bind()
         _cimExportRequestDispatcher,  {
         _cimExportResponseEncoder->getQueueId());    if(_acceptor!=NULL)
       { // Bind to the port
         _acceptor->bind();
   
         //listener.addAcceptor(false, portNumberHttp, false);
         Logger::put(Logger::STANDARD_LOG, System::CIMLISTENER, Logger::INFORMATION,
                           "Listening on HTTP port $0.", _portNumber);
  
     SSLContext * sslcontext = NULL;      }
   }
  
     _acceptor = new HTTPAcceptor(_monitor, _cimExportRequestDecoder, sslcontext);  void CIMListenerService::runForever()
   {
       if (!_dieNow)
       {
           _monitor->run(500000);
           static struct timeval lastIdleCleanupTime = {0, 0};
           struct timeval now;
           gettimeofday(&now, 0);
           if (now.tv_sec - lastIdleCleanupTime.tv_sec > 300)
           {
               lastIdleCleanupTime.tv_sec = now.tv_sec;
               try
               {
                   MessageQueueService::get_thread_pool()->cleanupIdleThreads();
               }
               catch(...)
               {
                   // Ignore!
               }
           }
       }
   }
   
   void CIMListenerService::shutdown()
   {
       PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::shutdown()");
   
       _dieNow = true;
       _monitor->tickle();
  
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
  
 CIMListener::~CIMListener()  void CIMListenerService::resume()
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::~CIMListener()");      PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::resume()");
  
     // Note: do not delete the acceptor because it belongs to the Monitor      if(_acceptor!=NULL)
     // which takes care of disposing of it.          _acceptor->reopenConnectionSocket();
  
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
  
 void CIMListener::bind(Uint32 port)  void CIMListenerService::stopClientConnection()
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::bind()");      PEG_METHOD_ENTER(TRC_LISTENER, "CIMListenerService::stopClientConnection()");
  
     // not the best place to build the service url, but it works for now      // tell Monitor to stop listening for client connections
     // because the address string is accessible  mdday      _monitor->stopListeningForConnections(true);
   
       //
       // Wait 150 milliseconds to allow time for the Monitor to stop
       // listening for client connections.
       //
       // This wait time is the timeout value for the select() call
       // in the Monitor's run() method (currently set to 100
       // milliseconds) plus a delta of 50 milliseconds.  The reason
       // for the wait here is to make sure that the Monitor entries
       // are updated before closing the connection sockets.
       //
       // pegasus_sleep(150); Not needed now due to the semaphore in the Monitor
  
     _acceptor->bind(port);      if(_acceptor!=NULL)
       _acceptor->closeConnectionSocket();
  
     PEG_METHOD_EXIT();     PEG_METHOD_EXIT();
 } }
  
 void CIMListener::runForever()  Uint32 CIMListenerService::getOutstandingRequestCount()
 { {
     //ATTN: Do not add Trace code in this method.      return _acceptor->getOutstandingRequestCount();
     if(!_dieNow)  
         _monitor->run(100);  
 } }
  
 void CIMListener::stopClientConnection()  CIMListenerIndicationDispatcher* CIMListenerService::getIndicationDispatcher() const
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::stopClientConnection()");      return _dispatcher;
   }
  
     _acceptor->closeConnectionSocket();  void CIMListenerService::setIndicationDispatcher(CIMListenerIndicationDispatcher* dispatcher)
   {
       _dispatcher = dispatcher;
   }
  
     PEG_METHOD_EXIT();  Uint32 CIMListenerService::getPortNumber() const
   {
   
       Uint32 portNumber = _portNumber;
   
       if (( portNumber == 0 ) && ( _acceptor != 0 ))
       {
           portNumber = _acceptor->getPortNumber();
 } }
  
 void CIMListener::shutdown()      return(portNumber);
   }
   
   PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL CIMListenerService::_listener_routine(void *param)
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::shutdown()");    try {
       AutoPtr<CIMListenerService> svc(reinterpret_cast<CIMListenerService *>(param));
  
     _dieNow = true;      //svc->init(); bug 1394
       while(!svc->terminated())
       {
   #if defined(PEGASUS_PLATFORM_DARWIN_PPC_GNU)
           pthread_testcancel();
   #endif
           svc->runForever();
       }
     } catch (...)
     {
           Tracer::trace(TRC_SERVER, Tracer::LEVEL2,
                           "Unknown exception thrown in _listener_routine.");
     }
       return 0;
   }
  
     PEG_METHOD_EXIT();  /////////////////////////////////////////////////////////////////////////////
   // CIMListenerRep
   /////////////////////////////////////////////////////////////////////////////
   class CIMListenerRep
   {
   public:
           CIMListenerRep(Uint32 portNumber, SSLContext* sslContext=NULL);
     ~CIMListenerRep();
   
           Uint32 getPortNumber() const;
   
           SSLContext* getSSLContext() const;
           void setSSLContext(SSLContext* sslContext);
   
           void start();
           void stop();
   
           Boolean isAlive();
   
           Boolean addConsumer(CIMIndicationConsumer* consumer);
           Boolean removeConsumer(CIMIndicationConsumer* consumer);
   
   private:
     Boolean waitForPendingRequests(Uint32 shutdownTimeout);
   
     Uint32 _portNumber;
     SSLContext* _sslContext;
   
     CIMListenerIndicationDispatcher* _dispatcher;
     ThreadPool* _thread_pool;
     CIMListenerService* _svc;
     Semaphore *_listener_sem;
   };
   
   CIMListenerRep::CIMListenerRep(Uint32 portNumber, SSLContext* sslContext)
   :_portNumber(portNumber)
   ,_sslContext(sslContext)
   ,_dispatcher(new CIMListenerIndicationDispatcher())
   ,_thread_pool(NULL)
   ,_svc(NULL)
   ,_listener_sem(NULL)
   {
 } }
  
 void CIMListener::resume()  CIMListenerRep::~CIMListenerRep()
   {
       // if port is alive, clean up the port
       if (_thread_pool != 0)
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::resume()");          // Block incoming export requests and unbind the port
           _svc->stopClientConnection();
  
     _acceptor->reopenConnectionSocket();          // Wait until pending export requests in the server are done.
           waitForPendingRequests(10);
  
     PEG_METHOD_EXIT();          // Shutdown the CIMListenerService
           _svc->shutdown();
 } }
  
 Uint32 CIMListener::getOutstandingRequestCount()      delete _sslContext;
       delete _dispatcher;
       delete _thread_pool;
       delete _listener_sem;
   
     // don't delete _svc, this is deleted by _listener_routine
   }
   
   Uint32 CIMListenerRep::getPortNumber() const
 { {
     PEG_METHOD_ENTER(TRC_SERVER, "CIMListener::getOutstandingRequestCount()");      Uint32 portNumber;
  
     PEG_METHOD_EXIT();      if ( _svc == 0 )
       {
           portNumber = _portNumber;
       }
       else portNumber = _svc->getPortNumber();
   
       return portNumber;
   }
   
   SSLContext* CIMListenerRep::getSSLContext() const
   {
       return _sslContext;
   }
   
   void CIMListenerRep::setSSLContext(SSLContext* sslContext)
   {
       delete _sslContext;
       _sslContext = sslContext;
   }
   
   void CIMListenerRep::start()
   {
       // spawn a thread to do this
       if(_thread_pool==0)
       {
           AutoPtr<CIMListenerService> svc(new CIMListenerService(_portNumber,_sslContext));
   
           svc->setIndicationDispatcher(_dispatcher);
           svc->init();
   
           struct timeval deallocateWait = {15, 0};
           AutoPtr<ThreadPool> threadPool(new ThreadPool(0, "Listener", 0, 1, deallocateWait));
           AutoPtr<Semaphore> sem(new Semaphore(0));
           if (threadPool->allocate_and_awaken(svc.get(), CIMListenerService::_listener_routine, sem.get()) != PEGASUS_THREAD_OK)
           {
               Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
                           "Not enough threads to start CIMListernerService.");
   
               Tracer::trace(TRC_SERVER, Tracer::LEVEL2,
                           "Could not allocate thread for CIMListenerService::_listener_routine.");
               throw Exception(MessageLoaderParms("Listener.CIMListener.CANNOT_ALLOCATE_THREAD",
                                   "Could not allocate thread."));
           }
           Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER, Logger::INFORMATION,
                           "CIMListener started");
   
           _svc = svc.release();
           _thread_pool = threadPool.release();
           _listener_sem = sem.release();
       }
   }
   
   void CIMListenerRep::stop()
   {
     if(_thread_pool!=NULL)
     {
       //
       // Graceful shutdown of the listener service
       //
   
       // Block incoming export requests and unbind the port
       _svc->stopClientConnection();
   
       // Wait until pending export requests in the server are done.
       waitForPendingRequests(10);
  
     return (_acceptor->getOutstandingRequestCount());      // Shutdown the CIMListenerService
       _svc->shutdown();
   
       // Wait for the _listener_routine thread to exit.
       // The thread could be delivering an export, so give it 3sec.
       // Note that _listener_routine deletes the CIMListenerService,
       // so no need to delete _svc.
       try
       {
         _listener_sem->time_wait(3000);
       }
       catch (const TimeOut &)
       {
         // No need to do anything, the thread pool will be deleted below
         // to cancel the _listener_routine thread if it is still running.
       }
   
       delete _listener_sem;
       _listener_sem = NULL;
   
       // Delete the thread pool.  This cancels the listener thread if it is still
       // running.
       delete _thread_pool;
       _thread_pool = NULL;
   
       Logger::put(Logger::STANDARD_LOG,System::CIMLISTENER,
                   Logger::INFORMATION,
                   "CIMListener stopped");
     }
   }
   
   Boolean CIMListenerRep::isAlive()
   {
           return (_thread_pool!=NULL)?true:false;
   }
   
   Boolean CIMListenerRep::addConsumer(CIMIndicationConsumer* consumer)
   {
           return _dispatcher->addConsumer(consumer);
   }
   Boolean CIMListenerRep::removeConsumer(CIMIndicationConsumer* consumer)
   {
           return _dispatcher->removeConsumer(consumer);
   }
   
   Boolean CIMListenerRep::waitForPendingRequests(Uint32 shutdownTimeout)
   {
     // Wait for 10 sec max
     Uint32 reqCount;
     Uint32 countDown = shutdownTimeout * 10;
     for (; countDown > 0; countDown--)
     {
       reqCount = _svc->getOutstandingRequestCount();
       if (reqCount > 0)
         pegasus_sleep(100);
       else
         return true;
     }
   
     return false;
   }
   
   /////////////////////////////////////////////////////////////////////////////
   // CIMListener
   /////////////////////////////////////////////////////////////////////////////
   CIMListener::CIMListener(Uint32 portNumber, SSLContext* sslContext)
   :_rep(new CIMListenerRep(portNumber,sslContext))
   {
   }
   CIMListener::~CIMListener()
   {
           if(_rep!=NULL)
                   delete static_cast<CIMListenerRep*>(_rep);
           _rep=NULL;
   }
   
   Uint32 CIMListener::getPortNumber() const
   {
           return static_cast<CIMListenerRep*>(_rep)->getPortNumber();
   }
   
   SSLContext* CIMListener::getSSLContext() const
   {
           return static_cast<CIMListenerRep*>(_rep)->getSSLContext();
   }
   void CIMListener::setSSLContext(SSLContext* sslContext)
   {
           static_cast<CIMListenerRep*>(_rep)->setSSLContext(sslContext);
   }
   void CIMListener::start()
   {
           static_cast<CIMListenerRep*>(_rep)->start();
   }
   void CIMListener::stop()
   {
           static_cast<CIMListenerRep*>(_rep)->stop();
   }
   
   Boolean CIMListener::isAlive() const
   {
           return static_cast<CIMListenerRep*>(_rep)->isAlive();
   }
   
   Boolean CIMListener::addConsumer(CIMIndicationConsumer* consumer)
   {
           return static_cast<CIMListenerRep*>(_rep)->addConsumer(consumer);
   }
   Boolean CIMListener::removeConsumer(CIMIndicationConsumer* consumer)
   {
           return static_cast<CIMListenerRep*>(_rep)->removeConsumer(consumer);
 } }
  
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.6  
changed lines
  Added in v.1.40.2.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2