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

Go to the SVN repository for this file.

1 #ifndef CORELIB___REQUEST_CONTROL__HPP
2 #define CORELIB___REQUEST_CONTROL__HPP
3 
4 /* $Id: request_control.hpp 84598 2018-11-20 20:23:54Z 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  * Authors: Denis Vakatov, Vladimir Ivanov, Victor Joukov
30  *
31  * File Description:
32  * Manage request rate to some shared resource
33  *
34  */
35 
36 #include <corelib/ncbi_limits.hpp>
37 #include <corelib/ncbitime.hpp>
38 #include <deque>
39 
40 /** @addtogroup Utility
41  *
42  * @{
43  */
44 
46 
47 
48 /////////////////////////////////////////////////////////////////////////////
49 ///
50 /// CRequestRateControlException --
51 ///
52 /// Define exceptions generated by CRequestThrottler.
53 ///
54 /// CRequestThrottlerException inherits its basic functionality from
55 /// CCoreException and defines additional error codes.
56 
58 {
59 public:
60  /// Error types that CRequestRateControl can generate.
61  enum EErrCode {
62  eNumRequestsMax, ///< Maximum number of requests exceeded;
63  eNumRequestsPerPeriod, ///< Number of requests per period exceeded;
64  eMinTimeBetweenRequests ///< The time between two consecutive requests
65  ///< is too short;
66  };
67  /// Translate from the error code value to its string representation.
68  virtual const char* GetErrCodeString(void) const override;
69 
70  // Standard exception boilerplate code.
72 };
73 
74 
75 
76 /////////////////////////////////////////////////////////////////////////////
77 ///
78 /// CRequestRateControl --
79 ///
80 /// Manage request rate to some shared resource, for example.
81 
83 {
84 public:
85  /// Special value for maximum number of allowed requests per period.
86  /// Disable any kind of request throttling.
87  ///
88  /// @sa
89  /// Reset
90  static const unsigned int kNoLimit = kMax_UInt;
91 
92  /// What to do if exceeded the rate limits.
94  eSleep, ///< Sleep till the rate requirements are met & return
95  eErrCode, ///< Return immediately with err code == FALSE
96  eException, ///< Throw an exception
97  eDefault ///< in c-tor -- eSleep; in Approve() -- value set in c-tor
98  };
99 
100  /// Throttle mode.
101  ///
102  /// In case if number of requests and time period are specified,
103  /// it is possible to select between two modes for request throttler.
104  /// First mode is eContinuous. It use internal time line to check number
105  /// of requests in the past period of time, using current time as ending
106  /// point for that period. Starting point determinates with ordinary
107  /// subtraction of "per_period" time, specified in object's constructor,
108  /// from current time. So the controlled time frame moves continuously
109  /// in time.
110  /// Contrary to continuos mode, eDiscrete mode have fixed starting point
111  /// for period of time, where throttler checks number of incoming
112  /// requests. First time period starts when CRequestRateControl object
113  /// creates. Each next period starts with interval of "per_period",
114  /// or from first approved request in case of long period of inactivity.
115  /// When each new period starts, the throttler drops all restrictions,
116  /// and starts to count number of allowed requests per period from zero.
117  /// Usually eDiscrete mode is a little bit faster and less memory consuming.
119  eContinuous, ///< Uses float time frame to check number of requests
120  eDiscrete ///< Uses fixed time frame to check number of requests
121  };
122 
123  /// Constructor.
124  ///
125  /// Construct class object. Run Reset() method.
126  ///
127  /// @sa
128  /// Reset, EThrottleAction, EThrottleMode
130  (unsigned int num_requests_allowed,
131  CTimeSpan per_period = CTimeSpan(1,0),
132  CTimeSpan min_time_between_requests = CTimeSpan(0,0),
133  EThrottleAction throttle_action = eDefault,
134  EThrottleMode throttle_mode = eContinuous);
135 
136  /// Set new restriction for throttling mechanism.
137  ///
138  /// Zero values for time spans 'per_period' or 'min_time_between_requests'
139  /// means no rate restriction for that throttling mechanism, respectively.
140  ///
141  /// @param num_requests_allowed
142  /// Maximum number of allowed requests per 'per_period'.
143  /// Can be kNoLimit for unlimited number of requests (throttler is disabled,
144  /// Approve() always returns TRUE).
145  /// @param per_period
146  /// Time span in which only 'num_requests_allowed' requests can be
147  /// approved.
148  /// @param min_time_between_requests
149  /// Minimum time between two succesful consecutive requests.
150  /// @param throttle_action
151  /// Set throttle action by default. The eDefault means eSleep here.
152  /// @param throttle_mode
153  /// Set throttle action by default. The eDefault means eSleep here.
154  /// For backward compatibility, use eContinuous mode by default.
155  /// @sa
156  /// Approve, ApproveTime
157  void Reset(unsigned int num_requests_allowed,
158  CTimeSpan per_period = CTimeSpan(1,0),
159  CTimeSpan min_time_between_requests = CTimeSpan(0,0),
160  EThrottleAction throttle_action = eDefault,
161  EThrottleMode throttle_mode = eContinuous);
162 
163  /// Approve a request.
164  ///
165  /// @param action
166  /// Throttle action used by this function call. If passed argument
167  /// equal to eDefault that use throttle action was set in
168  /// the constructor.
169  /// @return
170  /// Return TRUE if everything meet to established requirements.
171  /// Return FALSE if some requirements are not passed, or
172  /// throw exception if throttle action was set to eException.
173  /// @sa
174  /// Reset, ApproveTime
175  bool Approve(EThrottleAction action = eDefault);
176 
177  /// Get a time span in which request can be approved.
178  ///
179  /// You should call this method until it returns zero time span, otherwise
180  /// you should sleep (using Sleep() method) for indicated time.
181  ///
182  /// @return
183  /// Returns time to wait until actual request, zero if can proceed
184  /// immediately.
185  /// If you use this method with absolute limitation (no time period and
186  /// no minimum between requests) and the limitation is exhausted it will
187  /// throw an exception.
188  /// @sa
189  /// Reset, Approve
190  CTimeSpan ApproveTime(void);
191 
192  /// Sleep for CTimeSpan.
193  ///
194  /// @param sleep_time
195  /// For how long to sleep. If it's impossible to sleep to that long in
196  /// millisecond range, rounds up sleep time to the whole seconds.
197  static void Sleep(CTimeSpan sleep_time);
198 
199  /// Lock/unlock functions for use by generic RAII guard CGuard.
200  /// See 'corelib/guard.hpp' for details.
201 
202  void Lock() { Approve(eSleep); }
203  void Unlock() { /* do nothing */ }
204 
205  /// Check if throttling is enabled.
206  bool IsEnabled(void) const { return m_NumRequestsAllowed != kNoLimit; }
207 
208 private:
209  typedef double TTime;
210 
211  ///
212  bool x_Approve(EThrottleAction action, CTimeSpan *sleeptime);
213 
214  /// Remove from the list of approved requests all expared items.
215  void x_CleanTimeLine(TTime now);
216 
217 private:
218  // Saved parameters
220  unsigned int m_NumRequestsAllowed;
224 
225  CStopWatch m_StopWatch; ///< Stopwatch to measure elapsed time
226  typedef deque<TTime> TTimeLine;
227  TTimeLine m_TimeLine; ///< Vector of times of approvals
228  TTime m_LastApproved; ///< Last approve time
229  unsigned int m_NumRequests; ///< Num requests per period
230 };
231 
232 
233 //////////////////////////////////////////////////////////////////////////////
234 //
235 // Inline
236 //
237 
238 inline
240 {
241  return x_Approve(action, 0);
242 }
243 
244 inline
246 {
247  CTimeSpan sleeptime;
248  bool res = x_Approve(eSleep, &sleeptime);
249  if ( !res ) {
250  return sleeptime;
251  }
252  // Approve request
253  return CTimeSpan(0, 0);
254 }
255 
256 
258 
259 /* @} */
260 
261 #endif /* CORELIB___REQUEST_CONTROL__HPP */
CCoreException –.
Definition: ncbiexpt.hpp:1476
CRequestRateControlException –.
CRequestRateControl –.
CStopWatch –.
Definition: ncbitime.hpp:1938
CTimeSpan.
Definition: ncbitime.hpp:1313
virtual const char * GetErrCodeString(void) const override
Translate from the error code value to its string representation.
Definition: ncbiexpt.cpp:757
EErrCode
Error types that an application can generate.
Definition: ncbiexpt.hpp:884
#define kMax_UInt
Definition: ncbi_limits.h:185
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int m_NumRequests
Num requests per period.
EThrottleAction
What to do if exceeded the rate limits.
bool IsEnabled(void) const
Check if throttling is enabled.
EThrottleMode
Throttle mode.
EThrottleAction m_ThrottleAction
CStopWatch m_StopWatch
Stopwatch to measure elapsed time.
CTimeSpan ApproveTime(void)
Get a time span in which request can be approved.
unsigned int m_NumRequestsAllowed
TTimeLine m_TimeLine
Vector of times of approvals.
void Lock()
Lock/unlock functions for use by generic RAII guard CGuard.
bool Approve(EThrottleAction action=eDefault)
Approve a request.
deque< TTime > TTimeLine
NCBI_EXCEPTION_DEFAULT(CRequestRateControlException, CCoreException)
bool x_Approve(EThrottleAction action, CTimeSpan *sleeptime)
TTime m_LastApproved
Last approve time.
@ eSleep
Sleep till the rate requirements are met & return.
@ eException
Throw an exception.
@ eErrCode
Return immediately with err code == FALSE.
@ eContinuous
Uses float time frame to check number of requests.
@ eNumRequestsPerPeriod
Number of requests per period exceeded;.
@ eNumRequestsMax
Maximum number of requests exceeded;.
#define NCBI_XNCBI_EXPORT
Definition: ncbi_export.h:1283
Defines: CTimeFormat - storage class for time format.
Modified on Thu Feb 29 12:23:02 2024 by modify_doxy.py rev. 669887