NCBI C++ ToolKit
netservice_params.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: netservice_params.cpp 100701 2023-08-31 19:21:12Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * File Description:
27  * Definitions of the configuration parameters for connect/services.
28  *
29  * Authors:
30  * Dmitry Kazimirov
31  *
32  */
33 
34 #include <ncbi_pch.hpp>
35 #include <corelib/ncbireg.hpp>
36 #include <corelib/env_reg.hpp>
37 
38 #include "netservice_params.hpp"
39 
40 #include <mutex>
41 #include <unordered_map>
42 
44 
45 
46 // All these parameters must be added to CSynRegistry::CReport for conf reporting
47 NCBI_PARAM_DEF(bool, netservice_api, use_linger2, false);
48 NCBI_PARAM_DEF(unsigned int, netservice_api, connection_max_retries, CONNECTION_MAX_RETRIES);
49 NCBI_PARAM_DEF(double, netservice_api, retry_delay, RETRY_DELAY_DEFAULT);
50 NCBI_PARAM_DEF(int, netservice_api, max_find_lbname_retries, 3);
51 NCBI_PARAM_DEF(string, netcache_api, fallback_server, "");
52 NCBI_PARAM_DEF(int, netservice_api, max_connection_pool_size, 0); // unlimited
53 NCBI_PARAM_DEF(bool, netservice_api, connection_data_logging, false);
54 NCBI_PARAM_DEF(bool, netservice_api, error_on_unexpected_reply, false);
55 NCBI_PARAM_DEF(bool, netservice_api, warn_on_unexpected_reply, false);
56 NCBI_PARAM_DEF(unsigned, server, max_wait_for_servers, 24 * 60 * 60);
57 NCBI_PARAM_DEF(bool, server, stop_on_job_errors, true);
58 NCBI_PARAM_DEF(bool, server, allow_implicit_job_return, false);
59 
60 
62  m_Config(config)
63 {
64 }
65 
67 {
68  m_Config = config;
70 }
71 
73 {
74  NCBI_ALWAYS_TROUBLE("Not implemented");
75  return false; // Not reached
76 }
77 
78 CConfig* CConfigRegistry::GetSubConfig(const string& section) const
79 {
80  auto it = m_SubConfigs.find(section);
81 
82  if (it != m_SubConfigs.end()) return it->second.get();
83 
84  if (const CConfig::TParamTree* tree = m_Config->GetTree()) {
85  if (const CConfig::TParamTree* sub_tree = tree->FindSubNode(section)) {
86  unique_ptr<CConfig> sub_config(new CConfig(sub_tree));
87  auto result = m_SubConfigs.emplace(section, std::move(sub_config));
88  return result.first->second.get();
89  }
90  }
91 
92  return m_Config;
93 }
94 
95 const string& CConfigRegistry::x_Get(const string& section, const string& name, TFlags) const
96 {
98 
99  try {
100  const auto& found = GetSubConfig(section);
101  return found ? found->GetString(section, name, CConfig::eErr_Throw) : kEmptyStr;
102  }
103  catch (CConfigException& ex) {
105 
106  NCBI_RETHROW2(ex, CRegistryException, eErr, ex.GetMsg(), 0);
107  }
108 }
109 
110 bool CConfigRegistry::x_HasEntry(const string& section, const string& name, TFlags) const
111 {
112  _ASSERT(m_Config);
113 
114  try {
115  const auto& found = GetSubConfig(section);
116  if (!found) return false;
117  found->GetString(section, name, CConfig::eErr_Throw);
118  }
119  catch (CConfigException& ex) {
120  if (ex.GetErrCode() == CConfigException::eParameterMissing) return false;
121 
122  NCBI_RETHROW2(ex, CRegistryException, eErr, ex.GetMsg(), 0);
123  }
124 
125  return true;
126 }
127 
128 const string& CConfigRegistry::x_GetComment(const string&, const string&, TFlags) const
129 {
130  NCBI_ALWAYS_TROUBLE("Not implemented");
131  return kEmptyStr; // Not reached
132 }
133 
134 void CConfigRegistry::x_Enumerate(const string&, list<string>&, TFlags) const
135 {
136  NCBI_ALWAYS_TROUBLE("Not implemented");
137 }
138 
139 template <typename TType>
140 static string s_ToString(TType value)
141 {
142  return to_string(value);
143 }
144 
145 string s_ToString(string value)
146 {
147  return '"' + value + '"';
148 }
149 
151 
152 template <class TParam>
154 {
155 };
156 
157 template <class TDescription>
159 {
160  const auto& section = TDescription::sm_ParamDescription.section;
161  const auto& name = TDescription::sm_ParamDescription.name;
163 
164  vs[section].emplace(name, s_ToString(value));
165  return vs;
166 }
167 
168 template <class... TParams>
170 {
171 };
172 
173 // Clang needs TSecond (sees ambiguity between these two below otherwise)
174 template <class TFirst, class TSecond, class... TOther>
176 {
177  return vs << SParamReporter<TFirst>() << SListReporter<TSecond, TOther...>();
178 }
179 
180 template <class TParam>
182 {
183  return vs << SParamReporter<TParam>();
184 }
185 
187 {
188 public:
189  CReport();
190 
191  template <typename TType>
192  void Add(const string& section, const string& name, TType value);
193 
194  void Report(ostream& os) const;
195 
196 private:
198  mutable mutex m_Mutex;
199 };
200 
202 {
204  TServConn_ConnMaxRetries,
205  TServConn_RetryDelay,
206  TServConn_UserLinger2,
207  TServConn_MaxFineLBNameRetries,
208  TCGI_NetCacheFallbackServer,
209  TServConn_MaxConnPoolSize,
210  TServConn_ConnDataLogging,
211  TServConn_WarnOnUnexpectedReply,
212  TWorkerNode_MaxWaitForServers,
213  TWorkerNode_StopOnJobErrors,
214  TWorkerNode_AllowImplicitJobReturn>();
215 }
216 
217 void CSynRegistry::CReport::Report(ostream& os) const
218 {
219  lock_guard<mutex> lock(m_Mutex);
220 
221  for (const auto& section : m_Values) {
222  os << '[' << section.first << ']' << endl;;
223 
224  for (const auto& param : section.second) {
225  os << param.first << '=' << param.second << endl;
226  }
227 
228  os << endl;
229  }
230 }
231 
232 template <typename TType>
233 void CSynRegistry::CReport::Add(const string& section, const string& name, TType value)
234 {
235  lock_guard<mutex> lock(m_Mutex);
236  m_Values[section].emplace(name, s_ToString(value));
237 }
238 
240 {
241 public:
242  SRegSynonyms Get(const SRegSynonyms& sections, IRegistry& registry);
243 
244 private:
245  unordered_map<string, vector<string>> m_Includes;
246  mutex m_Mutex;
247 };
248 
250 {
251  SRegSynonyms rv{};
252  lock_guard<mutex> lock(m_Mutex);
253 
254  for (const auto& section : sections) {
255  auto result = m_Includes.insert({section, {}});
256  auto& included = result.first->second;
257 
258  // Have not checked for '.include' yet
259  if (result.second) {
260  auto included_value = registry.Get(string(section), ".include");
262  NStr::Split(included_value, ",; \t\n\r", included, flags);
263  }
264 
265  rv.push_back(section);
266  rv.insert(rv.end(), included.begin(), included.end());
267  }
268 
269  return rv;
270 }
271 
273 {
274 public:
275  void Set(string message);
276  void Report(ostream& os) const;
277  bool Ack(size_t id);
278 
279 private:
281  size_t m_CurrentID = 0;
282  mutable mutex m_Mutex;
283 };
284 
285 void CSynRegistry::CAlert::Set(string message)
286 {
287  lock_guard<mutex> lock(m_Mutex);
288  m_Alerts.emplace(++m_CurrentID, message);
289 }
290 
291 void CSynRegistry::CAlert::Report(ostream& os) const
292 {
293  lock_guard<mutex> lock(m_Mutex);
294  for (const auto& alert : m_Alerts) {
295  os << "Alert_" << alert.first << ": " << alert.second << endl;
296  }
297 }
298 
300 {
301  lock_guard<mutex> lock(m_Mutex);
302  return m_Alerts.erase(id) == 1;
303 }
304 
306  m_Report(new CReport),
307  m_Include(new CInclude),
308  m_Alert(new CAlert)
309 {
310 }
311 
313 {
314 }
315 
317 {
318  // Always add a registry as new top priority
320 }
321 
323 {
324  return m_Registry;
325 }
326 
327 void CSynRegistry::Report(ostream& os) const
328 {
329  m_Report->Report(os);
330 }
331 
332 void CSynRegistry::Alerts(ostream& os) const
333 {
334  m_Alert->Report(os);
335 }
336 
337 bool CSynRegistry::AckAlert(size_t id)
338 {
339  return m_Alert->Ack(id);
340 }
341 
342 template <typename TType>
343 TType CSynRegistry::TGet(const SRegSynonyms& sections, SRegSynonyms names, TType default_value)
344 {
346  _ASSERT(sections.size());
347  _ASSERT(names.size());
348 
349  const auto sections_plus_included = m_Include->Get(sections, m_Registry);
350 
351  for (const auto& section : sections_plus_included) {
352  for (const auto& name : names) {
353  if (!m_Registry.HasEntry(section, name)) continue;
354 
355  try {
356  auto rv = m_Registry.GetValue(section, name, default_value, IRegistry::eThrow);
357  m_Report->Add(section, name, rv);
358  return rv;
359  }
360  catch (CException& ex) {
361  string msg;
362  string separator;
363 
364  for (const auto* p = &ex; p; p = p->GetPredecessor()) {
365  msg += separator;
366  msg += p->GetMsg();
367  separator = ". ";
368  }
369 
370  ERR_POST(Warning << msg);
372  }
373  }
374  }
375 
376  // Cannot use sections.front() here.
377  // Otherwise, some default values would be reported twice (with different sections)
378  // due to configuration loading from NetSchedule which adds a special section in front.
379  m_Report->Add(sections.back(), names.front(), default_value);
380  return default_value;
381 }
382 
384 {
385  _ASSERT(sections.size());
386  _ASSERT(names.size());
387 
388  const auto sections_plus_included = m_Include->Get(sections, m_Registry);
389 
390  for (const auto& section : sections_plus_included) {
391  for (const auto& name : names) {
392  if (m_Registry.HasEntry(section, name)) return true;
393  }
394  }
395 
396  return false;
397 }
398 
399 template string CSynRegistry::TGet(const SRegSynonyms& sections, SRegSynonyms names, string default_value);
400 template bool CSynRegistry::TGet(const SRegSynonyms& sections, SRegSynonyms names, bool default_value);
401 template int CSynRegistry::TGet(const SRegSynonyms& sections, SRegSynonyms names, int default_value);
402 template double CSynRegistry::TGet(const SRegSynonyms& sections, SRegSynonyms names, double default_value);
403 
405 {
407 
408 
409  if (app) {
410  registry->Add(app->GetConfig());
411  } else {
412  // This code is safe, as the sub-registry ends up in CCompoundRegistry which uses CRef, too
413  CRef<IRegistry> env_registry(new CEnvironmentRegistry);
414  registry->Add(*env_registry);
415  }
416 
417  return registry;
418 }
419 
421 {
423  return s_CreateISynRegistry(guard.Get());
424 }
425 
427  m_Registry(s_CreateISynRegistry())
428 {
430 
431  m_Registry->Add(registry);
432 }
433 
435  m_Registry(s_CreateISynRegistry())
436 {
438 
439  if (config) {
440  // This code is safe, as the sub-registry ends up in CCompoundRegistry which uses CRef, too
441  CRef<IRegistry> config_registry(new CConfigRegistry(config));
442  m_Registry->Add(*config_registry);
443  }
444 }
445 
447  m_Registry(s_CreateISynRegistry(&app))
448 {
450 }
451 
453  m_Registry(registry)
454 {
455 }
456 
458 {
459  return GetIRegistry().Empty(flags);
460 }
461 
463 {
464  return GetIRegistry().Modified(flags);
465 }
466 
468 {
469  return GetIRegistry().SetModifiedFlag(modified, flags);
470 }
471 
472 const string& CSynRegistryToIRegistry::x_Get(const string&, const string&, TFlags) const
473 {
474  // Get* overrides must never call this method
475  _TROUBLE;
476  return kEmptyStr;
477 }
478 
479 bool CSynRegistryToIRegistry::x_HasEntry(const string&, const string&, TFlags) const
480 {
481  // Has override must never call this method
482  _TROUBLE;
483  return false;
484 }
485 
486 const string& CSynRegistryToIRegistry::x_GetComment(const string&, const string&, TFlags) const
487 {
488  // GetComment override must never call this method
489  _TROUBLE;
490  return kEmptyStr;
491 }
492 
493 void CSynRegistryToIRegistry::x_Enumerate(const string&, list<string>&, TFlags) const
494 {
495  // Enumerate* overrides must never call this method
496  _TROUBLE;
497 }
498 
500 {
501  return (GetIRegistry().*action)();
502 }
503 
504 const string& CSynRegistryToIRegistry::Get(const string& section, const string& name, TFlags flags) const
505 {
507 
508  // Cannot return reference to a temporary, so first call for caching and next for returning
509  m_Registry->Get(section, name, kEmptyStr);
510  return GetIRegistry().Get(section, name, flags);
511 }
512 
513 bool CSynRegistryToIRegistry::HasEntry(const string& section, const string& name, TFlags) const
514 {
516 
517  return m_Registry->Has(section, name);
518 }
519 
520 string CSynRegistryToIRegistry::GetString(const string& section, const string& name, const string& default_value, TFlags) const
521 {
523 
524  return m_Registry->Get(section, name, default_value);
525 }
526 
527 int CSynRegistryToIRegistry::GetInt(const string& section, const string& name, int default_value, TFlags, EErrAction) const
528 {
530 
531  return m_Registry->Get(section, name, default_value);
532 }
533 
534 bool CSynRegistryToIRegistry::GetBool(const string& section, const string& name, bool default_value, TFlags, EErrAction) const
535 {
537 
538  return m_Registry->Get(section, name, default_value);
539 }
540 
541 double CSynRegistryToIRegistry::GetDouble(const string& section, const string& name, double default_value, TFlags, EErrAction) const
542 {
544 
545  return m_Registry->Get(section, name, default_value);
546 }
547 
548 const string& CSynRegistryToIRegistry::GetComment(const string& section, const string& name, TFlags flags) const
549 {
550  return GetIRegistry().GetComment(section, name, flags);
551 }
552 
553 void CSynRegistryToIRegistry::EnumerateInSectionComments(const string& section, list<string>* comments, TFlags flags) const
554 {
555  return GetIRegistry().EnumerateInSectionComments(section, comments, flags);
556 }
557 
558 void CSynRegistryToIRegistry::EnumerateSections(list<string>* sections, TFlags flags) const
559 {
560  return GetIRegistry().EnumerateSections(sections, flags);
561 }
562 
563 void CSynRegistryToIRegistry::EnumerateEntries(const string& section, list<string>* entries, TFlags flags) const
564 {
565  return GetIRegistry().EnumerateEntries(section, entries, flags);
566 }
567 
568 
CConfigException –.
Definition: ncbi_config.hpp:53
bool x_HasEntry(const string &section, const string &name, TFlags flags) const override
map< string, unique_ptr< CConfig > > m_SubConfigs
void x_Enumerate(const string &section, list< string > &entries, TFlags flags) const override
void Reset(CConfig *config=nullptr)
const string & x_Get(const string &section, const string &name, TFlags flags) const override
CConfigRegistry(CConfig *config=nullptr)
CConfig * GetSubConfig(const string &section) const
bool x_Empty(TFlags flags) const override
Implementations of the fundamental operations above, to be run with the lock already acquired and som...
const string & x_GetComment(const string &section, const string &name, TFlags flags) const override
CEnvironmentRegistry –.
Definition: env_reg.hpp:87
CParam.
Definition: ncbi_param.hpp:447
CRegistryException –.
Definition: ncbireg.hpp:1005
void x_ChildLockAction(FLockAction action) final
const string & x_GetComment(const string &section, const string &name, TFlags flags) const final
double GetDouble(const string &section, const string &name, double default_value, TFlags flags=0, EErrAction err_action=eThrow) const final
Get double value of specified parameter name.
string GetString(const string &section, const string &name, const string &default_value, TFlags flags=0) const final
Get the parameter string value.
void EnumerateInSectionComments(const string &section, list< string > *comments, TFlags flags=fAllLayers) const final
Enumerate in-section comments.
bool x_HasEntry(const string &section, const string &name, TFlags flags) const final
const string & Get(const string &section, const string &name, TFlags flags=0) const final
Get the parameter value.
int GetInt(const string &section, const string &name, int default_value, TFlags flags=0, EErrAction err_action=eThrow) const final
Get integer value of specified parameter name.
void x_SetModifiedFlag(bool modified, TFlags flags) final
bool x_Modified(TFlags flags) const final
void x_Enumerate(const string &section, list< string > &entries, TFlags flags) const final
const string & GetComment(const string &section=kEmptyStr, const string &name=kEmptyStr, TFlags flags=0) const final
Get comment of the registry entry "section:name".
bool HasEntry(const string &section, const string &name=kEmptyStr, TFlags flags=0) const final
void EnumerateSections(list< string > *sections, TFlags flags=fAllLayers) const final
Enumerate section names.
CSynRegistryToIRegistry(CSynRegistry::TPtr registry)
IRegistry & GetIRegistry() const
CSynRegistry::TPtr m_Registry
const string & x_Get(const string &section, const string &name, TFlags flags) const final
void EnumerateEntries(const string &section, list< string > *entries, TFlags flags=fAllLayers) const final
Enumerate parameter names for a specified section.
bool GetBool(const string &section, const string &name, bool default_value, TFlags flags=0, EErrAction err_action=eThrow) const final
Get boolean value of specified parameter name.
bool x_Empty(TFlags flags) const final
Implementations of the fundamental operations above, to be run with the lock already acquired and som...
void Report(ostream &os) const
void Set(string message)
map< size_t, string > m_Alerts
SRegSynonyms Get(const SRegSynonyms &sections, IRegistry &registry)
unordered_map< string, vector< string > > m_Includes
void Add(const string &section, const string &name, TType value)
void Report(ostream &os) const
bool AckAlert(size_t id)
unique_ptr< CReport > m_Report
void Add(const IRegistry &registry)
unique_ptr< CAlert > m_Alert
CCompoundRegistry m_Registry
shared_ptr< CSynRegistry > TPtr
void Alerts(ostream &os) const
void Report(ostream &os) const
IRegistry & GetIRegistry()
unique_ptr< CInclude > m_Include
TType TGet(const SRegSynonyms &sections, SRegSynonyms names, TType default_value)
bool Has(const SRegSynonyms &sections, SRegSynonyms names)
definition of a Culling tree
Definition: ncbi_tree.hpp:100
IRegistry –.
Definition: ncbireg.hpp:73
const_iterator end() const
Definition: map.hpp:152
void clear()
Definition: map.hpp:169
const_iterator find(const key_type &key) const
Definition: map.hpp:153
static CMemoryRegistry registry
Definition: cn3d_tools.cpp:81
struct config config
static uch flags
Classes to support using environment variables as a backend for the registry framework.
static const struct name_t names[]
static CNcbiApplicationGuard InstanceGuard(void)
Singleton method.
Definition: ncbiapp.cpp:133
const CNcbiRegistry & GetConfig(void) const
Get the application's cached configuration parameters (read-only).
CNcbiApplicationAPI * Get(void)
#define NCBI_ALWAYS_TROUBLE(mess)
Definition: ncbidbg.hpp:85
#define ERR_POST(message)
Error posting with file, line number information but without error codes.
Definition: ncbidiag.hpp:186
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
TErrCode GetErrCode(void) const
Definition: ncbiexpt.hpp:1493
#define NCBI_RETHROW2(prev_exception, exception_class, err_code, message, extra)
Re-throw exception with extra parameter.
Definition: ncbiexpt.hpp:1761
const CException * GetPredecessor(void) const
Get "previous" exception from the backlog.
Definition: ncbiexpt.hpp:1041
const TParamTree * GetTree() const
@ eErr_Throw
Throw an exception on error.
@ eParameterMissing
Missing mandatory parameter.
Definition: ncbi_config.hpp:56
static TValueType GetDefault(void)
Get global default value.
int TFlags
Binary OR of "EFlags".
Definition: ncbireg.hpp:107
virtual void EnumerateSections(list< string > *sections, TFlags flags=fAllLayers) const
Enumerate section names.
Definition: ncbireg.cpp:497
virtual const string & Get(const string &section, const string &name, TFlags flags=0) const
Get the parameter value.
Definition: ncbireg.cpp:262
string GetValue(const string &section, const string &name, const string &default_value, EErrAction=eReturn, TFlags flags=0) const
Overloading of getters for generic programming.
Definition: ncbireg.hpp:250
EErrAction
What to do if parameter value is present but cannot be converted into the requested type.
Definition: ncbireg.hpp:200
virtual void EnumerateInSectionComments(const string &section, list< string > *comments, TFlags flags=fAllLayers) const
Enumerate in-section comments.
Definition: ncbireg.cpp:474
virtual bool HasEntry(const string &section, const string &name=kEmptyStr, TFlags flags=0) const
Definition: ncbireg.cpp:290
bool Empty(TFlags flags=fAllLayers) const
Verify if Registry is empty.
Definition: ncbireg.cpp:162
virtual void EnumerateEntries(const string &section, list< string > *entries, TFlags flags=fAllLayers) const
Enumerate parameter names for a specified section.
Definition: ncbireg.cpp:514
bool Modified(TFlags flags=fPersistent) const
Verify if persistent values have been modified.
Definition: ncbireg.cpp:173
virtual const string & GetComment(const string &section=kEmptyStr, const string &name=kEmptyStr, TFlags flags=0) const
Get comment of the registry entry "section:name".
Definition: ncbireg.cpp:450
void Add(const IRegistry &reg, TPriority prio=ePriority_Default, const string &name=kEmptyStr)
Non-empty names must be unique within each compound registry, but there is no limit to the number of ...
Definition: ncbireg.cpp:1186
void SetModifiedFlag(bool modified, TFlags flags=fPersistent)
Indicate whether any relevant values are out of sync with some external resource (typically a configu...
Definition: ncbireg.cpp:184
@ eThrow
Throw an exception if an error occurs.
Definition: ncbireg.hpp:201
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define kEmptyStr
Definition: ncbistr.hpp:123
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3461
static string JsonEncode(const CTempString str, EJsonEncode encoding=eJsonEnc_UTF8)
Encode a string for JSON.
Definition: ncbistr.cpp:4634
@ eJsonEnc_Quoted
Quote resulting string.
Definition: ncbistr.hpp:3094
@ fSplit_Truncate
Definition: ncbistr.hpp:2501
@ fSplit_MergeDelimiters
Merge adjacent delimiters.
Definition: ncbistr.hpp:2498
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
Process information in the NCBI Registry, including working with configuration files.
CSynRegistry::TPtr s_CreateISynRegistry(const CNcbiApplication *app)
static string s_ToString(TType value)
NCBI_PARAM_DEF(bool, netservice_api, use_linger2, false)
TValues & operator<<(TValues &vs, SParamReporter< CParam< TDescription >>)
#define RETRY_DELAY_DEFAULT
#define CONNECTION_MAX_RETRIES
CSynRegistryBuilder(const IRegistry &registry)
CSynRegistry::TPtr m_Registry
#define _TROUBLE
#define _ASSERT
else result
Definition: token2.c:20
static wxAcceleratorEntry entries[3]
Modified on Tue Apr 30 06:38:30 2024 by modify_doxy.py rev. 669887