OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/chromeos/drive/drive_resource_metadata_storage.h" | 5 #include "chrome/browser/chromeos/drive/drive_resource_metadata_storage.h" |
6 | 6 |
7 #include "base/callback.h" | 7 #include "base/callback.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
11 #include "chrome/browser/chromeos/drive/drive.pb.h" | 11 #include "chrome/browser/chromeos/drive/drive.pb.h" |
12 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 12 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 13 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
13 | 14 |
14 namespace drive { | 15 namespace drive { |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 const base::FilePath::CharType kResourceMapDBName[] = | 19 const base::FilePath::CharType kResourceMapDBName[] = |
19 FILE_PATH_LITERAL("resource_metadata_resource_map.db"); | 20 FILE_PATH_LITERAL("resource_metadata_resource_map.db"); |
20 const base::FilePath::CharType kChildMapDBName[] = | 21 const base::FilePath::CharType kChildMapDBName[] = |
21 FILE_PATH_LITERAL("resource_metadata_child_map.db"); | 22 FILE_PATH_LITERAL("resource_metadata_child_map.db"); |
22 | 23 |
23 // Meant to be a character which never happen to be in real resource IDs. | 24 // Meant to be a character which never happen to be in real resource IDs. |
24 const char kDBKeyDelimeter = '\0'; | 25 const char kDBKeyDelimeter = '\0'; |
25 | 26 |
26 // Returns a string to be used as the key for the header. | 27 // Returns a string to be used as the key for the header. |
27 std::string GetHeaderDBKey() { | 28 std::string GetHeaderDBKey() { |
28 std::string key; | 29 std::string key; |
29 key.push_back(kDBKeyDelimeter); | 30 key.push_back(kDBKeyDelimeter); |
30 key.append("HEADER"); | 31 key.append("HEADER"); |
31 return key; | 32 return key; |
32 } | 33 } |
33 | 34 |
34 // Returns a string to be used as a key for child entry. | |
35 std::string GetChildEntryKey(const std::string& parent_resource_id, | |
36 const std::string& child_name) { | |
37 std::string key = parent_resource_id; | |
38 key.push_back(kDBKeyDelimeter); | |
39 key.append(child_name); | |
40 key.push_back(kDBKeyDelimeter); | |
41 return key; | |
42 } | |
43 | |
44 // Returns true if |key| is a key for a child entry. | 35 // Returns true if |key| is a key for a child entry. |
45 bool IsChildEntryKey(const leveldb::Slice& key) { | 36 bool IsChildEntryKey(const leveldb::Slice& key) { |
46 return !key.empty() && key[key.size() - 1] == kDBKeyDelimeter; | 37 return !key.empty() && key[key.size() - 1] == kDBKeyDelimeter; |
47 } | 38 } |
48 | 39 |
49 } // namespace | 40 } // namespace |
50 | 41 |
51 DriveResourceMetadataStorage::DriveResourceMetadataStorage( | 42 DriveResourceMetadataStorage::DriveResourceMetadataStorage( |
52 const base::FilePath& directory_path) | 43 const base::FilePath& directory_path) |
53 : directory_path_(directory_path) { | 44 : directory_path_(directory_path) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 PutHeader(*header); | 116 PutHeader(*header); |
126 } | 117 } |
127 | 118 |
128 int64 DriveResourceMetadataStorage::GetLargestChangestamp() { | 119 int64 DriveResourceMetadataStorage::GetLargestChangestamp() { |
129 base::ThreadRestrictions::AssertIOAllowed(); | 120 base::ThreadRestrictions::AssertIOAllowed(); |
130 scoped_ptr<DriveResourceMetadataHeader> header = GetHeader(); | 121 scoped_ptr<DriveResourceMetadataHeader> header = GetHeader(); |
131 DCHECK(header); | 122 DCHECK(header); |
132 return header->largest_changestamp(); | 123 return header->largest_changestamp(); |
133 } | 124 } |
134 | 125 |
135 void DriveResourceMetadataStorage::PutEntry(const DriveEntryProto& entry) { | 126 bool DriveResourceMetadataStorage::PutEntry(const DriveEntryProto& entry) { |
136 base::ThreadRestrictions::AssertIOAllowed(); | 127 base::ThreadRestrictions::AssertIOAllowed(); |
137 DCHECK(!entry.resource_id().empty()); | 128 DCHECK(!entry.resource_id().empty()); |
138 | 129 |
139 std::string serialized_entry; | 130 std::string serialized_entry; |
140 if (!entry.SerializeToString(&serialized_entry)) { | 131 if (!entry.SerializeToString(&serialized_entry)) { |
141 DLOG(ERROR) << "Failed to serialize the entry: " << entry.resource_id(); | 132 DLOG(ERROR) << "Failed to serialize the entry: " << entry.resource_id(); |
142 return; | 133 return false; |
143 } | 134 } |
144 | 135 |
145 const leveldb::Status status = resource_map_->Put( | 136 leveldb::WriteBatch batch; |
146 leveldb::WriteOptions(), | 137 |
147 leveldb::Slice(entry.resource_id()), | 138 // Remove from the old parent. |
148 leveldb::Slice(serialized_entry)); | 139 scoped_ptr<DriveEntryProto> old_entry = GetEntry(entry.resource_id()); |
149 DCHECK(status.ok()); | 140 if (old_entry && !old_entry->parent_resource_id().empty()) { |
| 141 batch.Delete(GetChildEntryKey(old_entry->parent_resource_id(), |
| 142 old_entry->base_name())); |
| 143 } |
| 144 |
| 145 // Add to the new parent. |
| 146 if (!entry.parent_resource_id().empty()) { |
| 147 batch.Put(GetChildEntryKey(entry.parent_resource_id(), entry.base_name()), |
| 148 entry.resource_id()); |
| 149 } |
| 150 |
| 151 // Put the entry itself. |
| 152 batch.Put(entry.resource_id(), serialized_entry); |
| 153 |
| 154 const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(), |
| 155 &batch); |
| 156 return status.ok(); |
150 } | 157 } |
151 | 158 |
152 scoped_ptr<DriveEntryProto> DriveResourceMetadataStorage::GetEntry( | 159 scoped_ptr<DriveEntryProto> DriveResourceMetadataStorage::GetEntry( |
153 const std::string& resource_id) { | 160 const std::string& resource_id) { |
154 base::ThreadRestrictions::AssertIOAllowed(); | 161 base::ThreadRestrictions::AssertIOAllowed(); |
155 DCHECK(!resource_id.empty()); | 162 DCHECK(!resource_id.empty()); |
156 | 163 |
157 std::string serialized_entry; | 164 std::string serialized_entry; |
158 const leveldb::Status status = resource_map_->Get(leveldb::ReadOptions(), | 165 const leveldb::Status status = resource_map_->Get(leveldb::ReadOptions(), |
159 leveldb::Slice(resource_id), | 166 leveldb::Slice(resource_id), |
160 &serialized_entry); | 167 &serialized_entry); |
161 if (!status.ok()) | 168 if (!status.ok()) |
162 return scoped_ptr<DriveEntryProto>(); | 169 return scoped_ptr<DriveEntryProto>(); |
163 | 170 |
164 scoped_ptr<DriveEntryProto> entry(new DriveEntryProto); | 171 scoped_ptr<DriveEntryProto> entry(new DriveEntryProto); |
165 if (!entry->ParseFromString(serialized_entry)) | 172 if (!entry->ParseFromString(serialized_entry)) |
166 return scoped_ptr<DriveEntryProto>(); | 173 return scoped_ptr<DriveEntryProto>(); |
167 return entry.Pass(); | 174 return entry.Pass(); |
168 } | 175 } |
169 | 176 |
170 void DriveResourceMetadataStorage::RemoveEntry(const std::string& resource_id) { | 177 bool DriveResourceMetadataStorage::RemoveEntry(const std::string& resource_id) { |
171 base::ThreadRestrictions::AssertIOAllowed(); | 178 base::ThreadRestrictions::AssertIOAllowed(); |
172 DCHECK(!resource_id.empty()); | 179 DCHECK(!resource_id.empty()); |
173 | 180 |
174 const leveldb::Status status = resource_map_->Delete( | 181 scoped_ptr<DriveEntryProto> entry = GetEntry(resource_id); |
175 leveldb::WriteOptions(), | 182 if (!entry) |
176 leveldb::Slice(resource_id)); | 183 return false; |
177 DCHECK(status.ok()); | 184 |
| 185 leveldb::WriteBatch batch; |
| 186 |
| 187 // Remove from the parent. |
| 188 if (!entry->parent_resource_id().empty()) { |
| 189 batch.Delete(GetChildEntryKey(entry->parent_resource_id(), |
| 190 entry->base_name())); |
| 191 } |
| 192 // Remove the entry itself. |
| 193 batch.Delete(resource_id); |
| 194 |
| 195 const leveldb::Status status = resource_map_->Write(leveldb::WriteOptions(), |
| 196 &batch); |
| 197 return status.ok(); |
178 } | 198 } |
179 | 199 |
180 void DriveResourceMetadataStorage::Iterate(const IterateCallback& callback) { | 200 void DriveResourceMetadataStorage::Iterate(const IterateCallback& callback) { |
181 base::ThreadRestrictions::AssertIOAllowed(); | 201 base::ThreadRestrictions::AssertIOAllowed(); |
182 DCHECK(!callback.is_null()); | 202 DCHECK(!callback.is_null()); |
183 | 203 |
184 scoped_ptr<leveldb::Iterator> it( | 204 scoped_ptr<leveldb::Iterator> it( |
185 resource_map_->NewIterator(leveldb::ReadOptions())); | 205 resource_map_->NewIterator(leveldb::ReadOptions())); |
186 | 206 |
187 // Skip the header entry. | 207 // Skip the header entry. |
188 // Note: The header entry comes before all other entries because its key | 208 // Note: The header entry comes before all other entries because its key |
189 // starts with kDBKeyDelimeter. (i.e. '\0') | 209 // starts with kDBKeyDelimeter. (i.e. '\0') |
190 it->Seek(leveldb::Slice(GetHeaderDBKey())); | 210 it->Seek(leveldb::Slice(GetHeaderDBKey())); |
191 it->Next(); | 211 it->Next(); |
192 | 212 |
193 DriveEntryProto entry; | 213 DriveEntryProto entry; |
194 for (; it->Valid(); it->Next()) { | 214 for (; it->Valid(); it->Next()) { |
195 if (!IsChildEntryKey(it->key()) && | 215 if (!IsChildEntryKey(it->key()) && |
196 entry.ParseFromArray(it->value().data(), it->value().size())) | 216 entry.ParseFromArray(it->value().data(), it->value().size())) |
197 callback.Run(entry); | 217 callback.Run(entry); |
198 } | 218 } |
199 } | 219 } |
200 | 220 |
201 void DriveResourceMetadataStorage::PutChild( | |
202 const std::string& parent_resource_id, | |
203 const std::string& child_name, | |
204 const std::string& child_resource_id) { | |
205 base::ThreadRestrictions::AssertIOAllowed(); | |
206 | |
207 const leveldb::Status status = resource_map_->Put( | |
208 leveldb::WriteOptions(), | |
209 leveldb::Slice(GetChildEntryKey(parent_resource_id, child_name)), | |
210 leveldb::Slice(child_resource_id)); | |
211 DCHECK(status.ok()); | |
212 } | |
213 | |
214 std::string DriveResourceMetadataStorage::GetChild( | 221 std::string DriveResourceMetadataStorage::GetChild( |
215 const std::string& parent_resource_id, | 222 const std::string& parent_resource_id, |
216 const std::string& child_name) { | 223 const std::string& child_name) { |
217 base::ThreadRestrictions::AssertIOAllowed(); | 224 base::ThreadRestrictions::AssertIOAllowed(); |
218 | 225 |
219 std::string child_resource_id; | 226 std::string child_resource_id; |
220 resource_map_->Get( | 227 resource_map_->Get( |
221 leveldb::ReadOptions(), | 228 leveldb::ReadOptions(), |
222 leveldb::Slice(GetChildEntryKey(parent_resource_id, child_name)), | 229 leveldb::Slice(GetChildEntryKey(parent_resource_id, child_name)), |
223 &child_resource_id); | 230 &child_resource_id); |
(...skipping 10 matching lines...) Expand all Loading... |
234 resource_map_->NewIterator(leveldb::ReadOptions())); | 241 resource_map_->NewIterator(leveldb::ReadOptions())); |
235 for (it->Seek(parent_resource_id); | 242 for (it->Seek(parent_resource_id); |
236 it->Valid() && it->key().starts_with(leveldb::Slice(parent_resource_id)); | 243 it->Valid() && it->key().starts_with(leveldb::Slice(parent_resource_id)); |
237 it->Next()) { | 244 it->Next()) { |
238 if (IsChildEntryKey(it->key())) | 245 if (IsChildEntryKey(it->key())) |
239 children->push_back(it->value().ToString()); | 246 children->push_back(it->value().ToString()); |
240 } | 247 } |
241 DCHECK(it->status().ok()); | 248 DCHECK(it->status().ok()); |
242 } | 249 } |
243 | 250 |
244 void DriveResourceMetadataStorage::RemoveChild( | 251 // static |
| 252 std::string DriveResourceMetadataStorage::GetChildEntryKey( |
245 const std::string& parent_resource_id, | 253 const std::string& parent_resource_id, |
246 const std::string& child_name) { | 254 const std::string& child_name) { |
247 base::ThreadRestrictions::AssertIOAllowed(); | 255 std::string key = parent_resource_id; |
248 | 256 key.push_back(kDBKeyDelimeter); |
249 const leveldb::Status status = resource_map_->Delete( | 257 key.append(child_name); |
250 leveldb::WriteOptions(), | 258 key.push_back(kDBKeyDelimeter); |
251 leveldb::Slice(GetChildEntryKey(parent_resource_id, child_name))); | 259 return key; |
252 DCHECK(status.ok()); | |
253 } | 260 } |
254 | 261 |
255 void DriveResourceMetadataStorage::PutHeader( | 262 void DriveResourceMetadataStorage::PutHeader( |
256 const DriveResourceMetadataHeader& header) { | 263 const DriveResourceMetadataHeader& header) { |
257 base::ThreadRestrictions::AssertIOAllowed(); | 264 base::ThreadRestrictions::AssertIOAllowed(); |
258 | 265 |
259 std::string serialized_header; | 266 std::string serialized_header; |
260 if (!header.SerializeToString(&serialized_header)) { | 267 if (!header.SerializeToString(&serialized_header)) { |
261 DLOG(ERROR) << "Failed to serialize the header"; | 268 DLOG(ERROR) << "Failed to serialize the header"; |
262 return; | 269 return; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } | 361 } |
355 if (!it->status().ok() || num_child_entries != num_entries_with_parent) { | 362 if (!it->status().ok() || num_child_entries != num_entries_with_parent) { |
356 DLOG(ERROR) << "Error during checking resource map. status = " | 363 DLOG(ERROR) << "Error during checking resource map. status = " |
357 << it->status().ToString(); | 364 << it->status().ToString(); |
358 return false; | 365 return false; |
359 } | 366 } |
360 return true; | 367 return true; |
361 } | 368 } |
362 | 369 |
363 } // namespace drive | 370 } // namespace drive |
OLD | NEW |