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/experimental/wangle/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(); }
125 class CloseIdleConnsCallback :
126 public folly::EventBase::LoopCallback,
127 public folly::AsyncTimeout {
129 explicit CloseIdleConnsCallback(ConnectionManager* manager)
130 : folly::AsyncTimeout(manager->eventBase_),
133 void runLoopCallback() noexcept override {
134 VLOG(3) << "Draining more conns from loop callback";
135 manager_->drainAllConnections();
138 void timeoutExpired() noexcept override {
139 VLOG(3) << "Idle grace expired";
140 manager_->drainAllConnections();
144 ConnectionManager* manager_;
147 enum class ShutdownAction : uint8_t {
149 * Drain part 1: inform remote that you will soon reject new requests.
153 * Drain part 2: start rejecting new requests.
158 ~ConnectionManager() {}
160 ConnectionManager(const ConnectionManager&) = delete;
161 ConnectionManager& operator=(ConnectionManager&) = delete;
164 * Destroy all connections managed by this ConnectionManager that
165 * are currently idle, as determined by a call to each ManagedConnection's
168 void drainAllConnections();
170 /** All connections */
171 folly::CountedIntrusiveList<
172 ManagedConnection,&ManagedConnection::listHook_> conns_;
174 /** Connections that currently are registered for timeouts */
175 folly::HHWheelTimer::UniquePtr connTimeouts_;
177 /** Optional callback to notify of state changes */
180 /** Event base in which we run */
181 folly::EventBase* eventBase_;
183 /** Iterator to the next connection to shed; used by drainAllConnections() */
184 folly::CountedIntrusiveList<
185 ManagedConnection,&ManagedConnection::listHook_>::iterator idleIterator_;
186 CloseIdleConnsCallback idleLoopCallback_;
187 ShutdownAction action_{ShutdownAction::DRAIN1};
188 std::chrono::milliseconds timeout_;