12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SYNC_SYNCABLE_SYNCABLE_ID_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SYNC_SYNCABLE_SYNCABLE_ID_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iosfwd> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/base/sync_export.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockConnectionManager; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StringValue; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sql { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Statement; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EntryKernel; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Id; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SYNC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, const Id& id); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For historical reasons, 3 concepts got everloaded into the Id: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. A unique, opaque identifier for the object. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. Flag specifing whether server know about this object. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. Flag for root. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We originally wrapped an integer for this information, but now we use a 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string. It will have one of three forms: 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1. c<client only opaque id> for client items that have not been committed. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 2. r for the root item. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3. s<server provided opaque id> for items that the server knows about. 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SYNC_EXPORT Id { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This constructor will be handy even when we move away from int64s, just 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for unit tests. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Id() : s_("r") { } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Id(const Id& that) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Copy(that); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline Id& operator = (const Id& that) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Copy(that); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void Copy(const Id& that) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->s_ = that.s_; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool IsRoot() const { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "r" == s_; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool ServerKnows() const { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_[0] == 's' || s_ == "r"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sync): We could use null here, but to ease conversion we use "r". 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fix this, this is madness :) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool IsNull() const { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsRoot(); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void Clear() { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s_ = "r"; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline int compare(const Id& that) const { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_.compare(that.s_); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool operator == (const Id& that) const { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_ == that.s_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool operator != (const Id& that) const { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_ != that.s_; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool operator < (const Id& that) const { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_ < that.s_; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool operator > (const Id& that) const { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_ > that.s_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& value() const { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s_; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return the next highest ID in the lexicographic ordering. This is 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // useful for computing upper bounds on std::sets that are ordered 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by operator<. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Id GetLexicographicSuccessor() const; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dumps the ID as a value and returns it. Transfers ownership of 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the StringValue to the caller. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringValue* ToValue() const; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Three functions are used to work with our proto buffers. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GetServerId() const; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Id CreateFromServerId(const std::string& server_id); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should only be used if you get back a reference to a local 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // id from the server. Returns a client only opaque id. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Id CreateFromClientString(const std::string& local_id); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method returns an ID that will compare less than any valid ID. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The returned ID is not a valid ID itself. This is useful for 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // computing lower bounds on std::sets that are ordered by operator<. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Id GetLeastIdForLexicographicComparison(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend scoped_ptr<EntryKernel> UnpackEntry(sql::Statement* statement); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend void BindFields(const EntryKernel& entry, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement* statement); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SYNC_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& out, 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Id& id); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MockConnectionManager; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class SyncableIdTest; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string s_; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SYNC_EXPORT_PRIVATE Id GetNullId(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncable 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // SYNC_SYNCABLE_SYNCABLE_ID_H_ 133