owcimomd_main.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00037 #include "OW_config.h"
00038 #include "OW_CIMOMEnvironment.hpp"
00039 #include "OW_ConfigOpts.hpp"
00040 #include "OW_Platform.hpp"
00041 #include "OW_PlatformSignal.hpp"
00042 #include "OW_Assertion.hpp"
00043 #include "OW_Format.hpp"
00044 #include "OW_Logger.hpp"
00045 #include "OW_CerrLogger.hpp"
00046 #include "OW_CmdLineParser.hpp"
00047 
00048 #include <exception>
00049 #include <iostream> // for cout
00050 #include <new> // for new handler stuff
00051 
00052 #ifdef OW_USE_DL
00053 #include "OW_dlSharedLibrary.hpp"
00054 #endif
00055 
00056 using namespace OpenWBEM;
00057 
00058 
00059 namespace
00060 {
00061    enum
00062    {
00063       E_HELP_OPT,
00064       E_VERSION_OPT,
00065       E_LIBRARY_VERSION_OPT,
00066       E_DEBUG_MODE_OPT,
00067       E_CONFIG_FILE_OPT
00068    };
00069    const CmdLineParser::Option g_options[] =
00070       {
00071          {E_HELP_OPT, 'h', "help", CmdLineParser::E_NO_ARG, 0, "Show help about options and exit"},
00072          {E_VERSION_OPT, 'v', "version", CmdLineParser::E_NO_ARG, 0, "Show version information and exit"},
00073          {E_LIBRARY_VERSION_OPT, 'l', "libversion", CmdLineParser::E_NO_ARG, 0, "Show the required OpenWBEM library version and exit"},
00074          {E_DEBUG_MODE_OPT, 'd', "debug", CmdLineParser::E_NO_ARG, 0, "Use debug mode (does not detach from terminal)"},
00075          {E_CONFIG_FILE_OPT, 'c', "config", CmdLineParser::E_REQUIRED_ARG, 0, "Use <arg> instead of the default config file"},
00076          {0, 0, 0, CmdLineParser::E_NO_ARG, 0, 0}
00077       };
00078 
00079    // Process the command line, setting appropriate options in the cimom environment.
00080    void processCommandLine(int argc, char* argv[], CIMOMEnvironmentRef env);
00081    void printUsage(std::ostream& ostrm);
00082 
00083    const String COMPONENT_NAME("ow.owcimomd");
00084 }
00085 
00086 void owcimomd_new_handler();
00087 
00089 int main(int argc, char* argv[])
00090 {
00091     int rval = 0;
00092    CIMOMEnvironmentRef env = CIMOMEnvironment::instance();
00093 
00094    // until the config file is read and parsed, just use a logger that prints everything to stderr.
00095    LoggerRef logger(new CerrLogger());
00096 
00097    try
00098    {
00099       processCommandLine(argc, argv, env);
00100       // Initilize the cimom environment object
00101       env->init();
00102 
00103       // debug mode can be activated by -d or by the config file, so check both. The config file is loaded by env->init().
00104       bool debugMode = env->getConfigItem(ConfigOpts::DEBUGFLAG_opt, OW_DEFAULT_DEBUGFLAG).equalsIgnoreCase("true");
00105 
00106       // logger's not set up according to the config file until after init()
00107       logger = env->getLogger(COMPONENT_NAME);
00108       OW_LOG_INFO(logger, "owcimomd (" OW_VERSION ") beginning startup");
00109 
00110 #ifdef OW_USE_DL
00111       if (env->getConfigItem("owcimomd.dont_call_dlclose", "false").equalsIgnoreCase("true"))
00112       {
00113          dlSharedLibrary::setCallDlclose(false);
00114       }
00115 #endif
00116 
00117       // Call platform specific code to become a daemon/service
00118       try
00119       {
00120          Platform::daemonize(debugMode, OW_DAEMON_NAME, env);
00121       }
00122       catch (const DaemonException& e)
00123       {
00124          OW_LOG_FATAL_ERROR(logger, e.getMessage());
00125          OW_LOG_FATAL_ERROR(logger, "owcimomd failed to initialize. Aborting...");
00126          return 1;
00127       }
00128       // Start all of the cimom services
00129       env->startServices();
00130       OW_LOG_INFO(logger, "owcimomd is now running!");
00131 
00132       // Do this after initialization to prevent an infinite loop.
00133       std::unexpected_handler oldUnexpectedHandler = 0;
00134       std::terminate_handler oldTerminateHandler = 0;
00135       std::new_handler oldNewHandler = std::set_new_handler(owcimomd_new_handler);
00136 
00137       if (env->getConfigItem(ConfigOpts::RESTART_ON_ERROR_opt, OW_DEFAULT_RESTART_ON_ERROR).equalsIgnoreCase("true"))
00138       {
00139          const char* const restartDisabledMessage =
00140             "WARNING: even though the owcimomd.restart_on_error config option = true, it\n"
00141             "is not enabled. Possible reasons are that OpenWBEM is built in debug mode,\n"
00142             "owcimomd is running in debug mode (-d), or owcimomd was not run using an\n"
00143             "absolute path (argv[0][0] != '/')";
00144 
00145          // only do this in production mode. During development we want it to crash!
00146 #if !defined(OW_DEBUG)
00147          if ((debugMode == false) && argv[0][0] == '/') // if argv[0][0] != '/' the restart will not be predictable
00148          {
00149             Platform::installFatalSignalHandlers();
00150             oldUnexpectedHandler = std::set_unexpected(Platform::rerunDaemon);
00151             oldTerminateHandler = std::set_terminate(Platform::rerunDaemon);
00152          }
00153          else
00154          {
00155             OW_LOG_INFO(logger, restartDisabledMessage);
00156          }
00157 #else
00158          OW_LOG_INFO(logger, restartDisabledMessage);
00159 #endif
00160       }
00161 
00162       int sig;
00163       bool shuttingDown(false);
00164 
00165       Platform::sendDaemonizeStatus(Platform::DAEMONIZE_SUCCESS);
00166       while (!shuttingDown)
00167       {
00168          // runSelectEngine will only return once something has been put into
00169          // the signal pipe or an error has happened
00170          env->runSelectEngine();
00171          Platform::Signal::SignalInformation signalInfo;
00172 
00173          sig = Platform::popSig(signalInfo);
00174          switch (sig)
00175          {
00176             case Platform::SHUTDOWN:
00177 
00178                OW_LOG_INFO(logger, "owcimomd received shutdown notification."
00179                   " Initiating shutdown");
00180                OW_LOG_INFO(logger, Format("signal details:\n%1", signalInfo));
00181                shuttingDown = true;
00182 
00183 
00184 #if !defined(OW_DEBUG)
00185                // need to remove them so we don't restart while shutting down.
00186                Platform::removeFatalSignalHandlers();
00187                if (oldUnexpectedHandler)
00188                {
00189                   std::set_unexpected(oldUnexpectedHandler);
00190                }
00191                if (oldTerminateHandler)
00192                {
00193                   std::set_terminate(oldTerminateHandler);
00194                }
00195 #endif
00196 
00197                env->shutdown();
00198                break;
00199             case Platform::REINIT:
00200                OW_LOG_INFO(logger, "owcimomd received restart notification."
00201                   " Initiating restart");
00202                OW_LOG_INFO(logger, Format("signal details: %1", signalInfo));
00203                env->shutdown();
00204                env->clearConfigItems();
00205                env = CIMOMEnvironment::instance() = 0;
00206                // don't try to catch the DeamonException, because if it's thrown, stuff is so whacked, we should just exit!
00207                Platform::rerunDaemon();
00208 
00209                // typically on *nix, restartDaemon() doesn't return, however to account for environments where
00210                // it won't we'll leave this code here to re-initialize.
00211                env = CIMOMEnvironment::instance() = new CIMOMEnvironment;
00212                processCommandLine(argc, argv, env);
00213                env->init();
00214                env->startServices();
00215                break;
00216             default:
00217                OW_LOG_INFO(logger, Format("Ignoring signal. Details: %1", signalInfo));
00218                break;
00219          }
00220       }
00221    }
00222    catch (Exception& e)
00223    {
00224       OW_LOG_FATAL_ERROR(logger, "* EXCEPTION CAUGHT IN owcimomd MAIN!");
00225       OW_LOG_FATAL_ERROR(logger, Format("* %1", e));
00226       Platform::sendDaemonizeStatus(Platform::DAEMONIZE_FAIL);
00227       rval = 1;
00228    }
00229    catch (std::exception& se)
00230    {
00231       OW_LOG_FATAL_ERROR(logger, "* std::exception CAUGHT IN owcimomd MAIN!");
00232       OW_LOG_FATAL_ERROR(logger, Format("* Message: %1", se.what()));
00233       Platform::sendDaemonizeStatus(Platform::DAEMONIZE_FAIL);
00234       rval = 1;
00235    }
00236    catch(...)
00237    {
00238       OW_LOG_FATAL_ERROR(logger, "* UNKNOWN EXCEPTION CAUGHT owcimomd MAIN!");
00239       Platform::sendDaemonizeStatus(Platform::DAEMONIZE_FAIL);
00240       rval = 1;
00241    }
00242    // Call platform specific shutdown routine
00243    Platform::daemonShutdown(OW_DAEMON_NAME, env);
00244 
00245    CIMOMEnvironment::instance() = env = 0;
00246    
00247    OW_LOG_INFO(logger, "owcimomd has shutdown");
00248    return rval;
00249 }
00250 
00251 namespace
00252 {
00253 
00255 void
00256 processCommandLine(int argc, char* argv[], CIMOMEnvironmentRef env)
00257 {
00258    // Give store a copy of the initial arguments for later use (should we need
00259    // to restart).
00260    Platform::daemonInit(argc, argv);
00261 
00262    try
00263    {
00264       CmdLineParser parser(argc, argv, g_options, CmdLineParser::E_NON_OPTION_ARGS_INVALID);
00265 
00266       //
00267       // Options that will cause the cimom to exit.
00268       //
00269       if (parser.isSet(E_HELP_OPT))
00270       {
00271          printUsage(std::cout);
00272          exit(0);
00273       }
00274       else if (parser.isSet(E_VERSION_OPT))
00275       {
00276          std::cout << OW_DAEMON_NAME " from " OW_PACKAGE_STRING << std::endl;
00277          exit(0);
00278       }
00279       else if (parser.isSet(E_LIBRARY_VERSION_OPT))
00280       {
00281 #define STRINGIFY_ARGUMENT(x) #x
00282 #define STRINGIFY_DEFINITION_VALUE(x) STRINGIFY_ARGUMENT(x)
00283          std::cout << STRINGIFY_DEFINITION_VALUE(OW_OPENWBEM_LIBRARY_VERSION) << std::endl;
00284 #undef STRINGIFY_ARGUMENT
00285 #undef STRINGIFY_DEFINITION_VALUE
00286          exit(0);
00287       }
00288 
00289       //
00290       // Options that will change the behavior of the CIMOM
00291       //
00292       if (parser.isSet(E_DEBUG_MODE_OPT))
00293       {
00294          env->setConfigItem(ConfigOpts::DEBUGFLAG_opt, "true", ServiceEnvironmentIFC::E_PRESERVE_PREVIOUS);
00295          env->setConfigItem(ConfigOpts::LOG_LEVEL_opt, "debug");
00296       }
00297       if (parser.isSet(E_CONFIG_FILE_OPT))
00298       {
00299          env->setConfigItem(ConfigOpts::CONFIG_FILE_opt, parser.getOptionValue(E_CONFIG_FILE_OPT));
00300       }
00301    }
00302    catch (const CmdLineParserException& e)
00303    {
00304       switch (e.getErrorCode())
00305       {
00306          case CmdLineParser::E_INVALID_OPTION:
00307             std::cerr << "Invalid option: " << e.getMessage() << std::endl;
00308             break;
00309          case CmdLineParser::E_MISSING_ARGUMENT:
00310             std::cerr << "Argument not specified for option: " << e.getMessage() << std::endl;
00311             break;
00312       }
00313       printUsage(std::cerr);
00314       exit(1);
00315    }
00316 }
00317 
00319 void
00320 printUsage(std::ostream& ostrm)
00321 {
00322    ostrm << OW_DAEMON_NAME << " [OPTIONS]..." << std::endl;
00323    ostrm << CmdLineParser::getUsage(g_options) << std::endl;
00324 }
00325 
00326 } // end unnamed namespace
00328 void owcimomd_new_handler()
00329 {
00330 #if defined (OW_DEBUG)  || defined (OW_NETWARE)
00331    abort();
00332 #endif
00333 
00334    Platform::restartDaemon();
00335    throw std::bad_alloc();
00336 }
00337 

Generated on Thu Feb 9 08:48:29 2006 for openwbem by  doxygen 1.4.6