OLD | NEW |
---|---|
(Empty) | |
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 "google_apis/gcm/engine/user_list.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/files/file_path.h" | |
9 #include "base/location.h" | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/message_loop/message_loop_proxy.h" | |
14 #include "base/sequenced_task_runner.h" | |
15 #include "base/strings/string_number_conversions.h" | |
16 #include "base/strings/string_piece.h" | |
17 #include "third_party/leveldatabase/src/include/leveldb/db.h" | |
18 | |
19 namespace { | |
20 const int64 kSerialNumberMissing = -1; | |
21 } // namespace | |
22 | |
23 namespace gcm { | |
24 | |
25 UserList::UserInfo::UserInfo() | |
26 : serial_number(kSerialNumberMissing), | |
27 delegate(NULL) { | |
28 } | |
29 | |
30 UserList::UserInfo::UserInfo(int64 serial_number) | |
31 : serial_number(serial_number), | |
32 delegate(NULL) { | |
33 } | |
34 | |
35 UserList::UserInfo::UserInfo(GCMClient::Delegate* delegate, | |
36 const SetDelegateCallback callback) | |
37 : serial_number(kSerialNumberMissing), | |
38 delegate(delegate), | |
39 callback(callback) { | |
40 } | |
41 | |
42 UserList::UserInfo::~UserInfo() { | |
43 } | |
44 | |
45 UserList::UserList(GCMStore* gcm_store) | |
46 : initialized_(false), | |
47 next_serial_number_(kSerialNumberMissing), | |
48 gcm_store_(gcm_store) { | |
49 } | |
50 | |
51 UserList::~UserList() { | |
52 } | |
53 | |
54 void UserList::Initialize(const GCMStore::SerialNumberMappings& result) { | |
55 DCHECK(!initialized_); | |
56 DCHECK_GT(result.next_serial_number, 0); | |
57 | |
58 next_serial_number_ = result.next_serial_number; | |
59 for (std::map<std::string, int64>::const_iterator iter = | |
60 result.user_serial_numbers.begin(); | |
61 iter != result.user_serial_numbers.end(); | |
62 ++iter) { | |
63 SetSerialNumber(iter->first, iter->second); | |
64 } | |
65 initialized_ = true; | |
66 | |
67 for (UserInfoMap::iterator iter = delegates_.begin(); | |
68 iter != delegates_.end(); | |
69 ++iter) { | |
70 // Process only users with delegate and callback present. | |
71 if (iter->second.delegate && !iter->second.callback.is_null()) { | |
72 if (iter->second.serial_number == kSerialNumberMissing) | |
73 AssignSerialNumber(iter->first); | |
74 else | |
75 RespondWithSerialNumber(iter); | |
76 } | |
77 } | |
78 } | |
79 | |
80 void UserList::SetDelegate(const std::string& username, | |
81 GCMClient::Delegate* delegate, | |
82 const SetDelegateCallback& callback) { | |
83 DCHECK(!username.empty()); | |
84 DCHECK(delegate); | |
85 | |
86 UserInfoMap::iterator iter = delegates_.find(username); | |
87 if (iter != delegates_.end()) { | |
88 DCHECK(initialized_); | |
89 DCHECK(!iter->second.delegate); | |
90 iter->second.delegate = delegate; | |
91 iter->second.callback = callback; | |
92 } else { | |
93 delegates_.insert( | |
94 iter, | |
95 UserInfoMap::value_type(username, UserInfo(delegate, callback))); | |
96 } | |
97 | |
98 if (initialized_) { | |
99 UserInfoMap::iterator iter = delegates_.find(username); | |
100 if (iter->second.serial_number == kSerialNumberMissing) | |
101 AssignSerialNumber(iter->first); | |
102 else | |
103 RespondWithSerialNumber(iter); | |
104 } | |
105 } | |
106 | |
107 void UserList::AssignSerialNumber(const std::string& username) { | |
108 DCHECK(initialized_); | |
109 DCHECK_EQ(delegates_.count(username), 1UL); | |
110 DCHECK_EQ(delegates_[username].serial_number, kSerialNumberMissing); | |
111 | |
112 // Start by incrementing the |next_serial_number_| and persist it in the GCM | |
113 // store. | |
114 int64 serial_number = next_serial_number_++; | |
Nicolas Zea
2014/01/14 23:56:42
this needs to be pre-increment right?
fgorski
2014/01/15 01:29:21
next serial number is the next that is going to be
| |
115 gcm_store_->SetNextSerialNumber( | |
116 serial_number, | |
117 base::Bind(&UserList::IncrementSerialNumberCompleted, | |
118 base::Unretained(this), | |
119 username, | |
120 serial_number)); | |
121 } | |
122 | |
123 void UserList::IncrementSerialNumberCompleted(const std::string& username, | |
124 int64 user_serial_number, | |
125 bool success) { | |
126 // TODO(fgorski): Introduce retry logic. | |
Nicolas Zea
2014/01/14 23:56:42
I don't know that we want to retry on persistence
fgorski
2014/01/15 01:29:21
So a DCHECK?
| |
127 if (!success) | |
128 DCHECK(success) << "Updating the next serial number failed."; | |
129 | |
130 SetSerialNumber(username, user_serial_number); | |
131 gcm_store_->AddUserSerialNumber( | |
Nicolas Zea
2014/01/14 23:56:42
should this and SetNextSerialNumber be combined in
fgorski
2014/01/15 01:29:21
We could consider that. (Separate patch though.)
| |
132 username, | |
133 user_serial_number, | |
134 base::Bind(&UserList::AssignSerialNumberCompleted, | |
135 base::Unretained(this), | |
136 username)); | |
137 } | |
138 | |
139 void UserList::AssignSerialNumberCompleted(const std::string& username, | |
140 bool success) { | |
141 // TODO(fgorski): Introduce retry logic. | |
142 if (!success) { | |
143 DVLOG(1) << "It was not possible to persist username to serial number" | |
144 << " mapping for username: " << username; | |
Nicolas Zea
2014/01/14 23:56:42
Perhaps respond with a -1 or something?
fgorski
2014/01/15 01:29:21
I realized that the serial number part of the resp
| |
145 return; | |
146 } | |
147 | |
148 UserInfoMap::iterator iter = delegates_.find(username); | |
149 DCHECK(iter != delegates_.end()); | |
150 RespondWithSerialNumber(iter); | |
151 } | |
152 | |
153 void UserList::RespondWithSerialNumber(UserInfoMap::iterator& iter) { | |
154 base::MessageLoop::current()->PostTask( | |
155 FROM_HERE, | |
156 base::Bind(iter->second.callback, | |
157 iter->first, | |
158 iter->second.serial_number)); | |
159 iter->second.callback.Reset(); | |
160 } | |
161 | |
162 void UserList::SetSerialNumber(const std::string& username, | |
163 int64 serial_number) { | |
164 DCHECK(!username.empty()); | |
165 DCHECK_GT(serial_number, 0L); | |
166 | |
167 UserInfoMap::iterator iter = delegates_.find(username); | |
168 if (iter != delegates_.end()) { | |
169 DCHECK_EQ(iter->second.serial_number, kSerialNumberMissing); | |
170 iter->second.serial_number = serial_number; | |
171 } else { | |
172 delegates_.insert( | |
173 iter, UserInfoMap::value_type(username, UserInfo(serial_number))); | |
174 } | |
175 } | |
176 | |
177 GCMClient::Delegate* UserList::GetDelegateBySerialNumber(int64 serial_number) | |
178 const { | |
179 for (UserInfoMap::const_iterator iter = delegates_.begin(); | |
180 iter != delegates_.end(); | |
181 ++iter) { | |
182 if (iter->second.serial_number == serial_number) | |
183 return iter->second.delegate; | |
184 } | |
185 return NULL; | |
186 } | |
187 | |
188 GCMClient::Delegate* UserList::GetDelegateByUsername( | |
189 const std::string& username) const { | |
190 UserInfoMap::const_iterator iter = delegates_.find(username); | |
191 if (iter != delegates_.end()) | |
192 return iter->second.delegate; | |
193 return NULL; | |
jianli
2014/01/15 01:07:09
nit: return iter != delegates_.end() ? iter->secon
fgorski
2014/01/15 20:42:47
Done.
| |
194 } | |
195 | |
196 bool UserList::GetSerialNumberForUsername(const std::string& username, | |
197 int64* serial_number) const { | |
198 UserInfoMap::const_iterator iter = delegates_.find(username); | |
199 if (iter != delegates_.end() && | |
200 iter->second.serial_number != kSerialNumberMissing) { | |
201 *serial_number = iter->second.serial_number; | |
202 return true; | |
203 } | |
204 *serial_number = kSerialNumberMissing; | |
205 return false; | |
206 } | |
207 | |
208 } // namespace gcm | |
OLD | NEW |