| 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 "chrome/browser/chromeos/drive/change_list_processor.h" | 5 #include "chrome/browser/chromeos/drive/change_list_processor.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "chrome/browser/chromeos/drive/drive.pb.h" | 9 #include "chrome/browser/chromeos/drive/drive.pb.h" |
| 10 #include "chrome/browser/chromeos/drive/file_system_util.h" | 10 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 // /a/b/c is moved to /x/y/c. We want to notify both "/a/b" and "/x/y".) | 199 // /a/b/c is moved to /x/y/c. We want to notify both "/a/b" and "/x/y".) |
| 200 // The old paths must be calculated before we apply any actual changes. | 200 // The old paths must be calculated before we apply any actual changes. |
| 201 // The new paths are calculated after each change is applied. It correctly | 201 // The new paths are calculated after each change is applied. It correctly |
| 202 // sets the new path because we apply changes in such an order (see below). | 202 // sets the new path because we apply changes in such an order (see below). |
| 203 for (ResourceEntryMap::iterator it = entry_map_.begin(); | 203 for (ResourceEntryMap::iterator it = entry_map_.begin(); |
| 204 it != entry_map_.end(); ++it) { | 204 it != entry_map_.end(); ++it) { |
| 205 UpdateChangedDirs(it->second); | 205 UpdateChangedDirs(it->second); |
| 206 } | 206 } |
| 207 | 207 |
| 208 // Apply all entries except deleted ones to the metadata. | 208 // Apply all entries except deleted ones to the metadata. |
| 209 std::vector<ResourceEntry> deleted_entries; | 209 std::vector<std::string> deleted_resource_ids; |
| 210 deleted_entries.reserve(entry_map_.size()); | |
| 211 while (!entry_map_.empty()) { | 210 while (!entry_map_.empty()) { |
| 212 ResourceEntryMap::iterator it = entry_map_.begin(); | 211 ResourceEntryMap::iterator it = entry_map_.begin(); |
| 213 | 212 |
| 214 // Process deleted entries later to avoid deleting moved entries under it. | 213 // Process deleted entries later to avoid deleting moved entries under it. |
| 215 if (it->second.deleted()) { | 214 if (it->second.deleted()) { |
| 216 deleted_entries.push_back(ResourceEntry()); | 215 deleted_resource_ids.push_back(it->first); |
| 217 deleted_entries.back().Swap(&it->second); | |
| 218 entry_map_.erase(it); | 216 entry_map_.erase(it); |
| 219 continue; | 217 continue; |
| 220 } | 218 } |
| 221 | 219 |
| 222 // Start from entry_map_.begin() and traverse ancestors using the | 220 // Start from entry_map_.begin() and traverse ancestors using the |
| 223 // parent-child relationships in the result (after this apply) tree. | 221 // parent-child relationships in the result (after this apply) tree. |
| 224 // Then apply the topmost change first. | 222 // Then apply the topmost change first. |
| 225 // | 223 // |
| 226 // By doing this, assuming the result tree does not contain any cycles, we | 224 // By doing this, assuming the result tree does not contain any cycles, we |
| 227 // can guarantee that no cycle is made during this apply (i.e. no entry gets | 225 // can guarantee that no cycle is made during this apply (i.e. no entry gets |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 FileError error = ApplyEntry(it->second); | 276 FileError error = ApplyEntry(it->second); |
| 279 DLOG_IF(WARNING, error != FILE_ERROR_OK) | 277 DLOG_IF(WARNING, error != FILE_ERROR_OK) |
| 280 << "ApplyEntry failed: " << FileErrorToString(error) | 278 << "ApplyEntry failed: " << FileErrorToString(error) |
| 281 << ", title = " << it->second.title(); | 279 << ", title = " << it->second.title(); |
| 282 } | 280 } |
| 283 entry_map_.erase(it); | 281 entry_map_.erase(it); |
| 284 } | 282 } |
| 285 } | 283 } |
| 286 | 284 |
| 287 // Apply deleted entries. | 285 // Apply deleted entries. |
| 288 for (size_t i = 0; i < deleted_entries.size(); ++i) { | 286 for (size_t i = 0; i < deleted_resource_ids.size(); ++i) { |
| 289 // TODO(hashimoto): Handle ApplyEntry errors correctly. | 287 std::string local_id; |
| 290 FileError error = ApplyEntry(deleted_entries[i]); | 288 FileError error = resource_metadata_->GetIdByResourceId( |
| 291 DLOG_IF(WARNING, error != FILE_ERROR_OK) | 289 deleted_resource_ids[i], &local_id); |
| 292 << "ApplyEntry failed: " << FileErrorToString(error) | 290 if (error == FILE_ERROR_OK) |
| 293 << ", title = " << deleted_entries[i].title(); | 291 error = resource_metadata_->RemoveEntry(local_id); |
| 292 |
| 293 DLOG_IF(WARNING, error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) |
| 294 << "Failed to delete: " << FileErrorToString(error) |
| 295 << ", resource_id = " << deleted_resource_ids[i]; |
| 294 } | 296 } |
| 295 | 297 |
| 296 return FILE_ERROR_OK; | 298 return FILE_ERROR_OK; |
| 297 } | 299 } |
| 298 | 300 |
| 299 FileError ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) { | 301 FileError ChangeListProcessor::ApplyEntry(const ResourceEntry& entry) { |
| 302 DCHECK(!entry.deleted()); |
| 303 |
| 304 const std::string& parent_resource_id = |
| 305 parent_resource_id_map_[entry.resource_id()]; |
| 306 DCHECK(!parent_resource_id.empty()) << entry.resource_id(); |
| 307 |
| 308 std::string parent_local_id; |
| 309 FileError error = resource_metadata_->GetIdByResourceId( |
| 310 parent_resource_id, &parent_local_id); |
| 311 if (error != FILE_ERROR_OK) |
| 312 return error; |
| 313 |
| 300 // Lookup the entry. | 314 // Lookup the entry. |
| 301 std::string local_id; | 315 std::string local_id; |
| 302 FileError error = resource_metadata_->GetIdByResourceId(entry.resource_id(), | 316 error = resource_metadata_->GetIdByResourceId(entry.resource_id(), &local_id); |
| 303 &local_id); | 317 |
| 304 ResourceEntry existing_entry; | 318 ResourceEntry existing_entry; |
| 305 if (error == FILE_ERROR_OK) | 319 if (error == FILE_ERROR_OK) |
| 306 error = resource_metadata_->GetResourceEntryById(local_id, &existing_entry); | 320 error = resource_metadata_->GetResourceEntryById(local_id, &existing_entry); |
| 307 | 321 |
| 308 const FileError get_existing_entry_result = error; | 322 ResourceEntry new_entry(entry); |
| 309 if (entry.deleted()) { | 323 new_entry.set_parent_local_id(parent_local_id); |
| 310 // Deleted file/directory. | 324 |
| 311 switch (get_existing_entry_result) { | 325 switch (error) { |
| 312 case FILE_ERROR_OK: | 326 case FILE_ERROR_OK: // Entry exists and needs to be refreshed. |
| 313 error = resource_metadata_->RemoveEntry(local_id); | 327 new_entry.set_local_id(local_id); |
| 314 break; | 328 error = resource_metadata_->RefreshEntry(new_entry); |
| 315 case FILE_ERROR_NOT_FOUND: // Already deleted. | 329 break; |
| 316 error = FILE_ERROR_OK; | 330 case FILE_ERROR_NOT_FOUND: { // Adding a new entry. |
| 317 break; | 331 std::string local_id; |
| 318 default: | 332 error = resource_metadata_->AddEntry(new_entry, &local_id); |
| 319 error = get_existing_entry_result; | 333 break; |
| 320 } | 334 } |
| 321 } else { | 335 default: |
| 322 const std::string& parent_resource_id = | 336 return error; |
| 323 parent_resource_id_map_[entry.resource_id()]; | 337 } |
| 324 DCHECK(!parent_resource_id.empty()) << entry.resource_id(); | 338 if (error != FILE_ERROR_OK) |
| 339 return error; |
| 325 | 340 |
| 326 std::string parent_local_id; | 341 UpdateChangedDirs(entry); |
| 327 error = resource_metadata_->GetIdByResourceId( | 342 return FILE_ERROR_OK; |
| 328 parent_resource_id, &parent_local_id); | |
| 329 if (error == FILE_ERROR_OK) { | |
| 330 ResourceEntry new_entry(entry); | |
| 331 new_entry.set_parent_local_id(parent_local_id); | |
| 332 | |
| 333 switch (get_existing_entry_result) { | |
| 334 case FILE_ERROR_OK: // Entry exists and needs to be refreshed. | |
| 335 new_entry.set_local_id(local_id); | |
| 336 error = resource_metadata_->RefreshEntry(new_entry); | |
| 337 break; | |
| 338 case FILE_ERROR_NOT_FOUND: { // Adding a new entry. | |
| 339 std::string local_id; | |
| 340 error = resource_metadata_->AddEntry(new_entry, &local_id); | |
| 341 break; | |
| 342 } | |
| 343 default: | |
| 344 error = get_existing_entry_result; | |
| 345 } | |
| 346 | |
| 347 if (error == FILE_ERROR_OK) | |
| 348 UpdateChangedDirs(entry); | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 return error; | |
| 353 } | 343 } |
| 354 | 344 |
| 355 // static | 345 // static |
| 356 FileError ChangeListProcessor::RefreshDirectory( | 346 FileError ChangeListProcessor::RefreshDirectory( |
| 357 ResourceMetadata* resource_metadata, | 347 ResourceMetadata* resource_metadata, |
| 358 const DirectoryFetchInfo& directory_fetch_info, | 348 const DirectoryFetchInfo& directory_fetch_info, |
| 359 ScopedVector<ChangeList> change_lists, | 349 ScopedVector<ChangeList> change_lists, |
| 360 base::FilePath* out_file_path) { | 350 base::FilePath* out_file_path) { |
| 361 DCHECK(!directory_fetch_info.empty()); | 351 DCHECK(!directory_fetch_info.empty()); |
| 362 | 352 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 resource_metadata_->GetSubDirectoriesRecursively(local_id, | 436 resource_metadata_->GetSubDirectoriesRecursively(local_id, |
| 447 &sub_directories); | 437 &sub_directories); |
| 448 changed_dirs_.insert(sub_directories.begin(), sub_directories.end()); | 438 changed_dirs_.insert(sub_directories.begin(), sub_directories.end()); |
| 449 } | 439 } |
| 450 } | 440 } |
| 451 } | 441 } |
| 452 } | 442 } |
| 453 | 443 |
| 454 } // namespace internal | 444 } // namespace internal |
| 455 } // namespace drive | 445 } // namespace drive |
| OLD | NEW |