| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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_ |
| OLD | NEW |