| OLD | NEW |
| 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 "base/logging.h" | 5 #include "base/logging.h" |
| 6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "net/disk_cache/flash/format.h" | 8 #include "net/disk_cache/flash/format.h" |
| 9 #include "net/disk_cache/flash/log_structured_store.h" | 9 #include "net/disk_cache/flash/log_store.h" |
| 10 #include "net/disk_cache/flash/segment.h" | 10 #include "net/disk_cache/flash/segment.h" |
| 11 #include "net/disk_cache/flash/storage.h" | 11 #include "net/disk_cache/flash/storage.h" |
| 12 | 12 |
| 13 namespace disk_cache { | 13 namespace disk_cache { |
| 14 | 14 |
| 15 LogStructuredStore::LogStructuredStore(Storage* storage) | 15 LogStore::LogStore(Storage* storage) |
| 16 : storage_(storage), | 16 : storage_(storage), |
| 17 num_segments_(storage->size() / kFlashSegmentSize), | 17 num_segments_(storage->size() / kFlashSegmentSize), |
| 18 open_segments_(num_segments_), | 18 open_segments_(num_segments_), |
| 19 write_index_(0), | 19 write_index_(0), |
| 20 current_entry_id_(-1), | 20 current_entry_id_(-1), |
| 21 current_entry_num_bytes_left_to_write_(0), | 21 current_entry_num_bytes_left_to_write_(0), |
| 22 init_(false), | 22 init_(false), |
| 23 closed_(false) { | 23 closed_(false) { |
| 24 DCHECK(storage->size() % kFlashSegmentSize == 0); | 24 DCHECK(storage->size() % kFlashSegmentSize == 0); |
| 25 } | 25 } |
| 26 | 26 |
| 27 LogStructuredStore::~LogStructuredStore() { | 27 LogStore::~LogStore() { |
| 28 DCHECK(!init_ || closed_); | 28 DCHECK(!init_ || closed_); |
| 29 STLDeleteElements(&open_segments_); | 29 STLDeleteElements(&open_segments_); |
| 30 } | 30 } |
| 31 | 31 |
| 32 bool LogStructuredStore::Init() { | 32 bool LogStore::Init() { |
| 33 DCHECK(!init_); | 33 DCHECK(!init_); |
| 34 // TODO(agayev): Once we start persisting segment metadata to disk, we will | 34 // TODO(agayev): Once we start persisting segment metadata to disk, we will |
| 35 // start from where we left off during the last shutdown. | 35 // start from where we left off during the last shutdown. |
| 36 scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_)); | 36 scoped_ptr<Segment> segment(new Segment(write_index_, false, storage_)); |
| 37 if (!segment->Init()) | 37 if (!segment->Init()) |
| 38 return false; | 38 return false; |
| 39 | 39 |
| 40 segment->AddUser(); | 40 segment->AddUser(); |
| 41 open_segments_[write_index_] = segment.release(); | 41 open_segments_[write_index_] = segment.release(); |
| 42 init_ = true; | 42 init_ = true; |
| 43 return true; | 43 return true; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool LogStructuredStore::Close() { | 46 bool LogStore::Close() { |
| 47 DCHECK(init_ && !closed_); | 47 DCHECK(init_ && !closed_); |
| 48 open_segments_[write_index_]->ReleaseUser(); | 48 open_segments_[write_index_]->ReleaseUser(); |
| 49 if (!open_segments_[write_index_]->Close()) | 49 if (!open_segments_[write_index_]->Close()) |
| 50 return false; | 50 return false; |
| 51 closed_ = true; | 51 closed_ = true; |
| 52 return true; | 52 return true; |
| 53 // TODO(agayev): persist metadata to disk. | 53 // TODO(agayev): persist metadata to disk. |
| 54 } | 54 } |
| 55 | 55 |
| 56 bool LogStructuredStore::CreateEntry(int32 size, int32* id) { | 56 bool LogStore::CreateEntry(int32 size, int32* id) { |
| 57 DCHECK(init_ && !closed_); | 57 DCHECK(init_ && !closed_); |
| 58 DCHECK(current_entry_id_ == -1 && size <= disk_cache::kFlashSegmentFreeSpace); | 58 DCHECK(current_entry_id_ == -1 && size <= disk_cache::kFlashSegmentFreeSpace); |
| 59 | 59 |
| 60 // TODO(agayev): Avoid large entries from leaving the segments almost empty. | 60 // TODO(agayev): Avoid large entries from leaving the segments almost empty. |
| 61 if (!open_segments_[write_index_]->CanHold(size)) { | 61 if (!open_segments_[write_index_]->CanHold(size)) { |
| 62 if (!open_segments_[write_index_]->Close()) | 62 if (!open_segments_[write_index_]->Close()) |
| 63 return false; | 63 return false; |
| 64 | 64 |
| 65 open_segments_[write_index_]->ReleaseUser(); | 65 open_segments_[write_index_]->ReleaseUser(); |
| 66 if (open_segments_[write_index_]->HasNoUsers()) { | 66 if (open_segments_[write_index_]->HasNoUsers()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 78 } | 78 } |
| 79 | 79 |
| 80 *id = open_segments_[write_index_]->write_offset(); | 80 *id = open_segments_[write_index_]->write_offset(); |
| 81 open_segments_[write_index_]->StoreOffset(*id); | 81 open_segments_[write_index_]->StoreOffset(*id); |
| 82 current_entry_id_ = *id; | 82 current_entry_id_ = *id; |
| 83 current_entry_num_bytes_left_to_write_ = size; | 83 current_entry_num_bytes_left_to_write_ = size; |
| 84 open_entries_.insert(current_entry_id_); | 84 open_entries_.insert(current_entry_id_); |
| 85 return true; | 85 return true; |
| 86 } | 86 } |
| 87 | 87 |
| 88 bool LogStructuredStore::WriteData(const void* buffer, int32 size) { | 88 bool LogStore::WriteData(const void* buffer, int32 size) { |
| 89 DCHECK(init_ && !closed_); | 89 DCHECK(init_ && !closed_); |
| 90 DCHECK(current_entry_id_ != -1 && | 90 DCHECK(current_entry_id_ != -1 && |
| 91 size <= current_entry_num_bytes_left_to_write_); | 91 size <= current_entry_num_bytes_left_to_write_); |
| 92 if (open_segments_[write_index_]->WriteData(buffer, size)) { | 92 if (open_segments_[write_index_]->WriteData(buffer, size)) { |
| 93 current_entry_num_bytes_left_to_write_ -= size; | 93 current_entry_num_bytes_left_to_write_ -= size; |
| 94 return true; | 94 return true; |
| 95 } | 95 } |
| 96 return false; | 96 return false; |
| 97 } | 97 } |
| 98 | 98 |
| 99 bool LogStructuredStore::OpenEntry(int32 id) { | 99 bool LogStore::OpenEntry(int32 id) { |
| 100 DCHECK(init_ && !closed_); | 100 DCHECK(init_ && !closed_); |
| 101 if (open_entries_.find(id) != open_entries_.end()) | 101 if (open_entries_.find(id) != open_entries_.end()) |
| 102 return false; | 102 return false; |
| 103 | 103 |
| 104 // Segment is already open. | 104 // Segment is already open. |
| 105 int32 index = id / disk_cache::kFlashSegmentSize; | 105 int32 index = id / disk_cache::kFlashSegmentSize; |
| 106 if (open_segments_[index]) { | 106 if (open_segments_[index]) { |
| 107 if (!open_segments_[index]->HaveOffset(id)) | 107 if (!open_segments_[index]->HaveOffset(id)) |
| 108 return false; | 108 return false; |
| 109 open_segments_[index]->AddUser(); | 109 open_segments_[index]->AddUser(); |
| 110 open_entries_.insert(id); | 110 open_entries_.insert(id); |
| 111 return true; | 111 return true; |
| 112 } | 112 } |
| 113 | 113 |
| 114 // Segment is not open. | 114 // Segment is not open. |
| 115 scoped_ptr<Segment> segment(new Segment(index, true, storage_)); | 115 scoped_ptr<Segment> segment(new Segment(index, true, storage_)); |
| 116 if (!segment->Init() || !segment->HaveOffset(id)) | 116 if (!segment->Init() || !segment->HaveOffset(id)) |
| 117 return false; | 117 return false; |
| 118 | 118 |
| 119 segment->AddUser(); | 119 segment->AddUser(); |
| 120 open_segments_[index] = segment.release(); | 120 open_segments_[index] = segment.release(); |
| 121 open_entries_.insert(id); | 121 open_entries_.insert(id); |
| 122 return true; | 122 return true; |
| 123 } | 123 } |
| 124 | 124 |
| 125 bool LogStructuredStore::ReadData(int32 id, void* buffer, int32 size, | 125 bool LogStore::ReadData(int32 id, void* buffer, int32 size, |
| 126 int32 offset) const { | 126 int32 offset) const { |
| 127 DCHECK(init_ && !closed_); | 127 DCHECK(init_ && !closed_); |
| 128 DCHECK(open_entries_.find(id) != open_entries_.end()); | 128 DCHECK(open_entries_.find(id) != open_entries_.end()); |
| 129 | 129 |
| 130 int32 index = id / disk_cache::kFlashSegmentSize; | 130 int32 index = id / disk_cache::kFlashSegmentSize; |
| 131 DCHECK(open_segments_[index] && open_segments_[index]->HaveOffset(id)); | 131 DCHECK(open_segments_[index] && open_segments_[index]->HaveOffset(id)); |
| 132 return open_segments_[index]->ReadData(buffer, size, id + offset); | 132 return open_segments_[index]->ReadData(buffer, size, id + offset); |
| 133 } | 133 } |
| 134 | 134 |
| 135 void LogStructuredStore::CloseEntry(int32 id) { | 135 void LogStore::CloseEntry(int32 id) { |
| 136 DCHECK(init_ && !closed_); | 136 DCHECK(init_ && !closed_); |
| 137 std::set<int32>::iterator entry_iter = open_entries_.find(id); | 137 std::set<int32>::iterator entry_iter = open_entries_.find(id); |
| 138 DCHECK(entry_iter != open_entries_.end()); | 138 DCHECK(entry_iter != open_entries_.end()); |
| 139 | 139 |
| 140 if (current_entry_id_ != -1) { | 140 if (current_entry_id_ != -1) { |
| 141 DCHECK(id == current_entry_id_ && !current_entry_num_bytes_left_to_write_); | 141 DCHECK(id == current_entry_id_ && !current_entry_num_bytes_left_to_write_); |
| 142 open_entries_.erase(entry_iter); | 142 open_entries_.erase(entry_iter); |
| 143 current_entry_id_ = -1; | 143 current_entry_id_ = -1; |
| 144 return; | 144 return; |
| 145 } | 145 } |
| 146 | 146 |
| 147 int32 index = id / disk_cache::kFlashSegmentSize; | 147 int32 index = id / disk_cache::kFlashSegmentSize; |
| 148 DCHECK(open_segments_[index]); | 148 DCHECK(open_segments_[index]); |
| 149 open_entries_.erase(entry_iter); | 149 open_entries_.erase(entry_iter); |
| 150 | 150 |
| 151 open_segments_[index]->ReleaseUser(); | 151 open_segments_[index]->ReleaseUser(); |
| 152 if (open_segments_[index]->HasNoUsers()) { | 152 if (open_segments_[index]->HasNoUsers()) { |
| 153 delete open_segments_[index]; | 153 delete open_segments_[index]; |
| 154 open_segments_[index] = NULL; | 154 open_segments_[index] = NULL; |
| 155 } | 155 } |
| 156 } | 156 } |
| 157 | 157 |
| 158 int32 LogStructuredStore::GetNextSegmentIndex() { | 158 int32 LogStore::GetNextSegmentIndex() { |
| 159 DCHECK(init_ && !closed_); | 159 DCHECK(init_ && !closed_); |
| 160 int32 next_index = (write_index_ + 1) % num_segments_; | 160 int32 next_index = (write_index_ + 1) % num_segments_; |
| 161 | 161 |
| 162 while (InUse(next_index)) { | 162 while (InUse(next_index)) { |
| 163 next_index = (next_index + 1) % num_segments_; | 163 next_index = (next_index + 1) % num_segments_; |
| 164 DCHECK_NE(next_index, write_index_); | 164 DCHECK_NE(next_index, write_index_); |
| 165 } | 165 } |
| 166 return next_index; | 166 return next_index; |
| 167 } | 167 } |
| 168 | 168 |
| 169 bool LogStructuredStore::InUse(int32 index) const { | 169 bool LogStore::InUse(int32 index) const { |
| 170 DCHECK(init_ && !closed_); | 170 DCHECK(init_ && !closed_); |
| 171 DCHECK(index >= 0 && index < num_segments_); | 171 DCHECK(index >= 0 && index < num_segments_); |
| 172 return open_segments_[index] != NULL; | 172 return open_segments_[index] != NULL; |
| 173 } | 173 } |
| 174 | 174 |
| 175 } // namespace disk_cache | 175 } // namespace disk_cache |
| OLD | NEW |