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

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

Issue 18796003: When an idle socket is added back to a socket pool, check for stalled jobs in lower pools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Undo somewhat tangential change Created 7 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "net/socket/client_socket_pool_base.h" 5 #include "net/socket/client_socket_pool_base.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/format_macros.h" 8 #include "base/format_macros.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 : handle_(handle), 154 : handle_(handle),
155 callback_(callback), 155 callback_(callback),
156 priority_(priority), 156 priority_(priority),
157 ignore_limits_(ignore_limits), 157 ignore_limits_(ignore_limits),
158 flags_(flags), 158 flags_(flags),
159 net_log_(net_log) {} 159 net_log_(net_log) {}
160 160
161 ClientSocketPoolBaseHelper::Request::~Request() {} 161 ClientSocketPoolBaseHelper::Request::~Request() {}
162 162
163 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( 163 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper(
164 HigherLayeredPool* pool,
164 int max_sockets, 165 int max_sockets,
165 int max_sockets_per_group, 166 int max_sockets_per_group,
166 base::TimeDelta unused_idle_socket_timeout, 167 base::TimeDelta unused_idle_socket_timeout,
167 base::TimeDelta used_idle_socket_timeout, 168 base::TimeDelta used_idle_socket_timeout,
168 ConnectJobFactory* connect_job_factory) 169 ConnectJobFactory* connect_job_factory)
169 : idle_socket_count_(0), 170 : idle_socket_count_(0),
170 connecting_socket_count_(0), 171 connecting_socket_count_(0),
171 handed_out_socket_count_(0), 172 handed_out_socket_count_(0),
172 max_sockets_(max_sockets), 173 max_sockets_(max_sockets),
173 max_sockets_per_group_(max_sockets_per_group), 174 max_sockets_per_group_(max_sockets_per_group),
174 use_cleanup_timer_(g_cleanup_timer_enabled), 175 use_cleanup_timer_(g_cleanup_timer_enabled),
175 unused_idle_socket_timeout_(unused_idle_socket_timeout), 176 unused_idle_socket_timeout_(unused_idle_socket_timeout),
176 used_idle_socket_timeout_(used_idle_socket_timeout), 177 used_idle_socket_timeout_(used_idle_socket_timeout),
177 connect_job_factory_(connect_job_factory), 178 connect_job_factory_(connect_job_factory),
178 connect_backup_jobs_enabled_(false), 179 connect_backup_jobs_enabled_(false),
179 pool_generation_number_(0), 180 pool_generation_number_(0),
181 pool_(pool),
180 weak_factory_(this) { 182 weak_factory_(this) {
181 DCHECK_LE(0, max_sockets_per_group); 183 DCHECK_LE(0, max_sockets_per_group);
182 DCHECK_LE(max_sockets_per_group, max_sockets); 184 DCHECK_LE(max_sockets_per_group, max_sockets);
183 185
184 NetworkChangeNotifier::AddIPAddressObserver(this); 186 NetworkChangeNotifier::AddIPAddressObserver(this);
185 } 187 }
186 188
187 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { 189 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() {
188 // Clean up any idle sockets and pending connect jobs. Assert that we have no 190 // Clean up any idle sockets and pending connect jobs. Assert that we have no
189 // remaining active sockets or pending requests. They should have all been 191 // remaining active sockets or pending requests. They should have all been
190 // cleaned up prior to |this| being destroyed. 192 // cleaned up prior to |this| being destroyed.
191 FlushWithError(ERR_ABORTED); 193 FlushWithError(ERR_ABORTED);
192 DCHECK(group_map_.empty()); 194 DCHECK(group_map_.empty());
193 DCHECK(pending_callback_map_.empty()); 195 DCHECK(pending_callback_map_.empty());
194 DCHECK_EQ(0, connecting_socket_count_); 196 DCHECK_EQ(0, connecting_socket_count_);
195 CHECK(higher_layer_pools_.empty()); 197 CHECK(higher_pools_.empty());
196 198
197 NetworkChangeNotifier::RemoveIPAddressObserver(this); 199 NetworkChangeNotifier::RemoveIPAddressObserver(this);
200
201 // Remove from lower layer pools.
202 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
203 it != lower_pools_.end();
204 ++it) {
205 (*it)->RemoveHigherLayeredPool(pool_);
206 }
198 } 207 }
199 208
200 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() 209 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair()
201 : result(OK) { 210 : result(OK) {
202 } 211 }
203 212
204 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( 213 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair(
205 const CompletionCallback& callback_in, int result_in) 214 const CompletionCallback& callback_in, int result_in)
206 : callback(callback_in), 215 : callback(callback_in),
207 result(result_in) { 216 result(result_in) {
(...skipping 19 matching lines...) Expand all
227 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( 236 ClientSocketPoolBaseHelper::RemoveRequestFromQueue(
228 const RequestQueue::iterator& it, Group* group) { 237 const RequestQueue::iterator& it, Group* group) {
229 const Request* req = *it; 238 const Request* req = *it;
230 group->mutable_pending_requests()->erase(it); 239 group->mutable_pending_requests()->erase(it);
231 // If there are no more requests, we kill the backup timer. 240 // If there are no more requests, we kill the backup timer.
232 if (group->pending_requests().empty()) 241 if (group->pending_requests().empty())
233 group->CleanupBackupJob(); 242 group->CleanupBackupJob();
234 return req; 243 return req;
235 } 244 }
236 245
237 void ClientSocketPoolBaseHelper::AddLayeredPool(LayeredPool* pool) { 246 bool ClientSocketPoolBaseHelper::IsStalled() const {
238 CHECK(pool); 247 // If a lower layer pool is stalled, consider |this| stalled as well.
Ryan Hamilton 2013/07/21 14:53:54 This seems like mostly a good idea, but how does i
mmenke 2013/07/22 20:13:33 SpdySessions can never be stalled. They aren't co
Ryan Hamilton 2013/07/22 20:22:46 Works for me. FWIW, there is a streams/session li
mmenke 2013/07/24 19:05:23 Yea, I don't think so - that would need to be deal
239 CHECK(!ContainsKey(higher_layer_pools_, pool)); 248 for (std::set<LowerLayeredPool*>::const_iterator it = lower_pools_.begin();
240 higher_layer_pools_.insert(pool); 249 it != lower_pools_.end();
250 ++it) {
251 if ((*it)->IsStalled())
252 return true;
253 }
254
255 // If we are not using |max_sockets_|, then clearly we are not stalled
256 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
257 return false;
258 // So in order to be stalled we need to be using |max_sockets_| AND
259 // we need to have a request that is actually stalled on the global
260 // socket limit. To find such a request, we look for a group that
261 // a has more requests that jobs AND where the number of jobs is less
262 // than |max_sockets_per_group_|. (If the number of jobs is equal to
263 // |max_sockets_per_group_|, then the request is stalled on the group,
264 // which does not count.)
265 for (GroupMap::const_iterator it = group_map_.begin();
266 it != group_map_.end(); ++it) {
267 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
268 return true;
269 }
270 return false;
241 } 271 }
242 272
243 void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) { 273 void ClientSocketPoolBaseHelper::AddLowerLayeredPool(
244 CHECK(pool); 274 LowerLayeredPool* lower_pool) {
245 CHECK(ContainsKey(higher_layer_pools_, pool)); 275 DCHECK(pool_);
246 higher_layer_pools_.erase(pool); 276 CHECK(!ContainsKey(lower_pools_, lower_pool));
277 lower_pools_.insert(lower_pool);
278 lower_pool->AddHigherLayeredPool(pool_);
279 }
280
281 void ClientSocketPoolBaseHelper::AddHigherLayeredPool(
282 HigherLayeredPool* higher_pool) {
283 CHECK(higher_pool);
284 CHECK(!ContainsKey(higher_pools_, higher_pool));
285 higher_pools_.insert(higher_pool);
286 }
287
288 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool(
289 HigherLayeredPool* higher_pool) {
290 CHECK(higher_pool);
291 CHECK(ContainsKey(higher_pools_, higher_pool));
292 higher_pools_.erase(higher_pool);
247 } 293 }
248 294
249 int ClientSocketPoolBaseHelper::RequestSocket( 295 int ClientSocketPoolBaseHelper::RequestSocket(
250 const std::string& group_name, 296 const std::string& group_name,
251 const Request* request) { 297 const Request* request) {
252 CHECK(!request->callback().is_null()); 298 CHECK(!request->callback().is_null());
253 CHECK(request->handle()); 299 CHECK(request->handle());
254 300
255 // Cleanup any timed-out idle sockets if no timer is used. 301 // Cleanup any timed-out idle sockets if no timer is used.
256 if (!use_cleanup_timer_) 302 if (!use_cleanup_timer_)
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 delete socket; 823 delete socket;
778 } 824 }
779 825
780 CheckForStalledSocketGroups(); 826 CheckForStalledSocketGroups();
781 } 827 }
782 828
783 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { 829 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() {
784 // If we have idle sockets, see if we can give one to the top-stalled group. 830 // If we have idle sockets, see if we can give one to the top-stalled group.
785 std::string top_group_name; 831 std::string top_group_name;
786 Group* top_group = NULL; 832 Group* top_group = NULL;
787 if (!FindTopStalledGroup(&top_group, &top_group_name)) 833 if (!FindTopStalledGroup(&top_group, &top_group_name)) {
834 // There may still be a stalled group in a lower level pool.
835 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
836 it != lower_pools_.end();
837 ++it) {
838 if ((*it)->IsStalled()) {
839 CloseOneIdleSocket();
840 break;
841 }
842 }
788 return; 843 return;
844 }
789 845
790 if (ReachedMaxSocketsLimit()) { 846 if (ReachedMaxSocketsLimit()) {
791 if (idle_socket_count() > 0) { 847 if (idle_socket_count() > 0) {
792 CloseOneIdleSocket(); 848 CloseOneIdleSocket();
793 } else { 849 } else {
794 // We can't activate more sockets since we're already at our global 850 // We can't activate more sockets since we're already at our global
795 // limit. 851 // limit.
796 return; 852 return;
797 } 853 }
798 } 854 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 FlushWithError(ERR_NETWORK_CHANGED); 964 FlushWithError(ERR_NETWORK_CHANGED);
909 } 965 }
910 966
911 void ClientSocketPoolBaseHelper::FlushWithError(int error) { 967 void ClientSocketPoolBaseHelper::FlushWithError(int error) {
912 pool_generation_number_++; 968 pool_generation_number_++;
913 CancelAllConnectJobs(); 969 CancelAllConnectJobs();
914 CloseIdleSockets(); 970 CloseIdleSockets();
915 CancelAllRequestsWithError(error); 971 CancelAllRequestsWithError(error);
916 } 972 }
917 973
918 bool ClientSocketPoolBaseHelper::IsStalled() const {
919 // If we are not using |max_sockets_|, then clearly we are not stalled
920 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
921 return false;
922 // So in order to be stalled we need to be using |max_sockets_| AND
923 // we need to have a request that is actually stalled on the global
924 // socket limit. To find such a request, we look for a group that
925 // a has more requests that jobs AND where the number of jobs is less
926 // than |max_sockets_per_group_|. (If the number of jobs is equal to
927 // |max_sockets_per_group_|, then the request is stalled on the group,
928 // which does not count.)
929 for (GroupMap::const_iterator it = group_map_.begin();
930 it != group_map_.end(); ++it) {
931 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
932 return true;
933 }
934 return false;
935 }
936
937 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, 974 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job,
938 Group* group) { 975 Group* group) {
939 CHECK_GT(connecting_socket_count_, 0); 976 CHECK_GT(connecting_socket_count_, 0);
940 connecting_socket_count_--; 977 connecting_socket_count_--;
941 978
942 DCHECK(group); 979 DCHECK(group);
943 DCHECK(ContainsKey(group->jobs(), job)); 980 DCHECK(ContainsKey(group->jobs(), job));
944 group->RemoveJob(job); 981 group->RemoveJob(job);
945 982
946 // If we've got no more jobs for this group, then we no longer need a 983 // If we've got no more jobs for this group, then we no longer need a
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 if (group->IsEmpty()) 1131 if (group->IsEmpty())
1095 RemoveGroup(i); 1132 RemoveGroup(i);
1096 1133
1097 return true; 1134 return true;
1098 } 1135 }
1099 } 1136 }
1100 1137
1101 return false; 1138 return false;
1102 } 1139 }
1103 1140
1104 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() { 1141 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() {
1105 // This pool doesn't have any idle sockets. It's possible that a pool at a 1142 // This pool doesn't have any idle sockets. It's possible that a pool at a
1106 // higher layer is holding one of this sockets active, but it's actually idle. 1143 // higher layer is holding one of this sockets active, but it's actually idle.
1107 // Query the higher layers. 1144 // Query the higher layers.
1108 for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin(); 1145 for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin();
1109 it != higher_layer_pools_.end(); ++it) { 1146 it != higher_pools_.end(); ++it) {
1110 if ((*it)->CloseOneIdleConnection()) 1147 if ((*it)->CloseOneIdleConnection())
1111 return true; 1148 return true;
1112 } 1149 }
1113 return false; 1150 return false;
1114 } 1151 }
1115 1152
1116 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( 1153 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater(
1117 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { 1154 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) {
1118 CHECK(!ContainsKey(pending_callback_map_, handle)); 1155 CHECK(!ContainsKey(pending_callback_map_, handle));
1119 pending_callback_map_[handle] = CallbackResultPair(callback, rv); 1156 pending_callback_map_[handle] = CallbackResultPair(callback, rv);
(...skipping 15 matching lines...) Expand all
1135 CompletionCallback callback = it->second.callback; 1172 CompletionCallback callback = it->second.callback;
1136 int result = it->second.result; 1173 int result = it->second.result;
1137 pending_callback_map_.erase(it); 1174 pending_callback_map_.erase(it);
1138 callback.Run(result); 1175 callback.Run(result);
1139 } 1176 }
1140 1177
1141 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { 1178 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() {
1142 while (IsStalled()) { 1179 while (IsStalled()) {
1143 // Closing a socket will result in calling back into |this| to use the freed 1180 // Closing a socket will result in calling back into |this| to use the freed
1144 // socket slot, so nothing else is needed. 1181 // socket slot, so nothing else is needed.
1145 if (!CloseOneIdleConnectionInLayeredPool()) 1182 if (!CloseOneIdleConnectionInHigherLayeredPool())
1146 return; 1183 return;
1147 } 1184 }
1148 } 1185 }
1149 1186
1150 ClientSocketPoolBaseHelper::Group::Group() 1187 ClientSocketPoolBaseHelper::Group::Group()
1151 : unassigned_job_count_(0), 1188 : unassigned_job_count_(0),
1152 active_socket_count_(0), 1189 active_socket_count_(0),
1153 weak_factory_(this) {} 1190 weak_factory_(this) {}
1154 1191
1155 ClientSocketPoolBaseHelper::Group::~Group() { 1192 ClientSocketPoolBaseHelper::Group::~Group() {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 STLDeleteElements(&jobs_); 1279 STLDeleteElements(&jobs_);
1243 unassigned_job_count_ = 0; 1280 unassigned_job_count_ = 0;
1244 1281
1245 // Cancel pending backup job. 1282 // Cancel pending backup job.
1246 weak_factory_.InvalidateWeakPtrs(); 1283 weak_factory_.InvalidateWeakPtrs();
1247 } 1284 }
1248 1285
1249 } // namespace internal 1286 } // namespace internal
1250 1287
1251 } // namespace net 1288 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698