Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: net/socket/client_socket_pool_base.h

Issue 149027: Limit total number of sockets in the system.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: reorder Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_network_session.cc ('k') | net/socket/client_socket_pool_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 5 #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
6 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 6 #define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <map> 9 #include <map>
10 #include <set> 10 #include <set>
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 120
121 virtual ConnectJob* NewConnectJob( 121 virtual ConnectJob* NewConnectJob(
122 const std::string& group_name, 122 const std::string& group_name,
123 const Request& request, 123 const Request& request,
124 ConnectJob::Delegate* delegate) const = 0; 124 ConnectJob::Delegate* delegate) const = 0;
125 125
126 private: 126 private:
127 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); 127 DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
128 }; 128 };
129 129
130 ClientSocketPoolBase(int max_sockets_per_group, 130 ClientSocketPoolBase(int max_sockets,
131 int max_sockets_per_group,
131 ConnectJobFactory* connect_job_factory); 132 ConnectJobFactory* connect_job_factory);
132 133
133 ~ClientSocketPoolBase(); 134 ~ClientSocketPoolBase();
134 135
135 int RequestSocket(const std::string& group_name, 136 int RequestSocket(const std::string& group_name,
136 const HostResolver::RequestInfo& resolve_info, 137 const HostResolver::RequestInfo& resolve_info,
137 int priority, 138 int priority,
138 ClientSocketHandle* handle, 139 ClientSocketHandle* handle,
139 CompletionCallback* callback); 140 CompletionCallback* callback);
140 141
141 void CancelRequest(const std::string& group_name, 142 void CancelRequest(const std::string& group_name,
142 const ClientSocketHandle* handle); 143 const ClientSocketHandle* handle);
143 144
144 void ReleaseSocket(const std::string& group_name, 145 void ReleaseSocket(const std::string& group_name,
145 ClientSocket* socket); 146 ClientSocket* socket);
146 147
147 void CloseIdleSockets(); 148 void CloseIdleSockets();
148 149
149 int idle_socket_count() const { 150 int idle_socket_count() const {
150 return idle_socket_count_; 151 return idle_socket_count_;
151 } 152 }
152 153
153 int max_sockets_per_group() const {
154 return max_sockets_per_group_;
155 }
156
157 int IdleSocketCountInGroup(const std::string& group_name) const; 154 int IdleSocketCountInGroup(const std::string& group_name) const;
158 155
159 LoadState GetLoadState(const std::string& group_name, 156 LoadState GetLoadState(const std::string& group_name,
160 const ClientSocketHandle* handle) const; 157 const ClientSocketHandle* handle) const;
161 158
162 virtual void OnConnectJobComplete(int result, ConnectJob* job); 159 virtual void OnConnectJobComplete(int result, ConnectJob* job);
163 160
164 // Enables late binding of sockets. In this mode, socket requests are 161 // Enables late binding of sockets. In this mode, socket requests are
165 // decoupled from socket connection jobs. A socket request may initiate a 162 // decoupled from socket connection jobs. A socket request may initiate a
166 // socket connection job, but there is no guarantee that that socket 163 // socket connection job, but there is no guarantee that that socket
167 // connection will service the request (for example, a released socket may 164 // connection will service the request (for example, a released socket may
168 // service the request sooner, or a higher priority request may come in 165 // service the request sooner, or a higher priority request may come in
169 // afterward and receive the socket from the job). 166 // afterward and receive the socket from the job).
170 static void EnableLateBindingOfSockets(bool enabled); 167 static void EnableLateBindingOfSockets(bool enabled);
171 168
169 // For testing.
170 bool may_have_stalled_group() const { return may_have_stalled_group_; }
171
172 private: 172 private:
173 // Entry for a persistent socket which became idle at time |start_time|. 173 // Entry for a persistent socket which became idle at time |start_time|.
174 struct IdleSocket { 174 struct IdleSocket {
175 IdleSocket() : socket(NULL), used(false) {} 175 IdleSocket() : socket(NULL), used(false) {}
176 ClientSocket* socket; 176 ClientSocket* socket;
177 base::TimeTicks start_time; 177 base::TimeTicks start_time;
178 bool used; // Indicates whether or not the socket has been used yet. 178 bool used; // Indicates whether or not the socket has been used yet.
179 179
180 // An idle socket should be removed if it can't be reused, or has been idle 180 // An idle socket should be removed if it can't be reused, or has been idle
181 // for too long. |now| is the current time value (TimeTicks::Now()). 181 // for too long. |now| is the current time value (TimeTicks::Now()).
(...skipping 15 matching lines...) Expand all
197 197
198 bool IsEmpty() const { 198 bool IsEmpty() const {
199 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty(); 199 return active_socket_count == 0 && idle_sockets.empty() && jobs.empty();
200 } 200 }
201 201
202 bool HasAvailableSocketSlot(int max_sockets_per_group) const { 202 bool HasAvailableSocketSlot(int max_sockets_per_group) const {
203 return active_socket_count + static_cast<int>(jobs.size()) < 203 return active_socket_count + static_cast<int>(jobs.size()) <
204 max_sockets_per_group; 204 max_sockets_per_group;
205 } 205 }
206 206
207 int TopPendingPriority() const {
208 return pending_requests.front().priority;
209 }
210
207 std::deque<IdleSocket> idle_sockets; 211 std::deque<IdleSocket> idle_sockets;
208 std::set<const ConnectJob*> jobs; 212 std::set<const ConnectJob*> jobs;
209 RequestQueue pending_requests; 213 RequestQueue pending_requests;
210 RequestMap connecting_requests; 214 RequestMap connecting_requests;
211 int active_socket_count; // number of active sockets used by clients 215 int active_socket_count; // number of active sockets used by clients
212 }; 216 };
213 217
214 typedef std::map<std::string, Group> GroupMap; 218 typedef std::map<std::string, Group> GroupMap;
215 219
216 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap; 220 typedef std::map<const ClientSocketHandle*, ConnectJob*> ConnectJobMap;
217 typedef std::set<const ConnectJob*> ConnectJobSet; 221 typedef std::set<const ConnectJob*> ConnectJobSet;
218 222
219 static void InsertRequestIntoQueue(const Request& r, 223 static void InsertRequestIntoQueue(const Request& r,
220 RequestQueue* pending_requests); 224 RequestQueue* pending_requests);
221 225
222 // Closes all idle sockets if |force| is true. Else, only closes idle 226 // Closes all idle sockets if |force| is true. Else, only closes idle
223 // sockets that timed out or can't be reused. 227 // sockets that timed out or can't be reused.
224 void CleanupIdleSockets(bool force); 228 void CleanupIdleSockets(bool force);
225 229
226 // Called when the number of idle sockets changes. 230 // Called when the number of idle sockets changes.
227 void IncrementIdleCount(); 231 void IncrementIdleCount();
228 void DecrementIdleCount(); 232 void DecrementIdleCount();
229 233
230 // Called via PostTask by ReleaseSocket. 234 // Called via PostTask by ReleaseSocket.
231 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); 235 void DoReleaseSocket(const std::string& group_name, ClientSocket* socket);
232 236
237 // Scans the group map for groups which have an available socket slot and
238 // at least one pending request. Returns number of groups found, and if found
239 // at least one, fills |group| and |group_name| with data of the stalled group
240 // having highest priority.
241 int FindTopStalledGroup(Group** group, std::string* group_name);
242
233 // Called when timer_ fires. This method scans the idle sockets removing 243 // Called when timer_ fires. This method scans the idle sockets removing
234 // sockets that timed out or can't be reused. 244 // sockets that timed out or can't be reused.
235 void OnCleanupTimerFired() { 245 void OnCleanupTimerFired() {
236 CleanupIdleSockets(false); 246 CleanupIdleSockets(false);
237 } 247 }
238 248
239 // Removes the ConnectJob corresponding to |handle| from the 249 // Removes the ConnectJob corresponding to |handle| from the
240 // |connect_job_map_| or |connect_job_set_| depending on whether or not late 250 // |connect_job_map_| or |connect_job_set_| depending on whether or not late
241 // binding is enabled. |job| must be non-NULL when late binding is 251 // binding is enabled. |job| must be non-NULL when late binding is
242 // enabled. Also updates |group| if non-NULL. 252 // enabled. Also updates |group| if non-NULL.
(...skipping 19 matching lines...) Expand all
262 272
263 // Adds |socket| to the list of idle sockets for |group|. |used| indicates 273 // Adds |socket| to the list of idle sockets for |group|. |used| indicates
264 // whether or not the socket has previously been used. 274 // whether or not the socket has previously been used.
265 void AddIdleSocket(ClientSocket* socket, bool used, Group* group); 275 void AddIdleSocket(ClientSocket* socket, bool used, Group* group);
266 276
267 // Iterates through |connect_job_map_|, canceling all ConnectJobs. 277 // Iterates through |connect_job_map_|, canceling all ConnectJobs.
268 // Afterwards, it iterates through all groups and deletes them if they are no 278 // Afterwards, it iterates through all groups and deletes them if they are no
269 // longer needed. 279 // longer needed.
270 void CancelAllConnectJobs(); 280 void CancelAllConnectJobs();
271 281
282 // Returns true if we can't create any more sockets due to the total limit.
283 // TODO(phajdan.jr): Also take idle sockets into account.
284 bool ReachedMaxSocketsLimit() const;
285
272 GroupMap group_map_; 286 GroupMap group_map_;
273 287
274 ConnectJobMap connect_job_map_; 288 ConnectJobMap connect_job_map_;
275 289
276 // Timer used to periodically prune idle sockets that timed out or can't be 290 // Timer used to periodically prune idle sockets that timed out or can't be
277 // reused. 291 // reused.
278 base::RepeatingTimer<ClientSocketPoolBase> timer_; 292 base::RepeatingTimer<ClientSocketPoolBase> timer_;
279 293
280 // The total number of idle sockets in the system. 294 // The total number of idle sockets in the system.
281 int idle_socket_count_; 295 int idle_socket_count_;
282 296
297 // Number of connecting sockets across all groups.
298 int connecting_socket_count_;
299
300 // Number of connected sockets we handed out across all groups.
301 int handed_out_socket_count_;
302
303 // The maximum total number of sockets. See ReachedMaxSocketsLimit.
304 const int max_sockets_;
305
283 // The maximum number of sockets kept per group. 306 // The maximum number of sockets kept per group.
284 const int max_sockets_per_group_; 307 const int max_sockets_per_group_;
285 308
309 // Until the maximum number of sockets limit is reached, a group can only
310 // have pending requests if it exceeds the "max sockets per group" limit.
311 //
312 // This means when a socket is released, the only pending requests that can
313 // be started next belong to the same group.
314 //
315 // However once the |max_sockets_| limit is reached, this stops being true:
316 // groups can now have pending requests without having first reached the
317 // |max_sockets_per_group_| limit. So choosing the next request involves
318 // selecting the highest priority request across *all* groups.
319 //
320 // Since reaching the maximum number of sockets is an edge case, we make note
321 // of when it happens, and thus avoid doing the slower "scan all groups"
322 // in the common case.
323 bool may_have_stalled_group_;
324
286 const scoped_ptr<ConnectJobFactory> connect_job_factory_; 325 const scoped_ptr<ConnectJobFactory> connect_job_factory_;
287 326
288 // Controls whether or not we use late binding of sockets. 327 // Controls whether or not we use late binding of sockets.
289 static bool g_late_binding; 328 static bool g_late_binding;
290 329
291 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase); 330 DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolBase);
292 }; 331 };
293 332
294 } // namespace net 333 } // namespace net
295 334
296 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_ 335 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
OLDNEW
« no previous file with comments | « net/http/http_network_session.cc ('k') | net/socket/client_socket_pool_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698