ServiceManager.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:10k
- /* ====================================================================
- * The Vovida Software License, Version 1.0
- *
- * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The names "VOCAL", "Vovida Open Communication Application Library",
- * and "Vovida Open Communication Application Library (VOCAL)" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact vocal@vovida.org.
- *
- * 4. Products derived from this software may not be called "VOCAL", nor
- * may "VOCAL" appear in their name, without prior written
- * permission of Vovida Networks, Inc.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
- * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
- * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
- * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * ====================================================================
- *
- * This software consists of voluntary contributions made by Vovida
- * Networks, Inc. and many individuals on behalf of Vovida Networks,
- * Inc. For more information on Vovida Networks, Inc., please see
- * <http://www.vovida.org/>.
- *
- */
- static const char* const ServiceManager_cxx_Version =
- "$Id: ServiceManager.cxx,v 1.6 2001/06/27 23:12:00 bko Exp $";
- #include "ServiceManager.hxx"
- #include "Service.hxx"
- #include "ControlEvent.hxx"
- #include "SignalAction.hxx"
- #include "SignalHandler.hxx"
- #include "Thread.hxx"
- #include "VLog.hxx"
- using Vocal::Services::Event;
- using Vocal::Services::ServiceManager;
- using Vocal::Services::ControlEvent;
- using Vocal::Signals::SignalAction;
- using Vocal::Threads::Thread;
- using Vocal::Logging::VLog;
- using Vocal::ReturnCode;
- ServiceManager::ServiceManager(
- FifoBase< Sptr<Event> > & serviceMgrFifo,
- SignalAction * signalAction
- )
- : myFifo(serviceMgrFifo),
- mySignalAction(signalAction)
- {
- const string fn("ServiceManager::ServiceMananger");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": this = 0x" << this << VDEBUG_END(log);
- }
- ServiceManager::~ServiceManager()
- {
- const string fn("ServiceManager::~ServiceMananger");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": this = 0x" << this << VDEBUG_END(log);
- }
- void
- ServiceManager::manage(Service & service)
- {
- const string fn("ServiceManager::manage");
- VLog log(fn);
-
- VINFO(log) << fn << ": service = " << service.name() << VINFO_END(log);
- ServiceInfo serviceInfo;
-
- serviceInfo.service = &service;
- serviceInfo.thread = new Thread(service, service.name().c_str());
-
- myServiceList.push_back(serviceInfo);
- }
- void
- ServiceManager::unmanage()
- {
- const string fn("ServiceManager::unmanage");
- VLog log(fn);
-
- for ( ServiceList::reverse_iterator i = myServiceList.rbegin();
- i != myServiceList.rend();
- ++i
- )
- {
- VINFO(log) << fn << ": service = " << i->service->name()
- << VINFO_END(log);
-
- i->thread->join();
- delete i->thread;
- i->thread = 0;
- }
-
- myServiceList.clear();
- }
- ReturnCode
- ServiceManager::start()
- {
- const string fn("ServiceManager::start");
- VLog log(fn);
- ReturnCode rc = SUCCESS;
-
- for ( ServiceList::iterator iter = myServiceList.begin();
- rc == SUCCESS && iter != myServiceList.end();
- ++iter
- )
- {
- Service & service = *(iter->service);
-
- Sptr<ControlEvent> startEvent
- = new ControlEvent(ControlEvent::START, myFifo);
-
- int startId = startEvent->getControlEventId();
-
- service.getFifo().add(startEvent);
-
- bool started = false;
- while ( !started )
- {
- bool done = block();
-
- if ( done == true )
- {
- VINFO(log) << fn << ": Exiting on signal." << VINFO_END(log);
- break;
- }
-
- Sptr<Event> event;
-
- while ( !started && myFifo.messageAvailable() )
- {
- event = myFifo.getNext();
- Sptr<ControlEvent> ctrlEvent;
- ctrlEvent.dynamicCast(event);
- if ( ctrlEvent == 0 )
- {
- VWARN(log) << fn << ": Unknown event: "
- << ( event == 0 ? "No event" : event->name() )
- << VWARN_END(log);
- continue;
- }
- if ( ctrlEvent->getType() == ControlEvent::START )
- {
- if ( ctrlEvent->getControlEventId() == startId )
- {
- started = true;
- rc = ctrlEvent->getReturnCode();
- if ( rc != SUCCESS )
- {
- VWARN(log) << fn << ": Service: " << service.name()
- << ", start returned error. shutting down."
- << VWARN_END(log);
- }
- VINFO(log) << fn << ": Service: " << service.name()
- << ", started, rc = " << rc
- << VINFO_END(log);
- }
- else
- {
- VWARN(log) << fn << ": Unknown control event: "
- << *ctrlEvent << VWARN_END(log);
- }
- }
- else
- {
- VWARN(log) << fn << ": Unknown control event: "
- << *ctrlEvent << VWARN_END(log);
- }
- }
- }
- }
- return ( rc );
- }
- ReturnCode
- ServiceManager::run()
- {
- const string fn("ServiceManager::run");
- VLog log(fn);
- ReturnCode rc = SUCCESS;
- bool shutdown = false;
-
- while ( rc == SUCCESS )
- {
- bool done = block();
-
- if ( done == true )
- {
- VINFO(log) << fn << ": exiting on signal." << VINFO_END(log);
- break;
- }
- Sptr<Event> event;
- while ( !shutdown && myFifo.messageAvailable() )
- {
- event = myFifo.getNext();
- Sptr<ControlEvent> ctrlEvent;
- ctrlEvent.dynamicCast(event);
- if ( ctrlEvent == 0 )
- {
- VWARN(log) << fn << ": Unknown event: "
- << ( event == 0 ? "No event" : event->name() )
- << VWARN_END(log);
- }
-
- switch ( ctrlEvent->getType() )
- {
- // We received an unsolicited stop or shutdown message.
- // It's trouble, so let's shutdown.
- //
- case ControlEvent::STOP:
- case ControlEvent::SHUTDOWN:
- {
- rc = !SUCCESS;
- shutdown = true;
- VWARN(log) << fn << ": terminate via failure."
- << VWARN_END(log);
- break;
- }
- default:
- {
- break;
- }
- }
- }
- }
-
- return ( rc );
- }
- void
- ServiceManager::stop()
- {
- const string fn("ServiceManager::stop");
- VLog log(fn);
- for ( ServiceList::reverse_iterator iter = myServiceList.rbegin();
- iter != myServiceList.rend();
- ++iter
- )
- {
- Service & service = *(iter->service);
- Sptr<ControlEvent> stopEvent
- = new ControlEvent(ControlEvent::STOP, myFifo);
- int stopId = stopEvent->getControlEventId();
- service.getFifo().add(stopEvent);
- bool stopped = false;
- while ( !stopped )
- {
- block();
- Sptr<Event> event;
- while ( !stopped && myFifo.messageAvailable() )
- {
- event = myFifo.getNext();
- Sptr<ControlEvent> ctrlEvent;
- ctrlEvent.dynamicCast(event);
- if ( ctrlEvent == 0 )
- {
- VWARN(log) << fn << ": Unknown event: "
- << ( event == 0 ? "No event" : event->name() )
- << VWARN_END(log);
- continue;
- }
- if ( ctrlEvent->getType() == ControlEvent::STOP
- && ctrlEvent->getControlEventId() == stopId
- )
- {
- stopped = true;
- VINFO(log) << fn << ": Serivce: " << service.name()
- << ", stopped." << VINFO_END(log);
- }
- else
- {
- VWARN(log) << fn << ": Unknown service control event: "
- << *ctrlEvent << VWARN_END(log);
- }
- }
- }
- }
- }
- void
- ServiceManager::shutdown()
- {
- const string fn("ServiceManager::shutdown");
- VLog log(fn);
- for ( ServiceList::reverse_iterator iter = myServiceList.rbegin();
- iter != myServiceList.rend();
- ++iter
- )
- {
- Service & service = *(iter->service);
- Sptr<ControlEvent> shutdownEvent;
- shutdownEvent = new ControlEvent(ControlEvent::SHUTDOWN, myFifo);
- service.getFifo().add(shutdownEvent);
- VINFO(log) << fn << ": shutdown sent." << VINFO_END(log);
- }
- }
- void
- ServiceManager::blockSignals()
- {
- if ( mySignalAction )
- {
- Thread::self()->signalHandler().block(mySignalAction->signalSet());
- }
- }
-
-
- void
- ServiceManager::unblockSignals()
- {
- if ( mySignalAction )
- {
- Thread::self()->signalHandler().unblock(mySignalAction->signalSet());
- }
- }
-
- bool
- ServiceManager::signalCaught()
- {
- if ( mySignalAction )
- {
- return ( mySignalAction->signalCaught() );
- }
- return ( false );
- }
- bool
- ServiceManager::block()
- {
- const string fn("ServiceManager::block");
- VLog log(fn);
-
- unblockSignals();
- myFifo.block();
- blockSignals();
- VVERBOSE(log) << fn << ": fifo block returned." << VVERBOSE_END(log);
- return ( signalCaught() );
- }