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

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: Fix/add comments Created 7 years, 3 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/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.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) 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/message_loop.h" 10 #include "base/message_loop/message_loop.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 : handle_(handle), 158 : handle_(handle),
159 callback_(callback), 159 callback_(callback),
160 priority_(priority), 160 priority_(priority),
161 ignore_limits_(ignore_limits), 161 ignore_limits_(ignore_limits),
162 flags_(flags), 162 flags_(flags),
163 net_log_(net_log) {} 163 net_log_(net_log) {}
164 164
165 ClientSocketPoolBaseHelper::Request::~Request() {} 165 ClientSocketPoolBaseHelper::Request::~Request() {}
166 166
167 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( 167 ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper(
168 HigherLayeredPool* pool,
168 int max_sockets, 169 int max_sockets,
169 int max_sockets_per_group, 170 int max_sockets_per_group,
170 base::TimeDelta unused_idle_socket_timeout, 171 base::TimeDelta unused_idle_socket_timeout,
171 base::TimeDelta used_idle_socket_timeout, 172 base::TimeDelta used_idle_socket_timeout,
172 ConnectJobFactory* connect_job_factory) 173 ConnectJobFactory* connect_job_factory)
173 : idle_socket_count_(0), 174 : idle_socket_count_(0),
174 connecting_socket_count_(0), 175 connecting_socket_count_(0),
175 handed_out_socket_count_(0), 176 handed_out_socket_count_(0),
176 max_sockets_(max_sockets), 177 max_sockets_(max_sockets),
177 max_sockets_per_group_(max_sockets_per_group), 178 max_sockets_per_group_(max_sockets_per_group),
178 use_cleanup_timer_(g_cleanup_timer_enabled), 179 use_cleanup_timer_(g_cleanup_timer_enabled),
179 unused_idle_socket_timeout_(unused_idle_socket_timeout), 180 unused_idle_socket_timeout_(unused_idle_socket_timeout),
180 used_idle_socket_timeout_(used_idle_socket_timeout), 181 used_idle_socket_timeout_(used_idle_socket_timeout),
181 connect_job_factory_(connect_job_factory), 182 connect_job_factory_(connect_job_factory),
182 connect_backup_jobs_enabled_(false), 183 connect_backup_jobs_enabled_(false),
183 pool_generation_number_(0), 184 pool_generation_number_(0),
185 pool_(pool),
184 weak_factory_(this) { 186 weak_factory_(this) {
185 DCHECK_LE(0, max_sockets_per_group); 187 DCHECK_LE(0, max_sockets_per_group);
186 DCHECK_LE(max_sockets_per_group, max_sockets); 188 DCHECK_LE(max_sockets_per_group, max_sockets);
187 189
188 NetworkChangeNotifier::AddIPAddressObserver(this); 190 NetworkChangeNotifier::AddIPAddressObserver(this);
189 } 191 }
190 192
191 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { 193 ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() {
192 // Clean up any idle sockets and pending connect jobs. Assert that we have no 194 // Clean up any idle sockets and pending connect jobs. Assert that we have no
193 // remaining active sockets or pending requests. They should have all been 195 // remaining active sockets or pending requests. They should have all been
194 // cleaned up prior to |this| being destroyed. 196 // cleaned up prior to |this| being destroyed.
195 FlushWithError(ERR_ABORTED); 197 FlushWithError(ERR_ABORTED);
196 DCHECK(group_map_.empty()); 198 DCHECK(group_map_.empty());
197 DCHECK(pending_callback_map_.empty()); 199 DCHECK(pending_callback_map_.empty());
198 DCHECK_EQ(0, connecting_socket_count_); 200 DCHECK_EQ(0, connecting_socket_count_);
199 CHECK(higher_layer_pools_.empty()); 201 CHECK(higher_pools_.empty());
200 202
201 NetworkChangeNotifier::RemoveIPAddressObserver(this); 203 NetworkChangeNotifier::RemoveIPAddressObserver(this);
204
205 // Remove from lower layer pools.
206 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
207 it != lower_pools_.end();
208 ++it) {
209 (*it)->RemoveHigherLayeredPool(pool_);
210 }
202 } 211 }
203 212
204 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair() 213 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair()
205 : result(OK) { 214 : result(OK) {
206 } 215 }
207 216
208 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair( 217 ClientSocketPoolBaseHelper::CallbackResultPair::CallbackResultPair(
209 const CompletionCallback& callback_in, int result_in) 218 const CompletionCallback& callback_in, int result_in)
210 : callback(callback_in), 219 : callback(callback_in),
211 result(result_in) { 220 result(result_in) {
(...skipping 19 matching lines...) Expand all
231 ClientSocketPoolBaseHelper::RemoveRequestFromQueue( 240 ClientSocketPoolBaseHelper::RemoveRequestFromQueue(
232 const RequestQueue::iterator& it, Group* group) { 241 const RequestQueue::iterator& it, Group* group) {
233 const Request* req = *it; 242 const Request* req = *it;
234 group->mutable_pending_requests()->erase(it); 243 group->mutable_pending_requests()->erase(it);
235 // If there are no more requests, we kill the backup timer. 244 // If there are no more requests, we kill the backup timer.
236 if (group->pending_requests().empty()) 245 if (group->pending_requests().empty())
237 group->CleanupBackupJob(); 246 group->CleanupBackupJob();
238 return req; 247 return req;
239 } 248 }
240 249
241 void ClientSocketPoolBaseHelper::AddLayeredPool(LayeredPool* pool) { 250 bool ClientSocketPoolBaseHelper::IsStalled() const {
242 CHECK(pool); 251 // If a lower layer pool is stalled, consider |this| stalled as well.
243 CHECK(!ContainsKey(higher_layer_pools_, pool)); 252 for (std::set<LowerLayeredPool*>::const_iterator it = lower_pools_.begin();
244 higher_layer_pools_.insert(pool); 253 it != lower_pools_.end();
254 ++it) {
255 if ((*it)->IsStalled())
256 return true;
257 }
258
259 // If we are not using |max_sockets_|, then clearly we are not stalled.
akalin 2013/08/22 19:23:25 "not using |max_sockets_|" can be interpreted as "
mmenke 2013/08/22 19:53:05 Done. I also removed use of "we" (This was actual
260 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
261 return false;
262 // So in order to be stalled we need to be using |max_sockets_| AND
akalin 2013/08/22 19:23:25 same thing here? (although I realize it's kinda aw
mmenke 2013/08/22 19:53:05 Done (-> "using at least |max_sockets_|"). Also g
263 // we need to have a request that is actually stalled on the global
264 // socket limit. To find such a request, we look for a group that
265 // a has more requests that jobs AND where the number of jobs is less
266 // than |max_sockets_per_group_|. (If the number of jobs is equal to
267 // |max_sockets_per_group_|, then the request is stalled on the group,
268 // which does not count.)
269 for (GroupMap::const_iterator it = group_map_.begin();
270 it != group_map_.end(); ++it) {
271 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
272 return true;
273 }
274 return false;
245 } 275 }
246 276
247 void ClientSocketPoolBaseHelper::RemoveLayeredPool(LayeredPool* pool) { 277 void ClientSocketPoolBaseHelper::AddLowerLayeredPool(
248 CHECK(pool); 278 LowerLayeredPool* lower_pool) {
249 CHECK(ContainsKey(higher_layer_pools_, pool)); 279 DCHECK(pool_);
250 higher_layer_pools_.erase(pool); 280 CHECK(!ContainsKey(lower_pools_, lower_pool));
281 lower_pools_.insert(lower_pool);
282 lower_pool->AddHigherLayeredPool(pool_);
283 }
284
285 void ClientSocketPoolBaseHelper::AddHigherLayeredPool(
286 HigherLayeredPool* higher_pool) {
287 CHECK(higher_pool);
288 CHECK(!ContainsKey(higher_pools_, higher_pool));
289 higher_pools_.insert(higher_pool);
290 }
291
292 void ClientSocketPoolBaseHelper::RemoveHigherLayeredPool(
293 HigherLayeredPool* higher_pool) {
294 CHECK(higher_pool);
295 CHECK(ContainsKey(higher_pools_, higher_pool));
296 higher_pools_.erase(higher_pool);
251 } 297 }
252 298
253 int ClientSocketPoolBaseHelper::RequestSocket( 299 int ClientSocketPoolBaseHelper::RequestSocket(
254 const std::string& group_name, 300 const std::string& group_name,
255 const Request* request) { 301 const Request* request) {
256 CHECK(!request->callback().is_null()); 302 CHECK(!request->callback().is_null());
257 CHECK(request->handle()); 303 CHECK(request->handle());
258 304
259 // Cleanup any timed-out idle sockets if no timer is used. 305 // Cleanup any timed-out idle sockets if no timer is used.
260 if (!use_cleanup_timer_) 306 if (!use_cleanup_timer_)
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 socket.reset(); 829 socket.reset();
784 } 830 }
785 831
786 CheckForStalledSocketGroups(); 832 CheckForStalledSocketGroups();
787 } 833 }
788 834
789 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() { 835 void ClientSocketPoolBaseHelper::CheckForStalledSocketGroups() {
790 // If we have idle sockets, see if we can give one to the top-stalled group. 836 // If we have idle sockets, see if we can give one to the top-stalled group.
791 std::string top_group_name; 837 std::string top_group_name;
792 Group* top_group = NULL; 838 Group* top_group = NULL;
793 if (!FindTopStalledGroup(&top_group, &top_group_name)) 839 if (!FindTopStalledGroup(&top_group, &top_group_name)) {
840 // There may still be a stalled group in a lower level pool.
841 for (std::set<LowerLayeredPool*>::iterator it = lower_pools_.begin();
842 it != lower_pools_.end();
843 ++it) {
844 if ((*it)->IsStalled()) {
845 CloseOneIdleSocket();
846 break;
847 }
848 }
794 return; 849 return;
850 }
795 851
796 if (ReachedMaxSocketsLimit()) { 852 if (ReachedMaxSocketsLimit()) {
797 if (idle_socket_count() > 0) { 853 if (idle_socket_count() > 0) {
798 CloseOneIdleSocket(); 854 CloseOneIdleSocket();
799 } else { 855 } else {
800 // We can't activate more sockets since we're already at our global 856 // We can't activate more sockets since we're already at our global
801 // limit. 857 // limit.
802 return; 858 return;
803 } 859 }
804 } 860 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 FlushWithError(ERR_NETWORK_CHANGED); 973 FlushWithError(ERR_NETWORK_CHANGED);
918 } 974 }
919 975
920 void ClientSocketPoolBaseHelper::FlushWithError(int error) { 976 void ClientSocketPoolBaseHelper::FlushWithError(int error) {
921 pool_generation_number_++; 977 pool_generation_number_++;
922 CancelAllConnectJobs(); 978 CancelAllConnectJobs();
923 CloseIdleSockets(); 979 CloseIdleSockets();
924 CancelAllRequestsWithError(error); 980 CancelAllRequestsWithError(error);
925 } 981 }
926 982
927 bool ClientSocketPoolBaseHelper::IsStalled() const {
928 // If we are not using |max_sockets_|, then clearly we are not stalled
929 if ((handed_out_socket_count_ + connecting_socket_count_) < max_sockets_)
930 return false;
931 // So in order to be stalled we need to be using |max_sockets_| AND
932 // we need to have a request that is actually stalled on the global
933 // socket limit. To find such a request, we look for a group that
934 // a has more requests that jobs AND where the number of jobs is less
935 // than |max_sockets_per_group_|. (If the number of jobs is equal to
936 // |max_sockets_per_group_|, then the request is stalled on the group,
937 // which does not count.)
938 for (GroupMap::const_iterator it = group_map_.begin();
939 it != group_map_.end(); ++it) {
940 if (it->second->IsStalledOnPoolMaxSockets(max_sockets_per_group_))
941 return true;
942 }
943 return false;
944 }
945
946 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job, 983 void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job,
947 Group* group) { 984 Group* group) {
948 CHECK_GT(connecting_socket_count_, 0); 985 CHECK_GT(connecting_socket_count_, 0);
949 connecting_socket_count_--; 986 connecting_socket_count_--;
950 987
951 DCHECK(group); 988 DCHECK(group);
952 group->RemoveJob(job); 989 group->RemoveJob(job);
953 990
954 // If we've got no more jobs for this group, then we no longer need a 991 // If we've got no more jobs for this group, then we no longer need a
955 // backup job either. 992 // backup job either.
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 if (group->IsEmpty()) 1138 if (group->IsEmpty())
1102 RemoveGroup(i); 1139 RemoveGroup(i);
1103 1140
1104 return true; 1141 return true;
1105 } 1142 }
1106 } 1143 }
1107 1144
1108 return false; 1145 return false;
1109 } 1146 }
1110 1147
1111 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInLayeredPool() { 1148 bool ClientSocketPoolBaseHelper::CloseOneIdleConnectionInHigherLayeredPool() {
1112 // This pool doesn't have any idle sockets. It's possible that a pool at a 1149 // This pool doesn't have any idle sockets. It's possible that a pool at a
1113 // higher layer is holding one of this sockets active, but it's actually idle. 1150 // higher layer is holding one of this sockets active, but it's actually idle.
1114 // Query the higher layers. 1151 // Query the higher layers.
1115 for (std::set<LayeredPool*>::const_iterator it = higher_layer_pools_.begin(); 1152 for (std::set<HigherLayeredPool*>::const_iterator it = higher_pools_.begin();
1116 it != higher_layer_pools_.end(); ++it) { 1153 it != higher_pools_.end(); ++it) {
1117 if ((*it)->CloseOneIdleConnection()) 1154 if ((*it)->CloseOneIdleConnection())
1118 return true; 1155 return true;
1119 } 1156 }
1120 return false; 1157 return false;
1121 } 1158 }
1122 1159
1123 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater( 1160 void ClientSocketPoolBaseHelper::InvokeUserCallbackLater(
1124 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) { 1161 ClientSocketHandle* handle, const CompletionCallback& callback, int rv) {
1125 CHECK(!ContainsKey(pending_callback_map_, handle)); 1162 CHECK(!ContainsKey(pending_callback_map_, handle));
1126 pending_callback_map_[handle] = CallbackResultPair(callback, rv); 1163 pending_callback_map_[handle] = CallbackResultPair(callback, rv);
(...skipping 15 matching lines...) Expand all
1142 CompletionCallback callback = it->second.callback; 1179 CompletionCallback callback = it->second.callback;
1143 int result = it->second.result; 1180 int result = it->second.result;
1144 pending_callback_map_.erase(it); 1181 pending_callback_map_.erase(it);
1145 callback.Run(result); 1182 callback.Run(result);
1146 } 1183 }
1147 1184
1148 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() { 1185 void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() {
1149 while (IsStalled()) { 1186 while (IsStalled()) {
1150 // Closing a socket will result in calling back into |this| to use the freed 1187 // Closing a socket will result in calling back into |this| to use the freed
1151 // socket slot, so nothing else is needed. 1188 // socket slot, so nothing else is needed.
1152 if (!CloseOneIdleConnectionInLayeredPool()) 1189 if (!CloseOneIdleConnectionInHigherLayeredPool())
1153 return; 1190 return;
1154 } 1191 }
1155 } 1192 }
1156 1193
1157 ClientSocketPoolBaseHelper::Group::Group() 1194 ClientSocketPoolBaseHelper::Group::Group()
1158 : unassigned_job_count_(0), 1195 : unassigned_job_count_(0),
1159 active_socket_count_(0), 1196 active_socket_count_(0),
1160 weak_factory_(this) {} 1197 weak_factory_(this) {}
1161 1198
1162 ClientSocketPoolBaseHelper::Group::~Group() { 1199 ClientSocketPoolBaseHelper::Group::~Group() {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 STLDeleteElements(&jobs_); 1294 STLDeleteElements(&jobs_);
1258 unassigned_job_count_ = 0; 1295 unassigned_job_count_ = 0;
1259 1296
1260 // Cancel pending backup job. 1297 // Cancel pending backup job.
1261 weak_factory_.InvalidateWeakPtrs(); 1298 weak_factory_.InvalidateWeakPtrs();
1262 } 1299 }
1263 1300
1264 } // namespace internal 1301 } // namespace internal
1265 1302
1266 } // namespace net 1303 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/client_socket_pool_base.h ('k') | net/socket/client_socket_pool_base_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698