proxygen
ConnectionManager.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
19 
20 #include <chrono>
21 #include <iterator>
22 #include <utility>
23 #include <folly/Memory.h>
28 
29 namespace wangle {
30 
36  public:
37 
42  class Callback {
43  public:
44  virtual ~Callback() = default;
45 
50  virtual void onEmpty(const ConnectionManager& cm) = 0;
51 
55  virtual void onConnectionAdded(const ManagedConnection* conn) = 0;
56 
60  virtual void onConnectionRemoved(const ManagedConnection* conn) = 0;
61  };
62 
63  typedef std::unique_ptr<ConnectionManager, Destructor> UniquePtr;
64 
70  template<typename... Args>
71  static UniquePtr makeUnique(Args&&... args) {
72  return UniquePtr(new ConnectionManager(std::forward<Args>(args)...));
73  }
74 
79  std::chrono::milliseconds timeout,
80  Callback* callback = nullptr);
81 
90  void addConnection(ManagedConnection* connection,
91  bool timeout = false);
92 
96  void scheduleTimeout(ManagedConnection* const connection,
97  std::chrono::milliseconds timeout);
98 
99  /*
100  * Schedule a callback on the wheel timer
101  */
103  std::chrono::milliseconds timeout);
104 
112  void removeConnection(ManagedConnection* connection);
113 
114  /* Begin gracefully shutting down connections in this ConnectionManager.
115  * Notify all connections of pending shutdown, and after idleGrace,
116  * begin closing idle connections.
117  */
118  void initiateGracefulShutdown(std::chrono::milliseconds idleGrace);
119 
124  void drainConnections(double pct, std::chrono::milliseconds idleGrace);
125 
130  void dropAllConnections();
131 
136  void dropConnections(double pct);
137 
138  size_t getNumConnections() const { return conns_.size(); }
139 
140  template <typename F>
141  void iterateConns(F func) {
142  auto it = conns_.begin();
143  while ( it != conns_.end()) {
144  func(&(*it));
145  it++;
146  }
147  }
148 
149  std::chrono::milliseconds getDefaultTimeout() const {
150  return timeout_;
151  }
152 
153  void setLoweredIdleTimeout(std::chrono::milliseconds timeout) {
154  CHECK(timeout >= std::chrono::milliseconds(0));
155  CHECK(timeout <= timeout_);
156  idleConnEarlyDropThreshold_ = timeout;
157  }
158 
163  size_t dropIdleConnections(size_t num);
164 
168  void onActivated(ManagedConnection& conn) override;
169 
170  void onDeactivated(ManagedConnection& conn) override;
171 
172  private:
173 
174  enum class ShutdownState : uint8_t {
175  NONE = 0,
176  // All ManagedConnections receive notifyPendingShutdown
177  NOTIFY_PENDING_SHUTDOWN = 1,
178  // All ManagedConnections have received notifyPendingShutdown
179  NOTIFY_PENDING_SHUTDOWN_COMPLETE = 2,
180  // All ManagedConnections receive closeWhenIdle
181  CLOSE_WHEN_IDLE = 3,
182  // All ManagedConnections have received closeWhenIdle
183  CLOSE_WHEN_IDLE_COMPLETE = 4,
184  };
185 
186  class DrainHelper :
188  public folly::AsyncTimeout {
189  public:
190  explicit DrainHelper(ConnectionManager& manager)
191  : folly::AsyncTimeout(manager.eventBase_),
192  manager_(manager) {}
193 
195  // only cares about full shutdown state
196  if (!all_) {
197  return ShutdownState::NONE;
198  }
199  return shutdownState_;
200  }
201 
203  shutdownState_ = state;
204  }
205 
206  void startDrainPartial(double pct, std::chrono::milliseconds idleGrace);
207  void startDrainAll(std::chrono::milliseconds idleGrace);
208 
209  void runLoopCallback() noexcept override {
210  VLOG(3) << "Draining more conns from loop callback";
212  }
213 
214  void timeoutExpired() noexcept override {
215  VLOG(3) << "Idle grace expired";
217  }
218 
219  void drainConnections();
220 
222 
223  void startDrain(std::chrono::milliseconds idleGrace);
224 
225  ConnectionIterator drainStartIterator() const {
226  if (all_) {
227  return manager_.conns_.begin();
228  }
229  auto it = manager_.conns_.begin();
230  const auto conns_size = manager_.conns_.size();
231  const auto numToDrain =
232  std::max<size_t>(0, std::min<size_t>(conns_size, conns_size * pct_));
233  std::advance(it, conns_size - numToDrain);
234  return it;
235  }
236 
237  private:
238  bool all_{true};
239  double pct_{1.0};
242  };
243 
244  ~ConnectionManager() override = default;
245 
246  ConnectionManager(const ConnectionManager&) = delete;
248 
254  void drainAllConnections();
255 
260 
262 
270 
273 
276 
278  ConnectionIterator drainIterator_;
279  ConnectionIterator idleIterator_;
282 
287  std::chrono::milliseconds timeout_;
288 
298  std::chrono::milliseconds idleConnEarlyDropThreshold_;
299 };
300 
301 } // wangle
size_t dropIdleConnections(size_t num)
virtual void onEmpty(const ConnectionManager &cm)=0
void addConnection(ManagedConnection *connection, bool timeout=false)
ConnectionManager & operator=(ConnectionManager &)=delete
ConnectionIterator drainStartIterator() const
folly::EventBase * eventBase_
ConnectionManager(folly::EventBase *eventBase, std::chrono::milliseconds timeout, Callback *callback=nullptr)
std::unique_ptr< ConnectionManager, Destructor > UniquePtr
virtual void onConnectionRemoved(const ManagedConnection *conn)=0
std::chrono::milliseconds getDefaultTimeout() const
ConnectionIterator drainIterator_
size_t getNumConnections() const
folly::SafeIntrusiveListHook listHook_
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
void removeConnection(ManagedConnection *connection)
void onActivated(ManagedConnection &conn) override
void initiateGracefulShutdown(std::chrono::milliseconds idleGrace)
folly::CountedIntrusiveList< ManagedConnection,&ManagedConnection::listHook_ >::iterator ConnectionIterator
~ConnectionManager() override=default
void onDeactivated(ManagedConnection &conn) override
void scheduleTimeout(ManagedConnection *const connection, std::chrono::milliseconds timeout)
static UniquePtr makeUnique(Args &&...args)
ConnectionIterator idleIterator_
void drainConnections(double pct, std::chrono::milliseconds idleGrace)
std::chrono::milliseconds timeout_
DrainHelper(ConnectionManager &manager)
folly::CountedIntrusiveList< ManagedConnection,&ManagedConnection::listHook_ > conns_
virtual void onConnectionAdded(const ManagedConnection *conn)=0
void setLoweredIdleTimeout(std::chrono::milliseconds timeout)
std::chrono::milliseconds idleConnEarlyDropThreshold_
void setShutdownState(ShutdownState state)
boost::intrusive::list< T, boost::intrusive::member_hook< T, SafeIntrusiveListHook, PtrToMember >, boost::intrusive::constant_time_size< true >> CountedIntrusiveList
state
Definition: http_parser.c:272