2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <folly/wangle/acceptor/ManagedConnection.h>
22 #include <folly/Memory.h>
23 #include <folly/io/async/AsyncTimeout.h>
24 #include <folly/io/async/HHWheelTimer.h>
25 #include <folly/io/async/DelayedDestruction.h>
26 #include <folly/io/async/EventBase.h>
28 namespace folly { namespace wangle {
31 * A ConnectionManager keeps track of ManagedConnections.
33 class ConnectionManager: public folly::DelayedDestruction {
37 * Interface for an optional observer that's notified about
38 * various events in a ConnectionManager
42 virtual ~Callback() {}
45 * Invoked when the number of connections managed by the
46 * ConnectionManager changes from nonzero to zero.
48 virtual void onEmpty(const ConnectionManager& cm) = 0;
51 * Invoked when a connection is added to the ConnectionManager.
53 virtual void onConnectionAdded(const ConnectionManager& cm) = 0;
56 * Invoked when a connection is removed from the ConnectionManager.
58 virtual void onConnectionRemoved(const ConnectionManager& cm) = 0;
61 typedef std::unique_ptr<ConnectionManager, Destructor> UniquePtr;
64 * Returns a new instance of ConnectionManager wrapped in a unique_ptr
66 template<typename... Args>
67 static UniquePtr makeUnique(Args&&... args) {
68 return folly::make_unique<ConnectionManager, Destructor>(
69 std::forward<Args>(args)...);
73 * Constructor not to be used by itself.
75 ConnectionManager(folly::EventBase* eventBase,
76 std::chrono::milliseconds timeout,
77 Callback* callback = nullptr);
80 * Add a connection to the set of connections managed by this
83 * @param connection The connection to add.
84 * @param timeout Whether to immediately register this connection
85 * for an idle timeout callback.
87 void addConnection(ManagedConnection* connection,
88 bool timeout = false);
91 * Schedule a timeout callback for a connection.
93 void scheduleTimeout(ManagedConnection* connection);
96 * Schedule a callback on the wheel timer
98 void scheduleTimeout(folly::HHWheelTimer::Callback* callback,
99 std::chrono::milliseconds timeout);
102 * Remove a connection from this ConnectionManager and, if
103 * applicable, cancel the pending timeout callback that the
104 * ConnectionManager has scheduled for the connection.
106 * @note This method does NOT destroy the connection.
108 void removeConnection(ManagedConnection* connection);
110 /* Begin gracefully shutting down connections in this ConnectionManager.
111 * Notify all connections of pending shutdown, and after idleGrace,
112 * begin closing idle connections.
114 void initiateGracefulShutdown(std::chrono::milliseconds idleGrace);
117 * Destroy all connections Managed by this ConnectionManager, even
118 * the ones that are busy.
120 void dropAllConnections();
122 size_t getNumConnections() const { return conns_.size(); }
124 template <typename F>
125 void iterateConns(F func) {
126 auto it = conns_.begin();
127 while ( it != conns_.end()) {
134 class CloseIdleConnsCallback :
135 public folly::EventBase::LoopCallback,
136 public folly::AsyncTimeout {
138 explicit CloseIdleConnsCallback(ConnectionManager* manager)
139 : folly::AsyncTimeout(manager->eventBase_),
142 void runLoopCallback() noexcept override {
143 VLOG(3) << "Draining more conns from loop callback";
144 manager_->drainAllConnections();
147 void timeoutExpired() noexcept override {
148 VLOG(3) << "Idle grace expired";
149 manager_->drainAllConnections();
153 ConnectionManager* manager_;
156 enum class ShutdownAction : uint8_t {
158 * Drain part 1: inform remote that you will soon reject new requests.
162 * Drain part 2: start rejecting new requests.
167 ~ConnectionManager() {}
169 ConnectionManager(const ConnectionManager&) = delete;
170 ConnectionManager& operator=(ConnectionManager&) = delete;
173 * Destroy all connections managed by this ConnectionManager that
174 * are currently idle, as determined by a call to each ManagedConnection's
177 void drainAllConnections();
179 /** All connections */
180 folly::CountedIntrusiveList<
181 ManagedConnection,&ManagedConnection::listHook_> conns_;
183 /** Connections that currently are registered for timeouts */
184 folly::HHWheelTimer::UniquePtr connTimeouts_;
186 /** Optional callback to notify of state changes */
189 /** Event base in which we run */
190 folly::EventBase* eventBase_;
192 /** Iterator to the next connection to shed; used by drainAllConnections() */
193 folly::CountedIntrusiveList<
194 ManagedConnection,&ManagedConnection::listHook_>::iterator idleIterator_;
195 CloseIdleConnsCallback idleLoopCallback_;
196 ShutdownAction action_{ShutdownAction::DRAIN1};
197 std::chrono::milliseconds timeout_;