Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / deployment_configuration.cpp
blob03ffd776a448edd5380d55a81fef5cb13c5a4476
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2015 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 //-----------------------------------------------------------------------------
22 // include
23 //-----------------------------------------------------------------------------
25 // pre compiled headers
26 #include "stdpch.h"
28 // nel
29 #include "nel/misc/types_nl.h"
30 #include "nel/misc/common.h"
31 #include "nel/misc/time_nl.h"
32 #include "nel/misc/smart_ptr.h"
33 #include "nel/misc/singleton.h"
34 #include "nel/misc/command.h"
35 #include "nel/misc/file.h"
37 // game share
38 #include "utils.h"
39 #include "deployment_configuration.h"
42 //-----------------------------------------------------------------------------
43 // namespaces
44 //-----------------------------------------------------------------------------
46 using namespace std;
47 using namespace NLMISC;
50 //-----------------------------------------------------------------------------
51 // namespace DEPCFG
52 //-----------------------------------------------------------------------------
54 namespace DEPCFG
56 //-----------------------------------------------------------------------------
57 // forward class declarations
58 //-----------------------------------------------------------------------------
60 struct SExeRecord;
61 class CInfoBlock;
62 class CInfoContainer;
63 class CDeploymentConfigurationImplementation;
66 //-----------------------------------------------------------------------------
67 // struct SExeRecord
68 //-----------------------------------------------------------------------------
70 struct SExeRecord
72 typedef std::set<NLMISC::CSString> TDataEntries;
73 typedef std::vector<NLMISC::CSString> TCfgEntries;
75 NLMISC::CSString FullName;
77 NLMISC::CSString DomainName;
78 NLMISC::CSString ShardName;
79 NLMISC::CSString UniqueName;
80 NLMISC::CSString CmdLine;
81 NLMISC::CSString Host;
82 NLMISC::CSString StartOrder;
83 TDataEntries DataEntries;
84 TCfgEntries CfgEntries;
85 TCfgEntries CfgEntriesPost;
87 // serial method
88 void serial(NLMISC::IStream& stream)
90 stream.serial(FullName);
91 stream.serial(DomainName);
92 stream.serial(ShardName);
93 stream.serial(UniqueName);
94 stream.serial(CmdLine);
95 stream.serial(Host);
96 stream.serialCont(DataEntries);
97 stream.serialCont(CfgEntries);
98 stream.serialCont(CfgEntriesPost);
103 //-----------------------------------------------------------------------------
104 // class CInfoBlock
105 //-----------------------------------------------------------------------------
107 class CInfoBlock: public NLMISC::CRefCount
109 public:
110 // ctors
111 CInfoBlock(const NLMISC::CSString& name="");
113 // write accessors
114 void setDomainName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
115 void setShardName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
116 void setUniqueName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
117 void setCmdLine(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
118 void setHost(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
119 void setStartOrder(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
121 void addUseEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
122 void addDataEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
124 void addCfgEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
125 void addCfgEntryPost(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors);
127 void addCfgFile(const NLMISC::CSString& fileName,const NLMISC::CSString& context,uint32& errors);
128 void addCfgFilePost(const NLMISC::CSString& fileName,const NLMISC::CSString& context,uint32& errors);
130 // direct read accessors
131 uint32 getNumParents() const;
132 const NLMISC::CSString& getName() const;
133 const NLMISC::CSString& getDomainName() const;
135 // indirect read accessors
136 bool isDomain() const;
137 bool isShard() const;
139 // setup the _Children vector from the _UseEntries vector
140 void setupChildren(CInfoContainer* container,uint32& errors);
142 // traverse the tree of children, cumulating data on exes, and instantiating the exe records in 'container'
143 void buildExeSet(CInfoContainer* container,uint32& errors,const SExeRecord& parentExeRecord=SExeRecord());
145 // serial
146 void serial(NLMISC::IStream& stream);
148 // display the contents of the container
149 void dump(NLMISC::CLog& log) const;
151 private:
152 // data types
153 typedef std::set<NLMISC::CSString> TUseEntries;
154 typedef std::set<NLMISC::CSString> TDataEntries;
155 typedef std::vector<NLMISC::CSString> TCfgEntries;
157 typedef std::vector<CInfoBlock*> TChildren;
159 // private methods
160 bool _haveCircularRef(CInfoBlock* other) const;
162 // data (basics)
163 NLMISC::CSString _Name;
164 uint32 _NumParents;
165 TChildren _Children;
167 // data extracted from input file
168 NLMISC::CSString _DomainName;
169 NLMISC::CSString _ShardName;
170 NLMISC::CSString _UniqueName;
171 NLMISC::CSString _CmdLine;
172 NLMISC::CSString _Host;
173 NLMISC::CSString _StartOrder;
174 TUseEntries _UseEntries;
175 TDataEntries _DataEntries;
176 TCfgEntries _CfgEntries;
177 TCfgEntries _CfgEntriesPost;
181 //-----------------------------------------------------------------------------
182 // class CInfoContainer
183 //-----------------------------------------------------------------------------
185 class CInfoContainer
187 public:
188 // public interface
189 void clear();
190 bool empty() const;
192 bool read(const NLMISC::CSString& fileName);
193 void serial(NLMISC::IStream& stream);
195 void getHostNames(THostNames& result) const;
196 void getDomainNames(TDomainNames& result) const;
197 void getShardNames(const TDomainName& domainName,TShardNames& result) const;
198 void getAppNames(const THostName& hostName,const TDomainName& domainName,TAppNames& result) const;
199 void getAppNames(const THostName& hostName,const TDomainName& domainName,const TShardName& shardName,TAppNames& result) const;
201 void getHost(const THostName& hostName,SHostDescription& result) const;
202 void getDomain(const TDomainName& domainName, SDomainDescription& result) const;
203 void getShard(const TDomainName& domainName,const TShardName& shardName,SShardDescription& result) const;
204 void getApp(const TDomainName& domainName,const TAppName& appName,SAppDescription& result) const;
206 void dumpInfoBlocks(NLMISC::CLog& log) const;
207 void dumpDomains(NLMISC::CLog& log) const;
209 // interface used by CInfoBlock methods
210 CInfoBlock* getInfoBlock(const NLMISC::CSString& name);
211 void addExe(const SExeRecord& exeRecord,uint32& errors);
213 private:
214 // data types
215 typedef NLMISC::CSmartPtr<CInfoBlock> TInfoBlockPtr;
216 typedef std::map< NLMISC::CSString,TInfoBlockPtr > TInfoBlocks;
217 typedef std::set< NLMISC::CSString > TFileNameSet;
218 typedef std::vector< SExeRecord > TExeRecords;
219 typedef std::vector<uint32> TExeIdx;
220 typedef std::map<NLMISC::CSString,TExeIdx> TShardExes;
221 typedef std::map<NLMISC::CSString,TShardExes> TDomainExes;
223 // private methods
224 void _readFile(const NLMISC::CSString& fileName,uint32& errors,TFileNameSet& fileNameStack);
225 void _buildDomainTree(uint32& errors);
226 void _buildExeSet(uint32& errors);
228 // data
229 TInfoBlockPtr _CurrentInfoBlock;
230 TInfoBlocks _InfoBlocks;
231 TExeRecords _ExeRecords;
232 TDomainExes _DomainExes;
236 //-----------------------------------------------------------------------------
237 // class CDeploymentConfigurationImplementation
238 //-----------------------------------------------------------------------------
240 class CDeploymentConfigurationImplementation: public CSingleton<CDeploymentConfigurationImplementation>, public CDeploymentConfiguration
242 public:
243 bool read(const NLMISC::CSString& fileName);
244 void write(const NLMISC::CSString& fileName);
245 void serial(NLMISC::IStream& stream);
247 void getHostNames(THostNames& result) const;
248 void getDomainNames(TDomainNames& result) const;
249 void getShardNames(const TDomainName& domainName,TShardNames& result) const;
250 void getAppNames(const THostName& hostName,const TDomainName& domainName,TAppNames& result) const;
251 void getAppNames(const THostName& hostName,const TDomainName& domainName,const TShardName& shardName,TAppNames& result) const;
253 void getHost(const THostName& hostName,SHostDescription& result) const;
254 void getDomain(const TDomainName& domainName, SDomainDescription& result) const;
255 void getShard(const TDomainName& domainName,const TShardName& shardName,SShardDescription& result) const;
256 void getApp(const TDomainName& domainName,const TAppName& appName,SAppDescription& result) const;
258 void dumpInfoBlocks(NLMISC::CLog& log) const;
259 void dumpDomains(NLMISC::CLog& log) const;
261 private:
262 CInfoContainer _InfoContainer;
266 //-----------------------------------------------------------------------------
267 // methods CInfoBlock
268 //-----------------------------------------------------------------------------
270 CInfoBlock::CInfoBlock(const NLMISC::CSString& name)
272 _Name= name;
273 _NumParents= 0;
276 void CInfoBlock::setDomainName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
278 DROP_IF(!_DomainName.empty(),context+"Attempting to set a domain name more than once for the same info block",++errors; return);
279 DROP_IF(entry.empty(),context+"Attempting to set an empty domain name",++errors; return);
280 _DomainName=entry;
283 void CInfoBlock::setShardName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
285 DROP_IF(!_ShardName.empty(),context+"Attempting to set a shard name more than once for the same info block",++errors; return);
286 DROP_IF(entry.empty(),context+"Attempting to set an empty shard name",++errors; return);
287 _ShardName=entry;
290 void CInfoBlock::setUniqueName(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
292 DROP_IF(!_UniqueName.empty(),context+"Attempting to set a name more than once for the same info block",++errors; return);
293 DROP_IF(entry.empty(),context+"Attempting to set an empty name",++errors; return);
294 _UniqueName=entry;
297 void CInfoBlock::setCmdLine(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
299 DROP_IF(!_CmdLine.empty(),context+"Attempting to set a cmdLine more than once for the same info block",++errors; return);
300 DROP_IF(entry.empty(),context+"Attempting to set an empty cmdLine",++errors; return);
301 _CmdLine=entry;
304 void CInfoBlock::setHost(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
306 DROP_IF(!_Host.empty(),context+"Attempting to set a host more than once for the same info block",++errors; return);
307 DROP_IF(entry.empty(),context+"Attempting to set an empty host",++errors; return);
308 _Host=entry;
311 void CInfoBlock::setStartOrder(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
313 DROP_IF(!_StartOrder.empty(),context+"Attempting to set a startOrder more than once for the same info block",++errors; return);
314 DROP_IF(entry.empty(),context+"Attempting to set an empty startOrder",++errors; return);
315 _StartOrder=entry;
318 void CInfoBlock::addUseEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
320 DROP_IF(_UseEntries.find(entry) != _UseEntries.end(), context + "Ignoring duplicate refference to 'use' clause: " + entry.c_str(), return);
321 _UseEntries.insert(entry);
324 void CInfoBlock::addDataEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
326 DROP_IF(_DataEntries.find(entry) != _DataEntries.end(), context + "Ignoring duplicate refference to 'data' clause: " + entry.c_str(), return);
327 _DataEntries.insert(entry);
330 void CInfoBlock::addCfgEntry(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
332 _CfgEntries.push_back(entry);
335 void CInfoBlock::addCfgEntryPost(const NLMISC::CSString& entry,const NLMISC::CSString& context,uint32& errors)
337 _CfgEntriesPost.push_back(entry);
340 void CInfoBlock::addCfgFile(const NLMISC::CSString& fileName,const NLMISC::CSString& context,uint32& errors)
342 // make sure a file name is supplied
343 DROP_IF(fileName.empty(),context+"No file name found following 'cfgFile'", ++errors;return);
345 // read in the src file
346 NLMISC::CSString fileContents;
347 fileContents.readFromFile(fileName);
348 DROP_IF(fileContents.empty(),"File not found: "+fileName, ++errors;return);
350 // split the file contents into lines
351 NLMISC::CVectorSString lines;
352 fileContents.splitLines(lines);
354 // append the lines to the '_CfgEntries' container
355 _CfgEntries.insert(_CfgEntries.end(),lines.begin(),lines.end());
358 void CInfoBlock::addCfgFilePost(const NLMISC::CSString& fileName,const NLMISC::CSString& context,uint32& errors)
360 // make sure a file name is supplied
361 DROP_IF(fileName.empty(),context+"No file name found following 'cfgFilePost'", ++errors;return);
363 // read in the src file
364 NLMISC::CSString fileContents;
365 fileContents.readFromFile(fileName);
366 DROP_IF(fileContents.empty(),"File not found: "+fileName, ++errors;return);
368 // split the file contents into lines
369 NLMISC::CVectorSString lines;
370 fileContents.splitLines(lines);
372 // prepend the lines to the '_CfgEntriesPost' container
373 _CfgEntriesPost.insert(_CfgEntriesPost.begin(),lines.begin(),lines.end());
376 uint32 CInfoBlock::getNumParents() const
378 return _NumParents;
381 const NLMISC::CSString& CInfoBlock::getName() const
383 return _Name;
386 const NLMISC::CSString& CInfoBlock::getDomainName() const
388 return _DomainName;
391 bool CInfoBlock::isDomain() const
393 return !_DomainName.empty();
396 bool CInfoBlock::isShard() const
398 return !_ShardName.empty();
401 void CInfoBlock::setupChildren(CInfoContainer* container,uint32& errors)
403 // start by clearing out the child vector that we're going to fill
404 _Children.clear();
406 // iterate over the the 'use' clauses
407 for (TUseEntries::iterator it= _UseEntries.begin(); it!= _UseEntries.end(); ++it)
409 const NLMISC::CSString& theEntry= *it;
411 // try to get a pointer to the refferenced info block...
412 CInfoBlock* infoBlockPtr= container->getInfoBlock(theEntry);
413 DROP_IF(infoBlockPtr == NULL, "Failed to find block named '" + theEntry + "' while fixing up children of block: " + _Name.c_str(), ++errors; continue);
415 // make sure that this block doesn't figure amongst the children of the refferenced info block (to avoid circular refs)
416 DROP_IF(_haveCircularRef(infoBlockPtr), "Circular dependency found between definitions of '" + _Name + "' and '" + theEntry.c_str() + "'", ++errors; continue);
418 // add the info block to our children
419 _Children.push_back(infoBlockPtr);
420 ++(infoBlockPtr->_NumParents);
424 void CInfoBlock::buildExeSet(CInfoContainer* container,uint32& errors,const SExeRecord& parentExeRecord)
426 // setup a record to accumulate data into as we traverse the tree, starting
427 // with a copy of the data passed in from parents
428 SExeRecord theExe= parentExeRecord;
430 // add a chunk to the exe record's 'FullName' property
431 theExe.FullName+= (theExe.FullName.empty()?"":".")+ _Name;
433 // make sure we don't have any field duplication...
434 DROP_IF(!_DomainName.empty() && !theExe.DomainName.empty(), "more than one domain found in: "+theExe.FullName, ++errors );
435 DROP_IF(!_ShardName.empty() && !theExe.ShardName.empty(), "more than one shard found in: "+theExe.FullName, ++errors );
436 DROP_IF(!_CmdLine.empty() && !theExe.CmdLine.empty(), "more than one cmdLine found in: "+theExe.FullName, ++errors );
437 DROP_IF(!_Host.empty() && !theExe.Host.empty(), "more than one host found in: "+theExe.FullName, ++errors );
438 WARN_IF(!_UniqueName.empty() && !theExe.UniqueName.empty(), "replacing name '" + theExe.UniqueName + "' with '" + _UniqueName.c_str() + "' in: " + theExe.FullName.c_str());
440 // fill our own data into the exe record
441 if (!_DomainName.empty()) theExe.DomainName = _DomainName;
442 if (!_ShardName.empty()) theExe.ShardName = _ShardName;
443 if (!_UniqueName.empty()) theExe.UniqueName = _UniqueName;
444 if (!_CmdLine.empty()) theExe.CmdLine = _CmdLine;
445 if (!_Host.empty()) theExe.Host = _Host;
446 if (!_StartOrder.empty()) theExe.StartOrder = _StartOrder;
447 // merge contents of 2 sets
448 theExe.DataEntries.insert( _DataEntries.begin(), _DataEntries.end() );
449 // append or pre-pend contents of one vector to another
450 theExe.CfgEntries.insert( theExe.CfgEntries.end(), _CfgEntries.begin(), _CfgEntries.end() );
451 theExe.CfgEntriesPost.insert( theExe.CfgEntriesPost.begin(), _CfgEntriesPost.begin(), _CfgEntriesPost.end() );
453 // if this is the node with the cmdLine then think about updating the unique name...
454 if (!_CmdLine.empty() && theExe.UniqueName.empty())
456 theExe.UniqueName= _Name;
459 // do something with the exe record depending on whetherwe're a tree branch or leaf
460 if (_Children.empty())
462 // merge the cfg entries together to make a single block
463 theExe.CfgEntries.insert(theExe.CfgEntries.end(),theExe.CfgEntriesPost.begin(),theExe.CfgEntriesPost.end());
464 theExe.CfgEntriesPost.clear();
466 // this is a leaf node (it has no children) so it must describe an executable
467 container->addExe(theExe,errors);
469 else
471 // this is a branch node so recurse into children
472 for (TChildren::iterator it=_Children.begin();it!=_Children.end();++it)
474 (*it)->buildExeSet(container,errors,theExe);
479 void CInfoBlock::serial(NLMISC::IStream& stream)
481 if (stream.isReading())
483 // if we're reading then we clear out the children vector - it'll be rebuilt at the end of the serial
484 _Children.clear();
487 stream.serial(_Name);
488 stream.serial(_NumParents);
489 stream.serial(_DomainName);
490 stream.serial(_ShardName);
491 stream.serial(_UniqueName);
492 stream.serial(_CmdLine);
493 stream.serial(_Host);
495 stream.serialCont(_UseEntries);
496 stream.serialCont(_DataEntries);
497 stream.serialCont(_CfgEntries);
498 stream.serialCont(_CfgEntriesPost);
501 void CInfoBlock::dump(NLMISC::CLog& log) const
503 //*****************************
504 // NOTE:
505 // This method is called to
506 // create a text save of the
507 // data that we contain - it
508 // must output ALL data that
509 // read() requires and in a
510 // read()-compatible format
511 //*****************************
513 log.displayNL("define %s // refferenced by %u other defines",_Name.c_str(),_NumParents);
515 if (!_DomainName.empty())
517 log.displayNL("\tdomain\t%s",_DomainName.c_str());
520 if (!_ShardName.empty())
522 log.displayNL("\tshard\t%s",_ShardName.c_str());
525 if (!_UniqueName.empty())
527 log.displayNL("\tname\t%s",_UniqueName.c_str());
530 if (!_CmdLine.empty())
532 log.displayNL("\tcmdLine\t%s",_CmdLine.c_str());
535 if (!_Host.empty())
537 log.displayNL("\thost\t%s",_Host.c_str());
540 for (TUseEntries::const_iterator it=_UseEntries.begin(); it!=_UseEntries.end(); ++it)
542 log.displayNL("\tuse\t%s",it->c_str());
545 for (TDataEntries::const_iterator it=_DataEntries.begin(); it!=_DataEntries.end(); ++it)
547 log.displayNL("\tdata\t%s",it->c_str());
550 for (TCfgEntries::const_iterator it=_CfgEntries.begin(); it!=_CfgEntries.end(); ++it)
552 log.displayNL("\tcfg\t%s",it->c_str());
555 for (TCfgEntries::const_iterator it=_CfgEntriesPost.begin(); it!=_CfgEntriesPost.end(); ++it)
557 log.displayNL("\tcfgAfter\t%s",it->c_str());
560 log.displayNL("");
563 bool CInfoBlock::_haveCircularRef(CInfoBlock* other) const
565 // in the case of a circular refference we end up with the 'other'=='this'
566 if (this==other)
567 return true;
569 // recurse into children looking for a deep circular ref
570 for (TChildren::const_iterator it= other->_Children.begin();it!=other->_Children.end();++it)
572 CInfoBlock* child= *it;
573 if (_haveCircularRef(child))
574 return true;
577 // no circular ref found so return false
578 return false;
581 //-----------------------------------------------------------------------------
582 // methods CInfoContainer
583 //-----------------------------------------------------------------------------
585 void CInfoContainer::clear()
587 _InfoBlocks.clear();
588 _CurrentInfoBlock= NULL;
589 _ExeRecords.clear();
590 _DomainExes.clear();
593 bool CInfoContainer::empty() const
595 return _InfoBlocks.empty();
598 bool CInfoContainer::read(const NLMISC::CSString& fileName)
600 // start by clearing out our contents...
601 clear();
603 // setup some basics
604 uint32 errors= 0;
605 TFileNameSet fileNameSet;
607 // read in the src file
608 _readFile(fileName,errors,fileNameSet);
610 // build the blocks into a tree
611 _buildDomainTree(errors);
613 // build the set of executables from the tree
614 _buildExeSet(errors);
616 // make sure that no errors were encountered...
617 DROP_IF(errors!=0,NLMISC::toString("%s: Parse Failed: %u errors found",fileName.c_str(),errors),clear(); return false);
619 return true;
622 void CInfoContainer::_readFile(const NLMISC::CSString& fileName,uint32& errors,TFileNameSet& fileNameSet)
624 // read in the src file
625 NLMISC::CSString fileContents;
626 fileContents.readFromFile(fileName);
627 DROP_IF(fileContents.empty(),"File not found: "+fileName, ++errors;return);
629 // split the file into lines
630 NLMISC::CVectorSString lines;
631 fileContents.splitLines(lines);
633 // process the lines one by one
634 for (uint32 i=0;i<lines.size();++i)
636 // setup a context string to pre-pend to error messages
637 NLMISC::CSString context= NLMISC::toString("%s:%u: ",fileName.c_str(),i);
639 // remove comments and encapsulating blanks
640 NLMISC::CSString line= lines[i].splitToLineComment().strip();
641 if (line.empty()) continue;
643 // split the line into keyword and args
644 NLMISC::CSString args= line;
645 NLMISC::CSString keyword= args.strtok(" \t");
646 NLMISC::CSString rawArgs= lines[i].strip();
647 rawArgs.strtok(" \t");
649 // try to treat the keyword
650 if (keyword=="include")
652 DROP_IF(args.empty(), context + "No file name found following 'include': " + line.c_str(), ++errors; continue);
653 DROP_IF(fileNameSet.find(args) != fileNameSet.end(), context + "Warning: Duplicate 'include' block ignored: " + line.c_str(), continue);
654 fileNameSet.insert(args);
655 _readFile(args.unquoteIfQuoted(),errors,fileNameSet);
657 else if (keyword=="define")
659 DROP_IF(args.empty(), context + "No block name found following 'define': " + line.c_str(), ++errors; continue);
660 DROP_IF(_InfoBlocks.find(args) != _InfoBlocks.end(), context + "Duplicate 'define' block found: " + line.c_str(), ++errors; continue);
661 // create a new info block and push it into our infoblock set
662 _CurrentInfoBlock= new CInfoBlock(args);
663 _InfoBlocks[args]= _CurrentInfoBlock;
665 else
667 DROP_IF(_CurrentInfoBlock == NULL, context + "Expecting 'define <block_name>' but found: " + line.c_str(), ++errors; continue);
669 if (keyword=="domain") { _CurrentInfoBlock->setDomainName(args,context,errors); }
670 else if (keyword=="shard") { _CurrentInfoBlock->setShardName(args,context,errors); }
671 else if (keyword=="name") { _CurrentInfoBlock->setUniqueName(args,context,errors); }
672 else if (keyword=="cmdLine") { _CurrentInfoBlock->setCmdLine(args,context,errors); }
673 else if (keyword=="host") { _CurrentInfoBlock->setHost(args,context,errors); }
674 else if (keyword=="startOrder") { _CurrentInfoBlock->setStartOrder(args,context,errors); }
675 else if (keyword=="use") { _CurrentInfoBlock->addUseEntry(args,context,errors); }
676 else if (keyword=="data") { _CurrentInfoBlock->addDataEntry(args,context,errors); }
677 else if (keyword=="cfg") { _CurrentInfoBlock->addCfgEntry(rawArgs,context,errors); }
678 else if (keyword=="cfgAfter") { _CurrentInfoBlock->addCfgEntryPost(rawArgs,context,errors); }
679 else if (keyword=="cfgFile") { _CurrentInfoBlock->addCfgFile(args,context,errors); }
680 else if (keyword=="cfgFileAfter") { _CurrentInfoBlock->addCfgFilePost(args,context,errors); }
681 else { DROP(context + "Unrecognised keyword: " + line.c_str(), ++errors; continue); }
686 void CInfoContainer::_buildDomainTree(uint32& errors)
688 // iterate over the info block container, setting up 'child' vectors
689 for (TInfoBlocks::iterator it= _InfoBlocks.begin(); it!= _InfoBlocks.end(); ++it)
691 CInfoBlock& theInfoBlock= *it->second;
692 theInfoBlock.setupChildren(this,errors);
695 // display the list of orphans
696 for (TInfoBlocks::iterator it= _InfoBlocks.begin(); it!= _InfoBlocks.end(); ++it)
698 CInfoBlock& theInfoBlock= *it->second;
699 WARN_IF(!theInfoBlock.isDomain() && theInfoBlock.getNumParents()==0,"Found unrefferenced info block: "+theInfoBlock.getName());
703 void CInfoContainer::_buildExeSet(uint32& errors)
705 // iterate over the info block container, looking for domains
706 for (TInfoBlocks::iterator it= _InfoBlocks.begin(); it!= _InfoBlocks.end(); ++it)
708 CInfoBlock& theInfoBlock= *it->second;
709 if (theInfoBlock.isDomain())
711 const NLMISC::CSString& domainName= theInfoBlock.getDomainName();
712 DROP_IF(_DomainExes.find(domainName)!=_DomainExes.end(),"Duplicate domain name found: "+domainName,++errors;continue);
713 nldebug("Building executable set for domain: %s",domainName.c_str());
714 theInfoBlock.buildExeSet(this,errors);
717 // fixup the names in the domain to make them unique
719 // run through the exes a first time to determine which unique names are unique and which are not
720 std::map<NLMISC::CSString, uint32> nameCounts;
721 for (TExeRecords::iterator it2= _ExeRecords.begin(); it2!=_ExeRecords.end(); ++it2)
723 // skip anything that's not from our domain
724 if (it2->DomainName!=theInfoBlock.getDomainName())
725 continue;
727 // get hold of the name
728 NLMISC::CSString& name= it2->UniqueName;
729 // yell if the name already looks like a 'fixed up' name
730 DROP_IF(name.right(3).left(1)=="_" && (name.right(2)=="00" || name.right(2).atoui()!=0),"Appending '_' to name ending in '_00' style format as this can clash with auto renumbering => "+name+'_',name+='_')
731 // compose a second version of the name with the shard name added
732 NLMISC::CSString name_with_shard = name + '_' + it2->ShardName.c_str();
733 // insert both versions of the name into the unique name counter
734 ++nameCounts[name];
735 ++nameCounts[name_with_shard];
738 // run through the exes a second time to fix names that are not unique
739 std::map<NLMISC::CSString, uint32> nameIdx;
740 for (TExeRecords::iterator it2= _ExeRecords.begin(); it2!=_ExeRecords.end(); ++it2)
742 // skip anything that's not from our domain
743 if (it2->DomainName!=theInfoBlock.getDomainName())
744 continue;
746 // get hold of the name
747 NLMISC::CSString& name= it2->UniqueName;
748 // if the name is unique then continue
749 if (nameCounts[name]==1)
750 continue;
752 // compose a second version of the name with the shard name added
753 name+='_';
754 name+=it2->ShardName;
755 // if the name is unique within the shard then continue
756 if (nameCounts[name]==1)
757 continue;
759 // make the name name unique by appending a number to it
760 uint32 idx= ++nameIdx[name];
761 name+=NLMISC::toString("_%02u",idx);
766 void CInfoContainer::serial(NLMISC::IStream& stream)
768 if (stream.isReading())
770 // start by clearing out our contents...
771 clear();
773 // get the number of info blocks from the stream
774 uint32 count;
775 stream.serial(count);
777 // get the info blocks from the stream one by one
778 for (uint32 i=0;i<count;++i)
780 _CurrentInfoBlock= new CInfoBlock;
781 stream.serial(*_CurrentInfoBlock);
782 _InfoBlocks[_CurrentInfoBlock->getName()]= _CurrentInfoBlock;
785 // setup an error accumulator
786 uint32 errors= 0;
788 // build the blocks into a tree
789 _buildDomainTree(errors);
791 // build the set of executables from the tree
792 _buildExeSet(errors);
794 // make sure that no errors were encountered...
795 DROP_IF(errors!=0,NLMISC::toString("Serial Failed: %u errors found",errors), clear();return);
797 // note - on exit, _CurrentInfoBlock refferences the last info block read
799 else
801 // put the number of info blocks to the stream
802 uint32 count= (uint32)_InfoBlocks.size();
803 stream.serial(count);
804 // put the info blocks to the stream one by one
805 for (TInfoBlocks::iterator it= _InfoBlocks.begin(); it!=_InfoBlocks.end(); ++it)
807 stream.serial(*(it->second));
812 void CInfoContainer::getHostNames(THostNames& result) const
814 // clear out the result before we begin work...
815 result.clear();
817 // use a little set to avoid adding host names more than once
818 std::set<NLMISC::CSString> namesFound;
820 // fill the result in from our internal data
821 bool found= false;
822 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
824 const SExeRecord& theApp= *it;
826 // ignore exes that are on hosts that we've already dealt with
827 if (namesFound.find(theApp.Host)!=namesFound.end()) continue;
829 // we've found a new host so add it to our result container
830 result.push_back(theApp.Host);
831 namesFound.insert(theApp.Host);
833 found=true;
836 if (!found)
838 // as a note - if we get here it is because the request has failed - no hosts were identified with the given domain
839 // this is not an error case so we just add a debug for info
840 nldebug("getHostNames failed - no hosts found");
844 void CInfoContainer::getDomainNames(TDomainNames& result) const
846 // clear out the result before we begin work...
847 result.clear();
849 // fill the result in from our internal data
850 for (TDomainExes::const_iterator dit= _DomainExes.begin(); dit!=_DomainExes.end(); ++dit)
852 const NLMISC::CSString& domainName= dit->first;
853 result.push_back(domainName);
856 if (result.empty())
858 // as a note - if we get here it is because the request has failed - no domains were found
859 // this is not an error case so we just add a debug for info
860 nldebug("getDomainNames failed - no domains found");
864 void CInfoContainer::getShardNames(const TDomainName& domainName,TShardNames& result) const
866 // clear out the result before we begin work...
867 result.clear();
869 // fill the result in from our internal data
870 bool found= false;
871 for (TDomainExes::const_iterator dit= _DomainExes.begin(); dit!=_DomainExes.end(); ++dit)
873 // ignore shards that aren't in the requested domain
874 const NLMISC::CSString& domName= dit->first;
875 if (domName!=domainName) continue;
877 // run throught he shards for our chosen domain...
878 const TShardExes& shards= dit->second;
879 for (TShardExes::const_iterator sit= shards.begin(); sit!=shards.end(); ++sit)
881 const NLMISC::CSString shardName= sit->first;
882 result.push_back(shardName);
885 found=true;
888 if (!found)
890 // as a note - if we get here it is because the request has failed - no shards were identified with the given domain
891 // this is not an error case so we just add a debug for info
892 nldebug("getShardNames failed for domainName('%s')",domainName.c_str());
896 void CInfoContainer::getAppNames(const THostName& hostName,const TDomainName& domainName,TAppNames& result) const
898 // clear out the result before we begin work...
899 result.clear();
901 // fill the result in from our internal data
902 bool found= false;
903 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
905 const SExeRecord& theApp= *it;
907 // ignore exes that aren't in the requested domain
908 if (theApp.DomainName!=domainName) continue;
910 // ignore exes that are on the wrong host
911 if (theApp.Host!=hostName) continue;
913 // we've found a new host so add it to our result container
914 result.push_back(theApp.UniqueName);
916 found=true;
919 if (!found)
921 // as a note - if we get here it is because the request has failed - no apps were identified with the given host and domain
922 // this is not an error case so we just add a debug for info
923 nldebug("getAppNames failed for hostName('%s'), domainName('%s')",hostName.c_str(),domainName.c_str());
927 void CInfoContainer::getAppNames(const THostName& hostName,const TDomainName& domainName,const TShardName& shardName,TAppNames& result) const
929 // clear out the result before we begin work...
930 result.clear();
932 // fill the result in from our internal data
933 bool found= false;
934 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
936 const SExeRecord& theApp= *it;
938 // ignore exes that aren't in the requested domain
939 if (theApp.DomainName!=domainName) continue;
941 // ignore exes that are on the wrong host
942 if (theApp.Host!=hostName) continue;
944 // ignore exes that are on the shard host
945 if (theApp.ShardName!=shardName) continue;
947 // we've found a new host so add it to our result container
948 result.push_back(theApp.UniqueName);
950 found=true;
953 if (!found)
955 // as a note - if we get here it is because the request has failed - no apps were identified with the given host, shard and domain
956 // this is not an error case so we just add a debug for info
957 nldebug("getAppNames failed for hostName('%s'), domainName('%s'), shardName('%s')",hostName.c_str(),domainName.c_str(),shardName.c_str());
961 void CInfoContainer::getHost(const THostName& hostName,SHostDescription& result) const
963 // clear out the result before we begin work...
964 result.clear();
965 result.HostName= hostName;
967 // use a set to buildup lists of unique host names
968 typedef std::set<NLMISC::CSString> TNameSet;
969 TNameSet domainNames;
971 // fill the result in from our internal data
972 bool found= false;
973 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
975 const SExeRecord& theApp= *it;
977 // ignore exes that aren't on the requested host
978 if (theApp.Host!=hostName) continue;
980 // add this exe's domain to the domains set
981 domainNames.insert(theApp.DomainName);
983 found=true;
986 // copy the hosts set to the result record
987 for (TNameSet::const_iterator it= domainNames.begin(); it!=domainNames.end(); ++it)
989 result.Domains.push_back(*it);
992 if (!found)
994 // as a note - if we get here it is because the request has failed - no host was identified with the given name
995 // this is not an error case so we just add a debug for info
996 nldebug("getHost failed for hostName('%s')",hostName.c_str());
1000 void CInfoContainer::getDomain(const TDomainName& domainName, SDomainDescription& result) const
1002 // clear out the result before we begin work...
1003 result.clear();
1004 result.DomainName= domainName;
1006 // use a couple of sets to buildup lists of unique host and shard names
1007 typedef std::set<NLMISC::CSString> TNameSet;
1008 TNameSet hostNames;
1009 TNameSet shardNames;
1011 // fill the result in from our internal data
1012 bool found= false;
1013 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
1015 const SExeRecord& theApp= *it;
1017 // ignore exes that aren't in the requested domain
1018 if (theApp.DomainName!=domainName) continue;
1020 // add this exe's shard to the shards set
1021 shardNames.insert(theApp.ShardName);
1023 // add this exe's host to the hosts set
1024 hostNames.insert(theApp.Host);
1026 // add this exe's unique name to the result apps record
1027 result.Apps.push_back(theApp.UniqueName);
1029 found=true;
1032 // copy the hosts set to the result record
1033 for (TNameSet::const_iterator it= hostNames.begin(); it!=hostNames.end(); ++it)
1035 result.Hosts.push_back(*it);
1038 // copy the shards set to the result record
1039 for (TNameSet::const_iterator it= shardNames.begin(); it!=shardNames.end(); ++it)
1041 result.Shards.push_back(*it);
1044 if (!found)
1046 // as a note - if we get here it is because the request has failed - no domain was identified with the given name
1047 // this is not an error case so we just add a debug for info
1048 nldebug("getDomain failed for domainName('%s')",domainName.c_str());
1052 void CInfoContainer::getShard(const TDomainName& domainName,const TShardName& shardName,SShardDescription& result) const
1054 // clear out the result before we begin work...
1055 result.clear();
1056 result.DomainName= domainName;
1057 result.ShardName= shardName;
1059 // use a set to buildup lists of unique host names
1060 typedef std::set<NLMISC::CSString> TNameSet;
1061 TNameSet hostNames;
1063 // fill the result in from our internal data
1064 bool found= false;
1065 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
1067 const SExeRecord& theApp= *it;
1069 // ignore exes that aren't in the requested domain
1070 if (theApp.DomainName!=domainName) continue;
1072 // ignore exes that aren't in the requested shard
1073 if (theApp.ShardName!=shardName) continue;
1075 // add this exe's host to the hosts set
1076 hostNames.insert(theApp.Host);
1078 // add this exe's unique name to the result apps record
1079 result.Apps.push_back(theApp.UniqueName);
1081 found=true;
1084 // copy the hosts set to the result record
1085 for (TNameSet::const_iterator it= hostNames.begin(); it!=hostNames.end(); ++it)
1087 result.Hosts.push_back(*it);
1090 if (!found)
1092 // as a note - if we get here it is because the request has failed - no shard was identified with the given name and domain
1093 // this is not an error case so we just add a debug for info
1094 nldebug("getShard failed for domainName('%s'), shardName('%s')",domainName.c_str(),shardName.c_str());
1098 void CInfoContainer::getApp(const TDomainName& domainName,const TAppName& appName,SAppDescription& result) const
1100 // clear out the result before we begin work...
1101 result.clear();
1102 result.DomainName= domainName;
1103 result.AppName= appName;
1105 // use a set to buildup lists of unique host names
1106 typedef std::set<NLMISC::CSString> TNameSet;
1107 TNameSet domainNames;
1109 // fill the result in from our internal data
1110 for (TExeRecords::const_iterator it= _ExeRecords.begin(); it!=_ExeRecords.end(); ++it)
1112 const SExeRecord& theApp= *it;
1114 // skip exes that aren't in the requested domain
1115 if (theApp.DomainName!=domainName) continue;
1117 // skip exes that don't have the correct name
1118 if (theApp.UniqueName!=appName) continue;
1120 // we've found the exe so fill in the result record...
1121 result.ShardName= theApp.ShardName;
1122 result.HostName= theApp.Host;
1123 result.StartOrder= theApp.StartOrder;
1124 result.CmdLine= theApp.CmdLine;
1126 // setup the config file to start initialised with the app name for this app
1127 result.CfgFile=
1128 "// Auto generated config file\n"
1129 "// Use with commandline: "+theApp.CmdLine+"\n"
1130 "AESAliasName= \"" + appName.c_str() + "\";\n"
1131 "\n";
1133 // copy the cfg set to the result record (the cfgAfter set should have been merged in already)
1134 for (SExeRecord::TCfgEntries::const_iterator cit= theApp.CfgEntries.begin(); cit!=theApp.CfgEntries.end(); ++cit)
1136 result.CfgFile+=*cit;
1137 result.CfgFile+='\n';
1140 // copy the dataEntries set to the result record
1141 for (SExeRecord::TDataEntries::const_iterator dit= theApp.DataEntries.begin(); dit!=theApp.DataEntries.end(); ++dit)
1143 result.DataPacks.push_back(*dit);
1146 // we're all done so we can return merrily
1147 return;
1150 // as a note - if we get here it is because the request has failed - no app was identified with the given name and domain
1151 // this is not an error case so we just add a debug for info
1152 nldebug("getApp failed for domainName('%s'), appName('%s')",domainName.c_str(),appName.c_str());
1155 void CInfoContainer::dumpDomains(NLMISC::CLog& log) const
1157 for (TDomainExes::const_iterator dit= _DomainExes.begin(); dit!=_DomainExes.end(); ++dit)
1159 const NLMISC::CSString& domainName= dit->first;
1160 const TShardExes& shards= dit->second;
1161 log.displayNL("-- domain: %s",domainName.c_str());
1163 for (TShardExes::const_iterator sit= shards.begin(); sit!=shards.end(); ++sit)
1165 const NLMISC::CSString& shardName= sit->first;
1166 const TExeIdx& exeIdx= sit->second;
1167 log.displayNL(" -- shard: %s",shardName.c_str());
1169 for (TExeIdx::const_iterator eit= exeIdx.begin(); eit!=exeIdx.end(); ++eit)
1171 uint32 idx= *eit;
1172 nlassert(idx<_ExeRecords.size());
1173 const SExeRecord& theExe= _ExeRecords[idx];
1174 log.displayNL(" -- %s:%s (%s)",theExe.Host.c_str(),theExe.CmdLine.c_str(),theExe.UniqueName.c_str());
1180 void CInfoContainer::dumpInfoBlocks(NLMISC::CLog& log) const
1182 log.displayNL("//------------------------------------------------------------------------------");
1183 log.displayNL("// Dump of cfg database file contents");
1184 log.displayNL("//------------------------------------------------------------------------------");
1185 for (TInfoBlocks::const_iterator it=_InfoBlocks.begin(); it!=_InfoBlocks.end(); ++it)
1187 it->second->dump(log);
1189 log.displayNL("//------------------------------------------------------------------------------");
1192 CInfoBlock* CInfoContainer::getInfoBlock(const NLMISC::CSString& name)
1194 TInfoBlocks::iterator it= _InfoBlocks.find(name);
1195 return (it==_InfoBlocks.end())? NULL: it->second;
1198 void CInfoContainer::addExe(const SExeRecord& exeRecord,uint32& errors)
1200 // nldebug("Adding CmdLine: %s",exeRecord.FullName.c_str());
1202 // note: if we hit errors then we continue anyway to make sure we display a complete set of error messages
1203 DROP_IF(exeRecord.DomainName.empty(), "No 'domain' property found in: "+exeRecord.FullName, ++errors );
1204 DROP_IF(exeRecord.ShardName.empty(), "No 'shard' property found in: "+exeRecord.FullName, ++errors );
1205 DROP_IF(exeRecord.CmdLine.empty(), "No 'cmdLine' property found in: "+exeRecord.FullName, ++errors );
1206 DROP_IF(exeRecord.Host.empty(), "No 'host' property found in: "+exeRecord.FullName, ++errors );
1207 DROP_IF(exeRecord.CfgEntries.empty(), "No 'cfg' entriesfound in: "+exeRecord.FullName, ++errors );
1209 // add a refference from the domains' shard map to the exe...
1210 _DomainExes[exeRecord.DomainName][exeRecord.ShardName].push_back((uint32)_ExeRecords.size());
1212 // we may have hit errors but we go ahead anyway as in the case of errors the whole thing will be cleared out anyway
1213 _ExeRecords.push_back(exeRecord);
1216 //-----------------------------------------------------------------------------
1217 // methods CDeploymentConfigurationImplementation
1218 //-----------------------------------------------------------------------------
1220 bool CDeploymentConfigurationImplementation::read(const NLMISC::CSString& fileName)
1222 // setup a temp container to hold the version of the file that we're reading
1223 CInfoContainer container;
1225 // do the reading and make sure we catch any possible execeptions (like for read in progress)
1228 container.read(fileName);
1230 catch(...)
1232 container.clear();
1235 // if the read failed for whatever reason then giveup
1236 DROP_IF(container.empty(),"Failed to update deployment configuration from file: "+fileName,return false);
1238 // copy the temp container into our internal object
1239 _InfoContainer= container;
1241 // display a funky victory message
1242 nlinfo("Deployment configuration successfully updated from file: %s",fileName.c_str());
1244 return true;
1247 void CDeploymentConfigurationImplementation::write(const NLMISC::CSString& fileName)
1249 // create a displayer to gather the output of the command
1250 class CStringDisplayer: public IDisplayer
1252 public:
1253 NLMISC::CSString Data;
1254 void doDisplay( const CLog::TDisplayInfo& args, const char *message)
1256 Data += message;
1260 // instantiate the displayer and a log object and assign one to the other
1261 CStringDisplayer stringDisplayer;
1262 NLMISC::CLog myLog;
1263 myLog.addDisplayer(&stringDisplayer);
1265 // dump the info blocks to our log object (accumulating the result as a string)
1266 dumpInfoBlocks(myLog);
1268 // write the text accumulated in the log object to a text file
1269 stringDisplayer.Data.writeToFile(fileName);
1272 void CDeploymentConfigurationImplementation::serial(NLMISC::IStream& stream)
1274 // setup a temp container to hold the version of the file that we're reading (if we're reading)
1275 // and fill the container in with our internal object just in case we're writing
1276 CInfoContainer container= _InfoContainer;
1278 // do the serial and make sure we catch any possible execeptions (like for read in progress)
1281 stream.serial(container);
1283 catch(...)
1285 container.clear();
1288 // if the serial failed for whatever reason then giveup
1289 DROP_IF(container.empty(),"Failed to serial deployment configuration: ",return);
1291 // copy the temp container into our internal object (incase this was a read operation)
1292 _InfoContainer= container;
1294 // display a funky victory message
1295 nlinfo("Deployment configuration successfully serialised");
1298 void CDeploymentConfigurationImplementation::getDomainNames(TDomainNames& result) const
1300 _InfoContainer.getDomainNames(result);
1303 void CDeploymentConfigurationImplementation::getShardNames(const TDomainName& domainName,TShardNames& result) const
1305 _InfoContainer.getShardNames(domainName,result);
1308 void CDeploymentConfigurationImplementation::getHostNames(THostNames& result) const
1310 _InfoContainer.getHostNames(result);
1313 void CDeploymentConfigurationImplementation::getAppNames(const THostName& hostName,const TDomainName& domainName,TAppNames& result) const
1315 _InfoContainer.getAppNames(hostName,domainName,result);
1318 void CDeploymentConfigurationImplementation::getAppNames(const THostName& hostName,const TDomainName& domainName,const TShardName& shardName,TAppNames& result) const
1320 _InfoContainer.getAppNames(hostName,domainName,shardName,result);
1323 void CDeploymentConfigurationImplementation::getHost(const THostName& hostName,SHostDescription& result) const
1325 _InfoContainer.getHost(hostName,result);
1328 void CDeploymentConfigurationImplementation::getDomain(const TDomainName& domainName, SDomainDescription& result) const
1330 _InfoContainer.getDomain(domainName,result);
1333 void CDeploymentConfigurationImplementation::getShard(const TDomainName& domainName,const TShardName& shardName,SShardDescription& result) const
1335 _InfoContainer.getShard(domainName,shardName,result);
1338 void CDeploymentConfigurationImplementation::getApp(const TDomainName& domainName,const TAppName& appName,SAppDescription& result) const
1340 _InfoContainer.getApp(domainName,appName,result);
1343 void CDeploymentConfigurationImplementation::dumpInfoBlocks(NLMISC::CLog& log) const
1345 _InfoContainer.dumpInfoBlocks(log);
1348 void CDeploymentConfigurationImplementation::dumpDomains(NLMISC::CLog& log) const
1350 _InfoContainer.dumpDomains(log);
1354 //-----------------------------------------------------------------------------
1355 // methods CDeploymentConfiguration
1356 //-----------------------------------------------------------------------------
1358 CDeploymentConfiguration& CDeploymentConfiguration::getInstance()
1360 return CSingleton<CDeploymentConfigurationImplementation>::getInstance();
1363 } // end of namespace
1365 //NLMISC_CATEGORISED_COMMAND(depcfg,readDepCfgFile,"(re)read the deployment cfg file","[<file name>=\"server_park_database.txt\"]")
1367 // NLMISC::CSString fileName= defaultDeploymentConfigurationFileName;
1369 // switch (args.size())
1370 // {
1371 // case 1:
1372 // fileName=args[0];
1373 // break;
1375 // case 0:
1376 // break;
1378 // default:
1379 // return false;
1380 // }
1382 // DEPCFG::CDeploymentConfiguration::getInstance().read(fileName);
1384 // return true;
1387 //NLMISC_CATEGORISED_COMMAND(depcfg,writeDepCfgFile,"write the deployment cfg file","[<file name>=\"saved_server_park_database.txt\"]")
1389 // NLMISC::CSString fileName= CSString("saved_") + defaultDeploymentConfigurationFileName;
1391 // switch (args.size())
1392 // {
1393 // case 1:
1394 // fileName=args[0];
1395 // break;
1397 // case 0:
1398 // break;
1400 // default:
1401 // return false;
1402 // }
1404 // DEPCFG::CDeploymentConfiguration::getInstance().read(fileName);
1406 // return true;
1409 //NLMISC_CATEGORISED_COMMAND(depcfg,saveDepCfgBinary,"write a binary version of the deployment file to disk","<file name>")
1411 // if (args.size()!=1)
1412 // return false;
1414 // NLMISC::COFile outf(args[0]);
1415 // outf.serial(DEPCFG::CDeploymentConfiguration::getInstance());
1417 // return true;
1420 //NLMISC_CATEGORISED_COMMAND(depcfg,loadDepCfgBinary,"read a binary version of the deployment file from disk","<file name>")
1422 // if (args.size()!=1)
1423 // return false;
1425 // NLMISC::CIFile inf(args[0]);
1426 // inf.serial(DEPCFG::CDeploymentConfiguration::getInstance());
1428 // return true;
1431 NLMISC_CATEGORISED_COMMAND(depcfg,dumpDepCfgInfoBlocks,"dump the raw info blocks for the deployment config singleton","")
1433 if (args.size()!=0)
1434 return false;
1436 DEPCFG::CDeploymentConfiguration::getInstance().dumpInfoBlocks(log);
1438 return true;
1441 NLMISC_CATEGORISED_COMMAND(depcfg,dumpDepCfgDomains,"dump the domain set for the deployment config singleton","")
1443 if (args.size()!=0)
1444 return false;
1446 DEPCFG::CDeploymentConfiguration::getInstance().dumpDomains(log);
1448 return true;
1451 NLMISC_CATEGORISED_COMMAND(depcfg,dumpDepCfgHosts,"dump the host set for the deployment config singleton","")
1453 if (args.size()!=0)
1454 return false;
1456 log.displayNL("--------------------------------------------");
1457 log.displayNL("Hosts");
1458 log.displayNL("--------------------------------------------");
1460 DEPCFG::THostNames hostNames;
1461 DEPCFG::CDeploymentConfiguration::getInstance().getHostNames(hostNames);
1462 sort(hostNames.begin(),hostNames.end());
1463 for (DEPCFG::THostNames::iterator hit= hostNames.begin(); hit!=hostNames.end(); ++hit)
1465 DEPCFG::SHostDescription host;
1466 DEPCFG::CDeploymentConfiguration::getInstance().getHost(*hit,host);
1467 log.displayNL("Host %s (%d domains)",host.HostName.c_str(),host.Domains.size());
1469 for (DEPCFG::TDomainNames::iterator dit= host.Domains.begin(); dit!=host.Domains.end(); ++dit)
1471 log.displayNL("-- Domain %s",dit->c_str());
1475 return true;
1478 NLMISC_CATEGORISED_COMMAND(depcfg,dumpDepCfgShards,"dump the shard set for the deployment config singleton","")
1480 if (args.size()!=0)
1481 return false;
1483 log.displayNL("--------------------------------------------");
1484 log.displayNL("Shards");
1485 log.displayNL("--------------------------------------------");
1487 DEPCFG::TDomainNames domainNames;
1488 DEPCFG::CDeploymentConfiguration::getInstance().getDomainNames(domainNames);
1489 sort(domainNames.begin(),domainNames.end());
1490 for (DEPCFG::TDomainNames::iterator dit= domainNames.begin(); dit!=domainNames.end(); ++dit)
1492 DEPCFG::SDomainDescription domain;
1493 DEPCFG::CDeploymentConfiguration::getInstance().getDomain(*dit,domain);
1494 log.displayNL("Domain %s (%d shards with %d apps on %d hosts)",domain.DomainName.c_str(),domain.Shards.size(),domain.Apps.size(),domain.Hosts.size());
1496 DEPCFG::TShardNames shardNames;
1497 DEPCFG::CDeploymentConfiguration::getInstance().getShardNames(*dit,shardNames);
1498 nlassert(shardNames==domain.Shards);
1499 for (DEPCFG::TShardNames::iterator sit= shardNames.begin(); sit!=shardNames.end(); ++sit)
1501 DEPCFG::SShardDescription shard;
1502 DEPCFG::CDeploymentConfiguration::getInstance().getShard(*dit,*sit,shard);
1503 log.displayNL("-- Shard %s/%s (%d apps on %d hosts)",shard.DomainName.c_str(),shard.ShardName.c_str(),shard.Apps.size(),shard.Hosts.size());
1505 for (DEPCFG::THostNames::iterator hit= shard.Hosts.begin(); hit!=shard.Hosts.end(); ++hit)
1507 log.displayNL(" -- Host %s",hit->c_str());
1508 DEPCFG::TAppNames appNames;
1509 DEPCFG::CDeploymentConfiguration::getInstance().getAppNames(*hit,*dit,*sit,appNames);
1510 for (DEPCFG::TAppNames::iterator ait= appNames.begin(); ait!=appNames.end(); ++ait)
1512 DEPCFG::SAppDescription app;
1513 DEPCFG::CDeploymentConfiguration::getInstance().getApp(*dit,*ait,app);
1514 uint32 cfgFileLines=app.CfgFile.countLines();
1515 uint32 numDataPacks= (uint32)app.DataPacks.size();
1516 log.displayNL(" -- App: %-20s: %s (cfg file length: %d lines, data packs used: %d)",app.AppName.c_str(),app.CmdLine.c_str(),cfgFileLines,numDataPacks);
1522 return true;