util/EmbeddedServer.cpp

Go to the documentation of this file.
00001 /*-----------------------------------------------------------------------------
00002 Name:      EmbeddedServer.cpp
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Comment:   Testing the Timeout Features
00006 -----------------------------------------------------------------------------*/
00007 
00008 #include <util/EmbeddedServer.h>
00009 #include <util/Global.h>
00010 #include <util/lexical_cast.h>
00011 
00012 namespace org { namespace xmlBlaster { namespace util {
00013 
00014 using namespace std;
00015 using namespace org::xmlBlaster::util;
00016 using namespace org::xmlBlaster::util::qos;
00017 using namespace org::xmlBlaster::util::qos::address;
00018 using namespace org::xmlBlaster::util::thread;
00019 using namespace org::xmlBlaster::client;
00020 using namespace org::xmlBlaster::client::qos;
00021 using namespace org::xmlBlaster::client::key;
00022 
00023 EmbeddedServerRunner::EmbeddedServerRunner(EmbeddedServer& owner) : ME("EmbeddedServerRunner"), owner_(owner)
00024 {
00025 }
00026 
00027 void EmbeddedServerRunner::run()
00028 {  
00029 #if !defined(WINCE)
00030    if (owner_.log_.call()) owner_.log_.call(ME, "::run");
00031 
00032    if (owner_.isRunning_) {
00033       owner_.log_.warn(ME, "the current server is already running. ignoring the start command.");
00034       return;
00035    }
00036 /* currently commented out (could give problems if multithreading not supported)
00037    if (isSomeServerResponding()) {
00038       log_.error(ME, "an external server is already running. Please shut it down");
00039       return;
00040    }
00041 */
00042    string cmdLine = string("java ") + owner_.jvmArguments_ + " org.xmlBlaster.Main " + owner_.applArguments_;
00043    owner_.log_.info(ME, "starting the embedded server with command line: '" + cmdLine + "'");
00044    if (system(NULL)) {
00045       try {
00046          owner_.isRunning_ = true;
00047          int ret = system(cmdLine.c_str());
00048          owner_.log_.info(ME, "the embedded server with command line: '" + cmdLine + "' has been stopped, return code is: " + lexical_cast<std::string>(ret));
00049          owner_.isRunning_ = false;
00050       }
00051       catch (exception& ex) {
00052          owner_.log_.error(ME,string("could not start the server: ") + ex.what());
00053          owner_.isRunning_ = false;
00054       }
00055       catch (...) {
00056          owner_.log_.error(ME,"could not start the server: an unknown exception occured");
00057          owner_.isRunning_ = false;
00058       }
00059    }
00060    else {
00061       owner_.log_.error(ME, "could not start the embedded server: your OS does not have a command processor, plase start your server manually");
00062       owner_.isRunning_ = false;
00063    }
00064 #endif 
00065 }
00066 
00067 
00068 EmbeddedServer::EmbeddedServer(Global& glob, const string& jvmArguments, const string& applArguments, XmlBlasterAccess* externalAccess) 
00069    : ME("EmbeddedServer"), 
00070      global_(glob), 
00071      log_(glob.getLog("org.xmlBlaster.util"))
00072 {
00073    isRunning_      = false;
00074    applArguments_  = applArguments;
00075    jvmArguments_   = jvmArguments;
00076    externalAccess_ = externalAccess; 
00077    runner_         = false;
00078 }
00079 
00080 EmbeddedServer::~EmbeddedServer()
00081 {
00082    log_.call(ME, "destructor");
00083    // don't try to stop it with the borrowed external connection here since it could be a 
00084    // failsafe connection (which would queue this publish in case it is already disconnected)
00085    externalAccess_ = NULL;
00086    stop(false, false);
00087    log_.trace(ME, "destructor: stopped the server");
00088 }
00089 
00090 bool EmbeddedServer::start(bool blockUntilUp)
00091 {
00092    if (log_.call()) log_.call(ME, "start");
00093 
00094    if (runner_) return false;
00095    runner_ = new EmbeddedServerRunner(*this);
00096         const bool detached = false;
00097    bool ret  = runner_->start(detached);
00098    if (ret && blockUntilUp) {
00099       if (log_.trace()) log_.trace(ME, "start: setting up for a client connection");
00100       bool isConnected = false;
00101       int count = 0;
00102       while (!isConnected && count < 60) {
00103          if (log_.trace()) log_.trace(ME, "start: establishing a connection: trial nr. '" + lexical_cast<std::string>(count) + "'");
00104          try {
00105             count++;
00106             XmlBlasterAccess conn(global_);
00107             ConnectQos connQos(global_, "embeddedKiller", "secret");
00108             Address *address = new Address(global_);
00109             address->setDelay(0);
00110             connQos.setAddress(address);
00111             // to be sure not to store the kill msg in a client queue ...
00112             conn.connect(connQos, NULL);
00113             log_.trace(ME, "successfully connected to the embedded server");
00114             conn.disconnect(DisconnectQos(global_));
00115             log_.trace(ME, "successfully disconnected from the embedded server");
00116             isConnected = true;
00117          }
00118          catch (XmlBlasterException& ex) {
00119             if (log_.trace()) log_.trace(ME, "exception occurred when connecting: " + ex.toXml());
00120             if ( !ex.isCommunication() ) throw ex;
00121             if (log_.trace()) log_.trace(ME, "the exception occurred was a communication exception (connection not established yet). Will retry (sleep for 2 sec)");
00122             Thread::sleepSecs(2);
00123          }
00124          count++;
00125       }
00126       if (!isConnected) {
00127          log_.error(ME, "maximum number of retrials to establish a connection failed ");
00128          throw XmlBlasterException(COMMUNICATION_NOCONNECTION, ME, " start: could not establish a connection to the embedded server");
00129       }
00130 
00131    }
00132    return ret;
00133 }
00134 
00135 bool EmbeddedServer::stop(bool shutdownExternal, bool warnIfNotRunning)
00136 {
00137    if (log_.call()) log_.call(ME, "stop");
00138    if (!isRunning_ && !shutdownExternal) {
00139       if (warnIfNotRunning)
00140          log_.warn(ME, "the current embedded server is not running. Ignoring this 'stop' command");
00141       return false;
00142    }
00143 
00144    PublishKey key(global_);
00145    key.setOid("__cmd:?exit=0");
00146    PublishQos qos(global_);
00147    MessageUnit msgUnit(key, "0", qos);
00148 
00149    XmlBlasterAccess conn(global_);
00150    try {
00151       ConnectQos connQos(global_, "embeddedKiller", "secret");
00152       // to be sure not to store the kill msg in a client queue ...
00153       Address *address = new Address(global_);
00154       address->setDelay(0);
00155       connQos.setAddress(address);
00156       conn.connect(connQos, NULL);
00157    }
00158    catch (XmlBlasterException& ex) {
00159       if ( ex.isCommunication() ) {
00160          log_.warn(ME, "there is no server responding, ignoring this 'stop' command");
00161          return false;
00162       }
00163       throw ex;
00164    }
00165    conn.publish(msgUnit);
00166 
00167    if (log_.trace()) log_.trace(ME, "stop: going to join the threads");
00168    if (runner_) runner_->join();
00169 
00170    delete runner_;
00171    runner_ = NULL;
00172    if (log_.trace()) log_.trace(ME, "stop completed");
00173    return true;
00174 }
00175 
00176 
00177 bool EmbeddedServer::isSomeServerResponding() const
00178 {
00179    try {
00180       SessionQos sessionQos(global_);
00181       sessionQos.setAbsoluteName("embeddedTester");
00182       ConnectQos connQos(global_, "embeddedTester", "secret");
00183       connQos.setSessionQos(sessionQos);
00184       if (externalAccess_) {
00185          externalAccess_->connect(connQos, NULL);
00186       }
00187       else {
00188          XmlBlasterAccess conn(global_);
00189          conn.connect(connQos, NULL);
00190       }
00191       return true;
00192    }
00193    catch (XmlBlasterException& ex) {
00194       if (ex.isCommunication()) {
00195          return false;
00196       }
00197       throw ex; // then it is another exception
00198    }
00199 }
00200 
00201 
00202 }}}
00203 
00204 
00205 #ifdef _XMLBLASTER_CLASSTEST
00206 
00207 using namespace std;
00208 using namespace org::xmlBlaster::util;
00209 
00210 
00211 int main(int args, char* argv[])
00212 {
00213    Global& glob = Global::getInstance();
00214    glob.initialize(args, argv);
00215   
00216    EmbeddedServer server(glob, ""); // , "-info false -error false -warn false");
00217    server.start();
00218    Thread::sleepSecs(10);
00219    server.stop();
00220    Thread::sleepSecs(10);
00221    server.start();
00222    Thread::sleepSecs(10);
00223 
00224    return 0;
00225 }
00226 
00227 #endif
00228