/****************************************************************************
|
| Copyright (c) 2006 Novell, Inc.
| All Rights Reserved.
|
| This program is free software; you can redistribute it and/or
| modify it under the terms of version 2 of the GNU General Public License as
| published by the Free Software Foundation.
|
| This program is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
| GNU General Public License for more details.
|
| You should have received a copy of the GNU General Public License
| along with this program; if not, contact Novell, Inc.
|
| To contact Novell about this file by physical or electronic mail,
| you may find current contact information at www.novell.com
|
|***************************************************************************
/**
@author Jon Carey
*/
#include "config.h"
#include <openwbem/OW_CommonFwd.hpp>
#include <openwbem/OW_Socket.hpp>
#include <openwbem/OW_SelectEngine.hpp>
#include <openwbem/OW_MutexLock.hpp>
#include <openwbem/OW_Format.hpp>
#include <openwbem/OW_Assertion.hpp>
#include <openwbem/OW_SortedVectorMap.hpp>
#include <openwbem/OW_LogAppender.hpp>
#include <openwbem/OW_AppenderLogger.hpp>
#include <openwbem/OW_CerrLogger.hpp>
#include "omcclpdenv.h"
#include "omcclpdconfigopts.h"
#include "omcclpdsyslogappender.h"
#include "omcclpdserver.h"
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;
using namespace OW_NAMESPACE;
using namespace OMCClpdConfigOpts;
namespace
{
// The one and only
OMCClpdEnvRef theClpEnvironment(0);
} // end anonymous namespace
String OMCClpdEnv::COMPONENT_NAME("omcclpd.clpd");
//////////////////////////////////////////////////////////////////////////////
// STATIC
OMCClpdEnvRef&
OMCClpdEnv::instance()
{
if (!theClpEnvironment)
{
theClpEnvironment = OMCClpdEnvRef(new OMCClpdEnv);
}
return theClpEnvironment;
}
//////////////////////////////////////////////////////////////////////////////
OMCClpdEnv::OMCClpdEnv()
: IntrusiveCountableBase()
, m_isRunning(false)
, m_debugFlag(false)
, m_logger(new CerrLogger)
, m_selectables()
, m_selectableCallbacks()
, m_selectableGuard()
, m_sigPipe(UnnamedPipe::createUnnamedPipe())
, m_clpServer(0)
{
m_sigPipe->open();
m_sigPipe->setBlocking(UnnamedPipe::E_NONBLOCKING);
}
//////////////////////////////////////////////////////////////////////////////
OMCClpdEnv::~OMCClpdEnv()
{
try
{
shutdown();
m_logger = 0;
OMCClpdConfig::clearConfigItems();
}
catch(...)
{
// Don't let exceptions escape from dtors
}
}
//////////////////////////////////////////////////////////////////////////////
LoggerRef
OMCClpdEnv::getLogger() const
{
OW_ASSERT(m_logger);
LoggerRef rv(m_logger->clone());
return rv;
}
//////////////////////////////////////////////////////////////////////////////
LoggerRef
OMCClpdEnv::getLogger(const String& componentName) const
{
OW_ASSERT(m_logger);
LoggerRef rv(m_logger->clone());
rv->setDefaultComponent(componentName);
return rv;
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::init()
{
clearSelectables();
// The config file config item may be set by main before init() is called.
loadConfigItemsFromFile(getConfigItem(OMCClpdConfigOpts::CONFIG_FILE_opt,
OMCCLPD_DEFAULT_CONFIG_FILE));
// logger is treated special, so it goes in init() not startServices()
createLogger();
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::shutdown()
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::shutdown() entered");
if (m_isRunning)
{
if (m_clpServer)
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::shutdown() shutting down the server");
m_clpServer->shutdown();
m_clpServer = 0;
}
else
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::shutdown() no server to shutdown");
}
OW_LOG_DEBUG(m_logger, "clpd shutting down all sockets");
Socket::shutdownAllSockets();
m_isRunning = false;
}
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::createLogger()
{
AppenderLogger* pLogger = 0;
StringArray additionalLogs = OMCClpdConfig::getMultiConfigItem(
OMCClpdConfigOpts::ADDITIONAL_SERVER_LOGS_opt);
String logName, logMainType, logMainComponents;
String logMainCategories, logMainLevel, logMainFormat;
// this also gets set if clpd is run with -d
bool debugFlag = getConfigItem(OMCClpdConfigOpts::DEBUGFLAG_opt,
OMCCLPD_DEFAULT_DEBUGFLAG).equalsIgnoreCase("true");
if (debugFlag)
{
// stick it at the beginning as a possible slight logging performance optimization
additionalLogs.insert(additionalLogs.begin(), LOG_DEBUG_LOG_NAME);
}
for (size_t i = 0; i < additionalLogs.size(); ++i)
{
logName = additionalLogs[i];
logMainType = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_TYPE_opt, logName),
OMCCLPD_DEFAULT_LOG_1_TYPE);
logMainComponents = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_COMPONENTS_opt, logName),
OMCCLPD_DEFAULT_LOG_1_COMPONENTS);
logMainCategories = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_CATEGORIES_opt, logName));
if (logMainCategories.empty())
{
// convert level into categories
logMainLevel = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_LEVEL_opt, logName),
OMCCLPD_DEFAULT_LOG_1_LEVEL);
if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
{
logMainCategories = Logger::STR_DEBUG_CATEGORY + " " +
Logger::STR_INFO_CATEGORY + " " +
Logger::STR_ERROR_CATEGORY + " " +
Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
{
logMainCategories = Logger::STR_INFO_CATEGORY + " " +
Logger::STR_ERROR_CATEGORY + " " +
Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
{
logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
{
logMainCategories = Logger::STR_FATAL_CATEGORY;
}
}
logMainFormat = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_FORMAT_opt, logName),
OMCCLPD_DEFAULT_LOG_1_FORMAT);
if (logMainType.equalsIgnoreCase("syslog"))
{
pLogger = new AppenderLogger(COMPONENT_NAME, E_ALL_LEVEL,
LogAppenderRef(new OMCClpdSyslogAppender(logMainComponents.tokenize(),
logMainCategories.tokenize(), logMainFormat)));
}
else
{
pLogger = new AppenderLogger(COMPONENT_NAME, E_ALL_LEVEL,
LogAppender::createLogAppender(logName, logMainComponents.tokenize(),
logMainCategories.tokenize(), logMainFormat, logMainType,
OMCClpdConfig::getLogAppenderConfig()));
}
}
// This one will eventually be handled the same as all other logs by just sticking
// "main" in the additionalLogs array but we need to handle deprecated options for
// now, so it needs special treatment.
logName = LOG_SERVER_LOG_NAME;
logMainType = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_TYPE_opt, logName));
logMainComponents = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_COMPONENTS_opt, logName),
OMCCLPD_DEFAULT_LOG_1_COMPONENTS);
logMainCategories = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_CATEGORIES_opt, logName));
logMainLevel = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_LEVEL_opt, logName));
logMainFormat = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_FORMAT_opt, logName),
OMCCLPD_DEFAULT_LOG_1_FORMAT);
// If logMainType not specified, use syslog
if (logMainType.empty())
{
logMainType = "syslog";
}
// If no logMainCategoreis and the main level not specifed
if (logMainCategories.empty() && logMainLevel.empty())
{
logMainLevel = OMCCLPD_DEFAULT_LOG_1_LEVEL;
}
// convert level into categories
if (logMainCategories.empty())
{
// convert level into categories
logMainLevel = getConfigItem(Format(OMCClpdConfigOpts::LOG_1_LEVEL_opt, logName),
OMCCLPD_DEFAULT_LOG_1_LEVEL);
if (logMainLevel.equalsIgnoreCase(Logger::STR_DEBUG_CATEGORY))
{
logMainCategories = Logger::STR_DEBUG_CATEGORY + " " +
Logger::STR_INFO_CATEGORY + " " + Logger::STR_ERROR_CATEGORY +
" " + Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_INFO_CATEGORY))
{
logMainCategories = Logger::STR_INFO_CATEGORY + " " +
Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_ERROR_CATEGORY))
{
logMainCategories = Logger::STR_ERROR_CATEGORY + " " + Logger::STR_FATAL_CATEGORY;
}
else if (logMainLevel.equalsIgnoreCase(Logger::STR_FATAL_CATEGORY))
{
logMainCategories = Logger::STR_FATAL_CATEGORY;
}
}
LogAppenderRef appender;
if (logMainType.equalsIgnoreCase("syslog"))
{
appender = LogAppenderRef(new OMCClpdSyslogAppender(logMainComponents.tokenize(),
logMainCategories.tokenize(), logMainFormat));
}
else
{
appender = LogAppender::createLogAppender(logName,
logMainComponents.tokenize(), logMainCategories.tokenize(),
logMainFormat, logMainType, OMCClpdConfig::getLogAppenderConfig());
}
if (pLogger)
{
pLogger->addLogAppender(appender);
}
else
{
pLogger = new AppenderLogger(COMPONENT_NAME, E_ALL_LEVEL, appender);
}
m_logger = LoggerRef(pLogger);
m_logger->setDefaultComponent(COMPONENT_NAME);
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::startServices()
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::startServices entered");
Socket::createShutDownMechanism();
m_clpServer = OMCClpdServerRef(new OMCClpdServer);
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::startServices initializing server");
m_clpServer->init(this);
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::startServices starting server");
m_clpServer->start();
m_isRunning = true;
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::runSelectEngine() const
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::runSelectEngine entered");
OW_ASSERT(m_selectables.size() == m_selectableCallbacks.size());
SelectEngine engine;
// Insure the signal pipe is at the front of the select list
engine.addSelectableObject(m_sigPipe,
SelectableCallbackIFCRef(new SelectEngineStopper(engine)));
for (size_t i = 0; i < m_selectables.size(); ++i)
{
engine.addSelectableObject(m_selectables[i], m_selectableCallbacks[i]);
}
engine.go();
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::setConfigItem(
const String &item,
const String &value,
bool overwritePrevious)
{
OMCClpdConfig::setConfigItem(item, value, (overwritePrevious)
? OMCClpdConfig::E_OVERWRITE : OMCClpdConfig::E_NO_OVERWRITE);
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::clearSelectables()
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::clearSelectables entered");
MutexLock ml(m_selectableGuard);
m_selectables.clear();
m_selectableCallbacks.clear();
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::addSelectable(const SelectableIFCRef& obj,
const SelectableCallbackIFCRef& cb)
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::addSelectable entered");
MutexLock ml(m_selectableGuard);
m_selectables.push_back(obj);
m_selectableCallbacks.push_back(cb);
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::removeSelectable(const SelectableIFCRef& obj)
{
OW_LOG_DEBUG(m_logger, "OMCClpdEnv::removeSelectable entered");
MutexLock ml(m_selectableGuard);
for (size_t i = 0; i < m_selectables.size(); i++)
{
if (obj == m_selectables[i])
{
m_selectables.remove(i);
m_selectableCallbacks.remove(i);
--i;
}
}
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::loadConfigItemsFromFile(const String& filename)
{
OW_LOG_DEBUG(m_logger, "\nUsing config file: " + filename);
OMCClpdConfig::loadConfigFile(filename);
}
//////////////////////////////////////////////////////////////////////////////
String
OMCClpdEnv::getConfigItem(
const String &itemName,
const String& defRetVal) const
{
return OMCClpdConfig::getConfigItem(itemName, defRetVal);
}
//////////////////////////////////////////////////////////////////////////////
StringArray
OMCClpdEnv::getMultiConfigItem(
const String &itemName,
const char* tokenizeSeparator) const
{
return OMCClpdConfig::getMultiConfigItem(itemName, tokenizeSeparator);
}
//////////////////////////////////////////////////////////////////////////////
void
OMCClpdEnv::setDebug(bool debug)
{
const char* flag = (debug) ? "true" : "false";
setConfigItem(OMCClpdConfigOpts::DEBUGFLAG_opt, flag, true);
m_debugFlag = debug;
}