SystemMonitor.cpp

Go to the documentation of this file.
00001 /** @file    SystemMonitor.cpp
00002  *  @author  Alessandro Polo
00003  *  @version $Id: SystemMonitor.cpp 3775 2011-01-01 16:38:17Z alex $
00004  *  @brief
00005  * File containing methods for the wosh::SystemMonitor class.
00006  * The header for this class can be found in SystemMonitor.h, check that file
00007  * for class description.
00008  ****************************************************************************/
00009 /* Copyright (c) 2007-2011, WOSH - Wide Open Smart Home 
00010  * by Alessandro Polo - OpenSmartHome.com
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *     * Redistributions of source code must retain the above copyright
00016  *       notice, this list of conditions and the following disclaimer.
00017  *     * Redistributions in binary form must reproduce the above copyright
00018  *       notice, this list of conditions and the following disclaimer in the
00019  *       documentation and/or other materials provided with the distribution.
00020  *     * Neither the name of the OpenSmartHome.com WOSH nor the
00021  *       names of its contributors may be used to endorse or promote products
00022  *       derived from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
00025  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027  * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
00028  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00033  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  ****************************************************************************/
00035  
00036  #include <core/SystemMonitor.h>
00037  #include <core/ObjectFactory.h>
00038  #include <core/PersistenceManager.h>
00039  #include <core/SecurityManager.h>
00040  #include <core/WoshKernel.h>
00041  #include <core/SharedMemory.h>
00042  #include <core/MethodsCommon.h>
00043  #include <core/FilePath.h>
00044  #include <core/Utilities.h>
00045  #include <core/DateTime.h>
00046  #include <core/DataSet.h>
00047 
00048 
00049 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00050 #ifdef _OS_POSIX
00051 # include <core/posix/processes.h>
00052 # include <core/posix/desktop.h>
00053 #elif _OS_WIN32
00054 # include <core/win32/processes.h>
00055 # include <core/win32/desktop.h>
00056 #elif _OS_WINCE
00057 # include <core/wince/processes.h>
00058 # include <core/wince/desktop.h>
00059 #else
00060  long getCurrentProcessPID() { return 0L; }
00061  bool getSystemUserName( std::string& ) { return false; }
00062  bool retrieveProcessInfo( long , std::map<std::string, std::string>& ) { return false; }
00063 #endif
00064 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00065 
00066 
00067 using namespace std;
00068 namespace wosh {
00069 
00070 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00071 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00072 
00073 // Gamma singleton! static reference is allocated and maintained by WoshKernel
00074 extern "C" {
00075     SystemMonitor* SystemMonitor::getInstance() { 
00076         if ( WoshKernel::getInstance() == NULL ) return NULL;
00077         return &WoshKernel::getInstance()->monitor();
00078     }
00079 };
00080 
00081  // register as abstract because it is a singleton:
00082  WOSH_REGISTER_INTERFACE(wosh::SystemMonitor, wosh::WoshModule, _SystemMonitor_VER, core_SystemMonitor)
00083 
00084 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00085 //////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
00086 
00087 SystemMonitor::SystemMonitor( const WoshKernel* parent )
00088     : WoshModule(parent, _SystemMonitor_NAME, _SystemMonitor_URI) {
00089 
00090 //Log.setLevel( LOG_VERBOSE );
00091 
00092 #ifdef _ENABLE_PROFILING
00093     Log(LOG_INFO, " Acquiring SystemProfiler instance.. [_ENABLE_PROFILING]" );
00094     this->profiler = &SystemProfiler::getInstance();
00095 #else
00096     Log(LOG_VERBOSE, " Profiling DISABLED." );
00097 #endif
00098 
00099     Log(LOG_DEBUG, " Initializing Properties.." );
00100     Properties.set(_SystemMonitor_KEY_SaveOnExit, false, Permission(Permission::RW, Permission::Read, Permission::Read) );
00101     Properties.set(_SystemMonitor_KEY_ProcessPID, 0, Permission(Permission::Read) );
00102     Properties.set(_SystemMonitor_KEY_SystemUser, "", Permission(Permission::Read) );
00103     Properties.update( _KEY_Description, "Core-Module: Monitor System for failures and errors, provides functionalities for debugging" );
00104     Properties.update( _KEY_Version, _SystemMonitor_VER );
00105 
00106     Log(LOG_DEBUG, " Registering Methods.." );
00107     MethodRequest* mmProfilesList = Methods.create<MethodRequest>( _SystemMonitor_METHOD_profiles, "list profiling info", Permission::R_XR_XR__() );
00108     mmProfilesList->setMethod( this, (MethodRequestPtr)&SystemMonitor::mmDoProfilesList );
00109 
00110     MethodRequest* mmListDeprecated = Methods.create<MethodRequest>( _SystemMonitor_METHOD_deprecated, "list deprecated", Permission::R_XR_XR__() );
00111     mmListDeprecated->setMethod( this, (MethodRequestPtr)&SystemMonitor::mmDoListDeprecated );
00112 
00113     MethodWRESULT* mmSaveErrors = Methods.create<MethodWRESULT>( _SystemMonitor_METHOD_save_errors, "save errors", Permission::R_XR_XR__() );
00114     mmSaveErrors->setMethod( this, (MethodWRESULTPtr)&SystemMonitor::mmDoSaveErrors );
00115 
00116     MethodWRESULT* mmCleanErrors = Methods.create<MethodWRESULT>( _SystemMonitor_METHOD_clear_errors, "clean errors", Permission::R_XR_XR__() );
00117     mmCleanErrors->setMethod( this, (MethodWRESULTPtr)&SystemMonitor::mmDoCleanErrors );
00118 
00119     MethodWRESULT* mmUpdateSysInfo = Methods.create<MethodWRESULT>( _SystemMonitor_METHOD_update_sysinfo, "update sysinfo", Permission::R_XR_XR__() );
00120     mmUpdateSysInfo->setMethod( this, (MethodWRESULTPtr)&SystemMonitor::updateSystemInfo );
00121 
00122     MethodDataSetFields* mmListErrors = Methods.create<MethodDataSetFields>( _METHOD_List, "List SystemInfo(s)", Permission::R_XR__R__() );
00123     mmListErrors->setRetriever( DataSetFieldsReader_X<SystemInfo>::createFrom(&this->infoCache) );
00124 
00125     MethodRetrieve* mmRetrieveErrors = Methods.create<MethodRetrieve>( _METHOD_Retrieve, "Retrieve SystemInfo(s)", Permission::R_XR_XR__() );
00126     mmRetrieveErrors->setRetriever( DataSetRetriever_X<SystemInfo>::createFrom<int64>(&this->infoCache, &SystemInfo::getID ) );
00127 
00128     MethodDataSetFields* mmListDSMs = Methods.create<MethodDataSetFields>( _SystemMonitor_METHOD_dsm, "List DSM", Permission::R_XR_XR__() );
00129     mmListDSMs->setRetriever( DataSetFieldsReader_X<SharedMemory>::createFrom(&SharedMemory::getInstances()) );
00130 
00131 #ifdef _ENABLE_PROFILING
00132     this->profiler = &SystemProfiler::getInstance();
00133 #endif
00134  }
00135 
00136 SystemMonitor::~SystemMonitor() {
00137     Log(LOG_DEBUG, ":~SystemMonitor() Destroying.." );
00138     
00139     // this->profiler is destroyed by compiler because is a static singleton (meyer)
00140     
00141     this->infoProxies.transactionBeginWrite();
00142     Log(LOG_DEBUG, ":~SecurityManager() Freeing InfoProxy [%d]..", this->infoProxies.size() );
00143     ObjectFactory::destroySequence(this->infoProxies);
00144     this->infoProxies.clear();
00145     this->infoProxies.transactionEnd();
00146 
00147     Log(LOG_VERBOSE, ":~SecurityManager() Freeing Cache [%d]..", this->infoCache.size_safe() );
00148     this->infoCache.free_safe();
00149 
00150     Log(LOG_VERBOSE, " Destroyed." );
00151  }
00152 
00153 //////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
00154 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00155 /////////////////////////////////////////////////////////////////////////////////////////////// KERNEL EVENTS
00156 
00157 WRESULT SystemMonitor::onKernelInitializing() {
00158     WRESULT ret = WoshModule::onKernelInitializing();
00159 
00160     long pid = getCurrentProcessPID();
00161     Properties.transactionBeginWrite();
00162     Properties.update(_SystemMonitor_KEY_ProcessPID, pid );
00163     Properties.transactionEnd();
00164     Log(LOG_INFO, "init() : PID updated to %ld", pid );
00165     ret += updateSystemInfo_(true, true);
00166 
00167     return ret;
00168  }
00169 
00170 WRESULT SystemMonitor::onKernelInitialized() {
00171     WRESULT ret = WoshModule::onKernelInitialized();
00172     if ( Properties.exists(_SystemMonitor_KEY_AutoLoadSystemInfoProxies) ) {
00173         vector<string> proxies;
00174         string proxiesStr = Properties.getValueOf(_SystemMonitor_KEY_AutoLoadSystemInfoProxies).toString();
00175         String::split(proxies, proxiesStr, _WoshSettings_SEPARATOR, _String_SPLIT_OPTION_NOT_EMPTY | _String_SPLIT_OPTION_TRIM | _String_SPLIT_OPTION_UNIQUE);
00176         Log(LOG_INFO, ":onKernelInitializing() Loading %d SystemInfoProxy", proxies.size() );
00177         WRESULT ret_c = WRET_OK;
00178         std::vector<std::string>::iterator it;
00179         for ( it=proxies.begin(); it!=proxies.end(); ++it ) {
00180             ret_c = installSystemInfoProxies(*it);
00181             ret += ret_c;
00182          }
00183      }
00184     return ret;
00185  }
00186 
00187 WRESULT SystemMonitor::onKernelStopped() {
00188     WRESULT ret = WRET_OK;
00189     Variant saveMsg = this->Properties.getValueOf(_SystemMonitor_KEY_SaveOnExit);
00190     if ( !saveMsg.isEmpty() && saveMsg.toBoolean(true) ) {
00191         Log(LOG_INFO, "onKernelStopped() Saving Errors.." );
00192         ret += mmDoSaveErrors();
00193      }
00194     if ( WFAILED(ret) )
00195         Log(LOG_CRITICAL, ":onKernelStopped() ERROR#%d Saving Errors.", ret );
00196     ret = WoshModule::onKernelStopped();
00197     return ret;
00198  }
00199 
00200 /////////////////////////////////////////////////////////////////////////////////////////////// KERNEL EVENTS
00201 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00202 ///////////////////////////////////////////////////////////////////////////////////////////// PROPERTY EVENTS
00203 
00204 bool SystemMonitor::readingProperty( Property* property_curr, const PropertiesProvider* source ) {
00205     if ( property_curr != NULL && property_curr->getKey().find("SysInfo") == 0 )
00206         updateSystemInfo_(false, false);
00207     return WoshModule::readingProperty( property_curr, source );
00208  }
00209 
00210 ///////////////////////////////////////////////////////////////////////////////////////////// PROPERTY EVENTS
00211 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00212 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00213 
00214 WRESULT SystemMonitor::updateSystemInfo_( bool lock_props, bool force_update ) {
00215      if ( !force_update ) {
00216         if ( DateTime::std_time_sec() - this->systemInfoTs < _SystemMonitor_SystemInfoMinRefresh )
00217              return WRET_ERR_ILLEGAL_USE;
00218       }
00219     this->systemInfoTs = DateTime::std_time_sec();
00220     Log(LOG_VERBOSE, "updateSystemInfo_(%d) Updating System Info..", lock_props );
00221 
00222     string username;
00223     bool userOk = getSystemUserName(username);
00224     if ( !userOk ) {
00225         Log(LOG_CRITICAL, "updateSystemInfo_(%d) Error retrieving system user", lock_props );
00226      }
00227     long pid = getCurrentProcessPID();
00228 
00229     Properties.transactionBeginWrite();
00230     Properties.update(_SystemMonitor_KEY_SystemUser, username);
00231     Properties.transactionEnd();
00232 
00233     map<string, string> fields; Variant tmp;
00234     bool memInfo = retrieveProcessInfo( pid, fields );
00235     if ( memInfo ) {
00236         Properties.transactionBeginWrite();
00237         std::map<string, string>::const_iterator it;
00238         for ( it=fields.begin(); it!=fields.end(); ++it ) {
00239             tmp.fromString(it->second);
00240             Properties.update(it->first, tmp);
00241          }
00242         Properties.transactionEnd();
00243      }
00244     else {
00245         Log(LOG_CRITICAL, "updateSystemInfo_() ERRORS retrieving process info." );
00246         return WRET_ERR_INTERNAL;
00247      }
00248     return WRET_OK;
00249  }
00250 
00251 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00252 /////////////////////////////////////////////////////////////////////////////////////////// COLLECTOR METHODS
00253 
00254 WRESULT SystemMonitor::mmDoSaveErrors() {
00255     FilePath xmlFile;
00256     xmlFile.set("$DATABASE/systemerrors.xml");
00257     Log(LOG_VERBOSE, ":mmDoSaveErrors() : Saving to %s", xmlFile.getPathLocal().c_str() );
00258     this->infoCache.transactionBeginRead();
00259     WRESULT ret = PersistenceManager::saveObjects( this->infoCache.getContainer(), "XML", xmlFile.getPathLocal() );
00260     this->infoCache.transactionEnd();
00261     return ret;
00262  }
00263 
00264 /////////////////////////////////////////////////////////////////////////////////////////// COLLECTOR METHODS
00265 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00266 ////////////////////////////////////////////////////////////////////////////////////////// 
00267 
00268 void SystemMonitor::busMessage( const Message& message, const Bus* source ) {
00269     if ( message.isEmpty() ) return;
00270     WoshModule::busMessage( message, source );
00271     if ( message.getSourceUUID() == this->getEntityID() ) return;
00272     if ( message.getContent()->isSystemInfo() ) return;
00273     WRESULT valid;
00274     this->infoProxies.transactionBeginRead();
00275     tSystemInfoProxyList::ConstIterator it;
00276     const tSystemInfoProxyList::ConstIterator it_end = this->infoProxies.end();
00277     for( it=this->infoProxies.begin(); it!=it_end; ++it ) {
00278         if ( *it == NULL ) continue;
00279         valid = (*it)->validate(&message);
00280         if ( WFAILED(valid) ) continue;
00281         //(*it)->transform
00282         SystemInfo* sysinfo = (*it)->transform(&message);
00283         if ( sysinfo == NULL ) continue;
00284         Log(LOG_INFO, ":busMessage() : Adding SystemInfo#%"PRId64, sysinfo->getID() );
00285         this->infoCache.push_back_safe( sysinfo );
00286      }
00287     this->infoProxies.transactionEnd();
00288 
00289     return;
00290  }
00291 
00292 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00293 
00294 WRESULT SystemMonitor::installSystemInfoProxy( SystemInfoProxy* systeminfo_proxy ) {
00295     if ( systeminfo_proxy == NULL )
00296     if ( this->infoProxies.push_back_safe( systeminfo_proxy ) ) {
00297         Log(LOG_WARNING, ":installSystemInfoProxy(%p) FAILED", systeminfo_proxy );
00298         return WRET_ERR_PARAM;
00299      }
00300     Log(LOG_INFO, ":installSystemInfoProxy(%p)", systeminfo_proxy );
00301     return WRET_OK;
00302  }
00303 
00304 WRESULT SystemMonitor::installSystemInfoProxy( const std::string& systeminfo_proxy_classname_pattern, double version ) {
00305     Log(LOG_INFO, ":installSystemInfoProxy(%s, %g)", systeminfo_proxy_classname_pattern.c_str(), version );
00306     SystemInfoProxy* sip = ObjectFactory::createTypeOf<SystemInfoProxy>(systeminfo_proxy_classname_pattern, version);
00307     return installSystemInfoProxy(sip);
00308  }
00309 
00310 WRESULT SystemMonitor::installSystemInfoProxies( const std::string& systeminfo_proxy_classname_pattern ) {
00311     Log(LOG_INFO, ":installSystemInfoProxies(%s)", systeminfo_proxy_classname_pattern.c_str() );
00312     WRESULT ret = WRET_OK;
00313     VectorT<SystemInfoProxy*> proxies;
00314     ObjectFactory::createTypesOf<SystemInfoProxy>(proxies, systeminfo_proxy_classname_pattern);
00315     VectorT<SystemInfoProxy*>::Iterator it;
00316     for (it=proxies.begin(); it!=proxies.end(); ++it ) {
00317         ret |= installSystemInfoProxy(*it);
00318      }
00319     return ret;
00320  }
00321 
00322 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00323 ///////////////////////////////////////////////////////////////////////////////////////////////////// METHODS
00324 
00325 WRESULT SystemMonitor::mmDoCleanErrors() {
00326     Log(LOG_INFO, ":mmCleanErrors() Cleaning.. [%d records]", this->infoCache.size() );
00327     this->infoCache.free();
00328     return WRET_OK;
00329  }
00330 
00331 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00332 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00333 
00334 Response* SystemMonitor::mmDoProfilesList( const Request* request ) {
00335     if ( request == NULL ) return NULL;
00336     Variant target; Variant option1;
00337     request->extractArguments(target, option1);
00338     if ( !target.isStringNotEmpty() )
00339         return request->replyResponse(WRET_ERR_PARAM, "specify target {properties, methods, connectors}");
00340     Log(LOG_VERBOSE, ":mmDoProfilesList(%s)", target.asString().c_str() );
00341 #ifdef _ENABLE_PROFILING
00342     if ( this->profiler == NULL )
00343         return request->replyResponse(WRET_ERR_INTERNAL, "Internal error: Profiler is NULL");
00344 
00345     if ( target.asString() == "properties" )
00346         return request->replyResponse(WRET_OK, this->profiler->getProfilesPropertiesTable(option1.toInt64(1)) );
00347     else if ( target.asString() == "methods" )
00348         return request->replyResponse(WRET_OK, this->profiler->getProfilesMethodsTable(option1.toInt64(0)) );
00349     else if ( target.asString() == "connectors" )
00350         return request->replyResponse(WRET_OK, this->profiler->getProfilesConnectorsTable(option1.toInt64(0)) );
00351 #else
00352     return request->replyResponse(WRET_ERR_ILLEGAL_USE, "Profiling is not enabled in this built.");
00353 #endif
00354     return request->replyResponse(WRET_ERR_PARAM, "specify valid target {properties, methods, connectors}");
00355  }
00356 
00357 Response* SystemMonitor::mmDoListDeprecated( const Request* request ) {
00358     if ( request == NULL ) return NULL;
00359     string option = request->getArgument().toString();
00360     Log(LOG_VERBOSE, ":mmDoListDeprecated(%s)", option.c_str() );
00361 
00362                                                 WOSH_DEPRECATE( "SystemMonitor::mmDoListDeprecated", "SAMPLE" )
00363 
00364 #ifdef _ENABLE_PROFILING
00365     if ( this->profiler == NULL )
00366         return request->replyResponse(WRET_ERR_INTERNAL, "Internal error: Profiler is NULL");
00367     return request->replyResponse(WRET_OK, this->profiler->getDeprecatedTable() );
00368 #else
00369     return request->replyResponse(WRET_ERR_ILLEGAL_USE, "Deprecated Calls logging is not enabled in this built.");
00370 #endif
00371  }
00372 
00373 ///////////////////////////////////////////////////////////////////////////////////////////////////// METHODS
00374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00375 ////////////////////////////////////////////////////////////////////////////////////////////// STATIC METHODS
00376 
00377 WRESULT SystemMonitor::save( SystemInfo* sysInfo, const Object* source, bool raise_message ) {
00378     if ( sysInfo == NULL) return WRET_ERR_PARAM;
00379     if ( SystemMonitor::getInstance() == NULL ) return WRET_ERR_INTERNAL;
00380     if ( raise_message ) {
00381         Message* msg_system = new Message(sysInfo->clone());
00382         msg_system->setSource(source);
00383         msg_system->setDestinationBroadcast(false);
00384         msg_system->setDestinationBus(_Bus_Core);
00385         SecurityManager::getCredentialImplicit().signMessage(msg_system, source);
00386         SystemMonitor::getInstance()->BusCore.postMessage(msg_system);
00387      }
00388     ///@todo add to tuple space
00389     SystemMonitor::getInstance()->Log(LOG_INFO, ":save() : Adding SystemInfo#%"PRId64, sysInfo->getID() );
00390     SystemMonitor::getInstance()->infoCache.push_back_safe( sysInfo );
00391     return WRET_OK;
00392  }
00393 
00394 ////////////////////////////////////////////////////////////////////////////////////////////// STATIC METHODS
00395 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00396 
00397 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
00398 
00399 }; // namespace wosh

Generated on Tue Feb 8 2011 09:33:06 for WOSH system 0.8.888 [wolf] by Alessandro Polo, using DoxyGen 1.7.2 hosted by WOSH Framework