Service.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 Service_cxx_Version =
- "$Id: Service.cxx,v 1.6 2001/06/27 23:12:00 bko Exp $";
- #include "Service.hxx"
- #include "VException.hxx"
- #include "VLog.hxx"
- #include <cassert>
- using Vocal::Services::Service;
- using Vocal::Services::Event;
- using Vocal::Behavioral::EventObserver;
- using Vocal::Behavioral::EventSubject;
- using Vocal::Logging::VLog;
- using Vocal::ReturnCode;
- using Vocal::SUCCESS;
- Service::Service(
- FifoBase< Sptr<Event> > & serviceMgrFifo,
- const char * name
- )
- : myServiceManagerFifo(serviceMgrFifo),
- myName(name ? name : "Service")
- {
- }
- Service::~Service()
- {
- }
- FifoBase< Sptr<Event> > &
- Service::getServiceManagerFifo()
- {
- return ( myServiceManagerFifo );
- }
-
- const FifoBase< Sptr<Event> > &
- Service::getServiceManagerFifo() const
- {
- return ( myServiceManagerFifo );
- }
-
- EventSubject< Sptr<Event> > &
- Service::getEventSubject()
- {
- return ( mySubject );
- }
- const EventSubject< Sptr<Event> > &
- Service::getEventSubject() const
- {
- return ( mySubject );
- }
- ReturnCode
- Service::run()
- {
- const string fn("Service::run");
- VLog log(fn);
- VDEBUG(log) << fn << ": " << myName << " starting." << VDEBUG_END(log);
- ReturnCode rc = SUCCESS;
- bool done = false;
- while ( !done )
- {
- int numberMsgActive = 0;
- // Wait for activity.
- //
- try
- {
- VVERBOSE(log)<< fn << ": before wait"
- << ", number msgs active = " << numberMsgActive
- << VVERBOSE_END(log);
- numberMsgActive = getFifo().block();
- VVERBOSE(log) << fn << ": after wait"
- << ", number msgs active = " << numberMsgActive
- << VVERBOSE_END(log);
- }
- catch ( VException & exception )
- {
- done = onVException(exception);
- if ( done )
- {
- rc = exception.getError();
- }
- continue;
- }
- catch ( ... )
- {
- done = onException();
-
- if ( done )
- {
- rc = !SUCCESS;
- }
- continue;
- }
- // Process the messages.
- //
- try
- {
- done = processMessages(numberMsgActive);
- }
- catch ( VException & exception )
- {
- done = onVException(exception);
-
- if ( done )
- {
- rc = exception.getError();
- }
- continue;
- }
- catch ( ... )
- {
- done = onException();
-
- if ( done )
- {
- rc = !SUCCESS;
- }
- continue;
- }
- }
- VDEBUG(log) << fn << ": " << myName << " exiting"
- << ", rc = " << rc << VDEBUG_END(log);
- return ( rc );
- }
- void
- Service::subscribe(EventObserver< Sptr<Event> > & observer)
- {
- const string fn("Service::subscribe");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": observer = " << observer << VDEBUG_END(log);
-
- mySubject.attach(observer);
- VVERBOSE(log) << fn << ": subject = { " << mySubject << " }" << VVERBOSE_END(log);
- }
- void
- Service::unsubscribe(EventObserver< Sptr<Event> > & observer)
- {
- const string fn("Service::unsubscribe");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": observer = " << observer << VDEBUG_END(log);
-
- mySubject.detach(observer);
- VVERBOSE(log) << fn << ": subject = { " << mySubject << " }" << VVERBOSE_END(log);
- }
- ostream &
- Service::writeTo(ostream & out) const
- {
- return ( out << myName << ", subject = " << mySubject );
- }
- const string &
- Service::name() const
- {
- return ( myName );
- }
- ReturnCode
- Service::onStart()
- {
- return ( SUCCESS );
- }
- ReturnCode
- Service::onStop()
- {
- return ( SUCCESS );
- }
- void
- Service::onShutdown()
- {
- }
-
- bool
- Service::onVException(VException & exception)
- {
- const string fn("Service::onException");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": ignoring." << VDEBUG_END(log);
- return ( false );
- }
- bool
- Service::onException()
- {
- const string fn("Service::onException");
- VLog log(fn);
-
- VDEBUG(log) << fn << ": doing a hardShutdown." << VDEBUG_END(log);
- hardShutdown(!SUCCESS);
- return ( true );
- }
- bool
- Service::processMessages(int)
- {
- const string fn("Service::processMessages");
- VLog log(fn);
-
- bool done = false;
- while ( getFifo().messageAvailable() )
- {
- VVERBOSE(log) << fn << ": before getMessage." << VVERBOSE_END(log);
- Sptr<Event> event;
- try
- {
- event = getFifo().getNext();
- }
- catch ( ... )
- {
- // We checked messageAvailable, so we shouldn't ever get here.
- //
- assert(0);
- }
- Sptr<ControlEvent> ctrlEvent;
- ctrlEvent.dynamicCast(event);
- // Service control events detected. Call the appropriate
- // Service callbacks.
- //
- if ( ctrlEvent != 0 )
- {
- VDEBUG(log) << fn << ": event = { " << *ctrlEvent
- << " }" << VDEBUG_END(log);
- switch ( ctrlEvent->getType() )
- {
- case ControlEvent::START:
- {
- start(ctrlEvent);
- break;
- }
- case ControlEvent::STOP:
- {
- stop(ctrlEvent);
- break;
- }
- case ControlEvent::SHUTDOWN:
- {
- shutdown(ctrlEvent);
- done = true;
- break;
- }
- default:
- {
- // Perhaps someone has derived off of the
- // ControlEvent and wants to see it.
- //
- mySubject.setEvent(event);
- break;
- }
- }
- }
- // Unknown event, give it to the EventSubject to distribute it
- // to interested observers.
- //
- else
- {
- mySubject.setEvent(event);
- }
- }
- return ( done );
- }
- void
- Service::hardShutdown(ReturnCode errorCode)
- {
- const string fn("Service::hardShutdown");
- VLog log(fn);
- VDEBUG(log) << fn << ": stopping service"
- << ", error = " << errorCode << VDEBUG_END(log);
- shutdown(0);
- Sptr<ControlEvent> stopEvent
- = new ControlEvent(ControlEvent::STOP, getFifo());
- stopEvent->setReturnCode(errorCode);
-
- myServiceManagerFifo.add(stopEvent);
- VDEBUG(log) << fn << ": shutting down service"
- << ", error = " << errorCode << VDEBUG_END(log);
-
- Sptr<ControlEvent> shutdownEvent
- = new ControlEvent(ControlEvent::SHUTDOWN, getFifo());
- shutdownEvent->setReturnCode(errorCode);
- myServiceManagerFifo.add(shutdownEvent);
- }
- void
- Service::start(Sptr<ControlEvent> startEvent)
- {
- const string fn("Service::start");
- VLog log(fn);
- ReturnCode rc = SUCCESS;
-
- FifoBase< Sptr<Event> > * serviceMgrFifo = startEvent->getReplyFifo();
- if ( !serviceMgrFifo || *serviceMgrFifo != myServiceManagerFifo )
- {
- VWARN(log) << fn << ": received unathorized start event, event = "
- << *startEvent << VWARN_END(log);
- rc = !SUCCESS;
- }
- else
- {
- rc = onStart();
- }
- startEvent->setReturnCode(rc);
- serviceMgrFifo->add(startEvent);
- VDEBUG(log) << fn << ": returning start = " << *startEvent
- << VDEBUG_END(log);
- }
- void
- Service::stop(Sptr<ControlEvent> stopEvent)
- {
- const string fn("Service::onStop");
- VLog log(fn);
-
- ReturnCode rc = SUCCESS;
-
- FifoBase< Sptr<Event> > * serviceMgrFifo = stopEvent->getReplyFifo();
-
- if ( !serviceMgrFifo || *serviceMgrFifo != myServiceManagerFifo )
- {
- VWARN(log) << fn << ": received unathorized stop event, event = "
- << *stopEvent << VWARN_END(log);
-
- rc = !SUCCESS;
- }
- else
- {
- rc = onStop();
- }
- stopEvent->setReturnCode(rc);
- serviceMgrFifo->add(stopEvent);
- VDEBUG(log) << fn << ": returning stop = " << *stopEvent
- << VDEBUG_END(log);
- }
- void
- Service::shutdown(Sptr<ControlEvent> shutdownEvent)
- {
- const string fn("Service::onShutdown");
- VLog log(fn);
-
- if ( shutdownEvent == 0 )
- {
- VDEBUG(log) << fn << ": hard shutdown." << VDEBUG_END(log);
- return;
- }
-
- FifoBase< Sptr<Event> > * serviceMgrFifo = shutdownEvent->getReplyFifo();
-
- if ( !serviceMgrFifo || *serviceMgrFifo != myServiceManagerFifo )
- {
- VWARN(log) << fn << ": received unathorized shutdown event, event = "
- << *shutdownEvent << VWARN_END(log);
- return;
- }
- onShutdown();
-
- VDEBUG(log) << fn << ": recevied shutdown = " << *shutdownEvent
- << VDEBUG_END(log);
- }