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

Go to the SVN repository for this file.

1 /* $Id: nst_config.cpp 73130 2016-06-21 14:17:32Z satskyse $
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  * Authors: Sergey Satskiy
27  *
28  * File Description: NetStorage config file utilities
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
35 
36 #include "nst_config.hpp"
37 #include "nst_exception.hpp"
38 #include "nst_server.hpp"
39 #include "nst_constants.hpp"
40 
41 
43 
44 const string g_LogPrefix = "Validating config file: ";
45 
46 
47 static void NSTValidateServerSection(const IRegistry & reg,
48  vector<string> & warnings,
49  bool throw_port_exception);
50 static void NSTValidateDatabaseSection(const IRegistry & reg,
51  vector<string> & warnings);
52 static void NSTValidateMetadataSection(const IRegistry & reg,
53  vector<string> & warnings);
54 static void NSTValidateServices(const IRegistry & reg,
55  vector<string> & warnings);
56 static void NSTValidateProlongValue(const IRegistry & reg,
57  const string & section,
58  const string & entry,
59  vector<string> & warnings);
60 static void NSTValidateTTLValue(const IRegistry & reg,
61  const string & section,
62  const string & entry,
63  vector<string> & warnings);
64 static bool NSTValidateBool(const IRegistry & reg,
65  const string & section, const string & entry,
66  vector<string> & warnings);
67 static bool NSTValidateInt(const IRegistry & reg,
68  const string & section, const string & entry,
69  vector<string> & warnings);
70 static bool NSTValidateDouble(const IRegistry & reg,
71  const string & section, const string & entry,
72  vector<string> & warnings);
73 static bool NSTValidateString(const IRegistry & reg,
74  const string & section, const string & entry,
75  vector<string> & warnings);
76 static string NSTRegValName(const string & section, const string & entry);
77 static string NSTOutOfLimitMessage(const string & section,
78  const string & entry,
79  unsigned int low_limit,
80  unsigned int high_limit);
81 
82 
84  vector<string> & warnings,
85  bool throw_port_exception)
86 {
87  NSTValidateServerSection(reg, warnings, throw_port_exception);
88  NSTValidateDatabaseSection(reg, warnings);
89  NSTValidateMetadataSection(reg, warnings);
90  NSTValidateServices(reg, warnings);
91 }
92 
93 
94 // Returns true if the config file is well formed
96  vector<string> & warnings,
97  bool throw_port_exception)
98 {
99  const string section = "server";
100 
101  // port is a unique value in this section. NST must not start
102  // if there is a problem with port.
103  bool ok = NSTValidateInt(reg, section, "port", warnings);
104  if (ok) {
105  int port_val = reg.GetInt(section, "port", 0);
106  if (port_val < port_low_limit || port_val > port_high_limit) {
107  string msg = "Invalid " + NSTRegValName(section, "port") +
108  " value. Allowed range: " +
111  if (throw_port_exception)
112  NCBI_THROW(CNetStorageServerException, eInvalidConfig, msg);
113  warnings.push_back(msg);
114  }
115  } else {
116  if (throw_port_exception)
117  NCBI_THROW(CNetStorageServerException, eInvalidConfig,
118  "Invalid " + NSTRegValName(section, "port") +
119  " parameter.");
120  }
121 
122  ok = NSTValidateInt(reg, section, "max_connections", warnings);
123  if (ok) {
124  int val = reg.GetInt(section, "max_connections",
126  if (val < int(max_connections_low_limit) ||
128  warnings.push_back(
129  NSTOutOfLimitMessage(section, "max_connections",
132  }
133 
134  ok = NSTValidateInt(reg, section, "max_threads", warnings);
135  unsigned int max_threads_val = default_max_threads;
136  if (ok) {
137  int val = reg.GetInt(section, "max_threads", default_max_threads);
138  if (val < int(max_threads_low_limit) ||
140  warnings.push_back(
141  NSTOutOfLimitMessage(section, "max_threads",
144  else
145  max_threads_val = val;
146  }
147 
148  ok = NSTValidateInt(reg, section, "init_threads", warnings);
149  unsigned int init_threads_val = default_init_threads;
150  if (ok) {
151  int val = reg.GetInt(section, "init_threads", default_init_threads);
152  if (val < int(init_threads_low_limit) ||
154  warnings.push_back(
155  NSTOutOfLimitMessage(section, "init_threads",
158  else
159  init_threads_val = val;
160  }
161 
162  if (init_threads_val > max_threads_val)
163  warnings.push_back(g_LogPrefix + " values " +
164  NSTRegValName(section, "max_threads") + " and " +
165  NSTRegValName(section, "init_threads") +
166  " break the mandatory condition "
167  "init_threads <= max_threads");
168 
169 
170  ok = NSTValidateInt(reg, section, "network_timeout", warnings);
171  if (ok) {
172  int val = reg.GetInt(section, "network_timeout",
174  if (val <= 0)
175  warnings.push_back(g_LogPrefix + " value " +
176  NSTRegValName(section, "network_timeout") +
177  " must be > 0");
178  }
179 
180  NSTValidateBool(reg, section, "log", warnings);
181  NSTValidateBool(reg, section, "log_timing_nst_api", warnings);
182  NSTValidateBool(reg, section, "log_timing_client_socket", warnings);
183  NSTValidateString(reg, section, "admin_client_name", warnings);
184  NSTValidateString(reg, section, "data_path", warnings);
185 }
186 
187 
189  vector<string> & warnings)
190 {
191  const string section = "database";
192 
193  bool ok = NSTValidateString(reg, section, "service", warnings);
194  if (ok) {
195  string value = reg.GetString(section, "service", "");
196  if (value.empty())
197  warnings.push_back(g_LogPrefix + " value " +
198  NSTRegValName(section, "service") +
199  " must not be empty");
200  }
201 
202  ok = NSTValidateString(reg, section, "user_name", warnings);
203  if (ok) {
204  string value = reg.GetString(section, "user_name", "");
205  if (value.empty())
206  warnings.push_back(g_LogPrefix + " value " +
207  NSTRegValName(section, "user_name") +
208  " must not be empty");
209  }
210 
211  ok = NSTValidateString(reg, section, "password", warnings);
212  if (ok) {
213  string value = reg.GetString(section, "password", "");
214  if (value.empty())
215  warnings.push_back(g_LogPrefix + " value " +
216  NSTRegValName(section, "password") +
217  " must not be empty");
218  }
219 
220  ok = NSTValidateString(reg, section, "database", warnings);
221  if (ok) {
222  string value = reg.GetString(section, "database", "");
223  if (value.empty())
224  warnings.push_back(g_LogPrefix + " value " +
225  NSTRegValName(section, "database") +
226  " must not be empty");
227  }
228 
229  ok = NSTValidateDouble(reg, section, "execute_sp_timeout", warnings);
230  if (ok) {
231  double value = reg.GetDouble(section, "execute_sp_timeout",
233  if (value <= 0.0) {
234  warnings.push_back(g_LogPrefix + " value " +
235  NSTRegValName(section, "execute_sp_timeout") +
236  " must be > 0.0");
237  }
238  }
239 }
240 
241 
243  vector<string> & warnings)
244 {
245  const string section = "metadata_conf";
246 
247  NSTValidateTTLValue(reg, section, "ttl", warnings);
248  NSTValidateProlongValue(reg, section, "prolong_on_read", warnings);
249  NSTValidateProlongValue(reg, section, "prolong_on_write", warnings);
250  NSTValidateProlongValue(reg, section, "prolong_on_relocate", warnings);
251 }
252 
253 
254 // Case insensitive unary predicate for a list
256 {
257  SCaseInsensitivePredicate(const string & pattern) : p(pattern)
258  {}
259  bool operator()(const string & m)
260  { return NStr::CompareNocase(m, p) == 0; }
261 
262  string p;
263 };
264 
265 
266 // Checks the service_ZZZ sections
267 void NSTValidateServices(const IRegistry & reg, vector<string> & warnings)
268 {
269  list<string> sections;
270  reg.EnumerateSections(&sections);
271 
272  const string prefix = "service_";
273  for (list<string>::const_iterator k = sections.begin();
274  k != sections.end(); ++k) {
276  continue;
277 
278  string service(k->c_str() + prefix.size());
279  if (service.empty()) {
280  warnings.push_back("Section [" + *k + "] does not have "
281  "a service name.");
282  continue;
283  }
284 
285  if (!reg.HasEntry(*k, "metadata"))
286  continue;
287 
288  if (!NSTValidateBool(reg, *k, "metadata", warnings))
289  continue; // Warning has been added
290 
291  if (!reg.GetBool(*k, "metadata", false))
292  continue;
293 
294  NSTValidateTTLValue(reg, *k, "ttl", warnings);
295  NSTValidateProlongValue(reg, *k, "prolong_on_read", warnings);
296  NSTValidateProlongValue(reg, *k, "prolong_on_write", warnings);
297  NSTValidateProlongValue(reg, *k, "prolong_on_relocate", warnings);
298  }
299 }
300 
301 
303  const string & section,
304  const string & entry,
305  vector<string> & warnings)
306 {
307  bool ok = NSTValidateString(reg, section, entry, warnings);
308  if (ok) {
309  string value = reg.GetString(section, entry, "");
311 
312  if (!value.empty()) {
313  try {
314  if (NStr::EndsWith(value, "ttl", NStr::eNocase)) {
315  // Try to convert to double not forgetting that the 'ttl'
316  // suffix needs to be stripped and that spaces between the
317  // value and the suffix are allowed
318  double val = NStr::StringToDouble(
319  value.substr(0, value.size() - 3),
321  if (val < 0.0)
322  warnings.push_back("The " +
323  NSTRegValName(section, entry) + " multiplier must "
324  "be a positive value.");
325  } else {
326  ReadTimeSpan(value, false); // no infinity
327  }
328  } catch (const exception & ex) {
329  warnings.push_back("Exception while validating " +
330  NSTRegValName(section, entry) +
331  " value: " + ex.what());
332  } catch (...) {
333  warnings.push_back("Unknown exception while validating " +
334  NSTRegValName(section, entry) +
335  " value: " + value + ". It must be "
336  " in a recognizable format.");
337  }
338  }
339  }
340 }
341 
342 
344  const string & section,
345  const string & entry,
346  vector<string> & warnings)
347 {
348  bool ok = NSTValidateString(reg, section, entry, warnings);
349  if (ok) {
350  string value = reg.GetString(section, entry, "");
351  try {
352  ReadTimeSpan(value, true); // Allow infinity
353  } catch (const exception & ex) {
354  warnings.push_back("Exception while validating " +
355  NSTRegValName(section, entry) +
356  " value: " + ex.what());
357  } catch (...) {
358  warnings.push_back("Unknown exception while validating " +
359  NSTRegValName(section, entry) +
360  " value: " + value + ". It must be "
361  "'infinity' or a recognizable format.");
362  }
363  }
364 }
365 
366 
367 // Forms the ini file value name for logging
368 string NSTRegValName(const string & section, const string & entry)
369 {
370  return "[" + section + "]/" + entry;
371 }
372 
373 
374 // Forms an out of limits message
375 string NSTOutOfLimitMessage(const string & section,
376  const string & entry,
377  unsigned int low_limit,
378  unsigned int high_limit)
379 {
380  return g_LogPrefix + NSTRegValName(section, entry) +
381  " is out of limits (" + NStr::NumericToString(low_limit) + "..." +
382  NStr::NumericToString(high_limit) + ")";
383 
384 }
385 
386 
387 // Checks that a boolean value is fine
388 bool NSTValidateBool(const IRegistry & reg,
389  const string & section, const string & entry,
390  vector<string> & warnings)
391 {
392  try {
393  reg.GetBool(section, entry, false);
394  }
395  catch (...) {
396  warnings.push_back(g_LogPrefix + "unexpected value of " +
397  NSTRegValName(section, entry) +
398  ". Expected boolean value.");
399  return false;
400  }
401  return true;
402 }
403 
404 
405 // Checks that an integer value is fine
406 bool NSTValidateInt(const IRegistry & reg,
407  const string & section, const string & entry,
408  vector<string> & warnings)
409 {
410  try {
411  reg.GetInt(section, entry, 0);
412  }
413  catch (...) {
414  warnings.push_back(g_LogPrefix + "unexpected value of " +
415  NSTRegValName(section, entry) +
416  ". Expected integer value.");
417  return false;
418  }
419  return true;
420 }
421 
422 
423 
424 // Checks that a double value is fine
425 bool NSTValidateDouble(const IRegistry & reg,
426  const string & section, const string & entry,
427  vector<string> & warnings)
428 {
429  try {
430  reg.GetDouble(section, entry, 0.0);
431  }
432  catch (...) {
433  warnings.push_back(g_LogPrefix + "unexpected value of " +
434  NSTRegValName(section, entry) +
435  ". Expected floating point value.");
436  return false;
437  }
438  return true;
439 }
440 
441 
442 
443 // Checks that a double value is fine
444 bool NSTValidateString(const IRegistry & reg,
445  const string & section, const string & entry,
446  vector<string> & warnings)
447 {
448  try {
449  reg.GetString(section, entry, "");
450  }
451  catch (...) {
452  warnings.push_back(g_LogPrefix + "unexpected value of " +
453  NSTRegValName(section, entry) +
454  ". Expected string value.");
455  return false;
456  }
457  return true;
458 }
459 
460 
462  CNetStorageServer * server,
463  vector<string> & warnings)
464 {
465  // The requests should be repeated for each configured service
466  // plus no service.
467  // The backend throws exceptions if something is wrong and there is no way
468  // for nicely put warnings. Well, ...
469 
470  CJsonNode configuration = CJsonNode::NewObjectNode();
471 
472  // Start with the no service entry
473  try {
474  CDirectNetStorage storage(reg, kEmptyStr,
475  server->GetCompoundIDPool());
476  configuration.SetByKey(kEmptyStr, storage.ReportConfig());
477  } catch (const CException & ex) {
478  warnings.push_back(std::string("CException while retrieving "
479  "backend configuration when no "
480  "service is provided: ") + ex.what());
481  } catch (const std::exception & ex) {
482  warnings.push_back(std::string("std::exception while retrieving "
483  "backend configuration when no "
484  "service is provided: ") + ex.what());
485  } catch (...) {
486  warnings.push_back("Unknown exception while retrieving backend "
487  "configuration when no service is provided");
488  }
489 
490 
491  // Retrieve a list of services from the configuration file
492  list<string> sections;
493  reg.EnumerateSections(&sections);
494 
495  const string prefix = "service_";
496  for (list<string>::const_iterator k = sections.begin();
497  k != sections.end(); ++k) {
499  continue;
500 
501  string service(k->c_str() + prefix.size());
502  if (service.empty())
503  continue;
504 
505  // Request backend configuration for each service
506  try {
507  CDirectNetStorage storage(reg, service,
508  server->GetCompoundIDPool());
509  configuration.SetByKey(service, storage.ReportConfig());
510  } catch (const CException & ex) {
511  warnings.push_back("CException while retrieving backend "
512  "configuration for service " + service +
513  ": " + ex.what());
514  } catch (const std::exception & ex) {
515  warnings.push_back("std::exception while retrieving backend "
516  "configuration for service " + service +
517  ": " + ex.what());
518  } catch (...) {
519  warnings.push_back("Unknown exception while retrieving "
520  "backend configuration for service " + service);
521  }
522  }
523  return configuration;
524 }
525 
526 TNSTDBValue<CTimeSpan> ReadTimeSpan(const string & reg_value,
527  bool allow_infinity)
528 {
530 
531  if (allow_infinity) {
532  if (NStr::EqualNocase(reg_value, "infinity") || reg_value.empty()) {
533  result.m_IsNull = true;
534  return result;
535  }
536  }
537 
538  result.m_IsNull = false;
539  result.m_Value.AssignFromSmartString(reg_value);
540  return result;
541 }
542 
543 
545 
CJsonNode ReportConfig() const
Definition: netstorage.cpp:346
JSON node abstraction.
void SetByKey(const string &key, CJsonNode::TInstance value)
For a JSON object node, insert a new element or update an existing element.
static CJsonNode NewObjectNode()
Create a new JSON object node.
CCompoundIDPool GetCompoundIDPool(void) const
Definition: nst_server.hpp:89
IRegistry –.
Definition: ncbireg.hpp:73
string
Definition: cgiapp.hpp:687
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:342
virtual bool GetBool(const string &section, const string &name, bool default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get boolean value of specified parameter name.
Definition: ncbireg.cpp:391
virtual void EnumerateSections(list< string > *sections, TFlags flags=fAllLayers) const
Enumerate section names.
Definition: ncbireg.cpp:497
virtual int GetInt(const string &section, const string &name, int default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get integer value of specified parameter name.
Definition: ncbireg.cpp:362
virtual double GetDouble(const string &section, const string &name, double default_value, TFlags flags=0, EErrAction err_action=eThrow) const
Get double value of specified parameter name.
Definition: ncbireg.cpp:420
virtual bool HasEntry(const string &section, const string &name=kEmptyStr, TFlags flags=0) const
Definition: ncbireg.cpp:290
virtual string GetString(const string &section, const string &name, const string &default_value, TFlags flags=0) const
Get the parameter string value.
Definition: ncbireg.cpp:321
#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 int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
static bool EndsWith(const CTempString str, const CTempString end, ECase use_case=eCase)
Check if a string ends with a specified suffix value.
Definition: ncbistr.hpp:5430
static double StringToDouble(const CTempStringEx str, TStringToNumFlags flags=0)
Convert string to double.
Definition: ncbistr.cpp:1387
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate spaces in a string (in-place)
Definition: ncbistr.cpp:3201
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5412
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5353
static enable_if< is_arithmetic< TNumeric >::value||is_convertible< TNumeric, Int8 >::value, string >::type NumericToString(TNumeric value, TNumToStringFlags flags=0, int base=10)
Convert numeric value to string.
Definition: ncbistr.hpp:673
@ fAllowTrailingSpaces
Ignore trailing space characters.
Definition: ncbistr.hpp:297
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
const unsigned short port_high_limit
const unsigned int default_max_threads
const unsigned int default_init_threads
const unsigned short port_low_limit
const unsigned int max_threads_high_limit
const unsigned int max_connections_low_limit
const unsigned int default_max_connections
const unsigned int max_threads_low_limit
const unsigned int init_threads_high_limit
const unsigned int init_threads_low_limit
const unsigned int max_connections_high_limit
const unsigned int default_network_timeout
CJsonNode NSTGetBackendConfiguration(const IRegistry &reg, CNetStorageServer *server, vector< string > &warnings)
Definition: nst_config.cpp:461
static bool NSTValidateDouble(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:425
static string NSTRegValName(const string &section, const string &entry)
Definition: nst_config.cpp:368
static void NSTValidateDatabaseSection(const IRegistry &reg, vector< string > &warnings)
Definition: nst_config.cpp:188
static void NSTValidateProlongValue(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:302
static bool NSTValidateBool(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:388
const string g_LogPrefix
Definition: nst_config.cpp:44
TNSTDBValue< CTimeSpan > ReadTimeSpan(const string &reg_value, bool allow_infinity)
Definition: nst_config.cpp:526
static void NSTValidateServerSection(const IRegistry &reg, vector< string > &warnings, bool throw_port_exception)
Definition: nst_config.cpp:95
static bool NSTValidateString(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:444
static void NSTValidateServices(const IRegistry &reg, vector< string > &warnings)
Definition: nst_config.cpp:267
static void NSTValidateMetadataSection(const IRegistry &reg, vector< string > &warnings)
Definition: nst_config.cpp:242
static string NSTOutOfLimitMessage(const string &section, const string &entry, unsigned int low_limit, unsigned int high_limit)
Definition: nst_config.cpp:375
static bool NSTValidateInt(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:406
void NSTValidateConfigFile(const IRegistry &reg, vector< string > &warnings, bool throw_port_exception)
Definition: nst_config.cpp:83
static void NSTValidateTTLValue(const IRegistry &reg, const string &section, const string &entry, vector< string > &warnings)
Definition: nst_config.cpp:343
const double default_execute_sp_timeout
static const char * prefix[]
Definition: pcregrep.c:405
bool operator()(const string &m)
Definition: nst_config.cpp:259
SCaseInsensitivePredicate(const string &pattern)
Definition: nst_config.cpp:257
else result
Definition: token2.c:20
Modified on Wed Apr 17 13:09:54 2024 by modify_doxy.py rev. 669887