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

Side by Side Diff: net/http/http_cache.h

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Initial patch Created 4 years 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
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 // This file declares a HttpTransactionFactory implementation that can be 5 // This file declares a HttpTransactionFactory implementation that can be
6 // layered on top of another HttpTransactionFactory to add HTTP caching. The 6 // layered on top of another HttpTransactionFactory to add HTTP caching. The
7 // caching logic follows RFC 7234 (any exceptions are called out in the code). 7 // caching logic follows RFC 7234 (any exceptions are called out in the code).
8 // 8 //
9 // The HttpCache takes a disk_cache::Backend as a parameter, and uses that for 9 // The HttpCache takes a disk_cache::Backend as a parameter, and uses that for
10 // the cache storage. 10 // the cache storage.
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 // Disk cache entry data indices. 222 // Disk cache entry data indices.
223 enum { 223 enum {
224 kResponseInfoIndex = 0, 224 kResponseInfoIndex = 0,
225 kResponseContentIndex, 225 kResponseContentIndex,
226 kMetadataIndex, 226 kMetadataIndex,
227 227
228 // Must remain at the end of the enum. 228 // Must remain at the end of the enum.
229 kNumCacheEntryDataIndices 229 kNumCacheEntryDataIndices
230 }; 230 };
231 231
232 class Transaction;
233 struct ActiveEntry;
234 typedef std::list<Transaction*> TransactionList;
235 typedef std::unordered_set<Transaction*> TransactionSet;
236
237 // SharedWriters represents the set of all HttpCache::Transactions that are
238 // reading from the network using the same network transaction and writing to
239 // the same cache entry. It is owned by the ActiveEntry.
240 //
241 // An instance of SharedWriters will be created when the first writer has
242 // written the new response headers in the cache.
243 // At creation:
244 // - The writer’s network transaction’s ownership will be transferred to
245 // SharedWriters at that time so that it can be used by any of the
246 // HttpCache::Transactions for subsequent reading from the network.
247 // - The pending_queue will be traversed to see if there are other
248 // transactions that can be added to SharedWriters.
249 //
250 // Destroyed when any of the following happen:
251 // - All the data has been read from the network and written to cache.
252 // - ActiveEntry is destroyed.
253 // - Last transaction part of SharedWriters is destroyed.
254 class SharedWriters {
jkarlin 2016/12/06 18:08:17 Let's put this class in a new file and give it its
shivanisha 2016/12/06 21:53:35 Good idea, done.
255 public:
256 // Creates a new SharedWriters object, transfers the ownership of network
257 // transaction to SharedWriters, and adds the cache transaction to
258 // all_writers_.
259 SharedWriters(HttpCache* cache,
260 ActiveEntry* entry,
261 Transaction* cache_trans,
262 RequestPriority priority,
263 std::unique_ptr<HttpTransaction> transaction);
264 ~SharedWriters();
265
266 // Adds a transaction to SharedWriters. Invokes SetShared on the transaction
267 // and either assigns the transaction to validating_trans_ or inserts it in
268 // waiting_for_validation_.
269 bool AddTransaction(Transaction* transaction);
270
271 // Removes a transaction from waiting_for_validation_ and invokes
272 // ResetShared on it.
273 bool RemoveWaitingTransaction(Transaction* transaction);
274
275 // Invokes Read on network_trans_, assigns this transaction to
276 // current_reader_ and returns what network_trans_->Read() returns.
277 // In case a read is already in progress then this transaction is instead
278 // added to waiting_writers_, read_in_progress is set to true and
279 // ERR_IO_PENDING is returned.
280 int Read(IOBuffer* buf,
jkarlin 2016/12/06 18:08:18 It's against style to have an output argument (the
shivanisha 2016/12/06 21:53:35 Good to know. Will leave intact in this case, thou
281 int buf_len,
282 const CompletionCallback& callback,
283 Transaction* transaction,
284 bool& read_in_progress);
jkarlin 2016/12/06 18:08:17 If it's an output variable, prefer to pass as bool
shivanisha 2016/12/06 21:53:35 done.
285
286 // Callback to be invoked when the current_writer_ fails to write data to
287 // the cache. It transfers the ownership of the network transaction since
288 // shared writing can no longer continue, but current_writer_ can continue
289 // to read the remaning data from the network. Any waiting_writers_ will be
290 // notified of the failure. Any idle transactions will be set to a state so
291 // that they can fail any subsequent Read calls. If a validating_trans_
292 // exists, it can continue with its network transaction. Any transactions in
293 // waiting_for_validation_ will move to pending_queue.
294 HttpTransaction* OnCacheWriteFailure(Transaction* transaction);
295
296 // Callback to be invoked when the current_writer_ fails to read from the
297 // network. Both this transaction and any waiting_writers_ will return the
298 // failure code to their consumers. Any idle transactions will be set to a
299 // state so that they can fail any subsequent Read calls. If a
300 // validating_trans_ exists, it can continue with its network transaction.
301 // Any transactions in waiting_for_validation_ will move to pending_queue.
302 void OnNetworkReadFailure(const Transaction* trans, int result);
303
304 // Callback to be invoked when validating_trans_ wants to continue with the
305 // entry as the validation successfully matched it.
306 void OnValidationMatch(Transaction* transaction, RequestPriority priority);
307
308 // Callback to be invoked when validating_trans_ cannot continue with the
309 // entry as the validation did not return a 304.
310 // Its ok to continue writing to cache if this is the only transaction in
311 // SharedWriters, so network_trans ownership is transferred to
312 // SharedWriters. But if there are other transactions, doom the entry and
313 // this transaction will continue reading from the network so the return
314 // value will pass the ownership of the network transaction back to the
315 // transaction.
316 std::unique_ptr<HttpTransaction> OnValidationNoMatch(
317 Transaction* transactioan,
318 std::unique_ptr<HttpTransaction> network_trans,
319 RequestPriority priority);
320
321 // Callback to be invoked when current_writer_ successfully read from the
322 // network.
323 void OnNetworkReadSuccess(const Transaction* trans,
324 scoped_refptr<IOBuffer> buf,
325 int len);
326
327 // Callback to be invoked when current_writer_ successfully wrote to the
328 // cache.
329 void OnCacheWriteSuccess(const Transaction* trans, int result);
330
331 // Moves all transactions eligible for shared writing from entry's
332 // pending_queue to waiting_for_validation_.
333 void MoveFromPendingQueue();
334
335 // Posts a task for invoking the io callback of the first transaction in
336 // waiting_for_validation_.
337 void ProcessFirstWaitingValidation();
338
339 // Returns true if this object is empty: no transactions in all_writers and
340 // waiting_for_validation_ and validating_trans_.
341 bool empty();
342
343 // Removes a transaction which is in all_writers_ but not currently waiting
344 // on Read.
345 void RemoveIdleWriter(Transaction* trans);
346
347 // Callback to be invoked when the current_writer's consumer destroys it.
348 // Its ownership will then be transferred to SharedWriters till the read
349 // data is written to the cache.
350 void DoomCurrentWriter(std::unique_ptr<HttpTransaction> trans);
351
352 // Destroys doomed transaction. If this is part of an event that needs entry
353 // to be destroyed, destroy_entry will be set to true.
354 void FinalizeDoomedWriter(bool& out_destroy_entry);
355
356 // Removes a waiting_writer_ transaction.
357 void RemoveWaitingWriter(Transaction* trans);
358
359 // Removes the currently validating transaction.
360 void RemoveValidatingTransaction(Transaction* trans);
361
362 // Invoked when DoneReading is invoked on a shared transaction. If
363 // current_writer_ is set, do nothing, else consider it a read completion
364 // and process accordingly.
365 void DoneReading(Transaction* trans);
366
367 // Invoked when StopCaching is called for a shared writer transaction.
368 // It stops caching only if there are no other transactions in
369 // all_writers_.
370 std::unique_ptr<HttpTransaction> StopCaching(Transaction* transaction);
371
372 // Getter functions.
373 int GetTotalReceivedBytes() const;
374 int GetTotalSentBytes() const;
375 LoadState GetLoadState() const;
376 bool GetFullRequestHeaders(HttpRequestHeaders* headers) const;
377 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
378 bool GetRemoteEndpoint(IPEndPoint* endpoint) const;
379 void PopulateNetErrorDetails(NetErrorDetails* details) const;
380 void GetConnectionAttempts(ConnectionAttempts* out) const;
381
382 // Setter functions.
383 void SetPriority(RequestPriority priority);
384 void SetWebSocketHandshakeStreamCreateHelper(
385 WebSocketHandshakeStreamBase::CreateHelper* create_helper);
386
387 int ResumeNetworkStart();
388
389 private:
390 // Moves all transactions in waiting_for_validation_ to entry's
391 // pending_queue.
392 void MoveToPendingQueue();
393 // Notifies the waiting_writers_ of the result, by posting a task for each
jkarlin 2016/12/06 18:08:17 There should be a blank line above comments to aid
shivanisha 2016/12/06 21:53:34 Done.
394 // of them. While processing the task for a transaction, it's IO callback
395 // will be invoked.
396 void ProcessWaitingWriters(int result);
397
398 void OnProcessFirstWaitingValidation();
399
400 // Removes the current_writer_ transaction from this object.
401 void ResetAndRemoveCurrentWriter(bool continue_network_reading = false);
402
403 // Resets the current_writer_ to null and deleted doomed_writer_ if it
404 // exists.
405 void ResetCurrentWriter();
406
407 // Sets the state of idle writers so that they can fail any subsequent
408 // Read.
409 void SetIdleWritersFailState();
410
411 void MoveIdleWritersToReaders();
412 void ValidationDoneContinue(Transaction* transaction,
413 RequestPriority priority);
414
415 // Http Cache.
416 base::WeakPtr<HttpCache> cache_;
417 // The Active entry.
418 ActiveEntry* entry_;
jkarlin 2016/12/06 18:08:17 Document that the ActiveEntry* owns this.
shivanisha 2016/12/06 21:53:35 Done
419 // Network transaction created by the first HttpCache::Transaction that led
420 // to the creation of this SharedWriters object and later used by various
421 // other HttpCache::Transactions.
422 std::unique_ptr<HttpTransaction> network_trans_;
423 // The cache transaction that has currently invoked
424 // HttpNetworkTransaction::read() and is waiting for read to be completed.
425 // This is used to ensure there is at most one call to
426 // HttpNetworkTransaction::read(). After the read is successful and data
427 // written to cache, other waiting writers will be notified.
428 Transaction* current_writer_;
429 // This will point to the currently validating transaction.
430 // After the validation stage is successfully done, this transaction is
431 // added to all_writers_.
432 Transaction* validating_trans_;
433 // If a transaction is currently set in validating_trans_, these
434 // transactions will wait for that to complete and then the first of these
435 // will be assigned to validating_trans_.
436 TransactionList waiting_for_validation_;
437 // These transactions are waiting on their Read calls when current_writer_
438 // is not null. After current_writer_ completes writing the data to the
439 // cache, their buffer would be filled with the data and their callback
440 // would be invoked.
441 struct WaitingWriter {
442 Transaction* transaction;
443 scoped_refptr<IOBuffer> read_buf;
444 int read_buf_len;
445 int write_len;
446 WaitingWriter(Transaction* transaction,
447 scoped_refptr<IOBuffer> read_buf,
448 int len);
449 ~WaitingWriter();
450 WaitingWriter(const WaitingWriter&);
451 };
452 typedef std::list<WaitingWriter> WaitingWritersList;
453 WaitingWritersList waiting_writers_;
454 // Includes a transaction that is:
455 // 1. Currently reading or,
456 // 2. Currently waiting for the data being read by another transaction or,
457 // 3. Waiting for Read to be invoked from the consumer.
458 TransactionSet all_writers_;
459 // If the current_network_reader_'s consumer deletes it, we do not delete it
460 // but pass its ownership to SharedWriters for completing the async
461 // operation in progress. After the data is written in the cache, the
462 // transaction will be deleted.
463 std::unique_ptr<HttpTransaction> doomed_writer_;
464 // Current priority of the request. If a higher priority transaction is
465 // added to waiting_network_readers_, the priority will be increased.
466 // todo (shivanisha@): If the higher priority request dies, we do not change
467 // the priority back to a lower one. Fix this. The priority should be the
468 // highest of the existing requests.
469 RequestPriority priority_;
470 // Used to keep information that ehtry should be destroyed later in the
jkarlin 2016/12/06 18:08:18 s/ehtry/entry/
shivanisha 2016/12/06 21:53:35 done
471 // flow. iIt cannot be destroyed at this moment because doomed_writer_ needs
jkarlin 2016/12/06 18:08:18 s/iIt/It/
shivanisha 2016/12/06 21:53:35 done
472 // to be destroyed first.
473 bool destroy_entry_;
474 base::WeakPtrFactory<SharedWriters> weak_factory_;
475 };
476
232 class MetadataWriter; 477 class MetadataWriter;
233 class QuicServerInfoFactoryAdaptor; 478 class QuicServerInfoFactoryAdaptor;
234 class Transaction;
235 class WorkItem; 479 class WorkItem;
236 friend class Transaction;
237 friend class ViewCacheHelper; 480 friend class ViewCacheHelper;
238 struct PendingOp; // Info for an entry under construction. 481 struct PendingOp; // Info for an entry under construction.
239 482
240 typedef std::list<Transaction*> TransactionList;
241 typedef std::list<std::unique_ptr<WorkItem>> WorkItemList; 483 typedef std::list<std::unique_ptr<WorkItem>> WorkItemList;
242 484
243 struct ActiveEntry { 485 struct ActiveEntry {
244 explicit ActiveEntry(disk_cache::Entry* entry); 486 explicit ActiveEntry(disk_cache::Entry* entry);
245 ~ActiveEntry(); 487 ~ActiveEntry();
246 488
247 disk_cache::Entry* disk_entry; 489 disk_cache::Entry* disk_entry;
248 Transaction* writer; 490 Transaction* writer;
249 TransactionList readers; 491 TransactionSet readers;
jkarlin 2016/12/06 18:08:18 Is it okay to lose the ordering by changing from l
shivanisha 2016/12/06 21:53:35 Yes, since readers are only waiting for read to be
250 TransactionList pending_queue; 492 TransactionList pending_queue;
493 std::unique_ptr<SharedWriters> shared_writers;
251 bool will_process_pending_queue; 494 bool will_process_pending_queue;
252 bool doomed; 495 bool doomed;
253 }; 496 };
254 497
255 using ActiveEntriesMap = 498 using ActiveEntriesMap =
256 std::unordered_map<std::string, std::unique_ptr<ActiveEntry>>; 499 std::unordered_map<std::string, std::unique_ptr<ActiveEntry>>;
257 using PendingOpsMap = std::unordered_map<std::string, PendingOp*>; 500 using PendingOpsMap = std::unordered_map<std::string, PendingOp*>;
258 using ActiveEntriesSet = std::map<ActiveEntry*, std::unique_ptr<ActiveEntry>>; 501 using ActiveEntriesSet = std::map<ActiveEntry*, std::unique_ptr<ActiveEntry>>;
259 using PlaybackCacheMap = std::unordered_map<std::string, int>; 502 using PlaybackCacheMap = std::unordered_map<std::string, int>;
260 503
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 // Closes a previously doomed entry. 538 // Closes a previously doomed entry.
296 void FinalizeDoomedEntry(ActiveEntry* entry); 539 void FinalizeDoomedEntry(ActiveEntry* entry);
297 540
298 // Returns an entry that is currently in use and not doomed, or NULL. 541 // Returns an entry that is currently in use and not doomed, or NULL.
299 ActiveEntry* FindActiveEntry(const std::string& key); 542 ActiveEntry* FindActiveEntry(const std::string& key);
300 543
301 // Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk 544 // Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
302 // cache entry. 545 // cache entry.
303 ActiveEntry* ActivateEntry(disk_cache::Entry* disk_entry); 546 ActiveEntry* ActivateEntry(disk_cache::Entry* disk_entry);
304 547
305 // Deletes an ActiveEntry. 548 // Deletes an ActiveEntry. Expects all of the transactions to be reset to
549 // null, like writer, readers, shared_writers, pending_queue.
jkarlin 2016/12/06 18:08:17 s/null/nullptr/
shivanisha 2016/12/06 21:53:35 done
306 void DeactivateEntry(ActiveEntry* entry); 550 void DeactivateEntry(ActiveEntry* entry);
307 551
308 // Deletes an ActiveEntry using an exhaustive search. 552 // Deletes an ActiveEntry using an exhaustive search.
309 void SlowDeactivateEntry(ActiveEntry* entry); 553 void SlowDeactivateEntry(ActiveEntry* entry);
310 554
311 // Returns the PendingOp for the desired |key|. If an entry is not under 555 // Returns the PendingOp for the desired |key|. If an entry is not under
312 // construction already, a new PendingOp structure is created. 556 // construction already, a new PendingOp structure is created.
313 PendingOp* GetPendingOp(const std::string& key); 557 PendingOp* GetPendingOp(const std::string& key);
314 558
315 // Deletes a PendingOp. 559 // Deletes a PendingOp.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 // 628 //
385 // TODO(ajwong): The PendingOp lifetime management is very tricky. It might 629 // TODO(ajwong): The PendingOp lifetime management is very tricky. It might
386 // be possible to simplify it using either base::Owned() or base::Passed() 630 // be possible to simplify it using either base::Owned() or base::Passed()
387 // with the callback. 631 // with the callback.
388 static void OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache, 632 static void OnPendingOpComplete(const base::WeakPtr<HttpCache>& cache,
389 PendingOp* pending_op, 633 PendingOp* pending_op,
390 int result); 634 int result);
391 635
392 // Processes the backend creation notification. 636 // Processes the backend creation notification.
393 void OnBackendCreated(int result, PendingOp* pending_op); 637 void OnBackendCreated(int result, PendingOp* pending_op);
638 void DestroyEntryAndRestartPendingQueueTxns(ActiveEntry* entry);
jkarlin 2016/12/06 18:08:17 s/Txns/Transactions/
shivanisha 2016/12/06 21:53:35 done
639
640 // Creates a SharedWriters object.
641 void CreateSharedWriters(Transaction* cacheTrans,
642 std::unique_ptr<HttpTransaction> network_trans,
643 RequestPriority priority);
644
645 // Resets if entry contains an empty SharedWriters object and calls
646 // ProcessPendingQueue.
647 void ResetSharedWritersProcessPendingQueue(ActiveEntry* entry);
648
649 // Invokes the io callback of the transaction with the result.
650 void NotifyTransaction(Transaction* transaction, int result);
651
652 // Callbacks invoked by a transaction part of SharedWriters, for various
653 // events.
654 HttpTransaction* CacheWriteFailedSharedWriters(Transaction* trans,
655 ActiveEntry* entry);
656 void NetworkReadFailedSharedWriters(Transaction* trans,
657 ActiveEntry* entry,
658 int result);
659 void CacheWriteSuccessSharedWriters(Transaction* trans,
660 ActiveEntry* entry,
661 int result);
662 void DoneReadingSharedWriters(Transaction* trans, ActiveEntry* entry);
663 void DoomCurrentSharedWriter(std::unique_ptr<HttpTransaction> trans,
664 ActiveEntry* entry);
665 void FinalizeDoomedSharedWriter(ActiveEntry* entry);
666 void RemoveIdleSharedWriter(Transaction* trans,
667 ActiveEntry* entry,
668 bool success);
669 void RemoveValidatingTransSharedWriters(Transaction* trans,
670 ActiveEntry* entry);
671 void ValidationMatchSharedWriters(Transaction* transaction,
672 RequestPriority priority,
673 ActiveEntry* entry);
674 std::unique_ptr<HttpTransaction> ValidationNoMatchSharedWriters(
675 const std::string& key,
676 Transaction* transaction,
677 std::unique_ptr<HttpTransaction> network_trans,
678 RequestPriority priority,
679 ActiveEntry* entry);
680 std::unique_ptr<HttpTransaction> StopCachingSharedWriters(
681 Transaction* transaction,
682 ActiveEntry* entry);
394 683
395 // Variables ---------------------------------------------------------------- 684 // Variables ----------------------------------------------------------------
396 685
397 NetLog* net_log_; 686 NetLog* net_log_;
398 687
399 // Used when lazily constructing the disk_cache_. 688 // Used when lazily constructing the disk_cache_.
400 std::unique_ptr<BackendFactory> backend_factory_; 689 std::unique_ptr<BackendFactory> backend_factory_;
401 bool building_backend_; 690 bool building_backend_;
402 bool bypass_lock_for_test_; 691 bool bypass_lock_for_test_;
403 bool fail_conditionalization_for_test_; 692 bool fail_conditionalization_for_test_;
(...skipping 19 matching lines...) Expand all
423 std::unique_ptr<base::Clock> clock_; 712 std::unique_ptr<base::Clock> clock_;
424 713
425 base::WeakPtrFactory<HttpCache> weak_factory_; 714 base::WeakPtrFactory<HttpCache> weak_factory_;
426 715
427 DISALLOW_COPY_AND_ASSIGN(HttpCache); 716 DISALLOW_COPY_AND_ASSIGN(HttpCache);
428 }; 717 };
429 718
430 } // namespace net 719 } // namespace net
431 720
432 #endif // NET_HTTP_HTTP_CACHE_H_ 721 #endif // NET_HTTP_HTTP_CACHE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698