task_dependency_manager.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h" 6 7#include <utility> 8 9#include "base/logging.h" 10 11namespace sync_file_system { 12namespace drive_backend { 13 14namespace { 15 16// Erases all items in |item_to_erase| from |container|. 17template <typename Container1, typename Container2> 18void EraseContainer(const Container1& items_to_erase, Container2* container) { 19 for (typename Container1::const_iterator itr = items_to_erase.begin(); 20 itr != items_to_erase.end(); ++itr) { 21 container->erase(*itr); 22 } 23} 24 25// Inserts all items in |items_to_insert| to |container|, returns true if all 26// items are inserted successfully. Otherwise, returns false and leave 27// |container| have the original contents. 28template <typename Container1, typename Container2> 29bool InsertAllOrNone(const Container1& items_to_insert, Container2* container) { 30 typedef typename Container1::const_iterator iterator; 31 for (iterator itr = items_to_insert.begin(); 32 itr != items_to_insert.end(); ++itr) { 33 if (!container->insert(*itr).second) { 34 // Revert all successful insertion. 35 iterator end = itr; 36 itr = items_to_insert.begin(); 37 for (; itr != end; ++itr) 38 container->erase(*itr); 39 return false; 40 } 41 } 42 return true; 43} 44 45bool InsertPaths(std::vector<base::FilePath> paths_to_insert, 46 SubtreeSet* paths) { 47 typedef std::vector<base::FilePath>::const_iterator iterator; 48 for (iterator itr = paths_to_insert.begin(); 49 itr != paths_to_insert.end(); ++itr) { 50 if (!paths->insert(*itr)) { 51 iterator end = itr; 52 for (itr = paths_to_insert.begin(); itr != end; ++itr) 53 paths->erase(*itr); 54 return false; 55 } 56 } 57 return true; 58} 59 60} // namespace 61 62TaskBlocker::TaskBlocker() : exclusive(false) {} 63TaskBlocker::~TaskBlocker() {} 64 65TaskDependencyManager::TaskDependencyManager() 66 : running_task_count_(0), 67 running_exclusive_task_(false) {} 68 69TaskDependencyManager::~TaskDependencyManager() { 70 DCHECK(paths_by_app_id_.empty()); 71 DCHECK(file_ids_.empty()); 72 DCHECK(tracker_ids_.empty()); 73} 74 75bool TaskDependencyManager::Insert(const TaskBlocker* task_blocker) { 76 if (running_exclusive_task_) 77 return false; 78 79 if (!task_blocker) { 80 ++running_task_count_; 81 return true; 82 } 83 84 if (task_blocker->exclusive) { 85 if (running_task_count_ || 86 !tracker_ids_.empty() || 87 !file_ids_.empty() || 88 !paths_by_app_id_.empty()) 89 return false; 90 ++running_task_count_; 91 running_exclusive_task_ = true; 92 return true; 93 } 94 95 if (!InsertAllOrNone(task_blocker->tracker_ids, &tracker_ids_)) 96 goto fail_on_tracker_id_insertion; 97 98 if (!InsertAllOrNone(task_blocker->file_ids, &file_ids_)) 99 goto fail_on_file_id_insertion; 100 101 if (!task_blocker->app_id.empty() && 102 !InsertPaths(task_blocker->paths, 103 &paths_by_app_id_[task_blocker->app_id])) { 104 if (paths_by_app_id_[task_blocker->app_id].empty()) 105 paths_by_app_id_.erase(task_blocker->app_id); 106 goto fail_on_path_insertion; 107 } 108 109 ++running_task_count_; 110 return true; 111 112 fail_on_path_insertion: 113 EraseContainer(task_blocker->file_ids, &file_ids_); 114 fail_on_file_id_insertion: 115 EraseContainer(task_blocker->tracker_ids, &tracker_ids_); 116 fail_on_tracker_id_insertion: 117 118 return false; 119} 120 121void TaskDependencyManager::Erase(const TaskBlocker* task_blocker) { 122 --running_task_count_; 123 DCHECK_LE(0, running_task_count_); 124 if (!task_blocker) 125 return; 126 127 if (task_blocker->exclusive) { 128 DCHECK(running_exclusive_task_); 129 DCHECK(paths_by_app_id_.empty()); 130 DCHECK(file_ids_.empty()); 131 DCHECK(tracker_ids_.empty()); 132 DCHECK_EQ(0, running_task_count_); 133 134 running_exclusive_task_ = false; 135 return; 136 } 137 138 if (!task_blocker->app_id.empty()) { 139 EraseContainer(task_blocker->paths, 140 &paths_by_app_id_[task_blocker->app_id]); 141 if (paths_by_app_id_[task_blocker->app_id].empty()) 142 paths_by_app_id_.erase(task_blocker->app_id); 143 } 144 145 EraseContainer(task_blocker->file_ids, &file_ids_); 146 EraseContainer(task_blocker->tracker_ids, &tracker_ids_); 147} 148 149} // namespace drive_backend 150} // namespace sync_file_system 151