1 | // ESAF : Euso Simulation and Analysis Framework |
---|
2 | // $Id: Config.cc 2956 2011-06-28 18:54:32Z mabl $ |
---|
3 | // Author: Daniel De Marco Jan, 25 2002 |
---|
4 | // M.Pallavicini - added Standard configuration handling 1/10/02 |
---|
5 | |
---|
6 | /***************************************************************************** |
---|
7 | * ESAF: Euso Simulation and Analysis Framework * |
---|
8 | * * |
---|
9 | * Id: EsafMsgDispatcher * |
---|
10 | * Package: Base * |
---|
11 | * Coordinator: Marco.Pallavicini * |
---|
12 | * * |
---|
13 | *****************************************************************************/ |
---|
14 | |
---|
15 | //______________________________________________________________________________ |
---|
16 | // |
---|
17 | // Configuration Manager |
---|
18 | // ==================== |
---|
19 | // |
---|
20 | // |
---|
21 | |
---|
22 | |
---|
23 | #include "Config.hh" |
---|
24 | #include "StringsFileParser.hh" |
---|
25 | #include "EsafSys.hh" |
---|
26 | |
---|
27 | #include <TSystem.h> |
---|
28 | #include <fstream> |
---|
29 | |
---|
30 | ClassImp(Config) |
---|
31 | |
---|
32 | Config *Config::fMe = 0; |
---|
33 | |
---|
34 | //______________________________________________________________________________ |
---|
35 | Config::Config() { |
---|
36 | // |
---|
37 | // Ctor |
---|
38 | // |
---|
39 | fCurrentConfig = "None"; |
---|
40 | |
---|
41 | if ( !gEsafSys ) |
---|
42 | gEsafSys = new EsafSys(); |
---|
43 | |
---|
44 | fStdConfigList = ConfigFileParser::GetCfgDir(); |
---|
45 | fStdConfigList += "/Standard/StandardConfigs.lst"; |
---|
46 | fCfgDump = "./output/ConfigDump.cfg"; |
---|
47 | } |
---|
48 | |
---|
49 | //______________________________________________________________________________ |
---|
50 | Config::~Config() { |
---|
51 | // |
---|
52 | // Dtor |
---|
53 | // |
---|
54 | } |
---|
55 | |
---|
56 | //______________________________________________________________________________ |
---|
57 | Config* Config::Get() { |
---|
58 | // |
---|
59 | // Instance |
---|
60 | // |
---|
61 | if ( fMe == 0 ) |
---|
62 | fMe = new Config(); |
---|
63 | return fMe; |
---|
64 | } |
---|
65 | |
---|
66 | //______________________________________________________________________________ |
---|
67 | void Config::SetCfgDump( const char* name ) { |
---|
68 | // |
---|
69 | // |
---|
70 | // |
---|
71 | |
---|
72 | if ( !name ) return; |
---|
73 | |
---|
74 | string ext = ".cfg"; |
---|
75 | |
---|
76 | fCfgDump = name; |
---|
77 | |
---|
78 | if (fCfgDump.rfind(ext) != (fCfgDump.size()-ext.size())) |
---|
79 | fCfgDump += ext; |
---|
80 | } |
---|
81 | |
---|
82 | //______________________________________________________________________________ |
---|
83 | void Config::SaveConfig( const char* name ) { |
---|
84 | // |
---|
85 | // Save the current configuration in a single "standard config file" |
---|
86 | // |
---|
87 | |
---|
88 | TString fname = name ? name : fCfgDump.c_str(); |
---|
89 | |
---|
90 | if ( fname[0] != '/' ) |
---|
91 | gSystem->ExpandPathName(fname); |
---|
92 | |
---|
93 | Msg(EsafMsg::Debug) << "Saving config on file " << fname << MsgDispatch; |
---|
94 | ofstream of(fname.Data(),ios::out); |
---|
95 | |
---|
96 | if (!of) { |
---|
97 | Msg(EsafMsg::Error) << "Failed to open file " << fname << " to save the config" << MsgDispatch; |
---|
98 | return; |
---|
99 | } |
---|
100 | |
---|
101 | if ( IsStandardConfigDefined() ) { |
---|
102 | of << "## Standard config " << fCurrentConfig << " is being used." << endl; |
---|
103 | of << "## user defined variables dump" << endl; |
---|
104 | map<string, vector<string>*>::iterator jt; |
---|
105 | for(jt=fUserDef.begin(); jt != fUserDef.end(); jt++) { |
---|
106 | of << "## Dump for class name " << jt->first << endl; |
---|
107 | |
---|
108 | vector<string>::iterator jt2; |
---|
109 | for(jt2 = jt->second->begin(); jt2 != jt->second->end(); jt2++) |
---|
110 | of << (*jt2) << endl; |
---|
111 | |
---|
112 | of << "## End of dump for class name " << jt->first << endl; |
---|
113 | } |
---|
114 | of.close(); |
---|
115 | return; |
---|
116 | } |
---|
117 | of << "## config file dump generated by ESAF \n\n"; |
---|
118 | map<string, ConfigFileParser*>::const_iterator it; |
---|
119 | for(it=fCfs.begin(); it!=fCfs.end(); it++) { |
---|
120 | ConfigFileParser &cfp = *(it->second); |
---|
121 | of << "## Dump for class name " << it->first << endl; |
---|
122 | map<string,double>::const_iterator it2; |
---|
123 | for(it2=cfp.fNumbers.begin(); it2!=cfp.fNumbers.end(); it2++) { |
---|
124 | of << it2->first << " = " << it2->second << endl; |
---|
125 | } |
---|
126 | map<string,string>::const_iterator it3; |
---|
127 | for(it3=cfp.fChars.begin(); it3!=cfp.fChars.end(); it3++) { |
---|
128 | of << it3->first << " = " << it3->second << endl; |
---|
129 | } |
---|
130 | of << "## End of dump for class name " << it->first << endl; |
---|
131 | } |
---|
132 | of.close(); |
---|
133 | } |
---|
134 | |
---|
135 | //______________________________________________________________________________ |
---|
136 | ConfigFileParser *Config::GetCF(const string &ClassType, const string &ClassName, |
---|
137 | const string &path ) { |
---|
138 | // |
---|
139 | // if ClassName is name of a parent class whose real instance is a child, the |
---|
140 | // file corresponding to the child is returned |
---|
141 | // |
---|
142 | |
---|
143 | // if a standard config is defined, use it |
---|
144 | if ( IsStandardConfigDefined() ) { |
---|
145 | return fStandards[fCurrentConfig]; |
---|
146 | } |
---|
147 | |
---|
148 | // check if this class has a child |
---|
149 | string child_name; |
---|
150 | if ( fChildTable.count( ClassName ) == 0 ) |
---|
151 | child_name = ClassName; |
---|
152 | else |
---|
153 | child_name = *(fChildTable[ClassName]); |
---|
154 | |
---|
155 | map<string, string*>::iterator cit=fChildTable.begin(), |
---|
156 | cend=fChildTable.end(); |
---|
157 | string parent_name; |
---|
158 | for ( ; cit!=cend; cit++ ) { |
---|
159 | if ( *(cit->second) == ClassName ) { |
---|
160 | parent_name = cit->first; |
---|
161 | break; |
---|
162 | } |
---|
163 | } |
---|
164 | |
---|
165 | // create the ConfigFileParser if needed, and override parameters if required |
---|
166 | if ( fCfs.count(child_name) == 0 ) { |
---|
167 | fCfs[child_name] = new ConfigFileParser(ClassType,child_name,path); |
---|
168 | if ( fUserDef.count( child_name ) != 0 ) { |
---|
169 | vector<string>::iterator dummy; |
---|
170 | for( dummy = fUserDef[child_name]->begin(); |
---|
171 | dummy != fUserDef[child_name]->end() ;dummy++){ |
---|
172 | fCfs[child_name]->Replace( *dummy ); |
---|
173 | } |
---|
174 | } |
---|
175 | |
---|
176 | if ( parent_name.length()>0 ){ |
---|
177 | if ( fUserDef.count( parent_name ) != 0 ) { |
---|
178 | vector<string>::iterator dummy; |
---|
179 | for( dummy = fUserDef[parent_name]->begin(); |
---|
180 | dummy != fUserDef[parent_name]->end() ;dummy++){ |
---|
181 | fCfs[child_name]->Replace( *dummy ); |
---|
182 | } |
---|
183 | } |
---|
184 | } |
---|
185 | } |
---|
186 | |
---|
187 | // return ConfigFileParser |
---|
188 | return fCfs[child_name]; |
---|
189 | } |
---|
190 | |
---|
191 | // handling standard configuration |
---|
192 | // The file config/Standard/StandardConfigs.lst contains the names of the "Standard" |
---|
193 | // configurations, i.e. files with all ESAF parameters. |
---|
194 | // Each file will be also kept in the same directory |
---|
195 | |
---|
196 | |
---|
197 | //______________________________________________________________________________ |
---|
198 | Bool_t Config::UseConfig(const string& name) { |
---|
199 | // |
---|
200 | // Define a new config with the current configuration files |
---|
201 | // to be implemented |
---|
202 | // |
---|
203 | |
---|
204 | if ( fStandards.count(name) == 0 ) { |
---|
205 | Msg(EsafMsg::Warning) << name << " is not defined as standard configuration in " |
---|
206 | << fStdConfigList<< MsgDispatch; |
---|
207 | return kFALSE; |
---|
208 | } |
---|
209 | |
---|
210 | Msg(EsafMsg::Info) << "Using standard configuration " << name << MsgDispatch; |
---|
211 | fCurrentConfig = name; |
---|
212 | return kTRUE; |
---|
213 | } |
---|
214 | |
---|
215 | //______________________________________________________________________________ |
---|
216 | ConfigFileParser *Config::GetStandardConfig() { |
---|
217 | // |
---|
218 | // Get the current standard config if defined |
---|
219 | // returns NULL if not (no exception thrown) |
---|
220 | // |
---|
221 | if ( IsStandardConfigDefined() ) { |
---|
222 | if ( fStandards.find(fCurrentConfig) == fStandards.end() ) { |
---|
223 | Msg(EsafMsg::Warning) << "Standard config "+fCurrentConfig+" does not exist!!!" << MsgDispatch; |
---|
224 | return NULL; |
---|
225 | } else |
---|
226 | return fStandards[fCurrentConfig]; |
---|
227 | } |
---|
228 | return (ConfigFileParser*)NULL; |
---|
229 | } |
---|
230 | |
---|
231 | //______________________________________________________________________________ |
---|
232 | void Config::LoadStandardConfigs() { |
---|
233 | // |
---|
234 | // Load the list of defined standard configs |
---|
235 | // |
---|
236 | |
---|
237 | // open file |
---|
238 | ifstream in(fStdConfigList.c_str()); |
---|
239 | if(!in) FatalError("Can't open file "+fStdConfigList); |
---|
240 | |
---|
241 | // get list from file |
---|
242 | // each line not beginning with # is considered a standard config name |
---|
243 | string dummy; |
---|
244 | while(getline(in, dummy)) { |
---|
245 | size_t pos; |
---|
246 | |
---|
247 | // erase comments |
---|
248 | pos=dummy.find('#'); |
---|
249 | if(pos!=string::npos) dummy.erase(pos); |
---|
250 | |
---|
251 | // swallow spaces |
---|
252 | dummy=ltrim(dummy); |
---|
253 | |
---|
254 | // skip blank lines |
---|
255 | if(dummy.empty()) continue; |
---|
256 | |
---|
257 | // now ready with name |
---|
258 | string cfgName = dummy; |
---|
259 | //FIXME: conflict with EsafMsgDispatcher building |
---|
260 | //Messages can't be used here |
---|
261 | //Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch; |
---|
262 | Msg(EsafMsg::Info) << "Reading standard config " << cfgName << MsgDispatch; |
---|
263 | |
---|
264 | // build the ConfigFileParser object and put it into the map |
---|
265 | if ( fStandards.find(cfgName) == fStandards.end() ) { |
---|
266 | fStandards[cfgName] = new ConfigFileParser("Standard",cfgName); |
---|
267 | |
---|
268 | // override parameters if required |
---|
269 | // iterate on map elements |
---|
270 | map<string, vector<string>* >::iterator m_iter; |
---|
271 | for(m_iter = fUserDef.begin(); m_iter != fUserDef.end(); m_iter++) { |
---|
272 | // iterate on vector elements |
---|
273 | vector<string>::iterator v_iter; |
---|
274 | for(v_iter = m_iter->second->begin(); |
---|
275 | v_iter != m_iter->second->end(); v_iter++) { |
---|
276 | fStandards[cfgName]->Replace(*v_iter); |
---|
277 | } |
---|
278 | } |
---|
279 | } |
---|
280 | else { |
---|
281 | //FIXME: conflict with EsafMsgDispatcher building |
---|
282 | //Messages can't be used here |
---|
283 | Msg(EsafMsg::Panic) << "Duplicate name "+cfgName+" in ./config/Standard/Config.cfg" << MsgDispatch; |
---|
284 | } |
---|
285 | } |
---|
286 | } |
---|
287 | |
---|
288 | //______________________________________________________________________________ |
---|
289 | void Config::Reset(Bool_t user) { |
---|
290 | // |
---|
291 | // Reset the config |
---|
292 | // |
---|
293 | |
---|
294 | // FIXME: check for memory leak here. |
---|
295 | // Does map destroy the elements it points to ? |
---|
296 | map<string,ConfigFileParser*>::iterator dummy; |
---|
297 | if (fCfs.size() != 0) |
---|
298 | for (dummy = fCfs.begin(); dummy != fCfs.end(); ++dummy) |
---|
299 | delete dummy->second; |
---|
300 | fCfs.clear(); |
---|
301 | |
---|
302 | if ( user ) |
---|
303 | ResetUserDef(); |
---|
304 | } |
---|
305 | |
---|
306 | //______________________________________________________________________________ |
---|
307 | void Config::ResetUserDef() { |
---|
308 | // |
---|
309 | // Reset User settings |
---|
310 | // |
---|
311 | map<string, vector<string>* >::iterator dummy; |
---|
312 | if (fUserDef.size() != 0) |
---|
313 | for (dummy = fUserDef.begin(); dummy != fUserDef.end(); ++dummy) |
---|
314 | delete dummy->second; |
---|
315 | fUserDef.clear(); |
---|
316 | } |
---|
317 | |
---|
318 | //______________________________________________________________________________ |
---|
319 | void Config::AssociateParent(const string& c_name, const string& p_name) { |
---|
320 | // |
---|
321 | // associate class name and parent name |
---|
322 | // |
---|
323 | if ( fChildTable.count(p_name) == 0 ) { |
---|
324 | fChildTable[p_name] = new string(c_name); |
---|
325 | } |
---|
326 | else { |
---|
327 | if ( (*(fChildTable[p_name])) == c_name ) return; |
---|
328 | Msg(EsafMsg::Warning) << c_name << " is being associated to " |
---|
329 | << p_name << endl; |
---|
330 | Msg(EsafMsg::Warning) << *(fChildTable[p_name]) << MsgDispatch; |
---|
331 | } |
---|
332 | } |
---|
333 | |
---|
334 | //______________________________________________________________________________ |
---|
335 | void Config::AddUserDefinition(const string &c_name, const string &expr) { |
---|
336 | // |
---|
337 | // Overrides a parameter of the config files. |
---|
338 | // Syntax: |
---|
339 | // Config::Get()->AddUserDefinition( "classname","parameter=value") |
---|
340 | // |
---|
341 | |
---|
342 | string s = expr; |
---|
343 | s = ltrim( s ); |
---|
344 | if ( s.empty() ) |
---|
345 | FatalError("invalid expr: "+expr); |
---|
346 | |
---|
347 | if ( fUserDef.count(c_name) == 0) |
---|
348 | fUserDef[c_name] = new vector<string>; |
---|
349 | |
---|
350 | fUserDef[c_name]->push_back(expr); |
---|
351 | |
---|
352 | if ( IsStandardConfigDefined() && fUserDef.count( c_name ) != 0 ) |
---|
353 | fStandards[fCurrentConfig]->Replace( expr, kTRUE ); |
---|
354 | |
---|
355 | MsgForm(EsafMsg::Debug,"UserDef added: class=%s, expr=%s",c_name.c_str(), expr.c_str()); |
---|
356 | } |
---|
357 | |
---|
358 | //______________________________________________________________________________ |
---|
359 | Bool_t Config::LoadUserConfig( const char* name ) { |
---|
360 | // |
---|
361 | // Load a set of user definitions from file |
---|
362 | // |
---|
363 | // The definitions MUST have the following format |
---|
364 | // Classname.VarName=Value |
---|
365 | // |
---|
366 | |
---|
367 | TString fname = name; |
---|
368 | gSystem->ExpandPathName(fname); |
---|
369 | StringsFileParser parser( fname.Data() ); |
---|
370 | if ( parser.IsZombie() ) |
---|
371 | MsgForm(EsafMsg::Panic,"File %s not found",name); |
---|
372 | |
---|
373 | |
---|
374 | list< list<string> >& lines = parser.GetLines(); |
---|
375 | |
---|
376 | size_t nlines = lines.size(); |
---|
377 | size_t n(0); |
---|
378 | vector<string> keys(nlines); |
---|
379 | vector<string> expr(nlines); |
---|
380 | |
---|
381 | list<string>::const_iterator jt; |
---|
382 | list< list<string> >::const_iterator it; |
---|
383 | |
---|
384 | for( it = lines.begin(); it != lines.end(); it++ ) { |
---|
385 | // rebuild the line with 1 space |
---|
386 | string line; |
---|
387 | for (jt=it->begin(); jt != it->end();jt++ ) { |
---|
388 | if ( jt != it->begin() ) line += " "; |
---|
389 | line += *(jt); |
---|
390 | } |
---|
391 | |
---|
392 | |
---|
393 | if ( it->size() != 3 ) { |
---|
394 | MsgForm(EsafMsg::Warning,"Wrong number of elements in file %s at line:",name); |
---|
395 | Msg(EsafMsg::Panic) << line << " " << it->size() << MsgDispatch; |
---|
396 | return kFALSE; |
---|
397 | } |
---|
398 | |
---|
399 | // keyword |
---|
400 | jt = it->begin(); |
---|
401 | size_t pos = jt->find('.'); |
---|
402 | |
---|
403 | if ( pos == string::npos ) { |
---|
404 | MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",name); |
---|
405 | Msg(EsafMsg::Panic) << line << " " << it->size() << MsgDispatch; |
---|
406 | return kFALSE; |
---|
407 | } |
---|
408 | |
---|
409 | keys[n] = jt->substr(0,pos); |
---|
410 | |
---|
411 | // check on the '=' |
---|
412 | jt++; |
---|
413 | if ( *(jt) != "=" ) { |
---|
414 | MsgForm(EsafMsg::Warning,"Corrupted file %s at line:",name); |
---|
415 | Msg(EsafMsg::Panic) << line << " " << it->size() << MsgDispatch; |
---|
416 | return kFALSE; |
---|
417 | } |
---|
418 | |
---|
419 | expr[n] = line; |
---|
420 | |
---|
421 | n++; |
---|
422 | } |
---|
423 | |
---|
424 | MsgForm(EsafMsg::Info,"UserConfig %s loaded.", name); |
---|
425 | for (size_t i(0); i<n; i++) |
---|
426 | AddUserDefinition(keys[i],expr[i]); |
---|
427 | |
---|
428 | return kTRUE; |
---|
429 | } |
---|