task_dependency_manager.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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
62BlockingFactor::BlockingFactor() : exclusive(false) {}
63BlockingFactor::~BlockingFactor() {}
64
65TaskDependencyManager::TaskDependencyManager()
66    : running_exclusive_task_(false) {}
67
68TaskDependencyManager::~TaskDependencyManager() {
69  DCHECK(paths_by_app_id_.empty());
70  DCHECK(file_ids_.empty());
71  DCHECK(tracker_ids_.empty());
72}
73
74bool TaskDependencyManager::Insert(const BlockingFactor& blocking_factor) {
75  if (running_exclusive_task_)
76    return false;
77
78  if (blocking_factor.exclusive) {
79    if (!tracker_ids_.empty() ||
80        !file_ids_.empty() ||
81        !paths_by_app_id_.empty())
82      return false;
83    running_exclusive_task_ = true;
84    return true;
85  }
86
87  if (!InsertAllOrNone(blocking_factor.tracker_ids, &tracker_ids_))
88    goto fail_on_tracker_id_insertion;
89
90  if (!InsertAllOrNone(blocking_factor.file_ids, &file_ids_))
91    goto fail_on_file_id_insertion;
92
93  if (!blocking_factor.app_id.empty() &&
94      !InsertPaths(blocking_factor.paths,
95                   &paths_by_app_id_[blocking_factor.app_id])) {
96    if (paths_by_app_id_[blocking_factor.app_id].empty())
97      paths_by_app_id_.erase(blocking_factor.app_id);
98    goto fail_on_path_insertion;
99  }
100
101  return true;
102
103 fail_on_path_insertion:
104  EraseContainer(blocking_factor.file_ids, &file_ids_);
105 fail_on_file_id_insertion:
106  EraseContainer(blocking_factor.tracker_ids, &tracker_ids_);
107 fail_on_tracker_id_insertion:
108
109  return false;
110}
111
112void TaskDependencyManager::Erase(const BlockingFactor& blocking_factor) {
113  if (blocking_factor.exclusive) {
114    DCHECK(running_exclusive_task_);
115    DCHECK(paths_by_app_id_.empty());
116    DCHECK(file_ids_.empty());
117    DCHECK(tracker_ids_.empty());
118
119    running_exclusive_task_ = false;
120    return;
121  }
122
123  if (!blocking_factor.app_id.empty()) {
124    EraseContainer(blocking_factor.paths,
125                   &paths_by_app_id_[blocking_factor.app_id]);
126    if (paths_by_app_id_[blocking_factor.app_id].empty())
127      paths_by_app_id_.erase(blocking_factor.app_id);
128  }
129
130  EraseContainer(blocking_factor.file_ids, &file_ids_);
131  EraseContainer(blocking_factor.tracker_ids, &tracker_ids_);
132}
133
134}  // namespace drive_backend
135}  // namespace sync_file_system
136