1 #ifndef CONNECT___THREADED_SERVER__HPP
2 #define CONNECT___THREADED_SERVER__HPP
3 
4 /* $Id: threaded_server.hpp 575325 2018-11-27 18:22:00Z ucko $
5  * ===========================================================================
6  *
7  *                            PUBLIC DOMAIN NOTICE
8  *               National Center for Biotechnology Information
9  *
10  *  This software/database is a "United States Government Work" under the
11  *  terms of the United States Copyright Act.  It was written as part of
12  *  the author's official duties as a United States Government employee and
13  *  thus cannot be copyrighted.  This software/database is freely available
14  *  to the public for use. The National Library of Medicine and the U.S.
15  *  Government have not placed any restriction on its use or reproduction.
16  *
17  *  Although all reasonable efforts have been taken to ensure the accuracy
18  *  and reliability of the software and data, the NLM and the U.S.
19  *  Government do not and cannot warrant the performance or results that
20  *  may be obtained by using this software or data. The NLM and the U.S.
21  *  Government disclaim all warranties, express or implied, including
22  *  warranties of performance, merchantability or fitness for any particular
23  *  purpose.
24  *
25  *  Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Author:  Aaron Ucko
30  *
31  * File Description:
32  *   Framework for a multithreaded network server
33  *
34  */
35 
36 #include <connect/ncbi_conn_exception.hpp>
37 #include <connect/ncbi_core_cxx.hpp>
38 #include <connect/ncbi_socket.hpp>
39 
40 
41 /** @addtogroup ThreadedServer
42  *
43  * @{
44  */
45 
46 
47 BEGIN_NCBI_SCOPE
48 
49 
50 /// Exceptions thrown by CThreadedServer::Run
51 class NCBI_XCONNECT_EXPORT CThreadedServerException
52     : EXCEPTION_VIRTUAL_BASE public CConnException
53 {
54 public:
55     enum EErrCode {
56         eBadParameters, ///< Out-of-range parameters given
57         eCouldntListen  ///< Unable to bind listening port
58     };
59     virtual const char* GetErrCodeString(void) const override;
60     NCBI_EXCEPTION_DEFAULT(CThreadedServerException, CConnException);
61 };
62 
63 
64 /// CThreadedServer - abstract class for network servers using thread pools.
65 ///   This code maintains a pool of threads (initially m_InitThreads, but
66 ///   potentially as many as m_MaxThreads) to deal with incoming connections;
67 ///   each connection gets assigned to one of the worker threads, allowing
68 ///   the server to handle multiple requests in parallel while still checking
69 ///   for new requests.
70 ///
71 ///   You must define Process() to indicate what to do with each incoming
72 ///   connection; .../src/connect/test_threaded_server.cpp illustrates
73 ///   how you might do this.
74 ///
75 /// @deprecated  Use CServer instead.
76 
77 NCBI_DEPRECATED_CLASS NCBI_XCONNECT_EXPORT CThreadedServer
78     : protected CConnIniter
79 {
80 public:
81     CThreadedServer(unsigned short port) :
82         m_InitThreads(5), m_MaxThreads(10), m_QueueSize(20),
83         m_SpawnThreshold(1), m_AcceptTimeout(kInfiniteTimeout),
84         m_TemporarilyStopListening(false), m_Port(port) { }
85 
86     virtual ~CThreadedServer() { }
87 
88     /// Enter the main loop.
89     void Run(void);
90 
91     /// Start listening immediately, or throw an exception if it is
92     /// impossible to do so.  (Does nothing if *this* object is
93     /// already listening on the port.)  Calling StartListening()
94     /// before Run() will permit detecting port-in-use problems before
95     /// the last minute.  (On the other hand, clients that attempt to
96     /// connect in the interim will get no response until the main
97     /// loop actually starts.)
98     void StartListening(void);
99 
100     /// Runs asynchronously (from a separate thread) for each request.
101     /// Implementor must take care of closing the socket when done.
102     /// (Using it as the basis of a CConn_SocketStream object will do
103     /// so automatically.)
104     virtual void Process(SOCK sock) = 0;
105 
106     /// Get the listening port number back.
107     unsigned short GetPort() const { return m_Port; }
108 
109 protected:
110     /// Runs synchronously when request queue is full.
111     /// Implementor must take care of closing socket when done.
112     virtual void ProcessOverflow(SOCK sock) { SOCK_Close(sock); }
113 
114     /// Runs synchronously when accept has timed out.
115     virtual void ProcessTimeout(void) {}
116 
117     /// Runs synchronously between iterations.
118     virtual bool ShutdownRequested(void) { return false; }
119 
120     /// Called at the beginning of Run, before creating thread pool.
121     virtual void SetParams() {}
122 
123     /// Settings for thread pool (which is local to Run):
124 
125     unsigned int    m_InitThreads;     ///< Number of initial threads
126     unsigned int    m_MaxThreads;      ///< Maximum simultaneous threads
127     unsigned int    m_QueueSize;       ///< Maximum size of request queue
128     unsigned int    m_SpawnThreshold;  ///< Controls when to spawn more threads
129     const STimeout* m_AcceptTimeout;   ///< Maximum time between exit checks
130 
131     /// Temporarily close listener when queue fills?
132     bool            m_TemporarilyStopListening;
133 
134 private:
135     unsigned short   m_Port;  ///< TCP port to listen on
136     CListeningSocket m_LSock; ///< Listening socket
137 };
138 
139 
140 END_NCBI_SCOPE
141 
142 
143 /* @} */
144 
145 #endif  /* CONNECT___THREADED_SERVER__HPP */
146