• Classes
  • Modules
  • Namespaces
  • Files
  • Related Pages
  • File List
  • File Members

acsDaemonImpl.h

Go to the documentation of this file.
00001 #ifndef _ACS_DAEMON_IMPL_H_
00002 #define _ACS_DAEMON_IMPL_H_
00003 
00004 /*******************************************************************************
00005 *    ALMA - Atacama Large Millimiter Array
00006 *    (c) European Southern Observatory, 2002
00007 *    Copyright by ESO (in the framework of the ALMA collaboration)
00008 *    and Cosylab 2002, All rights reserved
00009 *
00010 *    This library is free software; you can redistribute it and/or
00011 *    modify it under the terms of the GNU Lesser General Public
00012 *    License as published by the Free Software Foundation; either
00013 *    version 2.1 of the License, or (at your option) any later version.
00014 *
00015 *    This library is distributed in the hope that it will be useful,
00016 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 *    Lesser General Public License for more details.
00019 *
00020 *    You should have received a copy of the GNU Lesser General Public
00021 *    License along with this library; if not, write to the Free Software
00022 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00023 *
00024 * "@(#) $Id: acsDaemonImpl.h,v 1.10 2011/10/21 13:20:39 msekoran Exp $"
00025 *
00026 * who       when      what
00027 * --------  --------  ----------------------------------------------
00028 * msekoran 2006-06-21 created 
00029 * agrimstr 2007-11-07 refactored common daemon implementation code to
00030 *                     template classes
00031 */
00032 
00033 #ifndef __cplusplus
00034 #error This is a C++ include file and cannot be used from plain C
00035 #endif
00036 
00037 #include "acsdaemonS.h"
00038 #include <ace/SString.h>
00039 #include "logging.h"
00040 #include <getopt.h>
00041 #include <acsutilPorts.h>
00042 #include <tao/IORTable/IORTable.h>
00043 #include <acserr.h>
00044 #include <acsdaemonErrType.h>
00045 #include <ACSErrTypeCommon.h>
00046 #include "acsdaemonORBTask.h"
00047 
00054 template <typename T>
00055 class ACSDaemonServiceImpl {
00056 
00057   public:
00058     
00062     ACSDaemonServiceImpl(LoggingProxy &logProxy, bool isProtected);
00063   
00067     virtual ~ACSDaemonServiceImpl();
00068     
00072     bool 
00073     isInitialized() { return m_isInitialized; }
00074     
00078     bool 
00079     isProtected() { return m_isProtected; }
00080     
00081 
00085     std::string
00086     getPort() { return handler.getPort(); }
00087 
00091     std::string
00092     getName() { return handler.getName(); }
00093 
00097     int
00098     startup (int argc, char *argv[]);
00099 
00104     int 
00105     run ();
00106 
00110     void
00111     shutdown (bool wait_for_completition); 
00112 
00116     const char*
00117     getIOR() const { return m_ior.in(); };
00118     
00119   protected:
00123     virtual int 
00124     init_ORB (int& argc, char *argv []);
00125 
00126     //--Common data members-------------------------------------
00127 
00129     bool m_isInitialized;
00130 
00132     bool m_isProtected;
00133 
00135     bool m_blockTermination;
00136 
00138     CORBA::ORB_var m_orb;
00139 
00141     LoggingProxy &m_logProxy;
00142 
00144     CORBA::String_var m_ior;
00145 
00147     T handler;
00148 };
00149 
00150 template <typename T>
00151 ACSDaemonServiceImpl<T>::ACSDaemonServiceImpl (LoggingProxy &logProxy, bool isProtected) :
00152     m_isInitialized(false), m_logProxy(logProxy)
00153 {
00154     // noop here
00155 
00156     m_isInitialized = true;
00157 
00158     m_isProtected = isProtected;
00159 
00160     m_blockTermination = false;
00161 
00162     ACS_CHECK_LOGGER;
00163     // daemon is a standalone process, replace global logger with named logger
00164     Logging::Logger::setGlobalLogger(getNamedLogger(handler.getName()));
00165 
00166     handler.setService(this);
00167 }
00168 
00169 template <typename T>
00170 ACSDaemonServiceImpl<T>::~ACSDaemonServiceImpl (void)
00171 {
00172 }
00173 
00174 template <typename T>
00175 int ACSDaemonServiceImpl<T>::startup (int argc, char *argv[])
00176 {
00177     ACS_SHORT_LOG ((LM_INFO, "Starting up the %s...", handler.getName().c_str()));
00178 
00179     // Initalize the ORB.
00180     if (init_ORB (argc, argv) != 0)
00181         {
00182         return -1;
00183         }
00184 
00185     // Initialize AES.
00186     if (!ACSError::init(m_orb.in()))
00187         {
00188         ACS_SHORT_LOG ((LM_ERROR, "Failed to initalize the ACS Error System."));
00189         return -1;
00190         }
00191 
00192     ACS_SHORT_LOG ((LM_INFO, "%s is initialized.", handler.getName().c_str()));
00193 
00194     return 0;
00195 }
00196 
00197 template <typename T>
00198 int ACSDaemonServiceImpl<T>::run (void)
00199 {
00200     ACS_SHORT_LOG ((LM_INFO, "%s is up and running...", handler.getName().c_str()));
00201 
00202   
00203     try
00204         {
00205         handler.initialize(m_orb.in());
00206 //      this->m_orb->run ();
00207 
00208       // constrcut CORBA ORB request handler task
00209       ORBTask task (this->m_orb.in(), &m_logProxy);
00210 const int m_serverThreads = 5;
00211       // activate task, i.e. spawn threads and handle requests
00212       if (task.activate (THR_NEW_LWP | THR_JOINABLE, m_serverThreads) == 0)
00213           // wait until CORBA ORB is shutdown or destroyed
00214           task.thr_mgr()->wait ();
00215       else
00216         {
00217           // failed to spawn threads
00218           ACS_LOG(LM_RUNTIME_CONTEXT, "ACSDaemonServiceImpl<T>::run", (LM_INFO, "Failed to activate CORBA ORB request handler threads..."));
00219           return -1;
00220         }
00221 
00222         }
00223     catch(...)
00224         {
00225         return -1;
00226         }
00227 
00228     return 0;
00229 }
00230 
00231 template <typename T>
00232 void ACSDaemonServiceImpl<T>::shutdown (bool wait_for_completition)
00233 {
00234     if (!m_blockTermination)
00235     {
00236         ACS_SHORT_LOG ((LM_INFO, "Stopping the %s...", this->getName().c_str()));
00237         m_blockTermination=true;
00238         // shutdown the ORB.
00239         if (!CORBA::is_nil (m_orb.in ()))
00240         {
00241             handler.dispose(m_orb.in());
00242             this->m_orb->shutdown (wait_for_completition);
00243         }
00244         // shutdown AES
00245         ACSError::done();
00246     }
00247 }
00248 
00249 template <typename T>
00250 int ACSDaemonServiceImpl<T>::init_ORB  (int& argc, char *argv [])
00251 {
00252     m_orb = CORBA::ORB_init(argc, argv, "TAO");
00253 
00254     try
00255         {
00256         // get a reference to the RootPOA
00257         CORBA::Object_var obj = m_orb->resolve_initial_references("RootPOA");
00258         PortableServer::POA_var root_poa = PortableServer::POA::_narrow(obj.in());
00259         PortableServer::POAManager_var poa_manager = root_poa->the_POAManager();
00260       
00261         // create policies
00262         CORBA::PolicyList policy_list;
00263         policy_list.length(5);
00264         policy_list[0] = root_poa->create_request_processing_policy(PortableServer::USE_DEFAULT_SERVANT);
00265         policy_list[1] =  root_poa->create_id_uniqueness_policy(PortableServer::MULTIPLE_ID);
00266         policy_list[2] = root_poa->create_id_assignment_policy(PortableServer::USER_ID); 
00267         policy_list[3] = root_poa->create_servant_retention_policy(PortableServer::NON_RETAIN); 
00268         policy_list[4] =  root_poa->create_lifespan_policy(PortableServer::PERSISTENT);
00269       
00270         // create a ACSDaemon POA with policies 
00271         PortableServer::POA_var poa = root_poa->create_POA(handler.getType().c_str(), poa_manager.in(), policy_list);
00272 
00273         // destroy policies
00274         for (CORBA::ULong i = 0; i < policy_list.length(); ++i)
00275             {
00276             CORBA::Policy_ptr policy = policy_list[i];
00277             policy->destroy();
00278             }
00279 
00280         // set as default servant
00281         poa->set_servant(&handler);
00282 
00283         // create reference
00284         PortableServer::ObjectId_var oid = PortableServer::string_to_ObjectId(handler.getType().c_str());
00285         obj = poa->create_reference_with_id (oid.in(), handler._interface_repository_id());
00286         m_ior = m_orb->object_to_string(obj.in());
00287 
00288         // bind to IOR table
00289         CORBA::Object_var table_object = m_orb->resolve_initial_references("IORTable");
00290         IORTable::Table_var adapter = IORTable::Table::_narrow(table_object.in());
00291       
00292         if (CORBA::is_nil(adapter.in()))
00293             {
00294             ACS_SHORT_LOG ((LM_ERROR, "Nil IORTable"));
00295             return -1;
00296             }
00297         else
00298             {
00299             adapter->bind(handler.getType().c_str(), m_ior.in());
00300             }
00301 
00302         // activate POA
00303         poa_manager->activate();
00304 
00305         ACS_SHORT_LOG((LM_INFO, "%s is waiting for incoming requests.", handler.getName().c_str()));
00306       
00307         }
00308     catch( CORBA::Exception &ex )
00309         {
00310         ACE_PRINT_EXCEPTION (ex, "EXCEPTION CAUGHT");
00311         return -1;
00312         }
00313   
00314     return 0;
00315 }
00316 
00324 template <typename T>
00325 class acsDaemonImpl
00326 {
00327 
00328   public:
00329 
00333     acsDaemonImpl(int argc, char *argv[]);
00334     
00338     ~acsDaemonImpl();
00339     
00343     void usage(const char *argv);
00344 
00348     int run();
00349 
00353     void shutdown();
00354 
00355   private:
00356 
00358     ACSDaemonServiceImpl<T> *service;
00359 
00361     ACE_CString iorFile;
00362 
00364     ACE_CString ORBEndpoint;
00365 
00367     int nargc;
00368     char** nargv;
00369     
00371     LoggingProxy *m_logger;
00372 };
00373 
00374 
00376 static struct option long_options[] = {
00377     {"help",        no_argument,       0, 'h'},
00378     {"outfile",     required_argument, 0, 'o'},
00379     {"ORBEndpoint", required_argument, 0, 'O'},
00380     {"unprotected", no_argument,       0, 'u'},
00381     {0, 0, 0, '\0'}};
00382 
00383 template <typename T>
00384 void acsDaemonImpl<T>::usage(const char *argv)
00385 {
00386     ACE_OS::printf ("\n\tusage: %s {-h} [-O iiop://ip:port] [-o iorfile]\n", argv);
00387     ACE_OS::printf ("\t   -h, --help         show this help message\n");
00388     ACE_OS::printf ("\t   -O, --ORBEndpoint  ORB end point\n");
00389     ACE_OS::printf ("\t   -o, --outfile      IOR output file\n");
00390     ACE_OS::printf ("\t   -u, --unprotected  start in unprotected mode\n");
00391 }
00392 
00393 template <typename T>
00394 acsDaemonImpl<T>::acsDaemonImpl(int argc, char *argv[])
00395 {
00396     nargc = 0;
00397     nargv = 0;
00398     service = 0;
00399     m_logger = 0;
00400     bool unprotected = false;
00401 
00402 
00403     // Extract and validate command line arguments
00404     int c;
00405     for(;;)
00406         {
00407         int option_index = 0;
00408         c = getopt_long (argc, argv, "ho:O:u",
00409                          long_options, &option_index); 
00410         if (c==-1) break;
00411         switch(c)
00412             {
00413                 case 'h':
00414                     usage(argv[0]);
00415                     return;
00416                 case 'o':
00417                     iorFile = optarg;
00418                     break;
00419                 case 'O':
00420                     ORBEndpoint = optarg;
00421                     break;
00422                 case 'u':
00423                     unprotected = true;
00424                     break;
00425                 default:
00426                     ACE_OS::printf("Ignoring unrecognized option %s", 
00427                                     argv[option_index]);
00428             }
00429         }
00430 
00431     // Host IP information is needed to initialize the logging system
00432     // and for ORBEndpoint creation
00433     const char* hostName = ACSPorts::getIP();
00434 
00435     // store env. var. value and disable logging to local file cache
00436     char * acsLogFileEnv = ACE_OS::getenv("ACS_LOG_FILE");
00437     ACE_CString acsLogFileValue(acsLogFileEnv);
00438     ACE_OS::setenv("ACS_LOG_FILE", "/dev/null", 1);
00439 
00440     // create logging proxy
00441     LoggingProxy::ProcessName(argv[0]);
00442     LoggingProxy::ThreadName("main");
00443     ACE_Log_Msg::instance()->local_host(hostName);
00444     m_logger = new LoggingProxy (0, 0, 31, 0);
00445     
00446     LoggingProxy::init (m_logger);  
00447 
00448     // reset ACS_LOG_FILE back
00449     if (acsLogFileEnv)
00450         ACE_OS::setenv("ACS_LOG_FILE", acsLogFileValue.c_str(), 1);
00451     else
00452         ACE_OS::unsetenv("ACS_LOG_FILE");
00453 
00454     // Ready the service manager
00455     service = new ACSDaemonServiceImpl<T>(*m_logger, !unprotected);
00456 
00457     // Generate the CORBA configuration for the service
00458     ACE_CString argStr;
00459     
00460     if(ORBEndpoint.length()<=0)
00461         {
00462         argStr = ACE_CString("-ORBEndpoint iiop://") + hostName + ":";
00463         argStr = argStr + service->getPort().c_str();
00464         }
00465     else
00466         {
00467         argStr = ACE_CString("-ORBEndpoint ") + ORBEndpoint;
00468         }
00469 
00470     ACS_SHORT_LOG((LM_INFO, "Command line is: %s", argStr.c_str()));
00471     ACE_OS::string_to_argv ((ACE_TCHAR*)argStr.c_str(), nargc, nargv);
00472 }
00473 
00474 template <typename T>
00475 acsDaemonImpl<T>::~acsDaemonImpl()
00476 {
00477     if (service != 0) delete service;
00478     if (m_logger != 0)
00479     {
00480         LoggingProxy::done();
00481         delete m_logger;
00482     }
00483 }
00484 
00485 
00486 template <typename T>
00487 int acsDaemonImpl<T>::run()
00488 {
00489     ACS_TRACE("acsDaemonImpl<T>::run");
00490     if (!service || !service->isInitialized())
00491         {
00492         return -1;
00493         }
00494     try
00495         {
00496         if (service->startup (nargc, nargv) != 0)
00497             {
00498             return -1;
00499             }
00500 
00501         // write IOR to file, if necessary
00502         if (iorFile.length() > 0)
00503             {
00504             FILE *output_file = ACE_OS::fopen (iorFile.c_str(), "w");
00505             if (output_file == 0) 
00506                 {
00507                 ACS_SHORT_LOG ((LM_ERROR, "Cannot open output file '%s' to write IOR.", iorFile.c_str()));
00508                 return  -1;
00509                 }
00510 
00511             int result = ACE_OS::fprintf (output_file, "%s", service->getIOR());
00512             if (result < 0) 
00513                 {
00514                 ACS_SHORT_LOG ((LM_ERROR, "ACE_OS::fprintf failed to write IOR."));
00515                 return  -1;
00516                 }
00517 
00518             ACE_OS::fclose (output_file);
00519             ACS_SHORT_LOG((LM_INFO, "%s IOR has been written into file '%s'.", service->getName().c_str(), iorFile.c_str()));
00520             }
00521 
00522         // run, run, run...
00523         if (service->run () == -1)
00524             {
00525             this->shutdown ();
00526             ACS_SHORT_LOG ((LM_ERROR, "Failed to run the %s.", service->getName().c_str()));
00527             return  1;
00528             }
00529         }
00530     catch(...)
00531         {
00532         ACS_SHORT_LOG((LM_ERROR, "Failed to start the %s.", service->getName().c_str()));
00533         return 1;
00534         }
00535   
00536 
00537     this->shutdown();
00538   
00539     ACS_SHORT_LOG ((LM_INFO, "%s stopped.", service->getName().c_str()));
00540 
00541     return 0;
00542 }
00543 
00544 template <typename T>
00545 void acsDaemonImpl<T>::shutdown()
00546 {
00547     service->shutdown(true);
00548 }
00549 
00550 #endif

Generated on Thu Jan 12 2012 23:13:50 for ACS-10.0 C++ API by  doxygen 1.7.0