Upstream version 6.35.121.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 BlockingFactor::BlockingFactor() : exclusive(false) {}
63 BlockingFactor::~BlockingFactor() {}
64
65 TaskDependencyManager::TaskDependencyManager()
66     : running_exclusive_task_(false) {}
67
68 TaskDependencyManager::~TaskDependencyManager() {
69   DCHECK(paths_by_app_id_.empty());
70   DCHECK(file_ids_.empty());
71   DCHECK(tracker_ids_.empty());
72 }
73
74 bool 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
112 void 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