NCBI C++ ToolKit
grid_worker.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef CONNECT_SERVICES__GRID_WORKER_HPP
2 #define CONNECT_SERVICES__GRID_WORKER_HPP
3 
4 
5 /* $Id: grid_worker.hpp 91314 2020-10-08 18:27:15Z grichenk $
6  * ===========================================================================
7  *
8  * PUBLIC DOMAIN NOTICE
9  * National Center for Biotechnology Information
10  *
11  * This software/database is a "United States Government Work" under the
12  * terms of the United States Copyright Act. It was written as part of
13  * the author's official duties as a United States Government employee and
14  * thus cannot be copyrighted. This software/database is freely available
15  * to the public for use. The National Library of Medicine and the U.S.
16  * Government have not placed any restriction on its use or reproduction.
17  *
18  * Although all reasonable efforts have been taken to ensure the accuracy
19  * and reliability of the software and data, the NLM and the U.S.
20  * Government do not and cannot warrant the performance or results that
21  * may be obtained by using this software or data. The NLM and the U.S.
22  * Government disclaim all warranties, express or implied, including
23  * warranties of performance, merchantability or fitness for any particular
24  * purpose.
25  *
26  * Please cite the author in any work or product based on this material.
27  *
28  * ===========================================================================
29  *
30  * Authors: Maxim Didneko, Anatoliy Kuznetsov, Dmitry Kazimirov
31  *
32  * File Description:
33  * NetSchedule Worker Node Framework Interfaces.
34  *
35  */
36 
37 /// @file grid_worker.hpp
38 /// Grid Framework specs.
39 ///
40 
41 #include "netschedule_api.hpp"
42 #include "netcache_api.hpp"
43 #include "error_codes.hpp"
45 
46 #include <connect/connect_export.h>
47 
48 #include <util/thread_pool.hpp>
49 
50 #include <corelib/ncbistre.hpp>
51 #include <corelib/ncbimisc.hpp>
52 #include <corelib/ncbireg.hpp>
53 #include <corelib/ncbithr.hpp>
54 #include <corelib/ncbiapp_api.hpp>
56 #include <corelib/request_ctx.hpp>
57 
58 #include <array>
59 
61 
62 /** @addtogroup NetScheduleClient
63  *
64  * @{
65  */
66 
67 class CArgs;
68 class IRegistry;
69 class CNcbiEnvironment;
70 
72 public:
73  /// Event notifying of a safe clean-up point. It is generated for a
74  /// job after the job is finished (or the worker node is shutting
75  /// down). It is also generated for the whole worker node -- when
76  /// it is shutting down.
78  /// For jobs -- run from the same thread after Do() is done;
79  /// for the whole WN -- run from a separate (clean-up) thread
80  /// after all jobs are done and cleaned up, and the whole worker
81  /// node is shutting down.
83 
84  /// Called on emergency shutdown, always from a different (clean-up)
85  /// thread, even for the jobs.
87  };
88 
89  virtual void HandleEvent(EWorkerNodeCleanupEvent cleanup_event) = 0;
91 };
92 
93 /// Clean-up event source for the worker node. This interface provides
94 /// for subscribing for EWorkerNodeCleanupEvent. It is used by both
95 /// IWorkerNodeInitContext (for the global worker node clean-up) and
96 /// IWorkerNodeJob (for per-job clean-up).
98 {
99 public:
100  virtual void AddListener(IWorkerNodeCleanupEventListener* listener) = 0;
101  virtual void RemoveListener(IWorkerNodeCleanupEventListener* listener) = 0;
102 
103  virtual void CallEventHandlers() = 0;
104 };
105 
106 /// Worker Node initialize context
107 ///
108 /// An instance of a class which implements this interface
109 /// is passed to a constructor of a worker node job class
110 /// The worker node job class can use this class to get
111 /// configuration parameters.
112 ///
113 /// @{
115 {
116 public:
118 
119  /// Get a config file registry
120  ///
121  virtual const IRegistry& GetConfig() const = 0;
122 
123  /// Get command line arguments
124  ///
125  virtual const CArgs& GetArgs() const = 0;
126 
127  /// Get environment variables
128  ///
129  virtual const CNcbiEnvironment& GetEnvironment() const = 0;
130 };
132 {
133 public:
134  /// Get interface for registering clean-up event listeners
135  ///
137 
138  /// Get the shared NetScheduleAPI object used by the worker node framework.
139  ///
140  virtual CNetScheduleAPI GetNetScheduleAPI() const = 0;
141 
142  /// Get the shared NetCacheAPI object used by the worker node framework.
143  ///
144  virtual CNetCacheAPI GetNetCacheAPI() const = 0;
145 };
146 /// @}
147 
150 /// Worker Node Job interface.
151 ///
152 /// This interface is a worker node workhorse.
153 /// Job is executed by method Do of this interface.
154 /// Worker node application may be configured to execute several jobs at once
155 /// using threads, so implementation must be thread safe.
156 ///
157 /// @sa CWorkerNodeJobContext, IWorkerNodeInitContext
158 ///
159 class IWorkerNodeJob : public CObject
160 {
161 public:
162  virtual ~IWorkerNodeJob() {}
163  /// Execute the job.
164  ///
165  /// Job is considered successfully done if the Do method calls
166  /// CommitJob (see CWorkerNodeJobContext).
167  /// If method does not call CommitJob job is considered unresolved
168  /// and returned back to the queue.
169  /// Method can throw an exception (derived from std::exception),
170  /// in this case job is considered failed (error message will be
171  /// redirected to the NetSchedule queue)
172  ///
173  /// @param context
174  /// Context where a job can get all required information
175  /// like input/output steams, the job key etc.
176  ///
177  /// @return
178  /// Job exit code
179  ///
180  virtual int Do(CWorkerNodeJobContext& context) = 0;
181 };
182 
183 class CGridWorkerNode;
184 class CWorkerNodeRequest;
185 
187 
188 /// Worker Node job context
189 ///
190 /// Context in which a job is running, gives access to input and output
191 /// storage and some job control parameters.
192 ///
193 /// @sa IWorkerNodeJob
194 ///
196 {
197  NCBI_NET_COMPONENT(WorkerNodeJobContext);
198 
199  /// Get the associated job structure to access all of its fields.
200  const CNetScheduleJob& GetJob() const;
201  CNetScheduleJob& GetJob();
202 
203  /// Get a job key
204  const string& GetJobKey() const;
205 
206  /// Get a job input string.
207  ///
208  /// This string can be used in two ways.
209  /// 1. It can be an input data for a job (if that data is short)
210  /// If it is so don't use GetIStream method.
211  /// 2. It holds a key to a data stored in an external data storage.
212  /// (NetCache) In this case use GetIStream method to get a stream with
213  /// an input data for the job
214  ///
215  const string& GetJobInput() const;
216 
217  /// Set a job's output. This string will be sent to
218  /// the queue when job is done.
219  ///
220  /// This method can be used to send a short data back to the client.
221  /// To send a large result use GetOStream method. Don't call this
222  /// method after GetOStream method is called.
223  ///
224  void SetJobOutput(const string& output);
225 
226  /// Set the return code of the job.
227  ///
228  void SetJobRetCode(int ret_code);
229 
230  /// Get a stream with input data for a job. Stream is based on network
231  /// data storage (NetCache). Size of the input data can be determined
232  /// using GetInputBlobSize.
233  ///
235 
236  /// Get the size of an input stream
237  ///
238  size_t GetInputBlobSize() const;
239 
240  /// Put progress message
241  ///
242  void PutProgressMessage(const string& msg, bool send_immediately = false,
243  bool overwrite = true);
244 
245  /// Get a stream where a job can write its result
246  ///
247  CNcbiOstream& GetOStream();
248 
249  void CloseStreams();
250 
251  /// Confirm that a job is done and result is ready to be sent
252  /// back to the client.
253  ///
254  /// This method should be called at the end of the
255  /// IWorkerNodeJob::Do() method.
256  ///
257  void CommitJob();
258 
259  /// Confirm that a job is finished, but an error has happened
260  /// during its execution.
261  ///
262  /// This method should be called at the end of the
263  /// IWorkerNodeJob::Do() method.
264  ///
265  void CommitJobWithFailure(const string& err_msg, bool no_retries = false);
266 
267  /// Schedule the job for return.
268  ///
269  /// This method should be called before exiting IWorkerNodeJob::Do()
270  /// if the job is not needed anymore (canceled, expired or already
271  /// executed elsewhere), or if the worker node is shutting down and
272  /// the execution of this job should be gracefully (yet urgently)
273  /// aborted and the job returned back to the network queue for
274  /// execution by other worker node instances. Use the
275  /// GetShutdownLevel() method to detect whether the job is not
276  /// needed anymore.
277  /// @see GetShutdownLevel()
278  ///
279  void ReturnJob();
280 
281  /// Put the job back in the queue with the specified affinity and group.
282  ///
283  /// This method should be called before exiting IWorkerNodeJob::Do().
284  void RescheduleJob(const string& affinity, const string& group = kEmptyStr);
285 
286  /// Check if job processing must be aborted.
287  ///
288  /// This method must be called periodically from within the Do()
289  /// method to check whether it needs to stop processing the current
290  /// job. If GetShutdownLevel() returns eShutdownImmediate or eDie,
291  /// the Do() method must immediately return its job to the server
292  /// by calling context.ReturnJob() and return a non-zero integer
293  /// to the caller.
294  ///
295  /// If GetShutdownLevel() returns eNormalShutdown, the Do() method
296  /// is free to decide whether the job processing must be aborted
297  /// or completed.
298  ///
299  /// Aside from the natural reason for GetShutdownLevel() to return
300  /// eNormalShutdown, eShutdownImmediate, or eDie, (that is, when
301  /// a worker node shutdown has been requested), this method can
302  /// also return eShutdownImmediate when the NetSchedule server
303  /// is not expecting the current job to complete. This can happen
304  /// due to multiple reasons:
305  /// 1. The job has been explicitly cancelled by the submitter or
306  /// administrator.
307  /// 2. The job was rescheduled to another worker node and has been
308  /// successfully finished.
309  /// 3. The job has expired.
310  ///
311  CNetScheduleAdmin::EShutdownLevel GetShutdownLevel();
312 
313  /// Get a name of a queue where this node is connected to.
314  ///
315  const string& GetQueueName() const;
316 
317  /// Get a node name
318  ///
319  const string& GetClientName() const;
320 
321  /// Increment job execution timeout
322  ///
323  /// When node picks up the job for execution it may periodically
324  /// communicate to the server that job is still alive and
325  /// prolong job execution timeout, so job server does not try to
326  /// reschedule.
327  ///
328  ///
329  /// @param runtime_inc
330  /// Estimated time in seconds(from the current moment) to
331  /// finish the job.
332  void JobDelayExpiration(unsigned runtime_inc);
333 
334  /// Check if logging was requested in config file
335  ///
336  bool IsLogRequested() const;
337 
338  /// Instruct the system that this job requires all system's resources
339  /// If this method is call, the node will not accept any other jobs
340  /// until this one is done. In the event if the mode has already been
341  /// requested by another job this job will be returned back to the queue.
342  void RequestExclusiveMode();
343 
344  const string& GetJobOutput() const;
345 
346  CNetScheduleAPI::TJobMask GetJobMask() const;
347 
348  unsigned int GetJobNumber() const;
349 
356  eCS_JobIsLost
357  };
358 
359  bool IsJobCommitted() const;
360  ECommitStatus GetCommitStatus() const;
361  static const char* GetCommitStatusDescription(ECommitStatus commit_status);
362 
363  bool IsJobLost() const;
364 
365  IWorkerNodeCleanupEventSource* GetCleanupEventSource();
366 
367  CGridWorkerNode GetWorkerNode() const;
368 };
369 
371 /// Worker Node Idle Task Context
372 ///
374 {
375 public:
376 
377  void RequestShutdown();
378  bool IsShutdownRequested() const;
379 
380  void SetRunAgain() { m_RunAgain = true; }
381  bool NeedRunAgain() const { return m_RunAgain; }
382 
383  void Reset();
384 
385 private:
386  friend class CWorkerNodeIdleThread;
388 
391 
392 private:
395 };
396 
397 /// Worker Node Idle Task Interface
398 ///
399 /// @sa IWorkerNodeJobFactory, CWorkerNodeIdleTaskContext
400 ///
402 {
403 public:
404  virtual ~IWorkerNodeIdleTask() {};
405 
406  /// Do the Idle task here.
407  /// It should not take a lot time, because while it is running
408  /// no real jobs will be processed.
409  virtual void Run(CWorkerNodeIdleTaskContext&) = 0;
410 };
411 
412 /// Worker Node Job Factory interface
413 ///
414 /// @sa IWorkerNodeJob
415 ///
417 {
418 public:
420  /// Create a job
421  ///
422  virtual IWorkerNodeJob* CreateInstance(void) = 0;
423 
424  /// Initialize a worker node factory
425  ///
426  virtual void Init(const IWorkerNodeInitContext& /*context*/) {}
427 
428  /// Get the job version
429  ///
430  virtual string GetJobVersion() const = 0;
431 
432  virtual string GetAppName() const {return GetJobVersion();}
433 
434  virtual string GetAppVersion() const { return kEmptyStr; }
435 
436  /// Get the Idle task
437  ///
438  virtual IWorkerNodeIdleTask* GetIdleTask() { return NULL; }
439 };
440 
441 template <typename TWorkerNodeJob>
443 {
444 public:
445  virtual void Init(const IWorkerNodeInitContext& context)
446  {
448  }
450  {
451  return new TWorkerNodeJob(*m_WorkerNodeInitContext);
452  }
453 
454  virtual string GetJobVersion() const { return m_JobVersion; }
455  virtual string GetAppName() const { return m_AppName; }
456 
457 protected:
459 
460 private:
461  static const char* const m_JobVersion;
462  static const char* const m_AppName;
463 };
464 
465 template <typename TWorkerNodeJob, typename TWorkerNodeIdleTask>
466 class CSimpleJobFactoryEx : public CSimpleJobFactory<TWorkerNodeJob>
467 {
468 public:
469  virtual void Init(const IWorkerNodeInitContext& context)
470  {
472  try {
473  m_IdleTask.reset(new TWorkerNodeIdleTask(context));
474  } catch (exception& ex) {
475  ERR_POST_XX(ConnServ_WorkerNode, 16,
476  "Error during Idle task construction: " << ex.what());
477  throw;
478  }
479  }
480  virtual IWorkerNodeIdleTask* GetIdleTask() { return m_IdleTask.get(); }
481 
482 private:
483  unique_ptr<TWorkerNodeIdleTask> m_IdleTask;
484 };
485 
486 #define NCBI_DECLARE_WORKERNODE_FACTORY_IMPL(TWorkerNodeJob, Version) \
487 BEGIN_NCBI_SCOPE \
488 template <> \
489 const char* const CSimpleJobFactory<TWorkerNodeJob>::m_JobVersion = \
490  #TWorkerNodeJob " version " NCBI_AS_STRING(Version); \
491 template <> \
492 const char* const CSimpleJobFactory<TWorkerNodeJob>::m_AppName = \
493  #TWorkerNodeJob; \
494 END_NCBI_SCOPE
495 
496 #define NCBI_DECLARE_WORKERNODE_FACTORY(TWorkerNodeJob, Version) \
497 typedef CSimpleJobFactory<TWorkerNodeJob> TWorkerNodeJob##Factory; \
498  NCBI_DECLARE_WORKERNODE_FACTORY_IMPL(TWorkerNodeJob, Version)
499 
500 #define NCBI_DECLARE_WORKERNODE_FACTORY_EX( \
501  TWorkerNodeJob, TWorkerNodeIdleTask, Version) \
502 typedef CSimpleJobFactoryEx<TWorkerNodeJob, TWorkerNodeIdleTask> \
503  TWorkerNodeJob##FactoryEx; \
504  NCBI_DECLARE_WORKERNODE_FACTORY_IMPL(TWorkerNodeJob, Version)
505 
506 /// Jobs watcher interface
508 {
509 public:
510  enum EEvent {
518  eJobLost
519  };
520 
521  virtual ~IWorkerNodeJobWatcher();
522 
523  virtual void Notify(const CWorkerNodeJobContext& job, EEvent event) = 0;
524 };
525 
527 
528 struct SGridWorkerNodeImpl;
529 /// Grid Worker Node
530 ///
531 /// It gets jobs from a NetSchedule server and runs them simultaneously
532 /// in the different threads (thread pool is used).
533 ///
534 /// @note
535 /// Worker node application is parameterized using INI file settings.
536 /// Please read the sample ini file for more information.
537 ///
539 {
540  NCBI_NET_COMPONENT(GridWorkerNode);
541 
542  /// Construct a worker node using class factories
543  ///
545 
546  void Init();
547 
548  /// Start job execution loop.
549  ///
550  int Run(
551 #ifdef NCBI_OS_UNIX
552  ESwitch daemonize = eDefault,
553 #endif
554  string procinfo_file_name = string());
555 
556  void RequestShutdown();
557 
558  void ForceSingleThread();
559 
560  void SetListener(IGridWorkerNodeApp_Listener* listener);
561 
562  IWorkerNodeJobFactory& GetJobFactory();
563 
564  /// Get the maximum threads running simultaneously
565  ///
566  unsigned int GetMaxThreads() const;
567 
568  /// Get total memory limit (automatic restart if node grows more than that)
569  ///
570  Uint8 GetTotalMemoryLimit() const;
571 
572  /// Get total time limit (automatic restart after that)
573  ///
574  unsigned GetTotalTimeLimit() const;
575  time_t GetStartupTime() const;
576  unsigned GetQueueTimeout() const;
577 
578  bool IsHostInAdminHostsList(const string& host) const;
579 
580  unsigned GetCommitJobInterval() const;
581  unsigned GetCheckStatusPeriod() const;
582  size_t GetServerOutputSize();
583 
584  const string& GetQueueName() const;
585 
586  const string& GetClientName() const;
587 
588  string GetAppName() const;
589 
590  typedef pair<string, SBuildInfo> TVersion;
591  TVersion GetAppVersion() const;
592 
593  const string& GetServiceName() const;
594 
595  CNetCacheAPI GetNetCacheAPI() const;
596  CNetScheduleAPI GetNetScheduleAPI() const;
597  CNetScheduleExecutor GetNSExecutor() const;
598 
599  /// Disable the automatic logging of request-start and
600  /// request-stop events by the framework itself.
604  eDisableStartOnly
605  };
606  static void DisableDefaultRequestEventLogging(
607  EDisabledRequestEvents disabled_events = eDisableStartStop);
608 
609  IWorkerNodeCleanupEventSource* GetCleanupEventSource();
610 
611  void Suspend(bool pullback, unsigned timeout);
612  void Resume();
613  bool IsSuspended() const;
614 };
615 
617 {
618 public:
619  enum EErrCode {
623  eExclusiveModeIsAlreadySet
624  };
625 
626  virtual const char* GetErrCodeString(void) const override
627  {
628  switch (GetErrCode())
629  {
630  case ePortBusy: return "ePortBusy";
631  case eJobIsLost: return "eJobIsLost";
632  case eJobFactoryIsNotSet: return "eJobFactoryIsNotSet";
633  case eExclusiveModeIsAlreadySet: return "eExclusiveModeIsAlreadySet";
634  default: return CException::GetErrCodeString();
635  }
636  }
637 
639 };
640 
641 
642 /* @} */
643 
644 
646 
647 #endif //CONNECT_SERVICES__GRID_WOKER_HPP
CArgs –.
Definition: ncbiargs.hpp:379
Grid Worker Node.
CNcbiApplicationAPI –.
CNcbiEnvironment –.
Definition: ncbienv.hpp:110
Client API for NetCache server.
Client API for NCBI NetSchedule server.
EShutdownLevel
Shutdown level.
Smart pointer to a part of the NetSchedule API that does job retrieval and processing on the worker n...
CObject –.
Definition: ncbiobj.hpp:180
Worker Node Idle Task Context.
Worker Node job context.
Listener of events generated by CGridWorkerNodeApp.
IRegistry –.
Definition: ncbireg.hpp:73
Clean-up event source for the worker node.
Definition: grid_worker.hpp:98
Worker Node Idle Task Interface.
Worker Node initialize context.
Worker Node Job Factory interface.
Jobs watcher interface.
Worker Node Job interface.
static void Init(void)
Definition: cursor6.c:76
static SQLCHAR output[256]
Definition: print.c:5
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST_XX(error_name, err_subcode, message)
Error posting with error code having given name and with given error subcode.
Definition: ncbidiag.hpp:564
virtual const char * GetErrCodeString(void) const
Get error code interpreted as text.
Definition: ncbiexpt.cpp:444
virtual void HandleEvent(EWorkerNodeCleanupEvent cleanup_event)=0
CWorkerNodeIdleThread & m_Thread
virtual void Init(const IWorkerNodeInitContext &context)
Initialize a worker node factory.
virtual void Init(const IWorkerNodeInitContext &context)
Initialize a worker node factory.
static const char *const m_AppName
virtual int Do(CWorkerNodeJobContext &context)=0
Execute the job.
unique_ptr< TWorkerNodeIdleTask > m_IdleTask
virtual ~IWorkerNodeJob()
virtual void AddListener(IWorkerNodeCleanupEventListener *listener)=0
virtual const CNcbiEnvironment & GetEnvironment() const =0
Get environment variables.
virtual CNetCacheAPI GetNetCacheAPI() const =0
Get the shared NetCacheAPI object used by the worker node framework.
virtual IWorkerNodeJob * CreateInstance(void)
Create a job.
virtual void Init(const IWorkerNodeInitContext &)
Initialize a worker node factory.
virtual ~IWorkerNodeJobFactory()
static const char *const m_JobVersion
pair< string, SBuildInfo > TVersion
virtual void Run(CWorkerNodeIdleTaskContext &)=0
Do the Idle task here.
virtual void Notify(const CWorkerNodeJobContext &job, EEvent event)=0
EDisabledRequestEvents
Disable the automatic logging of request-start and request-stop events by the framework itself.
virtual string GetJobVersion() const
Get the job version.
virtual IWorkerNodeIdleTask * GetIdleTask()
Get the Idle task.
virtual IWorkerNodeJob * CreateInstance(void)=0
Create a job.
const IWorkerNodeInitContext * m_WorkerNodeInitContext
virtual CNetScheduleAPI GetNetScheduleAPI() const =0
Get the shared NetScheduleAPI object used by the worker node framework.
virtual string GetJobVersion() const =0
Get the job version.
CWorkerNodeIdleTaskContext(const CWorkerNodeIdleTaskContext &)
virtual void RemoveListener(IWorkerNodeCleanupEventListener *listener)=0
NCBI_EXCEPTION_DEFAULT(CGridWorkerNodeException, CException)
virtual string GetAppVersion() const
virtual const char * GetErrCodeString(void) const override
Get error code interpreted as text.
virtual string GetAppName() const
virtual const CArgs & GetArgs() const =0
Get command line arguments.
virtual const IRegistry & GetConfig() const =0
Get a config file registry.
virtual void CallEventHandlers()=0
CWorkerNodeIdleTaskContext & operator=(const CWorkerNodeIdleTaskContext &)
EWorkerNodeCleanupEvent
Event notifying of a safe clean-up point.
Definition: grid_worker.hpp:77
virtual IWorkerNodeIdleTask * GetIdleTask()
Get the Idle task.
virtual IWorkerNodeCleanupEventSource * GetCleanupEventSource() const =0
Get interface for registering clean-up event listeners.
virtual string GetAppName() const
virtual ~IWorkerNodeIdleTask()
@ eRegularCleanup
For jobs – run from the same thread after Do() is done; for the whole WN – run from a separate (clean...
Definition: grid_worker.hpp:82
@ eOnHardExit
Called on emergency shutdown, always from a different (clean-up) thread, even for the jobs.
Definition: grid_worker.hpp:86
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#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
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
#define kEmptyStr
Definition: ncbistr.hpp:123
void Run(void)
Enter the main loop.
enum ENcbiSwitch ESwitch
Aux.
#define NCBI_XCONNECT_EXPORT
#define NCBI_OS_UNIX
Miscellaneous common-use basic types and functionality.
Process information in the NCBI Registry, including working with configuration files.
NCBI C++ stream class wrappers for triggering between "new" and "old" C++ stream libraries.
Multi-threading – classes, functions, and features.
NetCache client specs.
#define NCBI_NET_COMPONENT(component)
NetSchedule client specs.
Defines CRequestContext class for NCBI C++ diagnostic API.
Job description.
Pool of generic task-executing threads.
static CS_CONTEXT * context
Definition: will_convert.c:21
unique_ptr< CObjectIStream > GetIStream(string path, ESerialDataFormat serial_format)
Modified on Sun May 19 04:46:26 2024 by modify_doxy.py rev. 669887