1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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>
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 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
25 // pre compiled headers
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"
39 #include "deployment_configuration.h"
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
47 using namespace NLMISC
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
56 //-----------------------------------------------------------------------------
57 // forward class declarations
58 //-----------------------------------------------------------------------------
63 class CDeploymentConfigurationImplementation
;
66 //-----------------------------------------------------------------------------
68 //-----------------------------------------------------------------------------
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
;
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
);
96 stream
.serialCont(DataEntries
);
97 stream
.serialCont(CfgEntries
);
98 stream
.serialCont(CfgEntriesPost
);
103 //-----------------------------------------------------------------------------
105 //-----------------------------------------------------------------------------
107 class CInfoBlock
: public NLMISC::CRefCount
111 CInfoBlock(const NLMISC::CSString
& name
="");
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());
146 void serial(NLMISC::IStream
& stream
);
148 // display the contents of the container
149 void dump(NLMISC::CLog
& log
) const;
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
;
160 bool _haveCircularRef(CInfoBlock
* other
) const;
163 NLMISC::CSString _Name
;
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 //-----------------------------------------------------------------------------
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
);
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
;
224 void _readFile(const NLMISC::CSString
& fileName
,uint32
& errors
,TFileNameSet
& fileNameStack
);
225 void _buildDomainTree(uint32
& errors
);
226 void _buildExeSet(uint32
& errors
);
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
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;
262 CInfoContainer _InfoContainer
;
266 //-----------------------------------------------------------------------------
267 // methods CInfoBlock
268 //-----------------------------------------------------------------------------
270 CInfoBlock::CInfoBlock(const NLMISC::CSString
& name
)
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);
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);
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);
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);
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);
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);
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
381 const NLMISC::CSString
& CInfoBlock::getName() const
386 const NLMISC::CSString
& CInfoBlock::getDomainName() const
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
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
);
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
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 //*****************************
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());
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());
563 bool CInfoBlock::_haveCircularRef(CInfoBlock
* other
) const
565 // in the case of a circular refference we end up with the 'other'=='this'
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
))
577 // no circular ref found so return false
581 //-----------------------------------------------------------------------------
582 // methods CInfoContainer
583 //-----------------------------------------------------------------------------
585 void CInfoContainer::clear()
588 _CurrentInfoBlock
= NULL
;
593 bool CInfoContainer::empty() const
595 return _InfoBlocks
.empty();
598 bool CInfoContainer::read(const NLMISC::CSString
& fileName
)
600 // start by clearing out our contents...
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);
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
;
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())
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
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())
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)
752 // compose a second version of the name with the shard name added
754 name
+=it2
->ShardName
;
755 // if the name is unique within the shard then continue
756 if (nameCounts
[name
]==1)
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...
773 // get the number of info blocks from the stream
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
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
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...
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
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
);
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...
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
);
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...
869 // fill the result in from our internal data
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
);
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...
901 // fill the result in from our internal data
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
);
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...
932 // fill the result in from our internal data
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
);
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...
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
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
);
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
);
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...
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
;
1009 TNameSet shardNames
;
1011 // fill the result in from our internal data
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
);
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
);
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...
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
;
1063 // fill the result in from our internal data
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
);
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
);
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...
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
1128 "// Auto generated config file\n"
1129 "// Use with commandline: "+theApp
.CmdLine
+"\n"
1130 "AESAliasName= \"" + appName
.c_str() + "\";\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
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
)
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
);
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());
1247 void CDeploymentConfigurationImplementation::write(const NLMISC::CSString
& fileName
)
1249 // create a displayer to gather the output of the command
1250 class CStringDisplayer
: public IDisplayer
1253 NLMISC::CSString Data
;
1254 void doDisplay( const CLog::TDisplayInfo
& args
, const char *message
)
1260 // instantiate the displayer and a log object and assign one to the other
1261 CStringDisplayer stringDisplayer
;
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
);
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())
1372 // fileName=args[0];
1382 // DEPCFG::CDeploymentConfiguration::getInstance().read(fileName);
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())
1394 // fileName=args[0];
1404 // DEPCFG::CDeploymentConfiguration::getInstance().read(fileName);
1409 //NLMISC_CATEGORISED_COMMAND(depcfg,saveDepCfgBinary,"write a binary version of the deployment file to disk","<file name>")
1411 // if (args.size()!=1)
1414 // NLMISC::COFile outf(args[0]);
1415 // outf.serial(DEPCFG::CDeploymentConfiguration::getInstance());
1420 //NLMISC_CATEGORISED_COMMAND(depcfg,loadDepCfgBinary,"read a binary version of the deployment file from disk","<file name>")
1422 // if (args.size()!=1)
1425 // NLMISC::CIFile inf(args[0]);
1426 // inf.serial(DEPCFG::CDeploymentConfiguration::getInstance());
1431 NLMISC_CATEGORISED_COMMAND(depcfg
,dumpDepCfgInfoBlocks
,"dump the raw info blocks for the deployment config singleton","")
1436 DEPCFG::CDeploymentConfiguration::getInstance().dumpInfoBlocks(log
);
1441 NLMISC_CATEGORISED_COMMAND(depcfg
,dumpDepCfgDomains
,"dump the domain set for the deployment config singleton","")
1446 DEPCFG::CDeploymentConfiguration::getInstance().dumpDomains(log
);
1451 NLMISC_CATEGORISED_COMMAND(depcfg
,dumpDepCfgHosts
,"dump the host set for the deployment config singleton","")
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());
1478 NLMISC_CATEGORISED_COMMAND(depcfg
,dumpDepCfgShards
,"dump the shard set for the deployment config singleton","")
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
);