SFrame 3.6
core/src/SCycleConfig.cxx
Go to the documentation of this file.
00001 // $Id: SCycleConfig.cxx 331 2012-11-20 17:12:44Z krasznaa $
00002 
00003 // System include(s):
00004 #include <ctime>
00005 #include <locale>
00006 
00007 // STL include(s):
00008 #include <map>
00009 
00010 // ROOT include(s):
00011 #include <TSystem.h>
00012 
00013 // Local include(s):
00014 #include "../include/SCycleConfig.h"
00015 #include "../include/SLogger.h"
00016 
00017 #ifndef DOXYGEN_IGNORE
00018 ClassImp( SCycleConfig )
00019 #endif // DOXYGEN_IGNORE
00020 
00021 SCycleConfig::SCycleConfig( const char* name )
00022    : TNamed( name, "SFrame cycle configuration" ),
00023      m_cycleName( "Unknown" ), m_mode( LOCAL ),
00024      m_server( "" ), m_workdir( "" ), m_nodes( -1 ), m_properties(),
00025      m_inputData(), m_targetLumi( 1. ), m_outputDirectory( "" ),
00026      m_postFix( "" ), m_msgLevel( INFO ), m_useTreeCache( kFALSE ),
00027      m_cacheSize( 30000000 ), m_cacheLearnEntries( 100 ),
00028      m_processOnlyLocal( kFALSE ) {
00029 
00030 }
00031 
00032 const TString& SCycleConfig::GetCycleName() const {
00033 
00034    return m_cycleName;
00035 }
00036 
00037 void SCycleConfig::SetCycleName( const TString& name ) {
00038 
00039    m_cycleName = name;
00040    return;
00041 }
00042 
00043 SCycleConfig::RunMode SCycleConfig::GetRunMode() const {
00044 
00045    return m_mode;
00046 }
00047 
00048 void SCycleConfig::SetRunMode( SCycleConfig::RunMode mode ) {
00049 
00050    m_mode = mode;
00051    return;
00052 }
00053 
00054 const TString& SCycleConfig::GetProofServer() const {
00055 
00056    return m_server;
00057 }
00058 
00059 void SCycleConfig::SetProofServer( const TString& server ) {
00060 
00061    m_server = server;
00062    return;
00063 }
00064 
00065 const Int_t& SCycleConfig::GetProofNodes() const {
00066 
00067    return m_nodes;
00068 }
00069 
00070 void SCycleConfig::SetProofNodes( const Int_t nodes ) {
00071 
00072    m_nodes = nodes;
00073    return;
00074 }
00075 
00076 const TString& SCycleConfig::GetProofWorkDir() const {
00077 
00078    return m_workdir;
00079 }
00080 
00081 void SCycleConfig::SetProofWorkDir( const TString& workdir ) {
00082 
00083    m_workdir = workdir;
00084    return;
00085 }
00086 
00087 const SCycleConfig::property_type& SCycleConfig::GetProperties() const {
00088 
00089    return m_properties;
00090 }
00091 
00092 void SCycleConfig::SetProperty( const std::string& name, const std::string& value ) {
00093 
00094    m_properties.push_back( std::make_pair( name, value ) );
00095    return;
00096 }
00097 
00098 const SCycleConfig::id_type& SCycleConfig::GetInputData() const {
00099 
00100    return m_inputData;
00101 }
00102 
00103 void SCycleConfig::AddInputData( const SInputData& id ) {
00104 
00105    m_inputData.push_back( id );
00106    return;
00107 }
00108 
00109 void SCycleConfig::SetOutputDirectory( const TString& outDir ) {
00110 
00111    m_outputDirectory = outDir;
00112    return;
00113 }
00114 
00115 const TString& SCycleConfig::GetOutputDirectory() const {
00116 
00117    return m_outputDirectory;
00118 }
00119 
00120 void SCycleConfig::SetPostFix( const TString& postFix ) {
00121 
00122    m_postFix = postFix;
00123    return;
00124 }
00125 
00126 const TString& SCycleConfig::GetPostFix() const {
00127 
00128    return m_postFix;
00129 }
00130 
00131 void SCycleConfig::SetMsgLevel( SMsgType level ) {
00132 
00133    m_msgLevel = level;
00134    return;
00135 }
00136 
00137 SMsgType SCycleConfig::GetMsgLevel() const {
00138 
00139    return m_msgLevel;
00140 }
00141 
00142 void SCycleConfig::SetUseTreeCache( Bool_t status ) {
00143 
00144    m_useTreeCache = status;
00145    return;
00146 }
00147 
00148 Bool_t SCycleConfig::GetUseTreeCache() const {
00149 
00150    return m_useTreeCache;
00151 }
00152 
00153 void SCycleConfig::SetCacheSize( Long64_t size ) {
00154 
00155    m_cacheSize = size;
00156    return;
00157 }
00158 
00159 Long64_t SCycleConfig::GetCacheSize() const {
00160 
00161    return m_cacheSize;
00162 }
00163 
00164 void SCycleConfig::SetCacheLearnEntries( Int_t entries ) {
00165 
00166    m_cacheLearnEntries = entries;
00167    return;
00168 }
00169 
00170 Int_t SCycleConfig::GetCacheLearnEntries() const {
00171 
00172    return m_cacheLearnEntries;
00173 }
00174 
00175 void SCycleConfig::SetProcessOnlyLocal( Bool_t flag ) {
00176 
00177    m_processOnlyLocal = flag;
00178    return;
00179 }
00180 
00181 Bool_t SCycleConfig::GetProcessOnlyLocal() const {
00182 
00183    return m_processOnlyLocal;
00184 }
00185 
00186 void SCycleConfig::PrintConfig() const {
00187 
00188    SLogger logger( "SCycleConfig" );
00189    logger << INFO << "==========================================================="
00190           << SLogger::endmsg;
00191    logger << INFO << "                    Cycle configuration" << SLogger::endmsg;
00192    logger << INFO << "  - Running mode: "
00193           << ( m_mode == LOCAL ? "LOCAL" : "PROOF" ) << SLogger::endmsg;
00194    if( m_mode == PROOF ) {
00195       logger << INFO << "  - PROOF server: " << m_server << SLogger::endmsg;
00196       logger << INFO << "  - PROOF nodes: " << m_nodes << SLogger::endmsg;
00197    }
00198    logger << INFO << "  - Target luminosity: " << m_targetLumi << SLogger::endmsg;
00199    logger << INFO << "  - Output directory: " << m_outputDirectory << SLogger::endmsg;
00200    logger << INFO << "  - Post-fix: " << m_postFix << SLogger::endmsg;
00201    if( m_useTreeCache ) {
00202       logger << INFO << "  - Using TTreeCache with size: " << m_cacheSize << SLogger::endmsg;
00203       if( m_cacheLearnEntries > 0 ) {
00204          logger << INFO << "                 learn entries: " << m_cacheLearnEntries
00205                 << SLogger::endmsg;
00206       } else if( m_cacheLearnEntries < 0 ) {
00207          logger << INFO << "    All branches added to the cache" << SLogger::endmsg;
00208       } else {
00209          logger << INFO << "    The user is expected to choose branches to cache"
00210                 << SLogger::endmsg;
00211       }
00212    }
00213    if( m_processOnlyLocal ) {
00214       logger << INFO << "  - Workers will only process local files"
00215              << SLogger::endmsg;
00216    }
00217 
00218    for( id_type::const_iterator id = m_inputData.begin(); id != m_inputData.end();
00219         ++id ) {
00220       id->Print();
00221    }
00222 
00223    logger << INFO << "==========================================================="
00224           << SLogger::endmsg;
00225 
00226    return;
00227 }
00228 
00229 void SCycleConfig::ArrangeInputData() throw ( SError ) {
00230 
00231    // multimap to hold all type strings of InputData objects; will be
00232    // used to search InputData objects with the same name, to make
00233    // sure these will be processed directly consecutively so that they
00234    // end up in the same output file
00235    std::multimap< std::string, int > inputDataHelper;
00236    std::vector< SInputData >::iterator be = m_inputData.begin();
00237    std::vector< SInputData >::iterator en = m_inputData.end();
00238    int index = 0;
00239 
00240    // loop over InputData vector and copy the type names into the
00241    // multimap, remembering the position in the vector
00242    for( ; be != en; ++be,++index ) {
00243       inputDataHelper.insert( std::make_pair( be->GetType(), index ) );
00244    }
00245 
00246    std::multimap< std::string, int >::iterator help1 = inputDataHelper.begin();
00247    std::multimap< std::string, int >::iterator help2 = inputDataHelper.end();
00248    index = 0;
00249    std::vector< SInputData > tmpInput;
00250 
00251    // Now copy the InputData objects to a temporary vector in the
00252    // order we want them to be processed
00253    for( ; help1 != help2; ++help1,++index ) {
00254       if( help1->second != index ) {
00255          SLogger logger( "SCycleConfig" );
00256          logger << WARNING << "InputData of type \"" << help1->first
00257                 << "\" was given as input number " << ( help1->second + 1 )
00258                 << " but will be repositioned and instead processed as number "
00259                 << ( index + 1 ) << SLogger::endmsg;         
00260       }
00261       tmpInput.push_back( m_inputData[ help1->second ] );
00262    }
00263 
00264    // Sanity check
00265    if( m_inputData.size() != tmpInput.size() ) {
00266       SError error( SError::StopExecution );
00267       error << "Inconsistent InputData vectors: size " << m_inputData.size()
00268             << " and " << tmpInput.size();
00269       throw error;
00270    }
00271 
00272    // Now copy the objects back into the vector we use for processing
00273    for( size_t i = 0; i < tmpInput.size(); ++i ) {
00274       m_inputData[ i ] = tmpInput[ i ];
00275    }
00276 
00277    return;
00278 }
00279 
00280 void SCycleConfig::ValidateInput() {
00281 
00282    for( id_type::iterator id = m_inputData.begin(); id != m_inputData.end(); ++id ) {
00283       id->ValidateInput( m_server );
00284    }
00285 
00286    return;
00287 }
00288 
00299 TString SCycleConfig::GetStringConfig( const SInputData* id ) const {
00300 
00301    // The result string:
00302    TString result;
00303 
00304    // Get the system information:
00305    SysInfo_t sysInfo;
00306    gSystem->GetSysInfo( &sysInfo );
00307 
00308    // Get the user information:
00309    UserGroup_t* userInfo = gSystem->GetUserInfo();
00310 
00311    // Get the current time:
00312    time_t rawtime = time( NULL );
00313    const char* currentTime = ctime( &rawtime );
00314    TString printedTime = currentTime ? currentTime : "unknown";
00315    if( printedTime.EndsWith( "\n" ) ) {
00316       printedTime.Remove( printedTime.Length() - 1 );
00317    }
00318 
00319    // Interestingly enough, it's not needed to delete the return value of
00320    // ctime(...). It even causes problems if I try to do it. Even though
00321    // it actually returns "char*" and not "const char*". Very strange...
00322 
00323    // Some disclaimer:
00324    result += "<!-- Archived cycle configuration -->\n";
00325    result += TString::Format( "<!--  host: %s -->\n", gSystem->HostName() );
00326    result += TString::Format( "<!--  syst: %s / %s -->\n", sysInfo.fOS.Data(),
00327                               sysInfo.fModel.Data() );
00328    result += TString::Format( "<!--  user: %s (%s) -->\n",
00329                               ( userInfo ? userInfo->fUser.Data() :
00330                                 "unknown" ),
00331                               ( userInfo ? userInfo->fRealName.Data() :
00332                                 "N/A" ) );
00333    result += TString::Format( "<!--  time: %s -->\n\n", printedTime.Data() );
00334 
00335    // Delete the created object(s):
00336    if( userInfo ) delete userInfo;
00337 
00338    // Put together the <Cycle...> part of the configuration:
00339    result += TString::Format( "<Cycle Name=\"%s\"\n", m_cycleName.Data() );
00340    result += TString::Format( "       OutputDirectory=\"%s\"\n",
00341                               m_outputDirectory.Data() );
00342    result += TString::Format( "       PostFix=\"%s\"\n",
00343                               m_postFix.Data() );
00344    result += TString::Format( "       TargetLumi=\"%g\"\n", m_targetLumi );
00345    result += "       RunMode=\"";
00346    if( m_mode == LOCAL ) {
00347       result += "LOCAL";
00348    } else if( m_mode == PROOF ) {
00349       result += "PROOF";
00350    } else {
00351       result += "UNKNOWN";
00352    }
00353    result += "\"\n";
00354    result += TString::Format( "       ProofServer=\"%s\"\n",
00355                               m_server.Data() );
00356    result += TString::Format( "       ProofNodes=\"%i\"\n", m_nodes );
00357    result += TString::Format( "       ProofWorkDir=\"%s\"\n",
00358                               m_workdir.Data() );
00359    result += TString::Format( "       UseTreeCache=\"%s\"\n",
00360                               ( m_useTreeCache ? "True" : "False" ) );
00361    result += TString::Format( "       TreeCacheSize=\"%lld\"\n", m_cacheSize );
00362    result += TString::Format( "       TreeCacheLearnEntries=\"%i\"\n",
00363                               m_cacheLearnEntries );
00364    result += TString::Format( "       ProcessOnlyLocal=\"%s\">\n\n",
00365                               ( m_processOnlyLocal ? "True" : "False" ) );
00366 
00367    // Decide how to add the input data information:
00368    if( id ) {
00369       // Add just this one SInputData to the output:
00370       result += TString::Format( "%s\n\n", id->GetStringConfig().Data() );
00371    } else {
00372       // Put all the InputData options in there:
00373       id_type::const_iterator i_itr = m_inputData.begin();
00374       id_type::const_iterator i_end = m_inputData.end();
00375       for( ; i_itr != i_end; ++i_itr ) {
00376          result += TString::Format( "%s\n\n", i_itr->GetStringConfig().Data() );
00377       }
00378    }
00379 
00380    // Put all the user configuration options in there:
00381    result += "    <UserConfig>\n";
00382    property_type::const_iterator p_itr = m_properties.begin();
00383    property_type::const_iterator p_end = m_properties.end();
00384    for( ; p_itr != p_end; ++p_itr ) {
00385       result += TString::Format( "       <Item Name=\"%s\" Value=\"%s\"/>\n",
00386                                  p_itr->first.c_str(),
00387                                  p_itr->second.c_str() );
00388    }
00389    result += "    </UserConfig>\n";
00390 
00391    // Close the <Cycle> block:
00392    result += "</Cycle>";
00393 
00394    // Return the string that we just made:
00395    return result;
00396 }
00397 
00398 void SCycleConfig::ClearConfig() {
00399 
00400    m_mode = LOCAL;
00401    m_server = "";
00402    m_workdir = "";
00403    m_nodes = -1;
00404    m_properties.clear();
00405    m_inputData.clear();
00406    m_targetLumi = 1.0;
00407    m_outputDirectory = "./";
00408    m_postFix = "";
00409    m_msgLevel = INFO;
00410    m_useTreeCache = kFALSE;
00411    m_cacheSize = 30000000;
00412    m_cacheLearnEntries = 100;
00413 
00414    return;
00415 }