ConfAgent.cpp 12.8 KB
Newer Older
1
/***************************************************************************
2 3
 *   Copyright (C) 2004 by Olivier Stezowski                               *
 *   stezow(AT)ipnl.in2p3.fr                                               *
4 5 6 7 8 9 10 11 12 13 14 15
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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     *
16
 *   along with this program; if not, write to the                         *
17 18 19
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
20

21 22 23 24 25 26 27 28
/** \file ConfAgent.cpp compiled in libGWADF.so */

#ifndef ADF_ConfAgent
#include "ConfAgent.h"
#endif
#ifndef ADF_ConfigurationFrame
#include "ConfigurationFrame.h"
#endif
29 30 31 32 33 34
#ifndef ADF_RunAgent
#include "RunAgent.h"
#endif 
#ifndef ADF_DFAgent
#include "DFAgent.h"
#endif
35

36 37
#include <stdlib.h>

38
ADF::ConfAgent *ADF::ConfAgent::gTheGlobalAgent = 0x0;
39 40 41 42 43 44

using namespace ADF;
using namespace std;

namespace { UInt_t gAllocated = 0u; }

45
ConfAgent::ConfAgent() : DotConf("ADF::ConfAgent")
46
{ 
47 48
	gAllocated++;
	SetWithRecord(true);
49 50 51 52 53 54
} 

ConfAgent::~ConfAgent() 
{
	gAllocated--;
	
55
	if ( gAllocated == 1 ) {
56 57 58
#ifdef DEBUGSTATIC			
		std::clog << "[[static]] ConfAgent::~ConfAgent() ]\n[...\n" ;
#endif
59
		KilltheGlobalAgent();
60
#ifdef DEBUGSTATIC			
61
		std::clog << " done\n...]\n";	
62
#endif
63 64 65
	}
}

Guillaume Baulieu's avatar
Guillaume Baulieu committed
66
ConfAgent::EModel ConfAgent::GetModel(const std::string& model)
67 68 69 70 71
{
	ConfAgent::EModel m = ConfAgent::kSafe; 
	
	if ( model == "kStrict" )
		m = ConfAgent::kStrict;
72 73
	else if ( model == "kGrowing" )
		m = ConfAgent::kGrowing;
74
	
75 76 77
	return m;
}

78
const Char_t *ConfAgent::GetStringModel(ConfAgent::EModel m)
79
{
80
	const char *model = 0x0;
81 82 83 84 85 86 87 88 89
	switch (m) {
		case kStrict:
			model = "kStrict";
			break;	
		case kSafe:
			model = "kSafe";			
			break;	
		case kGrowing:
			model = "kGrowing";
90
			break;
91 92 93 94 95 96
	}
	return model; 
}

void ConfAgent::KilltheGlobalAgent()
{
97
	if ( gTheGlobalAgent && gAllocated == 1 ) {
98
#ifdef DEBUGSTATIC					
99 100
		std::clog << "[[static]] KilltheGlobalAgent() ]\n[...\n" ;
		std::clog << " Destroying the global agent ... " << std::endl;
101
#endif		
102
		delete gTheGlobalAgent;
103
#ifdef DEBUGSTATIC			
104
		std::clog << " done\n...]\n";	
105
#endif		
106
		gTheGlobalAgent = 0x0;	
107 108 109 110
	}
}


111 112
namespace ADF {
	
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
	//! The Agata Data Flow agent
	/*!
	 this contents all the information concerning the agata data flow @ a given point. A global, static agent is loaded @ the beginning.
	 It is initialised by the ADF.conf file. One is installed in the distribution, the other one is in the user space in the directory defined under ADF_CONF_PATH.
	 
	 Any sub-system (actor) has its own agent (local) which is a Clone of the global one so that @ the beginning all the system is synchronized.
	 Local agents could be re-configured locally (for instance by configuration frames) independently to adapt themself to the local data flow without breaking the whole system.
	 
	 As a agata data flow agent, it defines the factories needed to allocate keys/frames. The global agent has references to global (singleton) factories.
	 Local agent have clones of the global ones. 
	 The agent also defines the endianness of the data flow, the factories it really needs to work completely (it should be included in the list of loaded ones),
	 as well as the definition of the frames going one.
	 
	 The Primarykey is the minimum information to be able to map the flow. Indeed, one may have the length of the frames coded on 2 or 4 bytes.
	 The AutoConf frame is used by the inner ADF system to reconfigure itself the agent. Comment the line to switch off this feature.
	 
	 \code
	 # This is a begin of the ADF configuration record 
	 # Option is Init. It means the Agent is reset before being initialised 
	 # 
	 #////ADF::ConfAgent_beg//// Agata 1 Init 
	 #  
	 #
	 Endian: kLittle
	 #
	 # List of factories required 
	 # 
	 # Factories for Keys 
	 #
	 KeyFactory: Default 
	 KeyFactory: Agata 
	 #
	 # Factories for Frames
	 #
	 FrameFactory: Agata 
	 # 
	 # 
	 # Version of the primary key that structures the data flow 
	 # and the frame expected to reconfigure it
	 # 
	 PrimaryKey:	Default FS 0 1 
	 #
	 # comment/uncomment to switch off/on auto-reconf
	 AutoConf:	Agata conf:global 2 0 Agata conf:global 0 0
	 #
	 #
	 # Current Frames going through the data flow
	 #
	 Frame:  Agata data:crystal 4 0  Agata data:crystal 65000 0  
	 Frame:  Agata data:ccrystal 4 0  Agata data:ccrystal 65000 0  
	 Frame:  Agata data:ranc0 4 0  Agata data:ranc0 65000 0  
	 Frame:  Agata data:ranc1 4 0  Agata data:ranc1 65000 0  
	 Frame:  Agata data:psa 4 0  Agata data:psa 65000 1  
	 Frame:  Agata data:tracked 4 0  Agata data:tracked 65000 0  
	 Frame:  Agata event:data 4 0  Agata event:data 4 0  
	 Frame:  Agata event:data:psa 4 0  Agata event:data:psa 4 0  
	 #
	 # end of Data Flow Defaults  
	 #
	 #////ADF::ConfAgent_end//// 
	 \endcode
	 
	 To work with a factory version different that -1 (which is the default), just set
	 
	 \code
	 KeyFactory: Agata 0
	 \endcode
	 
	 
	 */
	class AgataConfAgent : public ConfAgent
	{	
	private:
		//! global AgataConf Agent
		static AgataConfAgent *gTheGlobalAgent;
188
		
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
	private:
		//! Agent in charge of the structrure of the data flow
		DFAgent *fDFAgent;	
		//! Agent in charge of the informations relatives to the run
		RunAgent *fRunAgent;
		
	public:
		//! used to set global agent
		AgataConfAgent(); 
		//! used to set local agent i.e. clones
		AgataConfAgent(const char *);
		//! destructor
		virtual ~AgataConfAgent(); 
		
		//! to get the Data Flow Agent in charge of knowing the structure of the DF
		virtual DFAgent *GetDFAgent()
205
		{ return fDFAgent ;}
206 207
		//! to get the run Agent in charge of knowing the conditions of the DF being processed
		virtual RunAgent *GetRunAgent()
208
		{ return fRunAgent ;}
209
		virtual const DFAgent *GetConstDFAgent() const
210
		{ return const_cast<const DFAgent *> (fDFAgent) ;}
211
		virtual const RunAgent *GetConstRunAgent() const
212
		{ return const_cast<const RunAgent *> (fRunAgent) ;}
213 214 215 216 217 218 219 220
		
		ConfAgent *Clone(const char *comment = "Clone of the global ConfAgent");
		
		// to get the global AGATA agent
		static AgataConfAgent *theGlobalAgent(); 
		
		//! to avoid some warning of hidden methods 
		virtual Bool_t Configure(const Char_t *name,  const char *option = "in", Bool_t allow_init = true)
221
		{ return DotConf::Configure(name,option,allow_init); }
222 223
		virtual Bool_t Configure(ConfigurationFrame *,  const char *option = "in", Bool_t allow_init = false);
	}; 	
224 225 226
} // namespace

ADF::AgataConfAgent *ADF::AgataConfAgent::gTheGlobalAgent = 0x0;
227 228

AgataConfAgent::AgataConfAgent() : 
229 230 231
ConfAgent(), 
fDFAgent(new DFAgent("ADF::ConfAgent","Agata",true,true)), 
fRunAgent(new RunAgent("ADF::ConfAgent","Run"))
232
{ 	
233 234 235 236 237 238 239 240
	fLog.GetProcessName() = "ADF::AgataConfAgent"; 
	SetLastModif();	
	
	if ( fDFAgent )
		AddConf(fDFAgent);
	if ( fRunAgent )
		AddConf(fRunAgent);	
	
241
	// configuration from the input file of the distribution
242
	// then the one pointed by ADF_CONF_PATH. if none of these two are found, try the current directory
243 244
	// if not found in the install path (make install not done properly)
	// try in the current directory
245
	std::string tmp; 
246
	
247
	// first the one in the distribution
248
	
249 250 251 252
	tmp = GetPathToConfFile();
	if ( tmp.size() > 0 && !(tmp.at(tmp.size()-1) == '/') ) 
		tmp += '/';
	tmp += "ADF.conf";
253
	
254 255 256
	if ( Configure(tmp.data(),"in") ) 
		fLog << info << "Init Global Conf Agent from distribution " << tmp << nline;
	else
257
		fLog << error << "Failed to init Global Conf Agent from distribution " << tmp << nline;
258
	
259 260 261 262 263 264
	// send snapshot of the agent in the log system
	if ( fLog.IsDebug(2) ) {
		fLog.SetLevel(LogMessage::kInfo,1);
		DoConfigure( fLog() );
		fLog.SetLevel(LogMessage::kInfo,0);
	}
265
	// second the one in the ADF_CONF_PATH path	or if not defined in the current directory
266
	if ( ::getenv("ADF_CONF_PATH") ) {
267
		
268 269 270 271 272
		tmp = ::getenv("ADF_CONF_PATH");
		
		if ( tmp.size() > 0 && !(tmp.at(tmp.size()-1) == '/') ) 
			tmp += '/';
		tmp += "ADF.conf";
273 274 275 276
		if ( Configure(tmp.data(),"in") ) 
			fLog << info << "Init Global Conf Agent from ADF_CONF_PATH " << tmp << nline;
		else 
			fLog << warning << "Failed to init Global Conf Agent from ADF_CONF_PATH " << tmp << nline;
277
	}	
278 279 280 281 282 283 284
	else {
		fLog << warning << "ADF_CONF_PATH NOT DEFINED !, try init Global Conf Agent from current dir ..." << nline;
		if ( Configure("./ADF.conf","in") ) 
			fLog << warning << "... DONE" << nline;
		else 
			fLog << warning << "... FAILED" << nline;
	}
285
	
286
	// send snapshot of the agent in the log system
Stezowski Olivier's avatar
Stezowski Olivier committed
287
	if ( fLog.IsDebug(2) ) {
288 289 290 291
		fLog.SetLevel(LogMessage::kInfo,1);
		DoConfigure( fLog() );
		fLog.SetLevel(LogMessage::kInfo,0);
	}
292
	fLog << dolog;
293 294
} 

295
AgataConfAgent::AgataConfAgent(const char *comment) : 
296 297 298
ConfAgent(), 
fDFAgent(new DFAgent("ADF::ConfAgent","Agata",true,false)), 
fRunAgent(new RunAgent("ADF::ConfAgent","Run"))
299 300 301
{ 	
	fLog.GetProcessName() = "ADF::AgataConfAgent"; 
	SetComment(comment);
302 303 304 305 306
	
	if ( fDFAgent )
		AddConf(fDFAgent);
	if ( fRunAgent )
		AddConf(fRunAgent);	
307 308
} 

309 310 311 312 313 314 315
AgataConfAgent::~AgataConfAgent() 
{
	if ( fDFAgent ) {
		delete fDFAgent; fDFAgent = 0x0;
	}
	if ( fRunAgent ) {
		delete fRunAgent; fRunAgent = 0x0;
316 317
    }
    gTheGlobalAgent = 0x0;
318
}
319

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
AgataConfAgent *AgataConfAgent::theGlobalAgent()
{
	if ( gTheGlobalAgent == 0x0 ) {
#ifdef DEBUGSTATIC			
		std::clog << "[[static]]  Creating the global ConfAgent ]\n[...\n";
#endif
		// be sure factories global main factories are there  
		// the two main factories are added to the main factory in case it has not yet been done
		// key factory	
		if ( !MainKeyFactory::theMainFactory().IsKnown("Agata") )
			MainKeyFactory::theMainFactory().Register("Agata"); 	
		// Frame factory
		if ( !MainFrameFactory::theMainFactory().IsKnown("Agata") )	
			MainFrameFactory::theMainFactory().Register("Agata"); 
		
		gTheGlobalAgent = new AgataConfAgent();	
		
#ifdef DEBUGSTATIC			
		if ( gTheGlobalAgent ) 
			std::clog << " done\n...]\n";
		else 
341
		{ std::clog << " *** ERROR *** \n"; std::clog << "...]\n"; }
342 343 344 345 346 347
#endif		
	}
	return gTheGlobalAgent; 
	
}

348
ConfAgent *AgataConfAgent::Clone(const char *comment)
349
{	
350
	// check the global agent exists
351
	AgataConfAgent::theGlobalAgent();
352 353
	
	// first creats a new agent
354
	AgataConfAgent *aconf = new AgataConfAgent(comment);
355 356
	if ( aconf == 0x0 )
		return 0x0;
357
	
358 359
	// now copy the content of the global agent to it using Configure
	std::ostringstream o;  
360
	AgataConfAgent::theGlobalAgent()->DoConfigure(o);
361 362 363
	std::string tmp;
	tmp = o.str();
	std::istringstream i(tmp);
364
	aconf->DoConfigure(i,true); // the new agent is cloned, so reset it first ... even if aconf has just been created ... needed ?
365
	
366
	return aconf;
367 368
}

369
Bool_t AgataConfAgent::Configure(ConfigurationFrame *frame,  const char *option, Bool_t allow_init)
370 371
{
	// set reference to this method for log system
372
	fLog.SetProcessMethod("Configure(ConfigurationFrame *name)");
373 374
	
	Bool_t ok; std::string opt = option;
375
	
376 377 378 379 380 381 382
	if ( opt == "in" ) {
		// load the content of the frame in the string
		frame->Read();
		// use stream facility 
		std::istringstream in;
		in.clear();
		in.str((frame->String()));
383
		ok = DoConfigure(in, allow_init);
384 385 386 387
	}
	else {
		// use stream facility 
		std::ostringstream out;
388
		
389 390 391
		// the global conf frame starts an adf file. if the global conf file is not set properly (too high !)
		// the reading of the conf frame is cut and this could cause a wrong initialisation of the Agent.
		// to be safe, add some blank space 
392
		out << ends << 	ends << ends << ends << ends << ends << ends << ends << ends << ends << ends << ends;
393
		out << ends << 	ends << ends << ends << ends << ends << ends << ends << "\n";	
394 395 396 397 398
		ok = DoConfigure(out);
		frame->String() = out.str();
		frame->Write();
	}
	fLog << dolog;
399
	
400 401
	return ok;
}	
402

403
ConfAgent *ConfAgent::theGlobalAgent(std::string which_agent)
404 405 406 407 408
{ 
	if ( gTheGlobalAgent == 0x0 ) {
#ifdef DEBUGSTATIC			
		std::clog << "[[static]]  Creating the global ConfAgent ]\n[...\n";
#endif
409 410 411
		if ( which_agent == "Agata" ) {
			gTheGlobalAgent = AgataConfAgent::theGlobalAgent();
		}
412 413 414 415
#ifdef DEBUGSTATIC			
		if ( gTheGlobalAgent ) 
			std::clog << " done\n...]\n";
		else 
416
		{ std::clog << " *** ERROR *** \n"; std::clog << "...]\n"; }
417 418 419 420
#endif		
	}
	return gTheGlobalAgent; 
}