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 |