| Index: net/disk_cache/rankings.cc | 
| =================================================================== | 
| --- net/disk_cache/rankings.cc	(revision 21084) | 
| +++ net/disk_cache/rankings.cc	(working copy) | 
| @@ -320,6 +320,7 @@ | 
| Trace("Remove 0x%x (0x%x 0x%x)", node->address().value(), node->Data()->next, | 
| node->Data()->prev); | 
| DCHECK(node->HasData()); | 
| +  InvalidateIterators(node); | 
| Addr next_addr(node->Data()->next); | 
| Addr prev_addr(node->Data()->prev); | 
| if (!next_addr.is_initialized() || next_addr.is_separate_file() || | 
| @@ -394,7 +395,6 @@ | 
| // entry. Otherwise we'll need reentrant transactions, which is an overkill. | 
| void Rankings::UpdateRank(CacheRankingsBlock* node, bool modified, List list) { | 
| Time start = Time::Now(); | 
| -  NotAnIterator(node); | 
| Remove(node, list); | 
| Insert(node, modified, list); | 
| CACHE_UMA(AGE_MS, "UpdateRank", 0, start); | 
| @@ -574,6 +574,19 @@ | 
| TrackRankingsBlock(node, false); | 
| } | 
|  | 
| +void Rankings::TrackRankingsBlock(CacheRankingsBlock* node, | 
| +                                  bool start_tracking) { | 
| +  if (!node) | 
| +    return; | 
| + | 
| +  IteratorPair current(node->address().value(), node); | 
| + | 
| +  if (start_tracking) | 
| +    iterators_.push_back(current); | 
| +  else | 
| +    iterators_.remove(current); | 
| +} | 
| + | 
| int Rankings::SelfCheck() { | 
| int total = 0; | 
| for (int i = 0; i < LAST_ELEMENT; i++) { | 
| @@ -727,19 +740,6 @@ | 
| return false; | 
| } | 
|  | 
| -void Rankings::TrackRankingsBlock(CacheRankingsBlock* node, | 
| -                                  bool start_tracking) { | 
| -  if (!node) | 
| -    return; | 
| - | 
| -  IteratorPair current(node->address().value(), node); | 
| - | 
| -  if (start_tracking) | 
| -    iterators_.push_back(current); | 
| -  else | 
| -    iterators_.remove(current); | 
| -} | 
| - | 
| // We expect to have just a few iterators at any given time, maybe two or three, | 
| // But we could have more than one pointing at the same mode. We walk the list | 
| // of cache iterators and update all that are pointing to the given node. | 
| @@ -747,7 +747,7 @@ | 
| CacheAddr address = node->address().value(); | 
| for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); | 
| ++it) { | 
| -    if (it->first == address) { | 
| +    if (it->first == address && it->second->HasData()) { | 
| CacheRankingsBlock* other = it->second; | 
| other->Data()->next = node->Data()->next; | 
| other->Data()->prev = node->Data()->prev; | 
| @@ -755,16 +755,14 @@ | 
| } | 
| } | 
|  | 
| -void Rankings::NotAnIterator(CacheRankingsBlock* node) { | 
| -#ifdef NDEBUG | 
| -  // This method is only enabled for debug builds. | 
| -  return; | 
| -#endif | 
| +void Rankings::InvalidateIterators(CacheRankingsBlock* node) { | 
| CacheAddr address = node->address().value(); | 
| for (IteratorList::iterator it = iterators_.begin(); it != iterators_.end(); | 
| ++it) { | 
| -    if (it->first == address) | 
| -      NOTREACHED(); | 
| +    if (it->first == address) { | 
| +      LOG(WARNING) << "Invalidating iterator at 0x" << std::hex << address; | 
| +      it->second->Discard(); | 
| +    } | 
| } | 
| } | 
|  | 
|  |