client/protocol/corba/CorbaDriverFactory.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 Name:      CorbaDriver.cpp
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Comment:   The client driver for the corba protocol
00006 ------------------------------------------------------------------------------*/
00007 
00008 #include <client/protocol/corba/CorbaDriverFactory.h>
00009 #include <util/ErrorCode.h>
00010 #include <util/XmlBlasterException.h>
00011 #include <util/Global.h>
00012 #include <util/lexical_cast.h>
00013 
00014 namespace org {
00015  namespace xmlBlaster {
00016   namespace client {
00017    namespace protocol {
00018     namespace corba {
00019 
00020 using namespace std;
00021 using namespace org::xmlBlaster::util;
00022 using namespace org::xmlBlaster::util::thread;
00023 
00024 CorbaDriverFactory::CorbaDriverFactory(Global& global, CORBA::ORB_ptr orb)
00025    : Thread(), 
00026      ME("CorbaDriverFactory"), 
00027      drivers_(),
00028      mutex_(),
00029      getterMutex_(),
00030      orbIsThreadSafe_(ORB_IS_THREAD_SAFE)
00031 {
00032    org::xmlBlaster::util::I_Log& log = global.getLog("org.xmlBlaster.client.protocol.corba");
00033    if (log.call()) 
00034       log.call("CorbaDriver", string("Constructor orbIsThreadSafe_=") + lexical_cast<std::string>(orbIsThreadSafe_));
00035    doRun_     = true;
00036    isRunning_ = false;
00037 
00038    if (orb) {
00039       orb_ = orb;
00040       isOwnOrb_ = false;
00041    }
00042    else {
00043       int args                 = global.getArgs();
00044       const char * const* argc = global.getArgc();
00045       orb_ = CORBA::ORB_init(args, const_cast<char **>(argc));
00046       isOwnOrb_ = true;
00047    }
00048 }
00049 
00050 CorbaDriverFactory::CorbaDriverFactory(const CorbaDriverFactory& factory)
00051 : Thread(), 
00052   ME(factory.ME), 
00053   drivers_(),
00054   doRun_(true),
00055   isRunning_(false),
00056   mutex_(),
00057   getterMutex_(),
00058   orbIsThreadSafe_(factory.orbIsThreadSafe_),
00059   orb_(factory.orb_),
00060   isOwnOrb_(factory.isOwnOrb_)
00061 {
00062    throw XmlBlasterException(INTERNAL_NOTIMPLEMENTED, ME, "private copy constructor");
00063 }
00064 
00065 CorbaDriverFactory& CorbaDriverFactory::operator =(const CorbaDriverFactory&)
00066 {
00067    throw XmlBlasterException(INTERNAL_NOTIMPLEMENTED, ME, "private assignement operator");
00068 }
00069 
00070 CorbaDriverFactory::~CorbaDriverFactory()
00071 {
00072    //if (log_.call()) log_.call(ME, "Destructor start");
00073    Lock lock(getterMutex_);
00074    DriversMap::iterator iter = drivers_.begin();
00075    while (iter != drivers_.end()) {
00076       delete ((*iter).second).first;
00077       iter++;
00078    }
00079    drivers_.erase(drivers_.begin(), drivers_.end());
00080    //if (log_.trace()) log_.trace(ME, "erased all drivers");
00081    if (!orbIsThreadSafe_) { // stop the running thread
00082       if (isRunning_) {
00083         //if (log_.trace()) log_.trace(ME, "stopping the thread which performs orb work");
00084         doRun_ = false;
00085         join();
00086       }
00087    }
00088    if (isOwnOrb_) {
00089       if (!CORBA::is_nil(orb_)) {
00090          //if (log_.trace()) log_.trace(ME, "shutting down the orb");
00091          orb_->shutdown(true);
00092 #if      !(defined(_WINDOWS) && defined(XMLBLASTER_TAO))
00093          //if (log_.trace()) log_.trace(ME, "destroying the orb");
00094          orb_->destroy();         // blocks forever on Windows XP VC7 with TAO 1.3
00095 #endif
00096          //if (log_.trace()) log_.trace(ME, "releasing the orb");
00097          CORBA::release(orb_);
00098       }                                 
00099    }
00100    //if (log_.trace()) log_.trace(ME, "Destructor end");
00101 }
00102 
00103 CorbaDriverFactory* CorbaDriverFactory::factory_ = NULL;
00104 
00105 CorbaDriverFactory& CorbaDriverFactory::getFactory(Global& global, CORBA::ORB_ptr orb)
00106 {
00107    //static CorbaDriverFactory factory(global, orb);
00108    //return factory;
00109    if(factory_ == NULL)
00110    {
00111      factory_ = new CorbaDriverFactory(global, orb);
00112      org::xmlBlaster::util::Object_Lifetime_Manager::instance()->manage_object("XB_CorbaDriverFactory", factory_);  // if not pre-allocated.
00113    }
00114    return *factory_;
00115 }
00116 
00117 CorbaDriver& CorbaDriverFactory::getDriverInstance(Global* global)
00118 {
00119    std::string instanceName = lexical_cast<std::string>(global);
00120    I_Log& log = global->getLog("org.xmlBlaster.client.protocol.corba");
00121    if (log.call()) log.call("CorbaDriver", string("getInstance for ") + instanceName);
00122    CorbaDriver*  driver = NULL;
00123    int count = 1;
00124    {
00125       Lock lock(getterMutex_);
00126       DriversMap::iterator iter = drivers_.find(global);
00127       if (iter == drivers_.end()) {
00128          if (log.trace()) log.trace("CorbaDriver", string("created a new instance for ") + instanceName);
00129 
00130          CORBA::ORB_ptr orb = CORBA::ORB::_duplicate(orb_);
00131          driver = new CorbaDriver(*global, mutex_, instanceName, orb);
00132          // initially the counter is set to 1
00133          drivers_.insert(DriversMap::value_type(global, pair<CorbaDriver*, int>(driver, 1)));
00134 
00135          // In a thread to support single thread orb->performwork to dispatch corba main loop
00136          const bool detached = false;
00137          if (!isRunning_) start(detached); // if threadSafe isRunning_ will never be set to true
00138       }
00139       else {
00140          driver = ((*iter).second).first;
00141          count = ((*iter).second).second++; // this is the counter ...
00142       }
00143    }
00144    if (log.trace()) 
00145       log.trace("CorbaDriver", string("number of instances for '") + instanceName + "' are " + lexical_cast<std::string>(count));
00146    return *driver;
00147 }
00148 
00149 
00150 int CorbaDriverFactory::killDriverInstance(Global* global)
00151 {
00152    std::string instanceName = lexical_cast<std::string>(global);
00153    I_Log& log = global->getLog("org.xmlBlaster.client.protocol.corba");
00154    log.call(ME, "killDriverInstance");
00155    Lock lock(getterMutex_);
00156    DriversMap::iterator iter = drivers_.find(global);
00157    if (iter == drivers_.end()) return -1;
00158    int ret = --(*iter).second.second;
00159    if (log.trace()) log.trace(ME, string("instances before deleting ") + lexical_cast<std::string>(ret));
00160    if (ret <= 0) {
00161       if (log.trace()) log.trace(ME, string("kill instance '") + instanceName + "' will be deleted now");
00162       // do remove it since the counter is zero
00163       CorbaDriver* driver = (*iter).second.first;
00164       drivers_.erase(iter);
00165       delete driver;
00166       if (drivers_.empty() && isOwnOrb_) {
00167          if (!orbIsThreadSafe_) {
00168             if (isRunning_) {
00169                doRun_ = false;
00170                join(); // wait until the run thread has returned ...
00171             }
00172          }
00173 //         orb_->shutdown(true);
00174 //         orb_->destroy();
00175          return 0;
00176       }
00177    }
00178    if (log.trace()) 
00179       log.trace("CorbaDriver", string("kill instance '") + instanceName + "' the number of references is " + lexical_cast<std::string>(ret));
00180    return ret;
00181 }
00182 
00183 bool CorbaDriverFactory::orbRun()
00184 {
00185    if (orb_ == NULL) return false;
00186    orb_->run();
00187    return true;
00188 }
00189 
00190 void CorbaDriverFactory::run()
00191 {
00192    //if (log_.trace()) log_.trace(ME, "the corba loop starts now");
00193    if (!isOwnOrb_) return;
00194 
00195    if (orbIsThreadSafe_) {
00196       orbRun(); // e.g. TAO
00197    }
00198    else {
00199       doRun_ = true;    // e.g. MICO
00200       if (isRunning_) return;
00201       //log_.info(ME, "the corba loop starts now");
00202       isRunning_ = true;
00203 
00204       try {
00205          while (doRun_) {
00206             {  // this is for the scope of the lock ...
00207                Lock lock(mutex_, orbIsThreadSafe_);
00208                //if (log_.trace()) log_.trace(ME, "sweep in running thread");
00209                while (orb_->work_pending()) orb_->perform_work();
00210             }
00211             //if (log_.trace()) log_.trace(ME, "sleeping for 20 millis");
00212             sleep(20); // sleep 20 milliseconds
00213             //if (log_.trace()) log_.trace(ME, string("awakening, doRun is: ") + lexical_cast<std::string>(doRun_));
00214          }
00215       }
00216       catch(CORBA::Exception &ex) {
00217          //log_.warn(ME, string("a corba exception occured in the running thread. It has now been stopped: ") + to_string(ex));
00218          std::cerr << ME << " " << string("a corba exception occured in the running thread. It has now been stopped: ") << to_string(ex) << std::endl;
00219       }
00220       catch (exception &ex) {
00221          //log_.warn(ME, string("an exception occured in the running thread. It has now been stopped: ") + ex.what());
00222          std::cerr << ME << string("an exception occured in the running thread. It has now been stopped: ") << ex.what() << std::endl;
00223       }
00224 
00225       catch (...) {
00226          //log_.warn(ME, "an unknown exception occured in the running thread. It has now been stopped");
00227          std::cerr << ME << "an unknown exception occured in the running thread. It has now been stopped" << std::endl;
00228       }
00229 
00230       //log_.info(ME, "the corba loop has ended now");
00231       isRunning_ = false;
00232    }
00233 }
00234 
00235 
00236 }}}}} // namespaces
00237