Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(454)

Side by Side Diff: sync/internal_api/public/base/unique_position.cc

Issue 11636006: WIP: The Bookmark Position Megapatch (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Various updates, including switch suffix to unique_client_tag style Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "sync/internal_api/public/base/unique_position.h" 5 #include "sync/internal_api/public/base/unique_position.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/rand_util.h"
9 #include "base/string_number_conversions.h" 8 #include "base/string_number_conversions.h"
10 9
11 namespace syncer { 10 namespace syncer {
12 11
12 const size_t UniquePosition::kSuffixLength = 28;
13
13 // static. 14 // static.
14 bool UniquePosition::IsValidSuffix(const std::string& suffix) { 15 bool UniquePosition::IsValidSuffix(const std::string& suffix) {
15 // The suffix must be exactly the specified length, otherwise unique suffixes 16 // The suffix must be exactly the specified length, otherwise unique suffixes
16 // are not sufficient to guarantee unique positions (because prefix + suffix 17 // are not sufficient to guarantee unique positions (because prefix + suffix
17 // == p + refixsuffix). 18 // == p + refixsuffix).
18 return suffix.length() == kSuffixLength; 19 return suffix.length() == kSuffixLength;
19 } 20 }
20 21
21 // static. 22 // static.
22 bool UniquePosition::IsValidBytes(const std::string& bytes) { 23 bool UniquePosition::IsValidBytes(const std::string& bytes) {
23 return bytes.length() > kSuffixLength 24 // The first condition ensures that our suffix uniqueness is sufficient to
24 && bytes[bytes.length()-1] == kTerminatorByte; 25 // guarantee position uniqueness. Otherwise, it's possible the end of some
26 // prefix + some short suffix == some long suffix.
27 // The second condition ensures that FindSmallerWithSuffix can always return a
28 // result.
29 return bytes.length() >= kSuffixLength
30 && bytes[bytes.length()-1] != 0;
25 } 31 }
26 32
27 // static. 33 // static.
28 UniquePosition UniquePosition::CreateInvalid() { 34 UniquePosition UniquePosition::CreateInvalid() {
29 UniquePosition pos; 35 UniquePosition pos;
30 DCHECK(!pos.IsValid()); 36 DCHECK(!pos.IsValid());
31 return pos; 37 return pos;
32 } 38 }
33 39
34 // static. 40 // static.
35 UniquePosition UniquePosition::FromBytes( 41 UniquePosition UniquePosition::FromBytes(
36 const std::string& bytes) { 42 const std::string& bytes) {
37 UniquePosition result(bytes); 43 UniquePosition result(bytes);
38 DCHECK(result.IsValid());
39 return result; 44 return result;
40 } 45 }
41 46
42 // static. 47 // static.
43 UniquePosition UniquePosition::FromInt64( 48 UniquePosition UniquePosition::FromInt64(
44 int64 x, const std::string& suffix) { 49 int64 x, const std::string& suffix) {
45 uint64 y = static_cast<uint64>(x); 50 uint64 y = static_cast<uint64>(x);
46 y ^= 0x8000000000000000ULL; // Make it non-negative. 51 y ^= 0x8000000000000000ULL; // Make it non-negative.
47 std::string bytes(8, 0); 52 std::string bytes(8, 0);
48 for (int i = 7; i >= 0; --i) { 53 for (int i = 7; i >= 0; --i) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 const std::string& suffix) { 91 const std::string& suffix) {
87 DCHECK(before.IsValid()); 92 DCHECK(before.IsValid());
88 DCHECK(after.IsValid()); 93 DCHECK(after.IsValid());
89 DCHECK(before.LessThan(after)); 94 DCHECK(before.LessThan(after));
90 DCHECK(IsValidSuffix(suffix)); 95 DCHECK(IsValidSuffix(suffix));
91 const std::string& mid = 96 const std::string& mid =
92 FindBetweenWithSuffix(before.bytes_, after.bytes_, suffix); 97 FindBetweenWithSuffix(before.bytes_, after.bytes_, suffix);
93 return UniquePosition(mid, suffix); 98 return UniquePosition(mid, suffix);
94 } 99 }
95 100
96 // static.
97 const std::string UniquePosition::GenerateUniqueSuffix() {
98 return base::RandBytesAsString(kSuffixLength);
99 }
100
101 // static.
102 const std::string UniquePosition::GenerateBookmarkSuffix(
103 const std::string& decoded_originator_cache_guid,
104 int64 numeric_originator_item_id) {
105 std::string result(8, 0);
106
107 // The first 8 bytes come from the originator id.
108 int64 byte_iterator = numeric_originator_item_id;
109 for (int i = 7; i >= 0; --i) {
110 result[i] = static_cast<uint8>(byte_iterator);
111 byte_iterator >>= 8;
112 }
113
114 // The next 16 bytes come from the decoded cache guid.
115 DCHECK_EQ(16u, decoded_originator_cache_guid.length());
116 result.append(decoded_originator_cache_guid);
117
118 return result;
119 }
120
121 UniquePosition::UniquePosition() : is_valid_(false) { }; 101 UniquePosition::UniquePosition() : is_valid_(false) { };
122 102
123 bool UniquePosition::LessThan(const UniquePosition& other) const { 103 bool UniquePosition::LessThan(const UniquePosition& other) const {
124 DCHECK(this->IsValid()); 104 DCHECK(this->IsValid());
125 DCHECK(other.IsValid()); 105 DCHECK(other.IsValid());
126 return bytes_ < other.bytes_; 106 return bytes_ < other.bytes_;
127 } 107 }
128 108
129 bool UniquePosition::Equals(const UniquePosition& other) const { 109 bool UniquePosition::Equals(const UniquePosition& other) const {
130 if (!this->IsValid() && !other.IsValid()) 110 if (!this->IsValid() && !other.IsValid())
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 std::string debug_string = base::HexEncode(bytes_.data(), bytes_.length()); 143 std::string debug_string = base::HexEncode(bytes_.data(), bytes_.length());
164 if (!IsValid()) { 144 if (!IsValid()) {
165 debug_string = "INVALID[" + debug_string + "]"; 145 debug_string = "INVALID[" + debug_string + "]";
166 } 146 }
167 return debug_string;; 147 return debug_string;;
168 } 148 }
169 149
170 std::string UniquePosition::FindSmallerWithSuffix( 150 std::string UniquePosition::FindSmallerWithSuffix(
171 const std::string& reference, 151 const std::string& reference,
172 const std::string& suffix) { 152 const std::string& suffix) {
173 // When comparing, we need to take into account the terminator that will be
174 // appended to the suffix when this is made into a UniquePosition.
175 const std::string suffixFF = suffix + kTerminatorByte;
176 std::string ret; 153 std::string ret;
177 154
178 // Does our suffix alone place us where we want to be? 155 // Does our suffix alone place us where we want to be?
179 if (suffixFF < reference) { 156 if (suffix < reference) {
180 return ""; 157 return "";
181 } 158 }
182 159
183 for (size_t i = 0; i < reference.length(); ++i) { 160 for (size_t i = 0; i < reference.length(); ++i) {
184 const uint8 digit = reference[i]; 161 const uint8 digit = reference[i];
185 if (digit != 0) { 162 if (digit != 0) {
186 ret.push_back(digit/2); 163 ret.push_back(digit/2);
187 return ret; 164 return ret;
188 } else { 165 } else {
189 ret.push_back(0); 166 ret.push_back(0);
190 // We failed to differentiate ourselves with this digit. But maybe the we 167 // We failed to differentiate ourselves with this digit. But maybe the we
191 // can append the suffix at this point and get the position we're looking 168 // can append the suffix at this point and get the position we're looking
192 // for that way. 169 // for that way.
193 if (suffixFF < reference.substr(i+1)) { 170 if (suffix < reference.substr(i+1)) {
194 return ret; 171 return ret;
195 } 172 }
196 } 173 }
197 } 174 }
198 175
199 // Was it 0x00 all the way to the end? Then we can't insert before it. 176 // Was it 0x00 all the way to the end? Then we can't insert before it.
200 // That's why we enforce that all positions should end with a max digit, 177 // That's why we enforce that all positions should end with a max digit,
201 // which should ensure we never end up here. 178 // which should ensure we never end up here.
202 NOTREACHED(); 179 NOTREACHED();
203 return ""; 180 return "";
204 } 181 }
205 182
206 // static 183 // static
207 std::string UniquePosition::FindGreaterWithSuffix( 184 std::string UniquePosition::FindGreaterWithSuffix(
208 const std::string& reference, 185 const std::string& reference,
209 const std::string& suffix) { 186 const std::string& suffix) {
210 // When comparing, we need to take into account the terminator that will be
211 // appended to the suffix when this is made into a UniquePosition.
212 const std::string suffixFF = suffix + kTerminatorByte;
213
214 std::string ret; 187 std::string ret;
215 188
216 // Does our suffix alone place us where we want to be? 189 // Does our suffix alone place us where we want to be?
217 if (reference < suffixFF) { 190 if (reference < suffix) {
218 return ""; 191 return "";
219 } 192 }
220 193
221 for (size_t i = 0; i < reference.length(); ++i) { 194 for (size_t i = 0; i < reference.length(); ++i) {
222 const uint8 digit = reference[i]; 195 const uint8 digit = reference[i];
223 if (digit != 255) { 196 if (digit != kuint8max) {
224 ret.push_back((digit+256U)/2U); 197 ret.push_back(digit + (kuint8max - digit + 1)/2);
225 return ret; 198 return ret;
226 } else { 199 } else {
227 ret.push_back(255); 200 ret.push_back(kuint8max);
228 // We failed to differentiate ourselves with this digit. But maybe the we 201 // We failed to differentiate ourselves with this digit. But maybe the we
229 // can append the suffix at this point and get the position we're looking 202 // can append the suffix at this point and get the position we're looking
230 // for that way. 203 // for that way.
231 if (reference.substr(i+1) < suffixFF) { 204 if (reference.substr(i+1) < suffix) {
232 return ret; 205 return ret;
233 } 206 }
234 } 207 }
235 } 208 }
236 209
237 // Still here? Then we must increase our length in order to exceed before. 210 // Still here? Then we must increase our length in order to exceed reference.
238 ret.push_back(255); 211 ret.push_back(kuint8max);
239 212
240 DCHECK_LT(reference, ret); 213 DCHECK_LT(reference, ret);
241 return ret; 214 return ret;
242 } 215 }
243 216
244 // static 217 // static
245 std::string UniquePosition::FindBetweenWithSuffix( 218 std::string UniquePosition::FindBetweenWithSuffix(
246 const std::string& before, 219 const std::string& before,
247 const std::string& after, 220 const std::string& after,
248 const std::string& suffix) { 221 const std::string& suffix) {
249 DCHECK(IsValidSuffix(suffix)); 222 DCHECK(IsValidSuffix(suffix));
250 DCHECK_NE(before, after); 223 DCHECK_NE(before, after);
251 DCHECK_LT(before, after); 224 DCHECK_LT(before, after);
252 225
253 // When comparing, we need to take into account the terminator that will be
254 // appended when this is made into a UniquePosition.
255 const std::string suffixFF = suffix + kTerminatorByte;
256
257 std::string mid; 226 std::string mid;
258 227
259 // Sometimes our suffix puts us where we want to be. 228 // Sometimes our suffix puts us where we want to be.
260 if (before < suffixFF && suffixFF < after) { 229 if (before < suffix && suffix < after) {
261 return ""; 230 return "";
262 } 231 }
263 232
264 size_t i = 0; 233 size_t i = 0;
265 for ( ; i < std::min(before.length(), after.length()); ++i) { 234 for ( ; i < std::min(before.length(), after.length()); ++i) {
266 uint8 a_digit = before[i]; 235 uint8 a_digit = before[i];
267 uint8 b_digit = after[i]; 236 uint8 b_digit = after[i];
268 237
269 if (b_digit - a_digit >= 2) { 238 if (b_digit - a_digit >= 2) {
270 mid.push_back((b_digit + a_digit) / 2U); 239 mid.push_back(a_digit + (b_digit - a_digit)/2);
271 return mid; 240 return mid;
272 } else if (a_digit == b_digit) { 241 } else if (a_digit == b_digit) {
273 mid.push_back(a_digit); 242 mid.push_back(a_digit);
274 243
275 // Both strings are equal so far. Will appending the suffix at this point 244 // Both strings are equal so far. Will appending the suffix at this point
276 // give us the comparison we're looking for? 245 // give us the comparison we're looking for?
277 if (suffixFF < before.substr(i, 0) && after.substr(i, 0) < suffixFF) { 246 if (before.substr(i+1) < suffix && suffix < after.substr(i+1)) {
278 return mid; 247 return mid;
279 } 248 }
280 } else { 249 } else {
281 DCHECK_EQ(b_digit - a_digit, 1); // Implied by above if branches. 250 DCHECK_EQ(b_digit - a_digit, 1); // Implied by above if branches.
282 251
283 // The two options are off by one digit. The choice of whether to round 252 // The two options are off by one digit. The choice of whether to round
284 // up or down here will have consequences on what we do with the remaining 253 // up or down here will have consequences on what we do with the remaining
285 // digits. Exploring both options is an optimization and is not required 254 // digits. Exploring both options is an optimization and is not required
286 // for the correctness of this algorithm. 255 // for the correctness of this algorithm.
287 256
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 // value, will make |before| < |mid|. Therefore, the following will get us a 290 // value, will make |before| < |mid|. Therefore, the following will get us a
322 // valid position. 291 // valid position.
323 292
324 mid.append(FindSmallerWithSuffix(after.substr(i), suffix)); 293 mid.append(FindSmallerWithSuffix(after.substr(i), suffix));
325 return mid; 294 return mid;
326 } 295 }
327 296
328 UniquePosition::UniquePosition(const std::string& internal_rep) 297 UniquePosition::UniquePosition(const std::string& internal_rep)
329 : bytes_(internal_rep), 298 : bytes_(internal_rep),
330 is_valid_(IsValidBytes(bytes_)) { 299 is_valid_(IsValidBytes(bytes_)) {
331 DCHECK(IsValid());
332 } 300 }
333 301
334 UniquePosition::UniquePosition( 302 UniquePosition::UniquePosition(
335 const std::string& prefix, 303 const std::string& prefix,
336 const std::string& suffix) 304 const std::string& suffix)
337 : bytes_(prefix + suffix + kTerminatorByte), 305 : bytes_(prefix + suffix),
338 is_valid_(IsValidBytes(bytes_)) { 306 is_valid_(IsValidBytes(bytes_)) {
339 DCHECK(IsValidSuffix(suffix)); 307 DCHECK(IsValidSuffix(suffix));
340 DCHECK(IsValid()); 308 DCHECK(IsValid());
341 } 309 }
342 310
343 } // namespace syncer 311 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/internal_api/public/base/unique_position.h ('k') | sync/internal_api/public/base/unique_position_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698