| 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 |