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