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 #include "net/http/http_cache.h" | 5 #include "net/http/http_cache.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 | 10 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 // This bit is set if the response info has vary header data. | 60 // This bit is set if the response info has vary header data. |
61 RESPONSE_INFO_HAS_VARY_DATA = 1 << 11, | 61 RESPONSE_INFO_HAS_VARY_DATA = 1 << 11, |
62 | 62 |
63 // TODO(darin): Add other bits to indicate alternate request methods and | 63 // TODO(darin): Add other bits to indicate alternate request methods and |
64 // whether or not we are storing a partial document. For now, we don't | 64 // whether or not we are storing a partial document. For now, we don't |
65 // support storing those. | 65 // support storing those. |
66 }; | 66 }; |
67 | 67 |
68 //----------------------------------------------------------------------------- | 68 //----------------------------------------------------------------------------- |
69 | 69 |
| 70 static int kTransactionTimeoutInMillisecond = 5000; |
| 71 |
70 struct HeaderNameAndValue { | 72 struct HeaderNameAndValue { |
71 const char* name; | 73 const char* name; |
72 const char* value; | 74 const char* value; |
73 }; | 75 }; |
74 | 76 |
75 // If the request includes one of these request headers, then avoid caching | 77 // If the request includes one of these request headers, then avoid caching |
76 // to avoid getting confused. | 78 // to avoid getting confused. |
77 static const HeaderNameAndValue kPassThroughHeaders[] = { | 79 static const HeaderNameAndValue kPassThroughHeaders[] = { |
78 { "range", NULL }, // causes unexpected 206s | 80 { "range", NULL }, // causes unexpected 206s |
79 { "if-modified-since", NULL }, // causes unexpected 304s | 81 { "if-modified-since", NULL }, // causes unexpected 304s |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 mode_(NONE), | 149 mode_(NONE), |
148 read_offset_(0), | 150 read_offset_(0), |
149 effective_load_flags_(0), | 151 effective_load_flags_(0), |
150 final_upload_progress_(0), | 152 final_upload_progress_(0), |
151 ALLOW_THIS_IN_INITIALIZER_LIST( | 153 ALLOW_THIS_IN_INITIALIZER_LIST( |
152 network_info_callback_(this, &Transaction::OnNetworkInfoAvailable)), | 154 network_info_callback_(this, &Transaction::OnNetworkInfoAvailable)), |
153 ALLOW_THIS_IN_INITIALIZER_LIST( | 155 ALLOW_THIS_IN_INITIALIZER_LIST( |
154 network_read_callback_(this, &Transaction::OnNetworkReadCompleted)), | 156 network_read_callback_(this, &Transaction::OnNetworkReadCompleted)), |
155 ALLOW_THIS_IN_INITIALIZER_LIST( | 157 ALLOW_THIS_IN_INITIALIZER_LIST( |
156 cache_read_callback_(new CancelableCompletionCallback<Transaction>( | 158 cache_read_callback_(new CancelableCompletionCallback<Transaction>( |
157 this, &Transaction::OnCacheReadCompleted))) { | 159 this, &Transaction::OnCacheReadCompleted))), |
| 160 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), |
| 161 is_waiting_for_entry_(false) { |
158 } | 162 } |
159 | 163 |
160 // Clean up the transaction. | 164 // Clean up the transaction. |
161 virtual ~Transaction(); | 165 virtual ~Transaction(); |
162 | 166 |
163 // HttpTransaction methods: | 167 // HttpTransaction methods: |
164 virtual int Start(const HttpRequestInfo*, CompletionCallback*); | 168 virtual int Start(const HttpRequestInfo*, CompletionCallback*); |
165 virtual int RestartIgnoringLastError(CompletionCallback*); | 169 virtual int RestartIgnoringLastError(CompletionCallback*); |
166 virtual int RestartWithAuth(const std::wstring& username, | 170 virtual int RestartWithAuth(const std::wstring& username, |
167 const std::wstring& password, | 171 const std::wstring& password, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 | 203 |
200 const std::string& key() const { return cache_key_; } | 204 const std::string& key() const { return cache_key_; } |
201 | 205 |
202 // Associates this transaction with a cache entry. | 206 // Associates this transaction with a cache entry. |
203 int AddToEntry(); | 207 int AddToEntry(); |
204 | 208 |
205 // Called by the HttpCache when the given disk cache entry becomes accessible | 209 // Called by the HttpCache when the given disk cache entry becomes accessible |
206 // to the transaction. Returns network error code. | 210 // to the transaction. Returns network error code. |
207 int EntryAvailable(ActiveEntry* entry); | 211 int EntryAvailable(ActiveEntry* entry); |
208 | 212 |
| 213 // Called by the HttpCache when the given disk cache entry is busy. Sets up |
| 214 // a timeout alarm to MessageLoop. |
| 215 void PendOnEntry(ActiveEntry* entry); |
| 216 |
209 private: | 217 private: |
210 // This is a helper function used to trigger a completion callback. It may | 218 // This is a helper function used to trigger a completion callback. It may |
211 // only be called if callback_ is non-null. | 219 // only be called if callback_ is non-null. |
212 void DoCallback(int rv); | 220 void DoCallback(int rv); |
213 | 221 |
214 // This will trigger the completion callback if appropriate. | 222 // This will trigger the completion callback if appropriate. |
215 int HandleResult(int rv); | 223 int HandleResult(int rv); |
216 | 224 |
217 // Set request_ and fields derived from it. | 225 // Set request_ and fields derived from it. |
218 void SetRequest(const HttpRequestInfo* request); | 226 void SetRequest(const HttpRequestInfo* request); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 | 279 |
272 // Called to signal completion of the network transaction's Start method: | 280 // Called to signal completion of the network transaction's Start method: |
273 void OnNetworkInfoAvailable(int result); | 281 void OnNetworkInfoAvailable(int result); |
274 | 282 |
275 // Called to signal completion of the network transaction's Read method: | 283 // Called to signal completion of the network transaction's Read method: |
276 void OnNetworkReadCompleted(int result); | 284 void OnNetworkReadCompleted(int result); |
277 | 285 |
278 // Called to signal completion of the cache's ReadData method: | 286 // Called to signal completion of the cache's ReadData method: |
279 void OnCacheReadCompleted(int result); | 287 void OnCacheReadCompleted(int result); |
280 | 288 |
| 289 // Called to bypass cache when it took too much time to get access to cache. |
| 290 void OnAddToEntryTimeout(ActiveEntry* entry); |
| 291 |
281 const HttpRequestInfo* request_; | 292 const HttpRequestInfo* request_; |
282 scoped_ptr<HttpRequestInfo> custom_request_; | 293 scoped_ptr<HttpRequestInfo> custom_request_; |
283 HttpCache* cache_; | 294 HttpCache* cache_; |
284 HttpCache::ActiveEntry* entry_; | 295 HttpCache::ActiveEntry* entry_; |
285 scoped_ptr<HttpTransaction> network_trans_; | 296 scoped_ptr<HttpTransaction> network_trans_; |
286 CompletionCallback* callback_; // consumer's callback | 297 CompletionCallback* callback_; // consumer's callback |
287 HttpResponseInfo response_; | 298 HttpResponseInfo response_; |
288 HttpResponseInfo auth_response_; | 299 HttpResponseInfo auth_response_; |
289 std::string cache_key_; | 300 std::string cache_key_; |
290 Mode mode_; | 301 Mode mode_; |
291 scoped_refptr<IOBuffer> read_buf_; | 302 scoped_refptr<IOBuffer> read_buf_; |
292 int read_offset_; | 303 int read_offset_; |
293 int effective_load_flags_; | 304 int effective_load_flags_; |
294 uint64 final_upload_progress_; | 305 uint64 final_upload_progress_; |
295 CompletionCallbackImpl<Transaction> network_info_callback_; | 306 CompletionCallbackImpl<Transaction> network_info_callback_; |
296 CompletionCallbackImpl<Transaction> network_read_callback_; | 307 CompletionCallbackImpl<Transaction> network_read_callback_; |
297 scoped_refptr<CancelableCompletionCallback<Transaction> > | 308 scoped_refptr<CancelableCompletionCallback<Transaction> > |
298 cache_read_callback_; | 309 cache_read_callback_; |
| 310 |
| 311 ScopedRunnableMethodFactory<Transaction> task_factory_; |
| 312 bool is_waiting_for_entry_; |
299 }; | 313 }; |
300 | 314 |
301 HttpCache::Transaction::~Transaction() { | 315 HttpCache::Transaction::~Transaction() { |
302 if (!revoked()) { | 316 if (!revoked()) { |
303 if (entry_) { | 317 if (entry_) { |
304 cache_->DoneWithEntry(entry_, this); | 318 cache_->DoneWithEntry(entry_, this); |
305 } else { | 319 } else { |
306 cache_->RemovePendingTransaction(this); | 320 cache_->RemovePendingTransaction(this); |
307 } | 321 } |
308 } | 322 } |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 // | 545 // |
532 // o if we are a reader for the transaction, then we can start reading the | 546 // o if we are a reader for the transaction, then we can start reading the |
533 // cache entry. | 547 // cache entry. |
534 // | 548 // |
535 // o if we can read or write, then we should check if the cache entry needs | 549 // o if we can read or write, then we should check if the cache entry needs |
536 // to be validated and then issue a network request if needed or just read | 550 // to be validated and then issue a network request if needed or just read |
537 // from the cache if the cache entry is already valid. | 551 // from the cache if the cache entry is already valid. |
538 // | 552 // |
539 int rv; | 553 int rv; |
540 entry_ = entry; | 554 entry_ = entry; |
| 555 is_waiting_for_entry_ = false; |
541 switch (mode_) { | 556 switch (mode_) { |
542 case READ: | 557 case READ: |
543 rv = BeginCacheRead(); | 558 rv = BeginCacheRead(); |
544 break; | 559 break; |
545 case WRITE: | 560 case WRITE: |
546 rv = BeginNetworkRequest(); | 561 rv = BeginNetworkRequest(); |
547 break; | 562 break; |
548 case READ_WRITE: | 563 case READ_WRITE: |
549 rv = BeginCacheValidation(); | 564 rv = BeginCacheValidation(); |
550 break; | 565 break; |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 | 958 |
944 if (result > 0) { | 959 if (result > 0) { |
945 read_offset_ += result; | 960 read_offset_ += result; |
946 } else if (result == 0) { // end of file | 961 } else if (result == 0) { // end of file |
947 cache_->DoneReadingFromEntry(entry_, this); | 962 cache_->DoneReadingFromEntry(entry_, this); |
948 entry_ = NULL; | 963 entry_ = NULL; |
949 } | 964 } |
950 HandleResult(result); | 965 HandleResult(result); |
951 } | 966 } |
952 | 967 |
| 968 void HttpCache::Transaction::PendOnEntry(ActiveEntry* entry) { |
| 969 if (is_waiting_for_entry_) { |
| 970 // Don't add timeout alarm more than once. |
| 971 return; |
| 972 } |
| 973 |
| 974 is_waiting_for_entry_ = true; |
| 975 |
| 976 MessageLoop::current()->PostDelayedTask( |
| 977 FROM_HERE, |
| 978 task_factory_.NewRunnableMethod(&Transaction::OnAddToEntryTimeout, entry), |
| 979 kTransactionTimeoutInMillisecond); |
| 980 } |
| 981 |
| 982 void HttpCache::Transaction::OnAddToEntryTimeout(ActiveEntry* entry) { |
| 983 if (!is_waiting_for_entry_) { |
| 984 // Already added to entry. |
| 985 return; |
| 986 } |
| 987 |
| 988 if (mode_ == READ) { |
| 989 // We cannot bypass the cache. |
| 990 return; |
| 991 } |
| 992 |
| 993 // Check that the writer is still busy, and then give up accessing cache. |
| 994 if (entry->writer && |
| 995 entry->writer->GetLoadState() == LOAD_STATE_WAITING_FOR_USER_ACTION) { |
| 996 // There is a writer transaction suspended due to some error. Bypass |
| 997 // cache if we can. |
| 998 entry->pending_queue.remove(this); |
| 999 mode_ = NONE; |
| 1000 is_waiting_for_entry_ = false; |
| 1001 BeginNetworkRequest(); |
| 1002 } |
| 1003 } |
| 1004 |
953 //----------------------------------------------------------------------------- | 1005 //----------------------------------------------------------------------------- |
954 | 1006 |
955 HttpCache::HttpCache(ProxyService* proxy_service, | 1007 HttpCache::HttpCache(ProxyService* proxy_service, |
956 const std::wstring& cache_dir, | 1008 const std::wstring& cache_dir, |
957 int cache_size) | 1009 int cache_size) |
958 : disk_cache_dir_(cache_dir), | 1010 : disk_cache_dir_(cache_dir), |
959 mode_(NORMAL), | 1011 mode_(NORMAL), |
960 type_(DISK_CACHE), | 1012 type_(DISK_CACHE), |
961 network_layer_(HttpNetworkLayer::CreateFactory(proxy_service)), | 1013 network_layer_(HttpNetworkLayer::CreateFactory(proxy_service)), |
962 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), | 1014 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 // We implement a basic reader/writer lock for the disk cache entry. If | 1362 // We implement a basic reader/writer lock for the disk cache entry. If |
1311 // there is already a writer, then everyone has to wait for the writer to | 1363 // there is already a writer, then everyone has to wait for the writer to |
1312 // finish before they can access the cache entry. There can be multiple | 1364 // finish before they can access the cache entry. There can be multiple |
1313 // readers. | 1365 // readers. |
1314 // | 1366 // |
1315 // NOTE: If the transaction can only write, then the entry should not be in | 1367 // NOTE: If the transaction can only write, then the entry should not be in |
1316 // use (since any existing entry should have already been doomed). | 1368 // use (since any existing entry should have already been doomed). |
1317 | 1369 |
1318 if (entry->writer || entry->will_process_pending_queue) { | 1370 if (entry->writer || entry->will_process_pending_queue) { |
1319 entry->pending_queue.push_back(trans); | 1371 entry->pending_queue.push_back(trans); |
| 1372 trans->PendOnEntry(entry); |
| 1373 |
1320 return ERR_IO_PENDING; | 1374 return ERR_IO_PENDING; |
1321 } | 1375 } |
1322 | 1376 |
1323 if (trans->mode() & Transaction::WRITE) { | 1377 if (trans->mode() & Transaction::WRITE) { |
1324 // transaction needs exclusive access to the entry | 1378 // transaction needs exclusive access to the entry |
1325 if (entry->readers.empty()) { | 1379 if (entry->readers.empty()) { |
1326 entry->writer = trans; | 1380 entry->writer = trans; |
1327 } else { | 1381 } else { |
1328 entry->pending_queue.push_back(trans); | 1382 entry->pending_queue.push_back(trans); |
1329 return ERR_IO_PENDING; | 1383 return ERR_IO_PENDING; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 return; // have to wait | 1511 return; // have to wait |
1458 | 1512 |
1459 entry->pending_queue.erase(entry->pending_queue.begin()); | 1513 entry->pending_queue.erase(entry->pending_queue.begin()); |
1460 | 1514 |
1461 AddTransactionToEntry(entry, next); | 1515 AddTransactionToEntry(entry, next); |
1462 } | 1516 } |
1463 | 1517 |
1464 //----------------------------------------------------------------------------- | 1518 //----------------------------------------------------------------------------- |
1465 | 1519 |
1466 } // namespace net | 1520 } // namespace net |
OLD | NEW |