Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / task_dependency_manager.cc
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
11 namespace sync_file_system {
12 namespace drive_backend {
13
14 namespace {
15
16 // Erases all items in |item_to_erase| from |container|.
17 template <typename Container1, typename Container2>
18 void 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.
28 template <typename Container1, typename Container2>
29 bool 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
45 bool 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
62 TaskBlocker::TaskBlocker() : exclusive(false) {}
63 TaskBlocker::~TaskBlocker() {}
64
65 TaskDependencyManager::TaskDependencyManager()
66     : running_task_count_(0),
67       running_exclusive_task_(false) {}
68
69 TaskDependencyManager::~TaskDependencyManager() {
70   DCHECK(paths_by_app_id_.empty());
71   DCHECK(file_ids_.empty());
72   DCHECK(tracker_ids_.empty());
73 }
74
75 bool 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
121 void 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