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

Go to the SVN repository for this file.

1 /* $Id: ncbiapp.cpp 100515 2023-08-08 18:50:35Z ivanov $
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: Vsevolod Sandomirskiy, Denis Vakatov
27  *
28  * File Description:
29  * CNcbiApplication -- a generic NCBI application class
30  * CCgiApplication -- a NCBI CGI-application class
31  *
32  */
33 
34 #include <ncbi_pch.hpp>
35 #ifndef HAVE_LOCAL_NCBI_BUILD_VER_H
36 # define HAVE_LOCAL_NCBI_BUILD_VER_H 1
37 #endif
38 #include <common/ncbi_source_ver.h>
39 #include <corelib/ncbiapp.hpp>
40 #undef CNcbiApplication
41 #undef CComponentVersionInfo
42 #undef CVersion
43 
44 #include <corelib/ncbifile.hpp>
45 #include <corelib/ncbi_system.hpp>
46 #include <corelib/ncbi_param.hpp>
47 #include <corelib/syslog.hpp>
48 #include <corelib/error_codes.hpp>
50 #include <corelib/request_ctx.hpp>
51 #include "ncbisys.hpp"
52 
53 #if defined(NCBI_OS_MSWIN)
54 # include <corelib/ncbi_os_mswin.hpp>
55 # include <corelib/ncbidll.hpp>
56 # include <io.h>
57 # include <fcntl.h>
58 #endif
59 
60 #if defined(NCBI_OS_UNIX)
61 # include <unistd.h>
62 #endif
63 
64 
65 #define NCBI_USE_ERRCODE_X Corelib_App
66 
67 
69 
70 
71 /////////////////////////////////////////////////////////////////////////////
72 // Constants
73 //
74 
75 extern const char* s_ArgLogFile;
76 extern const char* s_ArgCfgFile;
77 extern const char* s_ArgVersion;
78 extern const char* s_ArgFullVersion;
79 extern const char* s_ArgFullVersionXml;
80 extern const char* s_ArgFullVersionJson;
81 extern const char* s_ArgDryRun;
82 extern const char* s_ArgDelimiter;
83 
84 
85 /////////////////////////////////////////////////////////////////////////////
86 // Global variables
87 //
88 
89 static bool s_IsApplicationStarted = false;
90 
91 
92 ///////////////////////////////////////////////////////
93 // CNcbiApplication
94 //
95 
97 {
98  if (m_App) {
99  m_AppLock = make_shared<CReadLockGuard>(m_App->GetInstanceLock());
100  }
101 }
102 
103 
105 {
106 }
107 
108 
109 DEFINE_STATIC_MUTEX(s_InstanceMutex);
110 
112 {
113  return s_InstanceMutex;
114 }
115 
116 
118 
120 {
121  return s_InstanceRWLock.Get();
122 }
123 
124 
126 
128 {
129  return m_Instance;
130 }
131 
132 
134 {
136 }
137 
138 
140  : m_ConfigLoaded(false),
141  m_LogFile(0),
142  m_LogOptions(0)
143 {
145  // Initialize UID and start timer
147  GetDiagContext().InitMessages(size_t(-1));
149 
150  // Verify CPU compatibility
151  // First check. Print critical error only. See second check in x_TryInit() below.
152  {{
153  string err_message;
154  if (!VerifyCpuCompatibility(&err_message)) {
155  ERR_POST_X(22, Critical << err_message);
156  }
157  }}
158 
159  m_DisableArgDesc = 0;
160  m_HideArgs = 0;
161  m_StdioFlags = 0;
162  m_CinBuffer = 0;
164 
165  {
167  // Register the app. instance
168  if (m_Instance) {
170  "Second instance of CNcbiApplication is prohibited");
171  }
172  m_Instance = this;
173  }
174 
175  // Create empty version info
176  m_Version.Reset(new CVersionAPI(build_info));
177 
178  // Set version equal to package one if still empty (might have TeamCity build number)
179  if (m_Version->GetVersionInfo().IsAny()) {
180  auto package_info = m_Version->GetPackageVersion();
181  m_Version->SetVersionInfo(new CVersionInfo(package_info));
182  }
183 
184 #if NCBI_SC_VERSION_PROXY != 0
185  m_Version->AddComponentVersion("NCBI C++ Toolkit",
188 #endif
189  // Create empty application arguments & name
190  m_Arguments.reset(new CNcbiArguments(0,0));
191 
192  // Create empty application environment
193  m_Environ.reset(new CNcbiEnvironment);
194 
195  // Create an empty registry
197 
198  m_DryRun = false;
199 }
200 
202 {
204 }
205 
206 
208 {
209  CThread::sm_IsExiting = true;
210 
211  // Execute exit actions before waiting for all threads to stop.
212  // NOTE: The exit actions may already be executed by higher-level
213  // destructors. This is a final fail-safe place for this.
215 
216 #if defined(NCBI_THREADS)
218 #endif
219 
220  {
222  m_Instance = 0;
223  }
224  FlushDiag(0, true);
225  if (m_CinBuffer) {
226  delete [] m_CinBuffer;
227  }
228 
229 #if defined(NCBI_COMPILER_WORKSHOP)
230  // At least under these conditions:
231  // 1) WorkShop 5.5 on Solaris 10/SPARC, Release64MT, and
232  // 2) when IOS_BASE::sync_with_stdio(false) is called, and
233  // 3) the contents of 'cout' is not flushed
234  // some applications crash on exit() while apparently trying to
235  // flush 'cout' and getting confused by its own guts, with error:
236  // "*** libc thread failure: _thread_setschedparam_main() fails"
237  //
238  // This forced pre-flush trick seems to fix the problem.
239  NcbiCout.flush();
240 #endif
241 }
242 
243 
245 {
246  return dynamic_cast<CNcbiApplication*>(CNcbiApplicationAPI::Instance());
247 }
248 
249 
251  : CNcbiApplicationAPI(build_info)
252 {
253 }
254 
255 
257 {
258  // This earlier execution of the actions allows a safe use of
259  // CNcbiApplication::Instance() from the exit action functions. Instance()
260  // can return NULL pointer if called as part of CNcbiApplicationAPI dtor
261  // when the CNcbiApplication dtor already finished.
263 }
264 
265 
267 {
268  return;
269 }
270 
271 
273 {
274  ERR_POST_X(1, Info << "DryRun: default implementation does nothing");
275  return 0;
276 }
277 
278 
280 {
281  return;
282 }
283 
284 
286 {
287  if ( !m_Args.get() ) {
288  NCBI_THROW(CAppException, eUnsetArgs,
289  "Command-line argument description is not found");
290  }
291  return *m_Args;
292 }
293 
294 
296 {
297  if ( os ) {
298  SetDiagStream(os, true, 0, 0, "STREAM");
299  }
302  return 0;
303 }
304 
305 
306 #if defined(NCBI_OS_DARWIN)
307 static void s_MacArgMunging(CNcbiApplicationAPI& app,
308  int* argcPtr,
309  const char* const** argvPtr,
310  const string& exepath)
311 {
312 
313  // Sometimes on Mac there will be an argument -psn which
314  // will be followed by the Process Serial Number, e.g. -psn_0_13107201
315  // this is in situations where the application could have no other
316  // arguments like when it is double clicked.
317  // This will mess up argument processing later, so get rid of it.
318  static const char* s_ArgMacPsn = "-psn_";
319 
320  if (*argcPtr == 2 &&
321  NStr::strncmp((*argvPtr)[1], s_ArgMacPsn, strlen(s_ArgMacPsn)) == 0) {
322  --*argcPtr;
323  }
324 
325  if (*argcPtr > 1)
326  return;
327 
328  // Have no arguments from the operating system -- so use the '.args' file
329 
330  // Open the args file.
331  string exedir;
332  CDir::SplitPath(exepath, &exedir);
333  string args_fname = exedir + app.GetProgramDisplayName() + ".args";
334  CNcbiIfstream in(args_fname.c_str());
335 
336  if ( !in.good() ) {
337  ERR_POST_X(2, Info << "Mac arguments file not found: " << args_fname);
338  return;
339  }
340 
341  vector<string> v;
342 
343  // remember or fake the executable name.
344  if (*argcPtr > 0) {
345  v.push_back((*argvPtr)[0]); // preserve the original argv[0].
346  } else {
347  v.push_back(exepath);
348  }
349 
350  // grab the rest of the arguments from the file.
351  // arguments are separated by whitespace. Can be on
352  // more than one line.
353  string arg;
354  while (in >> arg) {
355  v.push_back(arg);
356  }
357 
358  // stash them away in the standard argc and argv places.
359  if (v.size() > kMax_Int) {
360  ERR_POST_X(24,
361  Critical << "Overly high argument count " << v.size()
362  << "; truncating to " << kMax_Int);
363  v.resize(kMax_Int);
364  }
365  *argcPtr = static_cast<int>(v.size());
366 
367  char** argv = new char*[v.size()];
368  int c = 0;
369  ITERATE(vector<string>, vp, v) {
370  argv[c++] = strdup(vp->c_str());
371  }
372  *argvPtr = argv;
373 }
374 #endif /* NCBI_OS_DARWIN */
375 
376 
377 NCBI_PARAM_DECL(bool, Debug, Catch_Unhandled_Exceptions);
378 NCBI_PARAM_DEF_EX(bool, Debug, Catch_Unhandled_Exceptions, true,
379  eParam_NoThread, DEBUG_CATCH_UNHANDLED_EXCEPTIONS);
380 typedef NCBI_PARAM_TYPE(Debug, Catch_Unhandled_Exceptions) TParamCatchExceptions;
381 
383 {
384  return TParamCatchExceptions::GetDefault();
385 }
386 
387 
388 NCBI_PARAM_DECL(bool, NCBI, TerminateOnCpuIncompatibility);
389 NCBI_PARAM_DEF_EX(bool, NCBI, TerminateOnCpuIncompatibility, false,
390  eParam_NoThread, NCBI_CONFIG__TERMINATE_ON_CPU_INCOMPATIBILITY);
391 
392 
393 void CNcbiApplicationAPI::x_TryInit(EAppDiagStream diag, const char* conf)
394 {
395  // Load registry from the config file
396  if ( conf ) {
397  string x_conf(conf);
398  LoadConfig(*m_Config, &x_conf);
399  } else {
401  }
402  m_ConfigLoaded = true;
403 
406 
407  // Setup the standard features from the config file.
408  // Don't call till after LoadConfig()
409  // NOTE: this will override environment variables,
410  // except DIAG_POST_LEVEL which is Set*Fixed*.
412 
413  // Application start
414  AppStart();
415 
416  // Verify CPU compatibility
417  // Second check. Print error message and allow to terminate program depends on configuration parameters.
418  // Also, see first check in CNcbiApplicationAPI() constructor.
419  {{
420  string err_message;
421  if (!VerifyCpuCompatibility(&err_message)) {
422  bool fatal = NCBI_PARAM_TYPE(NCBI, TerminateOnCpuIncompatibility)::GetDefault();
423  ERR_POST_X(22, (fatal ? Fatal : Critical) << err_message);
424  }
425  }}
426 
427  // Do init
428 #if (defined(NCBI_COMPILER_ICC) && NCBI_COMPILER_VERSION < 900)
429  // ICC 8.0 have an optimization bug in exceptions handling,
430  // so workaround it here
431  try {
432  Init();
433  }
434  catch (const CArgHelpException&) {
435  throw;
436  }
437 #else
438  Init();
439 #endif
440 
441  // If the app still has no arg description - provide default one
442  if (!m_DisableArgDesc && !m_ArgDesc.get()) {
443  unique_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
444  arg_desc->SetUsageContext
445  (GetArguments().GetProgramBasename(),
446  "This program has no mandatory arguments");
447  SetupArgDescriptions(arg_desc.release());
448  }
449 }
450 
451 // Macro to define a logging parameter
452 #define NCBI_LOG_PARAM(type,Name,NAME) \
453  NCBI_PARAM_DECL (type, Log, LogApp ## Name); \
454  NCBI_PARAM_DEF_EX(type, Log, LogApp ## Name, false, eParam_NoThread, DIAG_LOG_APP_ ## NAME); \
455  typedef NCBI_PARAM_TYPE(Log, LogApp ## Name) TLogApp ## Name;
456 
457 NCBI_LOG_PARAM(bool, Environment, ENVIRONMENT)
458 NCBI_LOG_PARAM(bool, EnvironmentOnStop, ENVIRONMENT_ON_STOP)
459 NCBI_LOG_PARAM(bool, Registry, REGISTRY)
460 NCBI_LOG_PARAM(bool, RegistryOnStop, REGISTRY_ON_STOP)
461 NCBI_LOG_PARAM(bool, Arguments, ARGUMENTS)
462 NCBI_LOG_PARAM(bool, Path, PATH)
463 NCBI_LOG_PARAM(bool, RunContext, RUN_CONTEXT)
464 NCBI_LOG_PARAM(bool, ResUsageOnStop, RESUSAGE_ON_STOP)
465 
466 
468  eStartEvent = 0x01, ///< right before AppMain()
469  eStopEvent = 0x02, ///< right after AppMain()
470  eOtherEvent = 0x03 ///< any case is fine
471 };
472 
473 
474 /// Flags to switch what to log
476  fLogAppEnvironment = 0x01, ///< log app environment on app start
477  fLogAppEnvironmentStop = 0x02, ///< log app environment on app stop
478  fLogAppRegistry = 0x04, ///< log app registry on app start
479  fLogAppRegistryStop = 0x08, ///< log app registry on app stop
480  fLogAppArguments = 0x10, ///< log app arguments
481  fLogAppPath = 0x20, ///< log app executable path
482  fLogAppResUsageStop = 0x40, ///< log resource usage on app stop
483 };
484 
485 
487 {
488  // Log all
489  if ( TLogAppRunContext::GetDefault() ) {
490  m_LogOptions = 0x7f; // all on
491  return;
492  }
493 
494  // Log registry
495  m_LogOptions |= TLogAppRegistry::GetDefault() ? fLogAppRegistry : 0;
496  m_LogOptions |= TLogAppRegistryOnStop::GetDefault() ? fLogAppRegistryStop : 0;
497 
498  // Log environment
499  m_LogOptions |= TLogAppEnvironment::GetDefault() ? fLogAppEnvironment : 0;
500  m_LogOptions |= TLogAppEnvironmentOnStop::GetDefault() ? fLogAppEnvironmentStop : 0;
501 
502  // Log arguments
503  m_LogOptions |= TLogAppArguments::GetDefault() ? fLogAppArguments : 0;
504 
505  // Log path
506  m_LogOptions |= TLogAppPath::GetDefault() ? fLogAppPath : 0;
507 
508  // Log resources usage
509  m_LogOptions |= TLogAppResUsageOnStop::GetDefault() ? fLogAppResUsageStop : 0;
510 }
511 
512 
513 void s_RoundResUsageSize(Uint8 value_in_bytes, string& suffix, Uint8& value)
514 {
515  const Uint8 limit = 1000;
516 
517  // KB by default
518  suffix = "_KB";
519  value = value_in_bytes / 1024;
520 
521  // Round to MB if value is too big
522  if (value / 1024 > limit) {
523  suffix = "_MB";
524  value /= 1024;
525  }
526 }
527 
528 #define RES_SIZE_USAGE(name, value_in_bytes) \
529  { \
530  string suffix; \
531  Uint8 value; \
532  s_RoundResUsageSize(value_in_bytes, suffix, value); \
533  extra.Print(name + suffix, value); \
534  }
535 
536 #define RES_TIME_USAGE(name, value) \
537  if (value >= 0 ) \
538  extra.Print(name, (Uint8)value)
539 
540 
541 void CNcbiApplicationAPI::x_LogOptions(int /*ELogOptionsEvent*/ event)
542 {
543  const bool start = (event & eStartEvent) != 0;
544  const bool stop = (event & eStopEvent) != 0;
545 
546  // Print environment values
547  if ( (m_LogOptions & fLogAppEnvironment && start) ||
548  (m_LogOptions & fLogAppEnvironmentStop && stop) ) {
550  extra.Print("LogAppEnvironment", "true");
551  list<string> env_keys;
553  env.Enumerate(env_keys);
554  ITERATE(list<string>, it, env_keys) {
555  const string& val = env.Get(*it);
556  extra.Print(*it, val);
557  }
558  }
559 
560  // Print registry values
561  if ( (m_LogOptions & fLogAppRegistry && start) ||
562  (m_LogOptions & fLogAppRegistryStop && stop) ) {
564  extra.Print("LogAppRegistry", "true");
565  list<string> reg_sections;
566  const CNcbiRegistry& reg = GetConfig();
567  reg.EnumerateSections(&reg_sections);
568  ITERATE(list<string>, it, reg_sections) {
569  string section, name;
570  list<string> section_entries;
571  reg.EnumerateEntries(*it, &section_entries);
572  ITERATE(list<string>, it_entry, section_entries) {
573  const string& val = reg.Get(*it, *it_entry);
574  string path = "[" + *it + "]" + *it_entry;
575  extra.Print(path, val);
576  }
577  }
578  }
579 
580  // Print arguments
581  if ( m_LogOptions & fLogAppArguments && start) {
583  extra.Print("LogAppArguments", "true");
584  string args_str;
585  extra.Print("Arguments", GetArgs().Print(args_str));
586  }
587 
588  // Print app path
589  if ( m_LogOptions & fLogAppPath && start) {
591  extra.Print("LogAppPath", "true");
592  extra.Print("Path", GetProgramExecutablePath());
593  }
594 
595  // Print resource usage
596  if ( m_LogOptions & fLogAppResUsageStop && stop) {
598  extra.Print("LogAppResUsage", "true");
599  // Memory usage
600  CProcess::SMemoryUsage mem_usage;
601  if ( CCurrentProcess::GetMemoryUsage(mem_usage) ) {
602  RES_SIZE_USAGE("mem_total", mem_usage.total );
603  RES_SIZE_USAGE("mem_total_peak", mem_usage.total_peak );
604  RES_SIZE_USAGE("rss_mem", mem_usage.resident );
605  RES_SIZE_USAGE("rss_peak_mem", mem_usage.resident_peak);
606  RES_SIZE_USAGE("shared.mem", mem_usage.shared );
607  RES_SIZE_USAGE("data.mem", mem_usage.data );
608  RES_SIZE_USAGE("stack.mem", mem_usage.stack );
609  }
610  // CPU time usage
611  double real, user, sys;
612  if ( CCurrentProcess::GetTimes(&real, &user, &sys, CProcess::eProcess) ) {
613  RES_TIME_USAGE("real.proc.cpu", real);
614  RES_TIME_USAGE("user.proc.cpu", user);
615  RES_TIME_USAGE("sys.proc.cpu", sys);
616  }
617  if ( CCurrentProcess::GetTimes(&real, &user, &sys, CProcess::eChildren) ) {
618  RES_TIME_USAGE("user.child.cpu", user);
619  RES_TIME_USAGE("sys.child.cpu", sys);
620  }
621  if ( CCurrentProcess::GetTimes(&real, &user, &sys, CProcess::eThread) ) {
622  RES_TIME_USAGE("user.thread.cpu", user);
623  RES_TIME_USAGE("sys.thread.cpu", sys);
624  }
625  }
626 }
627 
628 
630  const char* conf,
631  int* exit_code,
632  bool* got_exception)
633 {
634  // Initialize the application
635  try {
636  if ( s_HandleExceptions() ) {
637  try {
638  x_TryInit(diag, conf);
639  }
640  catch (const CArgHelpException&) {
641  // This exceptions will be caught later regardless of the
642  // handle-exceptions flag.
643  throw;
644  }
645  catch (const CArgException&) {
646 // NCBI_RETHROW_SAME(e, "Application's initialization failed");
647  throw;
648  }
649  catch (const CException& e) {
651  "Application's initialization failed", e);
652  *got_exception = true;
653  *exit_code = 2;
654  }
655  catch (const exception& e) {
656  ERR_POST_X(6, "Application's initialization failed: " << e.what());
657  *got_exception = true;
658  *exit_code = 2;
659  }
660  }
661  else {
662  x_TryInit(diag, conf);
663  }
664  }
665  catch (const CArgHelpException& e) {
667  // Print USAGE
669  m_ArgDesc->PrintUsageXml(cout);
670  } else {
672  string str;
673  m_ArgDesc->ShowAllArguments(code == CArgHelpException::eHelpShowAll)->PrintUsage
675  cout << str;
676  }
677  *exit_code = e.GetErrCode() == CArgHelpException::eHelpErr ? 2 : 0;
678  }
681  // Run application
682  if (*exit_code == 1) {
684  if ( s_HandleExceptions() ) {
685  try {
686  *exit_code = m_DryRun ? DryRun() : Run();
687  }
688  catch (CArgException& e) {
689  NCBI_RETHROW_SAME(e, "Application's execution failed");
690  }
691  catch (const CException& e) {
692  CRef<CRequestContext> cur_ctx(&GetDiagContext().GetRequestContext());
693  if (cur_ctx != &e.GetRequestContext()) {
696  "CException thrown", e);
698  }
700  "Application's execution failed", e);
701  *got_exception = true;
702  *exit_code = 3;
703  }
704  catch (const exception& e) {
705  ERR_POST_X(7, "Application's execution failed: " << e.what());
706  *got_exception = true;
707  *exit_code = 3;
708  }
709  }
710  else {
711  *exit_code = m_DryRun ? DryRun() : Run();
712  }
713  }
716 
717  // Close application
718  if ( s_HandleExceptions() ) {
719  try {
720  Exit();
721  }
722  catch (CArgException& e) {
723  NCBI_RETHROW_SAME(e, "Application's cleanup failed");
724  }
725  catch (const CException& e) {
726  NCBI_REPORT_EXCEPTION_X(17, "Application's cleanup failed", e);
727  *got_exception = true;
728  }
729  catch (const exception& e) {
730  ERR_POST_X(8, "Application's cleanup failed: "<< e.what());
731  *got_exception = true;
732  }
733  }
734  else {
735  Exit();
736  }
737 }
738 
739 #if defined(NCBI_OS_MSWIN) && defined(_UNICODE)
740 static
741 void s_Create_ArgsOrEnvW(
742  vector<string>& storage,
743  AutoArray<const char*>& pointers,
744  const TXChar* const* begin)
745 {
746  const TXChar* const* arg = begin;
747  size_t count = 0;
748  while( *(arg++) )
749  ++count;
750 
751  const char** args = new const char*[count+1];
752  if ( !args ) {
753  NCBI_THROW(CCoreException, eNullPtr, kEmptyStr);
754  }
755  pointers = args;
756 
757  arg = begin;
758  size_t i=0;
759  for (i=0; i<count; ++i) {
760  storage.push_back( _T_STDSTRING( *(arg++) ) );
761  }
762 
763  for (i=0; i < storage.size(); ++i) {
764  args[i] = storage[i].c_str();
765  }
766  args[i] = NULL;
767 }
768 
770 (int argc,
771  const TXChar* const* argv,
772  const TXChar* const* envp,
773  EAppDiagStream diag,
774  const TXChar* conf,
775  const TXString& name)
776 {
777  vector< string> argv_storage;
778  AutoArray<const char*> argv_pointers;
779  if (argv) {
780  s_Create_ArgsOrEnvW(argv_storage, argv_pointers, argv);
781  }
782 
783  vector< string> envp_storage;
784  AutoArray<const char*> envp_pointers;
785  if (envp) {
786  s_Create_ArgsOrEnvW(envp_storage, envp_pointers, envp);
787  }
788 
789  return AppMain(argc,
790  argv == NULL ? NULL : argv_pointers.get(),
791  envp == NULL ? NULL : envp_pointers.get(),
792  diag,
793  conf == NULL ? NULL : (conf == NcbiEmptyXCStr ? NcbiEmptyCStr : _T_CSTRING(conf)),
794  name == NcbiEmptyXString ? NcbiEmptyString : _T_STDSTRING(name));
795 }
796 #endif
797 
799 (int argc,
800  const char* const* argv,
801  const char* const* envp,
802  EAppDiagStream diag,
803  const char* conf,
804  const string& name)
805 {
806  if (conf) {
807  m_DefaultConfig = conf;
808  }
809  x_SetupStdio();
810 
811  // Check if logfile is set in the args.
812  m_LogFile = 0;
813  if (!m_DisableArgDesc && argc > 1 && argv && diag != eDS_User) {
814  for (int i = 1; i < argc; i++) {
815  if ( !argv[i] ) {
816  continue;
817  }
818  if ( NStr::strcmp(argv[i], s_ArgDelimiter) == 0 ) {
819  break;
820  }
821  if ( NStr::strcmp(argv[i], s_ArgLogFile) == 0 ) {
822  if (!argv[++i]) {
823  continue;
824  }
825  m_LogFile = argv[i];
826  } else if (NStr::StartsWith(argv[i], s_ArgLogFile)) {
827  const char *a = argv[i] + strlen(s_ArgLogFile);
828  if (*a == '=') {
829  m_LogFile = ++a;
830  }
831  }
832  }
833  }
834 
835  // Setup logging as soon as possible.
836  // Setup for diagnostics
837  try {
839  } catch (const CException& e) {
840  NCBI_RETHROW(e, CAppException, eSetupDiag,
841  "Application diagnostic stream's setup failed");
842  } catch (const exception& e) {
843  NCBI_THROW(CAppException, eSetupDiag,
844  "Application diagnostic stream's setup failed: " +
845  string(e.what()));
846  }
847 
848  // Get program executable's name & path.
849  string exepath = FindProgramExecutablePath(argc, argv, &m_RealExePath);
850  m_ExePath = exepath;
851 
852  // Get program display name
853  string appname = name;
854  if (appname.empty()) {
855  if (!exepath.empty()) {
856  CDirEntry::SplitPath(exepath, NULL, &appname);
857  } else if (argc > 0 && argv[0] != NULL && *argv[0] != '\0') {
858  CDirEntry::SplitPath(argv[0], NULL, &appname);
859  } else {
860  appname = "ncbi";
861  }
862  }
863  if ( m_ProgramDisplayName.empty() ) {
864  SetProgramDisplayName(appname);
865  }
866 
867  // Make sure we have something as our 'real' executable's name.
868  // though if it does not contain a full path it won't be much use.
869  if ( exepath.empty() ) {
871  << "Warning: Could not determine this application's "
872  "file name and location. Using \""
873  << appname << "\" instead.\n"
874  "Please fix FindProgramExecutablePath() on this platform.");
875  exepath = appname;
876  }
877 
878 #if defined(NCBI_OS_DARWIN)
879  // We do not know standard way of passing arguments to C++ program on Mac,
880  // so we will read arguments from special file having extension ".args"
881  // and name equal to display name of program (name argument of AppMain).
882  s_MacArgMunging(*this, &argc, &argv, exepath);
883 #endif
884 
885  CDiagContext& diag_context = GetDiagContext();
886 
887  // Preparse command line
888  if (PreparseArgs(argc, argv) == ePreparse_Exit) {
889  diag_context.DiscardMessages();
890  return 0;
891  }
892 
893  // Check command line for presence special arguments
894  // "-logfile", "-conffile", "-version"
895  const char* conf_arg = nullptr;
896  if (!m_DisableArgDesc && argc > 1 && argv) {
897  const char** v = new const char*[argc];
898  v[0] = argv[0];
899  int real_arg_index = 1;
900  bool skip = false;
901  for (int i = 1; i < argc; i++) {
902  if ( !argv[i] ) {
903  continue;
904  }
905  if ( NStr::strcmp(argv[i], s_ArgDelimiter) == 0 ) {
906  skip = true;
907  }
908  if (skip) {
909  v[real_arg_index++] = argv[i];
910  continue;
911  }
912  // Log file - ignore if diag is eDS_User - the user wants to
913  // take care about logging.
914  if ( diag != eDS_User &&
915  NStr::strcmp(argv[i], s_ArgLogFile) == 0 ) {
916  if (!argv[++i]) {
917  continue;
918  }
919  v[real_arg_index++] = argv[i - 1];
920  v[real_arg_index++] = argv[i];
921  // Configuration file
922  } else if ( NStr::strcmp(argv[i], s_ArgCfgFile) == 0 ) {
923  if (!argv[++i]) {
924  continue;
925  }
926  v[real_arg_index++] = argv[i - 1];
927  v[real_arg_index++] = argv[i];
928  conf_arg = argv[i];
929 
930  }
931  else if (NStr::StartsWith(argv[i], s_ArgCfgFile)) {
932  v[real_arg_index++] = argv[i];
933  const char* a = argv[i] + strlen(s_ArgCfgFile);
934  if (*a == '=') {
935  conf_arg = ++a;
936  }
937 
938  // Version
939  } else if ( NStr::strcmp(argv[i], s_ArgVersion) == 0 ) {
940  delete[] v;
941  // Print VERSION
943  diag_context.DiscardMessages();
944  return 0;
945 
946  // Full version
947  } else if ( NStr::strcmp(argv[i], s_ArgFullVersion) == 0 ) {
948  delete[] v;
949  // Print full VERSION
950  cout << GetFullVersion().Print( appname );
951  diag_context.DiscardMessages();
952  return 0;
953  } else if ( NStr::strcmp(argv[i], s_ArgFullVersionXml) == 0 ) {
954  delete[] v;
955  // Print full VERSION in XML format
956  cout << GetFullVersion().PrintXml( appname );
957  diag_context.DiscardMessages();
958  return 0;
959  } else if ( NStr::strcmp(argv[i], s_ArgFullVersionJson) == 0 ) {
960  delete[] v;
961  // Print full VERSION in JSON format
962  cout << GetFullVersion().PrintJson( appname );
963  diag_context.DiscardMessages();
964  return 0;
965 
966  // Dry run
967  } else if ( NStr::strcmp(argv[i], s_ArgDryRun) == 0 ) {
968  m_DryRun = true;
969 
970  // Save real argument
971  } else {
972  v[real_arg_index++] = argv[i];
973  }
974  }
975  if (real_arg_index == argc ) {
976  delete[] v;
977  } else {
978  argc = real_arg_index;
979  argv = v;
980  }
981  if (conf_arg) {
982  if (CFile(conf_arg).Exists()) {
983  conf = conf_arg;
984  }
985  else {
986  ERR_POST_X(23, Critical << "Registry file \"" << conf_arg << "\" not found, aborting.");
987  Abort();
988  }
989  }
990  }
991 
992  // Reset command-line args and application name
993  m_Arguments->Reset(argc, argv, exepath, m_RealExePath);
994 
995  // Reset application environment
996  m_Environ->Reset(envp);
997 
998  // Setup some debugging features from environment variables.
999  if ( !m_Environ->Get(DIAG_TRACE).empty() ) {
1001  }
1002  string post_level = m_Environ->Get(DIAG_POST_LEVEL);
1003  if ( !post_level.empty() ) {
1004  EDiagSev sev;
1005  if (CNcbiDiag::StrToSeverityLevel(post_level.c_str(), sev)) {
1006  SetDiagFixedPostLevel(sev);
1007  }
1008  }
1009  if ( !m_Environ->Get(ABORT_ON_THROW).empty() ) {
1010  SetThrowTraceAbort(true);
1011  }
1012 
1013  // Clear registry content
1014  m_Config->Clear();
1015 
1016  // Call: Init() + Run() + Exit()
1017  int exit_code = 1;
1018  bool got_exception = false;
1019  s_IsApplicationStarted = true;
1020 
1021  try {
1022  if ( s_HandleExceptions() ) {
1023  try {
1024  x_TryMain(diag, conf, &exit_code, &got_exception);
1025  }
1026  catch (const CArgException&) {
1027  // This exceptions will be caught later regardless of the
1028  // handle-exceptions flag.
1029  throw;
1030  }
1031 #if defined(NCBI_COMPILER_MSVC) && defined(_DEBUG)
1032  // Microsoft promotes many common application errors to exceptions.
1033  // This includes occurrences such as dereference of a NULL pointer and
1034  // walking off of a dangling pointer. The catch-all is lifted only in
1035  // debug mode to permit easy inspection of such error conditions, while
1036  // maintaining safety of production, release-mode applications.
1037  catch (...) {
1038  ERR_POST_X(10, Warning <<
1039  "Application has thrown an exception of unknown type");
1040  throw;
1041  }
1042 #endif
1043  }
1044  else {
1045 #ifdef NCBI_OS_MSWIN
1046  if ( !IsDebuggerPresent() ) {
1048  }
1049 #endif
1050  x_TryMain(diag, conf, &exit_code, &got_exception);
1051  }
1052  }
1053  catch (const CArgException& e) {
1054  // Print USAGE and the exception error message
1055  if ( e.GetErrCode() != CArgException::eNoValue && m_ArgDesc.get() ) {
1056  x_AddDefaultArgs();
1057  string str;
1058  if ( !m_ArgDesc->IsSetMiscFlag(CArgDescriptions::fNoUsage) ) {
1059  m_ArgDesc->PrintUsage(str);
1060  cerr << str;
1061  }
1062  if ( !m_ArgDesc->IsSetMiscFlag(CArgDescriptions::fDupErrToCerr) ) {
1063  CStreamDiagHandler* errh =
1064  dynamic_cast<CStreamDiagHandler*>(GetDiagHandler());
1065  if (!errh || errh->GetStream() != &cerr) {
1066  cerr << "Error in command-line arguments. "
1067  "See error logs for more details." << endl;
1068  }
1069  }
1070  else {
1071  cerr << "Error in command-line arguments." << endl;
1072  cerr << e.what() << endl;
1073  }
1074  cerr << string(72, '=') << endl << endl;
1075  }
1077  NCBI_REPORT_EXCEPTION_X(18, "", e);
1078  got_exception = true;
1079  exit_code = 1;
1080  }
1081 
1082  if (!diag_context.IsSetExitCode()) {
1083  diag_context.SetExitCode(exit_code);
1084  }
1085 
1086  if (m_ExitCodeCond == eAllExits
1087  || (got_exception && m_ExitCodeCond == eExceptionalExits)) {
1088  _TRACE("Overriding exit code from " << exit_code
1089  << " to " << m_ExitCode);
1090  exit_code = m_ExitCode;
1091  }
1092 
1093  // Application stop
1094  AppStop(exit_code);
1095 
1096  if ((m_AppFlags & fSkipSafeStaticDestroy) == 0) {
1097  // Destroy short-lived statics
1099  }
1100 
1101  // Exit
1102  return exit_code;
1103 }
1104 
1105 
1106 void CNcbiApplicationAPI::SetEnvironment(const string& name, const string& value)
1107 {
1108  SetEnvironment().Set(name, value);
1109 }
1110 
1111 #if 0
1113 {
1115 }
1116 
1117 void CNcbiApplicationAPI::SetVersion(int major, int minor)
1118 {
1120 }
1121 
1122 void CNcbiApplicationAPI::SetVersion(int major, int minor, int patch)
1123 {
1124  m_Version->SetVersionInfo(major, minor, patch,
1126 }
1127 #else
1129 {
1131 }
1132 #endif
1133 
1134 
1136 {
1137  if ( s_IsApplicationStarted ) {
1138  ERR_POST_X(19, "SetVersion() should be used from constructor of " \
1139  "CNcbiApplication derived class, see description");
1140  }
1142 }
1143 
1145  const SBuildInfo& build_info)
1146 {
1147  if ( s_IsApplicationStarted ) {
1148  ERR_POST_X(19, "SetVersion() should be used from constructor of " \
1149  "CNcbiApplication derived class, see description");
1150  }
1151  m_Version->SetVersionInfo(new CVersionInfo(version), build_info);
1152 }
1153 
1155 {
1156  if ( s_IsApplicationStarted ) {
1157  ERR_POST_X(19, "SetFullVersion() should be used from constructor of "\
1158  "CNcbiApplication derived class, see description");
1159  }
1160  m_Version.Reset( version );
1161 }
1162 
1163 
1165 {
1166  return m_Version->GetVersionInfo();
1167 }
1168 
1170 {
1171  return *m_Version;
1172 }
1173 
1174 
1176 {
1177  m_ArgDesc.reset(arg_desc);
1178 
1179  if ( arg_desc ) {
1180  if ( !m_DisableArgDesc ) {
1181  for(CArgDescriptions* desc : m_ArgDesc->GetAllDescriptions()) {
1182  desc->AddDefaultFileArguments(m_DefaultConfig);
1183  }
1184  }
1185  m_Args.reset(arg_desc->CreateArgs(GetArguments()));
1186  } else {
1187  m_Args.reset();
1188  }
1189 }
1190 
1191 
1193 {
1195  return true;
1196 }
1197 
1198 
1200 {
1202  return true;
1203 }
1204 
1205 
1207  const string* conf,
1208  CNcbiRegistry::TFlags reg_flags)
1209 {
1210  string basename (m_Arguments->GetProgramBasename(eIgnoreLinks));
1211  string basename2(m_Arguments->GetProgramBasename(eFollowLinks));
1212  CMetaRegistry::SEntry entry;
1213 
1214  if ( !conf ) {
1215  if (reg.IncludeNcbircIfAllowed(reg_flags)) {
1217  ("ncbi", CMetaRegistry::eName_RcOrIni);
1218  }
1219  m_ConfigLoaded = true;
1220  return false;
1221  } else if (conf->empty()) {
1223  reg_flags, &reg);
1224  if ( !entry.registry && basename2 != basename ) {
1225  entry = CMetaRegistry::Load(basename2, CMetaRegistry::eName_Ini, 0,
1226  reg_flags, &reg);
1227  }
1229  } else {
1231  reg_flags, &reg);
1232  }
1233  if ( !entry.registry ) {
1234  // failed; complain as appropriate
1235  string dir;
1236  CDirEntry::SplitPath(*conf, &dir, 0, 0);
1237  if (dir.empty()) {
1238  ERR_POST_X(11, Info <<
1239  "Registry file of application \"" << basename
1240  << "\" is not found");
1241  } else {
1242  NCBI_THROW(CAppException, eNoRegistry,
1243  "Registry file \"" + *conf + "\" cannot be opened");
1244  }
1245  // still consider pulling in defaults from .ncbirc
1246  if (reg.IncludeNcbircIfAllowed(reg_flags)) {
1248  ("ncbi", CMetaRegistry::eName_RcOrIni);
1249  }
1250  m_ConfigLoaded = true;
1251  return false;
1252  } else if (entry.registry != static_cast<IRWRegistry*>(&reg)) {
1253  // should be impossible with new CMetaRegistry interface...
1254  if (&reg == m_Config && reg.Empty()) {
1255  m_Config.Reset(dynamic_cast<CNcbiRegistry*>
1256  (entry.registry.GetPointer()));
1257  } else {
1258  // copy into reg
1260  entry.registry->Write(str);
1261  str.seekg(0);
1262  reg.Read(str);
1263  }
1264  }
1265  m_ConfigPath = entry.actual_name;
1266  m_ConfigLoaded = true;
1267  return true;
1268 }
1269 
1270 
1272  const string* conf)
1273 {
1274  return LoadConfig(reg, conf, IRegistry::fWithNcbirc);
1275 }
1276 
1277 
1280  const char* const* /*argv*/)
1281 {
1282  return ePreparse_Continue;
1283 }
1284 
1285 
1287 {
1288  m_DisableArgDesc = disable;
1289 }
1290 
1291 
1293 {
1294  m_HideArgs = hide_mask;
1295 }
1296 
1297 
1299 {
1300  // do not call this function more than once
1301  // and from places other than App constructor
1302  _ASSERT(m_StdioFlags == 0);
1303  m_StdioFlags = stdio_flags;
1304 }
1305 
1306 
1308 {
1309  if ((m_StdioFlags & fNoSyncWithStdio) != 0) {
1310  IOS_BASE::sync_with_stdio(false);
1311  }
1312 
1314 #ifdef NCBI_OS_UNIX
1315  && !isatty(0)
1316 #endif
1317  ) {
1318 #if defined(NCBI_COMPILER_GCC) && defined(NCBI_OS_SOLARIS)
1319  _ASSERT(!m_CinBuffer);
1320  // Ugly workaround for ugly interaction between g++ and Solaris C RTL
1321  const size_t kCinBufSize = 5120;
1322  m_CinBuffer = new char[kCinBufSize];
1323  cin.rdbuf()->pubsetbuf(m_CinBuffer, kCinBufSize);
1324 #endif
1325  }
1326 #ifdef NCBI_OS_MSWIN
1327  if ((m_StdioFlags & fBinaryCin) != 0) {
1328  NcbiSys_setmode(NcbiSys_fileno(stdin), O_BINARY);
1329  }
1330  if ((m_StdioFlags & fBinaryCout) != 0) {
1331  NcbiSys_setmode(NcbiSys_fileno(stdout), O_BINARY);
1332  }
1333 #endif
1334 }
1335 
1337 {
1339  for(CArgDescriptions* desc : m_ArgDesc->GetAllDescriptions())
1340  {
1341  desc->AddStdArguments(mask);
1343  }
1344 }
1345 
1347 {
1348  if (app_name.empty()) return;
1349  m_ProgramDisplayName = app_name;
1350  // Also set app_name in the diag context
1351  if ( GetDiagContext().GetAppName().empty() ) {
1352  GetDiagContext().SetAppName(app_name);
1353  }
1354 }
1355 
1356 
1357 string CNcbiApplicationAPI::GetAppName(EAppNameType name_type, int argc, const char* const* argv)
1358 {
1359  CNcbiApplicationGuard instance = InstanceGuard();
1360  string app_name;
1361 
1362  switch (name_type) {
1363  case eBaseName:
1364  if (instance) {
1365  app_name = instance->GetProgramDisplayName();
1366  } else {
1367  string exe_path = FindProgramExecutablePath(argc, argv);
1368  CDirEntry::SplitPath(exe_path, NULL, &app_name);
1369  }
1370  break;
1371 
1372  case eFullName:
1373  if (instance) {
1374  app_name = instance->GetProgramExecutablePath(eIgnoreLinks);
1375  } else {
1376  app_name = FindProgramExecutablePath(argc, argv);
1377  }
1378  break;
1379 
1380  case eRealName:
1381  if (instance) {
1382  app_name = instance->GetProgramExecutablePath(eFollowLinks);
1383  } else {
1384  FindProgramExecutablePath(argc, argv, &app_name);
1385  }
1386  break;
1387  }
1388 
1389  return app_name;
1390 }
1391 
1392 
1394  int argc,
1395  const char* const* argv,
1396  string* real_path
1397 )
1398 {
1399  // Cache program executable path, it doesn't change during execution
1400 
1401  static CSafeStatic<string> s_Path;
1402  static CSafeStatic<string> s_RealPath;
1403  static bool s_Init = false;
1404 
1405  if (s_Init) {
1406  // Return cached value
1407  if (real_path) {
1408  *real_path = *s_RealPath;
1409  }
1410  return *s_Path;
1411  }
1412  s_Init = true;
1413 
1414  CNcbiApplicationGuard instance = InstanceGuard();
1415  string ret_val;
1416 
1417  _ASSERT(argc >= 0); // formally signed for historical reasons
1418  _ASSERT(argv != NULL || argc == 0);
1419  if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0') {
1420  ret_val = argv[0];
1421  } else if (instance) {
1422  ret_val = instance->GetArguments().GetProgramName();
1423  }
1424 
1425 #if defined(NCBI_OS_MSWIN) || defined(NCBI_OS_UNIX)
1426 
1427 # ifdef NCBI_OS_MSWIN
1428 
1429  // MS Windows: Try more accurate method of detection.
1430  try {
1431  // Load PSAPI dynamic library -- it should exist on MS-Win NT/2000/XP
1432  CDll dll_psapi("psapi.dll", CDll::eLoadNow, CDll::eAutoUnload);
1433 
1434  // Get function entry-point from DLL
1435  BOOL (STDMETHODCALLTYPE FAR * dllEnumProcessModules)
1436  (HANDLE hProcess, // handle to process
1437  HMODULE *lphModule, // array of module handles
1438  DWORD cb, // size of array
1439  LPDWORD lpcbNeeded // number of bytes required
1440  ) = NULL;
1441 
1442  dllEnumProcessModules = dll_psapi.GetEntryPoint_Func("EnumProcessModules", &dllEnumProcessModules);
1443  if ( !dllEnumProcessModules ) {
1445  }
1446 
1447  // Find executable file in the midst of all loaded modules
1448  HANDLE process = GetCurrentProcess();
1449  HMODULE module = 0;
1450  DWORD needed = 0;
1451 
1452  // Get first module of current process (it should be .exe file)
1453  if ( dllEnumProcessModules(process, &module, sizeof(HMODULE), &needed) ) {
1454  if ( needed && module ) {
1455  TXChar buf[MAX_PATH + 1];
1456  DWORD ncount = GetModuleFileName(module, buf, MAX_PATH);
1457  if (ncount > 0) {
1458  // Save to cache and return
1459  *s_Path = _T_STDSTRING(buf);
1460  *s_RealPath = CDirEntry::NormalizePath(*s_Path, eFollowLinks);
1461  if (real_path) {
1462  *real_path = *s_RealPath;
1463  }
1464  return *s_Path;
1465  }
1466  }
1467  }
1468  }
1469  catch (const CException&) {
1470  ; // Just catch an all exceptions from CDll
1471  }
1472  // This method didn't work -- use standard method
1473 # endif
1474 
1475 # ifdef NCBI_OS_LINUX
1476  // Linux OS: Try more accurate method of detection for real_path
1477  if (ret_val.empty() && !real_path) {
1478  real_path = &ret_val;
1479  }
1480  if (real_path) {
1481  char buf[PATH_MAX + 1];
1482  string procfile = "/proc/" + NStr::IntToString(getpid()) + "/exe";
1483  int ncount = (int)readlink((procfile).c_str(), buf, PATH_MAX);
1484  if (ncount > 0) {
1485  real_path->assign(buf, ncount);
1486  if (real_path == &ret_val || ret_val.empty()) {
1487  // Save to cache and return
1488  *s_Path = *real_path;
1489  *s_RealPath = *real_path;
1490  return *real_path;
1491  }
1492  real_path = 0;
1493  }
1494  }
1495 # endif
1496 
1497  if (ret_val.empty()) {
1498  // nothing to go on :-/
1499  // don't need to update cached values, they are empty
1500  if (real_path) {
1501  real_path->erase();
1502  }
1503  // This can happens on non-Windows/Linux platforms if logging is used
1504  // before CNcbiApplication initialization, and no argc/argv valuies passed in arguments.
1505  // As a fallback reset the initialization state, so it can be (maybe) initialized correctly later.
1506 #if !defined(NCBI_OS_MSWIN) && !defined(NCBI_OS_LINUX)
1507  if (argc == 0) {
1508  s_Init = false;
1509  }
1510 #endif
1511  return kEmptyStr;
1512  }
1513 
1514  // Default approach (using value from arguments):
1515 
1516  string app_path = ret_val;
1517 
1518  if ( !CDirEntry::IsAbsolutePath(app_path) ) {
1519 # ifdef NCBI_OS_MSWIN
1520  // Add default ".exe" extention to the name of executable file
1521  // if it running without extension
1522  string dir, title, ext;
1523  CDirEntry::SplitPath(app_path, &dir, &title, &ext);
1524  if ( ext.empty() ) {
1525  app_path = CDirEntry::MakePath(dir, title, "exe");
1526  }
1527 # endif
1528  if ( CFile(app_path).Exists() ) {
1529  // Relative path from the the current directory
1530  app_path = CDir::GetCwd() + CDirEntry::GetPathSeparator() + app_path;
1531  if ( !CFile(app_path).Exists() ) {
1532  app_path = kEmptyStr;
1533  }
1534  } else {
1535  // Running from some path from PATH environment variable.
1536  // Try to determine that path.
1537  string env_path;
1538  if (instance) {
1539  env_path = instance->GetEnvironment().Get("PATH");
1540  } else {
1541  env_path = _T_STDSTRING(NcbiSys_getenv(_TX("PATH")));
1542  }
1543  list<string> split_path;
1544 # ifdef NCBI_OS_MSWIN
1545  NStr::Split(env_path, ";", split_path,
1547 # else
1548  NStr::Split(env_path, ":", split_path,
1550 # endif
1551  string base_name = CDirEntry(app_path).GetBase();
1552  ITERATE(list<string>, it, split_path) {
1553  app_path = CDirEntry::MakePath(*it, base_name);
1554  if ( CFile(app_path).Exists() ) {
1555  break;
1556  }
1557  app_path = kEmptyStr;
1558  }
1559  }
1560  }
1561  ret_val = CDirEntry::NormalizePath(
1562  (app_path.empty() && argv != NULL && argv[0] != NULL) ? argv[0] : app_path);
1563 
1564 #else // defined (NCBI_OS_MSWIN) || defined(NCBI_OS_UNIX)
1565 
1566 # error "Unsupported platform, sorry -- please contact NCBI"
1567 
1568 #endif
1569 
1570  // Save to cache and return
1571  *s_Path = ret_val;
1572  *s_RealPath = CDirEntry::NormalizePath(ret_val, eFollowLinks);
1573  if (real_path) {
1574  *real_path = *s_RealPath;
1575  }
1576  return *s_Path;
1577 }
1578 
1579 
1581 {
1582  if (reg == 0) {
1583  reg = m_Config.GetPointer();
1584  if (reg == 0)
1585  return;
1586  }
1587 
1589 
1590  // [NCBI.MEMORY_FILL]
1591  CObject::SetAllocFillMode(reg->Get("NCBI", "MEMORY_FILL"));
1592 
1593  {{
1594  CSysLog* syslog = dynamic_cast<CSysLog*>(GetDiagHandler());
1595  if (syslog) {
1596  syslog->HonorRegistrySettings(reg);
1597  }
1598  }}
1599 
1600  // Debugging features
1601 
1602  // [DEBUG.DIAG_TRACE]
1603  if ( !reg->Get("DEBUG", DIAG_TRACE).empty() ) {
1605  }
1606 
1607  // [DEBUG.ABORT_ON_THROW]
1608  if ( !reg->Get("DEBUG", ABORT_ON_THROW).empty() ) {
1609  SetThrowTraceAbort(true);
1610  }
1611 
1612  // [DEBUG.DIAG_POST_LEVEL]
1613  string post_level = reg->Get("DEBUG", DIAG_POST_LEVEL);
1614  if ( !post_level.empty() ) {
1615  EDiagSev sev;
1616  if (CNcbiDiag::StrToSeverityLevel(post_level.c_str(), sev)) {
1617  SetDiagFixedPostLevel(sev);
1618  }
1619  }
1620 
1621  // [DEBUG.MessageFile]
1622  string msg_file = reg->Get("DEBUG", DIAG_MESSAGE_FILE);
1623  if ( !msg_file.empty() ) {
1625  if ( !info || !info->Read(msg_file) ) {
1626  if ( info ) {
1627  delete info;
1628  }
1629  ERR_POST_X(12, Warning << "Applications message file \""
1630  << msg_file
1631  << "\" is not found");
1632  } else {
1634  }
1635  }
1636 
1637  // [DEBUG.GuardAgainstThreadsOnStaticDataDestruction]
1638  if ( !reg->GetBool("DEBUG", "GuardAgainstThreadsOnStaticDataDestruction", true, 0, IRegistry::eErrPost) ) {
1640  }
1641 
1642  // CPU and memory limitations
1643 
1644  // [NCBI.HeapSizeLimit]
1645  if ( !reg->Get("NCBI", "HeapSizeLimit").empty() ) {
1646  ERR_POST_X(13, Warning
1647  << "Config param [NCBI.HeapSizeLimit] is deprecated,"
1648  << "please use [NCBI.MemorySizeLimit] instead.");
1649  int mem_size_limit = reg->GetInt("NCBI", "HeapSizeLimit", 0);
1650  if (mem_size_limit < 0) {
1651  NCBI_THROW(CAppException, eLoadConfig,
1652  "Configuration file error: [NCBI.HeapSizeLimit] < 0");
1653  }
1654  SetMemoryLimit(size_t(mem_size_limit) * 1024 * 1024);
1655  }
1656  // [NCBI.MemorySizeLimit]
1657  if ( !reg->Get("NCBI", "MemorySizeLimit").empty() ) {
1658  size_t mem_size_limit = 0;
1659  string s = reg->GetString("NCBI", "MemorySizeLimit", kEmptyStr);
1660  size_t pos = s.find("%");
1661  if (pos != NPOS) {
1662  // Size in percents of total memory
1663  size_t percents = NStr::StringToUInt(CTempString(s, 0, pos));
1664  if (percents > 100) {
1665  NCBI_THROW(CAppException, eLoadConfig,
1666  "Configuration file error: [NCBI.HeapSizeLimit] > 100%");
1667  }
1668  mem_size_limit = (size_t)(CSystemInfo::GetTotalPhysicalMemorySize() * percents / 100);
1669  } else {
1670  try {
1671  // Size is specified in MiB by default if no suffixes
1672  // (converted without exception)
1673  mem_size_limit = NStr::StringToSizet(s) * 1024 * 1024;
1674  }
1675  catch (const CStringException&) {
1676  // Otherwise, size have suffix (MiB, G, GB, etc)
1678  if ( bytes > get_limits(mem_size_limit).max() ) {
1679  NCBI_THROW(CAppException, eLoadConfig,
1680  "Configuration file error: [NCBI.MemorySizeLimit] is too big");
1681  }
1682  mem_size_limit = (size_t)bytes;
1683  }
1684  }
1685  SetMemoryLimit(mem_size_limit);
1686  }
1687 
1688  // [NCBI.CpuTimeLimit]
1689  if ( !reg->Get("NCBI", "CpuTimeLimit").empty() ) {
1690  int cpu_time_limit = reg->GetInt("NCBI", "CpuTimeLimit", 0);
1691  if (cpu_time_limit < 0) {
1692  NCBI_THROW(CAppException, eLoadConfig,
1693  "Configuration file error: [NCBI.CpuTimeLimit] < 0");
1694  }
1695  SetCpuTimeLimit((unsigned int)cpu_time_limit, 5, NULL, NULL);
1696  }
1697 
1698  // TRACE and POST filters
1699 
1700  try {
1701  // [DIAG.TRACE_FILTER]
1702  string trace_filter = reg->Get("DIAG", "TRACE_FILTER");
1703  if ( !trace_filter.empty() )
1704  SetDiagFilter(eDiagFilter_Trace, trace_filter.c_str());
1705  } NCBI_CATCH_X(20,
1706  "Failed to load and set diag. filter for traces");
1707 
1708  try {
1709  // [DIAG.POST_FILTER]
1710  string post_filter = reg->Get("DIAG", "POST_FILTER");
1711  if ( !post_filter.empty() )
1712  SetDiagFilter(eDiagFilter_Post, post_filter.c_str());
1713  } NCBI_CATCH_X(21,
1714  "Failed to load and set diag. filter for regular errors");
1715 }
1716 
1717 
1719 {
1720  string cmd_line = GetProgramExecutablePath();
1721  if ( m_Arguments.get() ) {
1722  if ( cmd_line.empty() ) {
1723  cmd_line = (*m_Arguments)[0];
1724  }
1725  for (SIZE_TYPE arg = 1; arg < m_Arguments->Size(); ++arg) {
1726  cmd_line += " ";
1727  cmd_line += NStr::ShellEncode((*m_Arguments)[arg]);
1728  }
1729  }
1730 
1731  // Print application start message
1733  GetDiagContext().PrintStart(cmd_line);
1734  }
1735 }
1736 
1737 
1738 void CNcbiApplicationAPI::AppStop(int exit_code)
1739 {
1741  if ( !ctx.IsSetExitCode() ) {
1742  ctx.SetExitCode(exit_code);
1743  }
1744 }
1745 
1746 
1748 {
1749  m_ExitCode = exit_code;
1750  m_ExitCodeCond = when;
1751 }
1752 
1753 const char* CAppException::GetErrCodeString(void) const
1754 {
1755  switch (GetErrCode()) {
1756  case eUnsetArgs: return "eUnsetArgs";
1757  case eSetupDiag: return "eSetupDiag";
1758  case eLoadConfig: return "eLoadConfig";
1759  case eSecond: return "eSecond";
1760  case eNoRegistry: return "eNoRegistry";
1761  default: return CException::GetErrCodeString();
1762  }
1763 }
1764 
1765 
1767 {
1769 }
1770 
1771 
1773 {
1774 public:
1777 
1779  void SetIdler(INcbiIdler* idler, EOwnership own);
1780  void RunIdler(void);
1781 
1782 private:
1785 };
1786 
1787 
1788 inline
1790 {
1791  CMutexGuard guard(m_Mutex);
1792  m_Idler.reset(m_Idler.release(), own);
1793  return m_Idler.get();
1794 }
1795 
1796 
1797 inline
1799 {
1800  CMutexGuard guard(m_Mutex);
1801  m_Idler.reset(idler, own);
1802 }
1803 
1804 
1805 inline
1807 {
1808  if ( m_Idler.get() ) {
1809  CMutexGuard guard(m_Mutex);
1810  if ( m_Idler.get() ) {
1811  m_Idler->Idle();
1812  }
1813  }
1814 }
1815 
1816 
1818 
1820 {
1821  return s_IdlerWrapper.Get().GetIdler(ownership);
1822 }
1823 
1824 
1825 void SetIdler(INcbiIdler* idler, EOwnership ownership)
1826 {
1827  s_IdlerWrapper.Get().SetIdler(idler, ownership);
1828 }
1829 
1830 
1831 void RunIdler(void)
1832 {
1833  s_IdlerWrapper.Get().RunIdler();
1834 }
1835 
1836 
static void fatal(const char *msg,...)
Definition: attributes.c:18
ncbi::TMaskedQueryRegions mask
#define false
Definition: bool.h:36
AutoArray –.
Definition: ncbimisc.hpp:527
CAppException –.
Definition: ncbiapp_api.hpp:76
CArgDescriptions –.
Definition: ncbiargs.hpp:541
CArgException –.
Definition: ncbiargs.hpp:120
CArgHelpException –.
Definition: ncbiargs.hpp:158
CArgs –.
Definition: ncbiargs.hpp:379
CCoreException –.
Definition: ncbiexpt.hpp:1476
Default idler.
Temporary object for holding extra message arguments.
Definition: ncbidiag.hpp:1828
CDiagErrCodeInfo –.
Definition: ncbidiag.hpp:3029
CDirEntry –.
Definition: ncbifile.hpp:262
CDll –.
Definition: ncbidll.hpp:107
CFile –.
Definition: ncbifile.hpp:1604
void RunIdler(void)
Definition: ncbiapp.cpp:1806
CIdlerWrapper(void)
Definition: ncbiapp.cpp:1775
AutoPtr< INcbiIdler > m_Idler
Definition: ncbiapp.cpp:1784
~CIdlerWrapper(void)
Definition: ncbiapp.cpp:1776
INcbiIdler * GetIdler(EOwnership own)
Definition: ncbiapp.cpp:1789
void SetIdler(INcbiIdler *idler, EOwnership own)
Definition: ncbiapp.cpp:1798
CMutex m_Mutex
Definition: ncbiapp.cpp:1783
static SEntry Load(const string &name, ENameStyle style=eName_AsIs, TFlags flags=0, TRegFlags reg_flags=0, IRWRegistry *reg=0, const string &path=kEmptyStr)
Load the configuration file "name".
Definition: metareg.cpp:139
@ eName_RcOrIni
C Toolkit style; mostly useful with name = "ncbi".
Definition: metareg.hpp:66
@ eName_AsIs
Take the specified filename as is.
Definition: metareg.hpp:61
@ eName_Ini
Add .ini, dropping existing extensions as needed.
Definition: metareg.hpp:62
static string FindRegistry(const string &name, ENameStyle style=eName_AsIs)
Yield the path to a registry with the given name if available, or the empty string otherwise.
Definition: metareg.hpp:251
CMutex –.
Definition: ncbimtx.hpp:749
CNcbiApplicationAPI –.
static CNcbiApplication * Instance(void)
Singleton method.
Definition: ncbiapp.cpp:244
CNcbiApplication(const SBuildInfo &build_info=NCBI_SBUILDINFO_DEFAULT())
Constructor.
Definition: ncbiapp.cpp:250
virtual ~CNcbiApplication(void)
Destructor.
Definition: ncbiapp.cpp:256
CNcbiArguments –.
Definition: ncbienv.hpp:230
CNcbiEnvironment –.
Definition: ncbienv.hpp:104
CNcbiRegistry –.
Definition: ncbireg.hpp:913
CRWLock –.
Definition: ncbimtx.hpp:953
static void Destroy(CSafeStaticLifeSpan::ELifeLevel level)
Explicitly destroy all on-demand variables up to a specified level.
static void DisableChildThreadsCheck()
Disable checking on child thread(s) running during destruction.
CSafeStaticLifeSpan::
@ eLifeLevel_AppMain
Destroyed in CNcbiApplication::AppMain, if possible.
CSafeStatic<>::
static void s_HonorSignalHandlingConfiguration(void)
Definition: ncbi_stack.cpp:189
CStreamDiagHandler –.
Definition: ncbidiag.hpp:2596
CStringException –.
Definition: ncbistr.hpp:4505
static Uint8 GetTotalPhysicalMemorySize(void)
Return the amount of actual/total physical memory, in bytes.
CTempString implements a light-weight string on top of a storage buffer whose lifetime management is ...
Definition: tempstr.hpp:65
CVersionInfo –.
Interface for application idler.
IRWRegistry –.
Definition: ncbireg.hpp:407
IRegistry –.
Definition: ncbireg.hpp:73
void Print(const CCompactSAMApplication::AlignInfo &ai)
char value[7]
Definition: config.c:431
constexpr auto begin(const ct_const_array< T, N > &in) noexcept
CS_CONTEXT * ctx
Definition: t0006.c:12
string Path(const string &dir, const string &file)
Definition: fileutil.cpp:243
void x_LogOptions(int event)
Log environment, registry, command arguments, path.
Definition: ncbiapp.cpp:541
unique_ptr< CNcbiArguments > m_Arguments
Command-line arguments.
virtual EPreparseArgs PreparseArgs(int argc, const char *const *argv)
Check the command line arguments before parsing them.
Definition: ncbiapp.cpp:1279
CNcbiApplicationAPI * m_App
void SetFullVersion(CRef< CVersionAPI > version)
Set version data for the program.
Definition: ncbiapp.cpp:1154
int TStdioSetupFlags
Binary OR of "EStdioSetup".
void reset(element_type *p=0, EOwnership ownership=eTakeOwnership)
Reset will delete the old pointer (if owned), set content to the new value, and assume the ownership ...
Definition: ncbimisc.hpp:480
void ExecuteActions(void)
Definition: ncbimisc.hpp:1397
SIZE_TYPE FlushDiag(CNcbiOstream *os, bool close_diag=false)
Flush the in-memory diagnostic stream (for "eDS_ToMemory" case only).
Definition: ncbiapp.cpp:295
string m_ConfigPath
Path to .ini file used.
CNcbiActionGuard m_OnExitActions
Actions executed on app destruction.
bool SetupDiag(EAppDiagStream diag)
Setup the application diagnostic stream.
Definition: ncbiapp.cpp:1192
TDisableArgDesc m_DisableArgDesc
Arg desc. disabled.
void HideStdArgs(THideStdArgs hide_mask)
Set the hide mask for the Hide Std Flags.
Definition: ncbiapp.cpp:1292
TStdioSetupFlags m_StdioFlags
Std C++ I/O adjustments.
static string GetAppName(EAppNameType name_type=eBaseName, int argc=0, const char *const *argv=NULL)
Definition: ncbiapp.cpp:1357
friend class CNcbiApplicationGuard
void x_TryMain(EAppDiagStream diag, const char *conf, int *exit_code, bool *got_exception)
Definition: ncbiapp.cpp:629
void x_TryInit(EAppDiagStream diag, const char *conf)
Definition: ncbiapp.cpp:393
string m_ProgramDisplayName
Display name of app.
void x_SetupStdio(void)
Setup C++ standard I/O streams' behaviour.
Definition: ncbiapp.cpp:1307
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
Definition: ncbiapp.cpp:1753
void ExecuteOnExitActions()
Should only be called from the destructors of classes derived from CNcbiApplicationAPI - if it is nec...
Definition: ncbiapp.cpp:201
virtual int Run(void)=0
Run the application.
int m_LogOptions
logging of env, reg, args, path
string m_ExePath
Program executable path.
const CNcbiEnvironment & GetEnvironment(void) const
Get the application's cached environment.
CNcbiEnvironment & SetEnvironment(void)
Get a non-const copy of the application's cached environment.
const string & GetProgramExecutablePath(EFollowLinks follow_links=eIgnoreLinks) const
Get the application's executable path.
static CNcbiApplicationGuard InstanceGuard(void)
Singleton method.
Definition: ncbiapp.cpp:133
virtual void Init(void)
Initialize the application.
Definition: ncbiapp.cpp:266
EExitMode
When to return a user-set exit code.
virtual void AppStop(int exit_code)
Method to be called before application exit.
Definition: ncbiapp.cpp:1738
const CNcbiRegistry & GetConfig(void) const
Get the application's cached configuration parameters (read-only).
~CNcbiApplicationGuard(void)
Definition: ncbiapp.cpp:104
virtual const CArgs & GetArgs(void) const
Get parsed command line arguments.
Definition: ncbiapp.cpp:285
int AppMain(int argc, const char *const *argv, const char *const *envp=0, EAppDiagStream diag=eDS_Default, const char *conf=NcbiEmptyCStr, const string &name=NcbiEmptyString)
Main function (entry point) for the NCBI application.
Definition: ncbiapp.cpp:799
CVersionInfo GetVersion(void) const
Get the program version information.
Definition: ncbiapp.cpp:1164
virtual bool SetupDiag_AppSpecific(void)
Setup application specific diagnostic stream.
Definition: ncbiapp.cpp:1199
virtual void SetupArgDescriptions(CArgDescriptions *arg_desc)
Setup the command line argument descriptions.
Definition: ncbiapp.cpp:1175
int m_ExitCode
Exit code to force.
char * m_CinBuffer
Cin buffer if changed.
EPreparseArgs
Result of PreparseArgs()
static CNcbiApplicationAPI * Instance(void)
Singleton method.
Definition: ncbiapp.cpp:127
virtual bool LoadConfig(CNcbiRegistry &reg, const string *conf, CNcbiRegistry::TFlags reg_flags)
Load settings from the configuration file to the registry.
Definition: ncbiapp.cpp:1206
INcbiIdler * GetIdler(EOwnership ownership)
Return currently installed idler or NULL.
Definition: ncbiapp.cpp:1819
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
const char * m_LogFile
Logfile if set in the command line.
bool m_DryRun
Dry run.
void SetStdioFlags(TStdioSetupFlags stdio_flags)
Adjust the behavior of standard I/O streams.
Definition: ncbiapp.cpp:1298
shared_ptr< CReadLockGuard > m_AppLock
unique_ptr< CNcbiEnvironment > m_Environ
Cached application env.
element_type * get(void) const
Get pointer.
Definition: ncbimisc.hpp:469
void SetVersionByBuild(int major)
Definition: ncbiapp.cpp:1128
unique_ptr< CArgs > m_Args
Parsed cmd.-line args.
int THideStdArgs
Binary OR of "EHideStdArgs".
virtual void Exit(void)
Cleanup on application exit.
Definition: ncbiapp.cpp:279
void x_AddDefaultArgs(void)
Definition: ncbiapp.cpp:1336
CNcbiApplicationGuard(CNcbiApplicationAPI *app)
Definition: ncbiapp.cpp:96
static string FindProgramExecutablePath(int argc, const char *const *argv, string *real_path=0)
Find the application's executable file.
Definition: ncbiapp.cpp:1393
const string & GetProgramDisplayName(void) const
Get the application's "display" name.
EExitMode m_ExitCodeCond
When to force it (if ever)
void DisableArgDescriptions(TDisableArgDesc disable=fDisableStdArgs)
Definition: ncbiapp.cpp:1286
virtual void AppStart(void)
Method to be called before application start.
Definition: ncbiapp.cpp:1718
static CRWLock & GetInstanceLock(void)
Definition: ncbiapp.cpp:119
unique_ptr< CArgDescriptions > m_ArgDesc
Cmd.-line arg descriptions.
virtual void Idle(void)=0
int TDisableArgDesc
Binary OR of "EDisableArgDesc".
CRef< CNcbiRegistry > m_Config
Guaranteed to be non-NULL.
static SSystemMutex & GetInstanceMutex(void)
Mutex for application singleton object.
Definition: ncbiapp.cpp:111
static CNcbiApplicationAPI * m_Instance
Current app. instance.
virtual int DryRun(void)
Test run the application.
Definition: ncbiapp.cpp:272
void SetProgramDisplayName(const string &app_name)
Set program's display name.
Definition: ncbiapp.cpp:1346
const CVersionAPI & GetFullVersion(void) const
Get the program version information.
Definition: ncbiapp.cpp:1169
void SetIdler(INcbiIdler *idler, EOwnership ownership)
Set new idler and ownership.
Definition: ncbiapp.cpp:1825
string m_RealExePath
Symlink-free executable path.
virtual void Idle(void)
Definition: ncbiapp.cpp:1766
virtual ~CNcbiApplicationAPI(void)
Destructor.
Definition: ncbiapp.cpp:207
element_type * get(void) const
Get pointer.
Definition: ncbimisc.hpp:581
const CNcbiArguments & GetArguments(void) const
Get the application's cached unprocessed command-line arguments.
void RunIdler(void)
Execute currently installed idler if any.
Definition: ncbiapp.cpp:1831
bool m_ConfigLoaded
Finished loading config.
THideStdArgs m_HideArgs
Std cmd.-line flags to hide.
element_type * release(void)
Release will release ownership of pointer to caller.
Definition: ncbimisc.hpp:472
void SetExitCode(int exit_code, EExitMode when=eExceptionalExits)
Force the program to return a specific exit code later, either when it exits due to an exception or u...
Definition: ncbiapp.cpp:1747
void SetVersion(const CVersionInfo &version)
Set the version number for the program.
Definition: ncbiapp.cpp:1135
string m_DefaultConfig
conf parameter to AppMain
CNcbiApplicationAPI(const SBuildInfo &build_info)
Constructor.
Definition: ncbiapp.cpp:139
void x_HonorStandardSettings(IRegistry *reg=0)
Read standard NCBI application configuration settings.
Definition: ncbiapp.cpp:1580
CRef< CVersionAPI > m_Version
Program version.
void x_ReadLogOptions()
Read switches that are stored in m_LogOptions from registry and environment.
Definition: ncbiapp.cpp:486
@ fHideFullHelp
Hide full help description.
@ fHideFullVersion
Hide full version description.
@ fHideAll
Hide all standard argument descriptions.
@ fHideHelp
Hide help description.
@ fHideVersion
Hide version description.
@ eAllExits
always (ignoring Run's return value)
@ eNoExits
never (stick to existing logic)
@ eExceptionalExits
when an (uncaught) exception occurs
@ fBinaryCout
treat standard output as binary
@ fNoSyncWithStdio
Turn off synchronizing of "C++" cin/cout/cerr streams with their "C" counterparts,...
@ fDefault_CinBufferSize
Use compiler-specific default of Cin buffer size.
@ fBinaryCin
treat standard input as binary
@ ePreparse_Exit
Exit the application with zero exit code.
@ ePreparse_Continue
Continue application execution.
@ eNoRegistry
Registry file cannot be opened.
Definition: ncbiapp_api.hpp:86
@ eUnsetArgs
Command-line argument description not found.
Definition: ncbiapp_api.hpp:82
@ eSecond
Second instance of CNcbiApplicationAPI is prohibited.
Definition: ncbiapp_api.hpp:85
@ eLoadConfig
Registry data failed to load from config file.
Definition: ncbiapp_api.hpp:84
@ eSetupDiag
Application diagnostic stream setup failed.
Definition: ncbiapp_api.hpp:83
@ eIgnoreLinks
Do not follow symbolic links.
Definition: ncbimisc.hpp:144
@ eFollowLinks
Follow symbolic links.
Definition: ncbimisc.hpp:145
@ eFullName
per GetProgramExecutablePath(eIgnoreLinks)
@ eRealName
per GetProgramExecutablePath(eFollowLinks)
@ eBaseName
per GetProgramDisplayName
CArgs * CreateArgs(TSize argc, TArray argv) const
Create parsed arguments in CArgs object.
Definition: ncbiargs.hpp:1279
@ eHelpShowAll
Error code for detailed help message which includes hidden arguments.
Definition: ncbiargs.hpp:164
@ eHelpErr
Show short help message and return error.
Definition: ncbiargs.hpp:166
@ eHelpXml
Error code for XML formatted help message.
Definition: ncbiargs.hpp:165
@ eHelpFull
Error code for detailed help message.
Definition: ncbiargs.hpp:163
@ fNoUsage
Do not print USAGE on argument error.
Definition: ncbiargs.hpp:1028
@ fDupErrToCerr
Print arg error to both log and cerr.
Definition: ncbiargs.hpp:1032
@ eNoValue
Expecting an argument value.
Definition: ncbiargs.hpp:128
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define FAR
Definition: ncbistd.hpp:278
#define _TRACE(message)
Definition: ncbidbg.hpp:122
void SetDiagFilter(EDiagFilter what, const char *filter_str)
Set diagnostic filter.
Definition: ncbidiag.cpp:7670
CDiagContext_Extra & Print(const string &name, const string &value)
The method does not print the argument, but adds it to the string.
Definition: ncbidiag.cpp:2622
static bool IsSetOldPostFormat(void)
Check old/new format flag (for compatibility only)
Definition: ncbidiag.cpp:3346
void PrintStart(const string &message)
Print start/stop etc.
Definition: ncbidiag.cpp:2095
CDiagContext & GetDiagContext(void)
Get diag context instance.
Definition: logging.cpp:818
static void SetRequestContext(CRequestContext *ctx)
Shortcut to CDiagContextThreadData::GetThreadData().SetRequestContext()
Definition: ncbidiag.cpp:1907
void SetDiagFixedPostLevel(EDiagSev post_sev)
Sets and locks the level, combining the previous two calls.
Definition: ncbidiag.cpp:6179
void DiagHandler_Reopen(void)
Ask diagnostic handler to reopen log files if necessary.
Definition: ncbidiag.cpp:6344
CDiagContext_Extra Extra(void) const
Create a temporary CDiagContext_Extra object.
Definition: ncbidiag.hpp:2095
bool IsSetExitCode(void) const
Check if exit code has been set.
Definition: ncbidiag.hpp:2172
TUID GetUID(void) const
Return (create if not created yet) unique diagnostic ID.
Definition: ncbidiag.cpp:1664
EAppDiagStream
Where to write the application's diagnostics to.
Definition: ncbidiag.hpp:1780
#define DIAG_POST_LEVEL
Diagnostic post severity level.
Definition: ncbidiag.hpp:1447
void FlushMessages(CDiagHandler &handler)
Flush the collected messages to the current diag handler.
Definition: ncbidiag.cpp:3387
void SetAppName(const string &app_name)
Set application name.
Definition: ncbidiag.cpp:1884
void DiscardMessages(void)
Discard the collected messages without printing them.
Definition: ncbidiag.cpp:3411
CDiagHandler * GetDiagHandler(bool take_ownership=false, bool *current_ownership=0)
Get the currently set diagnostic handler class.
Definition: ncbidiag.cpp:6329
NCBI_XNCBI_EXPORT void Abort(void)
Smart abort function.
Definition: ncbidiag.cpp:8147
void SetDiagErrCodeInfo(CDiagErrCodeInfo *info, bool can_delete=true)
Set handler for processing error codes.
Definition: ncbidiag.cpp:7644
void SetExitCode(int exit_code)
Set exit code.
Definition: ncbidiag.hpp:2176
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
virtual CNcbiOstream * GetStream(void)
Definition: ncbidiag.hpp:2612
static void x_FinalizeSetupDiag(void)
Internal function, should be used only by CNcbiApplication.
Definition: ncbidiag.cpp:3501
static void SetupDiag(EAppDiagStream ds=eDS_Default, CNcbiRegistry *config=NULL, EDiagCollectMessages collect=eDCM_NoChange, const char *cmd_logfile=NULL)
Application-wide diagnostics setup.
Definition: ncbidiag.cpp:3545
void InitMessages(size_t max_size=100)
Start collecting all messages (the collected messages can be flushed to a new destination later).
Definition: ncbidiag.cpp:3370
void SetDiagTrace(EDiagTrace how, EDiagTrace dflt=eDT_Default)
Set the diagnostic trace settings.
Definition: ncbidiag.cpp:6226
EDiagSev
Severity level for the posted diagnostics.
Definition: ncbidiag.hpp:650
TDiagPostFlags SetDiagPostAllFlags(TDiagPostFlags flags)
Set global post flags to "flags".
Definition: ncbidiag.cpp:6065
#define DIAG_MESSAGE_FILE
Diagnostic message file.
Definition: ncbidiag.hpp:3092
#define DIAG_TRACE
Diagnostic trace setting.
Definition: ncbidiag.hpp:1540
static bool StrToSeverityLevel(const char *str_sev, EDiagSev &sev)
Get severity from string.
Definition: ncbidiag.cpp:7904
void SetDiagStream(CNcbiOstream *os, bool quick_flush=true, FDiagCleanup cleanup=0, void *cleanup_data=0, const string &stream_name="")
Set diagnostic stream.
Definition: ncbidiag.cpp:8083
void SetGlobalAppState(EDiagAppState state)
Set global application state.
Definition: ncbidiag.cpp:2809
void HonorRegistrySettings(const IRegistry *reg=0)
Definition: syslog.cpp:252
@ eDPF_Severity
Severity (default)
Definition: ncbidiag.hpp:697
@ eDCM_NoChange
Continue collecting messages if already started.
Definition: ncbidiag.hpp:1803
@ eDCM_Flush
Flush the collected messages and stop collecting.
Definition: ncbidiag.hpp:1804
@ eDS_User
Leave as was previously set (or not set) by user.
Definition: ncbidiag.hpp:1787
@ eDS_ToStderr
To standard error stream.
Definition: ncbidiag.hpp:1782
@ eDT_Enable
Enable messages of severity "eDiag_Trace".
Definition: ncbidiag.hpp:1550
@ eDiagAppState_AppEnd
AE.
Definition: ncbidiag.hpp:793
@ eDiagAppState_AppBegin
AB.
Definition: ncbidiag.hpp:791
@ eDiagAppState_AppRun
A.
Definition: ncbidiag.hpp:792
@ eDiagFilter_Post
for all non-TRACE, non-FATAL
Definition: ncbidiag.hpp:2530
@ eDiagFilter_Trace
for TRACEs only
Definition: ncbidiag.hpp:2529
TFunc GetEntryPoint_Func(const string &name, TFunc *func)
Get DLLs entry point (function).
Definition: ncbidll.hpp:273
@ eAutoUnload
Definition: ncbidll.hpp:144
@ eLoadNow
Definition: ncbidll.hpp:138
void Set(const string &name, const string &value)
Set an environment variable by name.
Definition: ncbienv.cpp:147
const string & Get(const string &name, bool *found=NULL) const
Get environment value by name.
Definition: ncbienv.cpp:109
const string & GetProgramName(EFollowLinks follow_links=eIgnoreLinks) const
Get program name.
Definition: ncbienv.cpp:373
void Critical(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1203
TErrCode GetErrCode(void) const
Get error code.
Definition: ncbiexpt.cpp:453
#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
#define NCBI_RETHROW_SAME(prev_exception, message)
Generic macro to re-throw the same exception.
Definition: ncbiexpt.hpp:749
#define NCBI_CATCH_X(err_subcode, message)
Catch CExceptions as well with default error code and given error subcode placed in diagnostics.
Definition: ncbiexpt.hpp:615
CRequestContext & GetRequestContext(void) const
Get the request context in which the exception was thrown.
Definition: ncbiexpt.cpp:472
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
void Fatal(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1209
int TErrCode
Definition: ncbiexpt.hpp:889
#define ABORT_ON_THROW
ABORT_ON_THROW controls if program should be aborted.
Definition: ncbiexpt.hpp:80
TErrCode GetErrCode(void) const
Definition: ncbiexpt.hpp:1493
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
virtual const char * what(void) const noexcept
Standard report (includes full backlog).
Definition: ncbiexpt.cpp:342
#define NCBI_REPORT_EXCEPTION_X(err_subcode, title, ex)
Generate a report on the exception with default error code and given subcode.
Definition: ncbiexpt.hpp:761
#define NCBI_RETHROW(prev_exception, exception_class, err_code, message)
Generic macro to re-throw an exception.
Definition: ncbiexpt.hpp:737
void SetThrowTraceAbort(bool abort_on_throw_trace)
Specify whether to call "abort()" inside the DoThrowTraceAbort().
Definition: ncbiexpt.cpp:66
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
static string NormalizePath(const string &path, EFollowLinks follow_links=eIgnoreLinks)
Normalize a path.
Definition: ncbifile.cpp:820
static bool IsAbsolutePath(const string &path)
Check if a "path" is absolute for the current OS.
Definition: ncbifile.cpp:508
string GetBase(void) const
Get the base entry name without extension.
Definition: ncbifile.hpp:3924
static string MakePath(const string &dir=kEmptyStr, const string &base=kEmptyStr, const string &ext=kEmptyStr)
Assemble a path from basic components.
Definition: ncbifile.cpp:413
static char GetPathSeparator(void)
Get path separator symbol specific for the current platform.
Definition: ncbifile.cpp:433
static string GetCwd(void)
Get the current working directory.
Definition: ncbifile.cpp:3708
string GetName(void) const
Get the base entry name with extension (if any).
Definition: ncbifile.hpp:3916
#define PATH_MAX
Definition: ncbifile.hpp:106
static void SplitPath(const string &path, string *dir=0, string *base=0, string *ext=0)
Split a path string into its basic components.
Definition: ncbifile.cpp:358
static void SetAllocFillMode(EAllocFillMode mode)
Definition: ncbiobj.cpp:436
TObjectType * GetPointer(void) THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:998
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
@ eParam_NoThread
Do not use per-thread values.
Definition: ncbi_param.hpp:418
#define kMax_Int
Definition: ncbi_limits.h:184
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
ncbi_numeric_limits< T > get_limits(const T &)
Generic template to get STD limits by a variable.
size_t resident_peak
Peak resident set size ("high water mark")
size_t total_peak
Peak total memory usage.
size_t resident
Resident/working set size (RSS).
size_t total
Total memory usage.
size_t shared
Shared memory usage.
static bool GetMemoryUsage(SMemoryUsage &usage)
Get current process memory usage.
size_t data
Data segment size.
static bool GetTimes(double *real, double *user, double *sys, EWhat what=eProcess)
Get current process execution times.
size_t stack
Stack size of the initial thread in the process.
@ eChildren
All children of the calling process.
@ eThread
Current thread.
@ eProcess
Current process.
int TFlags
Binary OR of "EFlags".
Definition: ncbireg.hpp:107
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 const string & Get(const string &section, const string &name, TFlags flags=0) const
Get the parameter value.
Definition: ncbireg.cpp:262
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
bool Empty(TFlags flags=fAllLayers) const
Verify if Registry is empty.
Definition: ncbireg.cpp:162
bool IncludeNcbircIfAllowed(TFlags flags=fWithNcbirc)
Attempt to load a systemwide configuration file (.ncbirc on Unix, ncbi.ini on Windows) as a low-prior...
Definition: ncbireg.cpp:1634
virtual void EnumerateEntries(const string &section, list< string > *entries, TFlags flags=fAllLayers) const
Enumerate parameter names for a specified section.
Definition: ncbireg.cpp:514
IRWRegistry * Read(CNcbiIstream &is, TFlags flags=0, const string &path=kEmptyStr)
Read and parse the stream "is", and merge its content with current Registry entries.
Definition: ncbireg.cpp:605
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
bool Write(CNcbiOstream &os, TFlags flags=0) const
Write the registry content to output stream.
Definition: ncbireg.cpp:196
void Clear(TFlags flags=fAllLayers)
Reset the registry content.
Definition: ncbireg.cpp:590
@ fWithNcbirc
Include .ncbirc (used only by CNcbiReg.)
Definition: ncbireg.hpp:93
@ eErrPost
Log the error message and return default value.
Definition: ncbireg.hpp:202
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
#define NcbiCout
Definition: ncbistre.hpp:543
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
#define NcbiEmptyCStr
Definition: ncbistr.hpp:59
#define kEmptyStr
Definition: ncbistr.hpp:123
#define NcbiEmptyXCStr
Definition: ncbistr.hpp:184
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:630
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:3457
#define NcbiEmptyXString
Definition: ncbistr.hpp:185
char TXChar
Definition: ncbistr.hpp:172
static int strcmp(const char *s1, const char *s2)
String compare.
Definition: ncbistr.hpp:5207
static Uint8 StringToUInt8_DataSize(const CTempString str, TStringToNumFlags flags=0)
Convert string that can contain "software" qualifiers to Uint8.
Definition: ncbistr.cpp:1539
#define NPOS
Definition: ncbistr.hpp:133
static size_t StringToSizet(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to size_t.
Definition: ncbistr.cpp:1769
string TXString
Definition: ncbistr.hpp:173
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5083
#define _T_STDSTRING(x)
Definition: ncbistr.hpp:180
#define _T_CSTRING(x)
Definition: ncbistr.hpp:182
#define NcbiEmptyString
Definition: ncbistr.hpp:122
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:5411
#define _TX(x)
Definition: ncbistr.hpp:176
static unsigned int StringToUInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to unsigned int.
Definition: ncbistr.cpp:642
static int strncmp(const char *s1, const char *s2, size_t n)
String compare up to specified number of characters.
Definition: ncbistr.hpp:5213
static string ShellEncode(const string &str)
Quotes a string in Bourne Again Shell (BASH) syntax, in a way that disallows non-printable characters...
Definition: ncbistr.cpp:4676
@ fSplit_Truncate
Definition: ncbistr.hpp:2501
@ fSplit_MergeDelimiters
Merge adjacent delimiters.
Definition: ncbistr.hpp:2498
static bool WaitForAllThreads(void)
Definition: ncbithr.cpp:974
static void InitializeMainThreadId(void)
Initialize main thread's TID.
Definition: ncbithr.cpp:482
static bool sm_IsExiting
Definition: ncbithr.hpp:660
enum ENcbiOwnership EOwnership
Ownership relations between objects.
string GetExtraValue(EExtra key, const string &default_value=kEmptyStr) const
Definition: version.cpp:464
void SetVersionInfo(int ver_major, int ver_minor, int patch_level=0, const string &ver_name=kEmptyStr)
Set version information.
Definition: version.cpp:648
const SBuildInfo & GetBuildInfo() const
Get build info (date and tag, if set)
Definition: version.cpp:695
const CVersionInfo & GetVersionInfo() const
Get version information.
Definition: version.cpp:676
static CVersionInfo GetPackageVersion(void)
Definition: version.cpp:705
#define NCBI_APP_SBUILDINFO_DEFAULT()
Definition: version.hpp:121
string Print(const string &appname, TPrintFlags flags=fPrintAll) const
Print version data, plain text.
Definition: version.cpp:718
bool IsAny() const
Check if version is all zero (major, minor, patch) Convention is that all-zero version used in reques...
string PrintXml(const string &appname, TPrintFlags flags=fPrintAll) const
Print version data, XML.
Definition: version.cpp:764
void AddComponentVersion(const string &component_name, int ver_major, int ver_minor, int patch_level, const string &ver_name, const SBuildInfo &build_info)
Add component version information.
Definition: version.cpp:681
string PrintJson(const string &appname, TPrintFlags flags=fPrintAll) const
Print version data, JSON.
Definition: version.cpp:814
@ fPackageShort
Print package info, if available.
@ fVersionInfo
Print version info.
@ eTeamCityBuildNumber
Definition: version_api.hpp:69
@ eTeamCityProjectName
Definition: version_api.hpp:67
@ eStableComponentsVersion
Definition: version_api.hpp:72
#define HANDLE
An abstraction for a file handle.
Definition: mdb.c:383
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Definition of all error codes used in corelib (xncbi.lib).
char * buf
int i
static MDB_envinfo info
Definition: mdb_load.c:37
static int version
Definition: mdb_load.c:29
constexpr bool empty(list< Ts... >) noexcept
static string s_Path
Directory for all database files of the storage.
Definition: nc_storage.cpp:215
#define strdup
Definition: ncbi_ansi_ext.h:70
#define NCBI_SC_VERSION_PROXY
#define NCBI_TEAMCITY_PROJECT_NAME_PROXY
#define NCBI_TEAMCITY_BUILD_NUMBER_PROXY
#define NCBI_SUBVERSION_REVISION_PROXY
unsigned int a
Definition: ncbi_localip.c:102
Defines MS Windows specifics for our "C++" code.
Static variables safety - create on demand, destroy on application termination.
bool SetCpuTimeLimit(unsigned int max_cpu_time, unsigned int terminate_delay_time, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set CPU time usage limit.
@ fSuppress_Exception
Unhandled exceptions.
bool SetMemoryLimit(size_t max_size, TLimitsPrintHandler handler=NULL, TLimitsPrintParameter parameter=NULL)
[UNIX only] Set memory limit.
bool VerifyCpuCompatibility(string *message=nullptr)
Verify that the CPU, where an application run, is compatible with flags it compiled for.
void SuppressSystemMessageBox(TSuppressSystemMessageBox mode=fSuppress_Default)
Suppress popup messages on execution errors.
CSafeStatic< CIdlerWrapper > s_IdlerWrapper
Definition: ncbiapp.cpp:1817
#define NCBI_LOG_PARAM(type, Name, NAME)
Definition: ncbiapp.cpp:452
const char * s_ArgFullVersionXml
Definition: ncbiargs.cpp:86
const char * s_ArgFullVersionJson
Definition: ncbiargs.cpp:87
NCBI_PARAM_DEF_EX(bool, Debug, Catch_Unhandled_Exceptions, true, eParam_NoThread, DEBUG_CATCH_UNHANDLED_EXCEPTIONS)
static CSafeStatic< CRWLock > s_InstanceRWLock(CSafeStaticLifeSpan(CSafeStaticLifeSpan::eLifeSpan_Long, 1))
ELogOptionsEvent
Definition: ncbiapp.cpp:467
@ eStartEvent
right before AppMain()
Definition: ncbiapp.cpp:468
@ eOtherEvent
any case is fine
Definition: ncbiapp.cpp:470
@ eStopEvent
right after AppMain()
Definition: ncbiapp.cpp:469
const char * s_ArgFullVersion
Definition: ncbiargs.cpp:85
typedef NCBI_PARAM_TYPE(Debug, Catch_Unhandled_Exceptions) TParamCatchExceptions
#define RES_SIZE_USAGE(name, value_in_bytes)
Definition: ncbiapp.cpp:528
bool s_HandleExceptions(void)
Definition: ncbiapp.cpp:382
const char * s_ArgLogFile
Definition: ncbiargs.cpp:82
const char * s_ArgCfgFile
Definition: ncbiargs.cpp:83
DEFINE_STATIC_MUTEX(s_InstanceMutex)
NCBI_PARAM_DECL(bool, Debug, Catch_Unhandled_Exceptions)
ELogOptions
Flags to switch what to log.
Definition: ncbiapp.cpp:475
@ fLogAppRegistryStop
log app registry on app stop
Definition: ncbiapp.cpp:479
@ fLogAppPath
log app executable path
Definition: ncbiapp.cpp:481
@ fLogAppResUsageStop
log resource usage on app stop
Definition: ncbiapp.cpp:482
@ fLogAppArguments
log app arguments
Definition: ncbiapp.cpp:480
@ fLogAppEnvironment
log app environment on app start
Definition: ncbiapp.cpp:476
@ fLogAppRegistry
log app registry on app start
Definition: ncbiapp.cpp:478
@ fLogAppEnvironmentStop
log app environment on app stop
Definition: ncbiapp.cpp:477
static bool s_IsApplicationStarted
Definition: ncbiapp.cpp:89
#define RES_TIME_USAGE(name, value)
Definition: ncbiapp.cpp:536
void s_RoundResUsageSize(Uint8 value_in_bytes, string &suffix, Uint8 &value)
Definition: ncbiapp.cpp:513
const char * s_ArgDryRun
Definition: ncbiargs.cpp:88
const char * s_ArgVersion
Definition: ncbiargs.cpp:84
const char * s_ArgDelimiter
Definition: ncbiargs.cpp:89
Defines the CNcbiApplication and CAppException classes for creating NCBI applications.
#define NCBI_OS_UNIX
Define class Dll and for Portable DLL handling.
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
@ eSecond
Definition: ncbitime.cpp:2758
T max(T x_, T y_)
std::istream & in(std::istream &in_, double &x_)
#define BOOL
Definition: odbcinst.h:18
static const char * suffix[]
Definition: pcregrep.c:408
#define basename(path)
Definition: replacements.h:116
Defines CRequestContext class for NCBI C++ diagnostic API.
DWORD * LPDWORD
Definition: sqltypes.h:113
unsigned int DWORD
Definition: sqltypes.h:98
#define NcbiSys_getenv
Definition: ncbisys.hpp:90
#define NcbiSys_setmode
Definition: ncbisys.hpp:47
#define NcbiSys_fileno
Definition: ncbisys.hpp:43
NCBI
Definition: static_set.hpp:72
static const char * str(char *buf, int n)
Definition: stats.c:84
CCompressionStreamProcessor * s_Init(EInitType type, CCompressStream::EMethod method, ICompression::TFlags flags, ICompression::ELevel level)
Definition: stream_util.cpp:92
CRef< IRWRegistry > registry
Definition: metareg.hpp:78
string actual_name
Either an absolute path or empty.
Definition: metareg.hpp:75
Process memory usage information, in bytes.
This class allows to add build info (date and tag) to application version.
Definition: version_api.hpp:62
Definition: inftrees.h:24
Portable system-logging API.
#define _ASSERT
static HENV env
Definition: transaction2.c:38
Modified on Wed Nov 29 02:24:34 2023 by modify_doxy.py rev. 669887