1 // Copyright 2012 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.
5 #include "sync/syncable/syncable_util.h"
7 #include "base/base64.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/sha1.h"
11 #include "sync/syncable/directory.h"
12 #include "sync/syncable/entry.h"
13 #include "sync/syncable/mutable_entry.h"
14 #include "sync/syncable/syncable_id.h"
15 #include "sync/syncable/syncable_write_transaction.h"
20 // Returns the number of unsynced entries.
21 int GetUnsyncedEntries(BaseTransaction
* trans
,
22 std::vector
<int64
> *handles
) {
23 trans
->directory()->GetUnsyncedMetaHandles(trans
, handles
);
24 DVLOG_IF(1, !handles
->empty()) << "Have " << handles
->size()
25 << " unsynced items.";
26 return handles
->size();
29 bool IsLegalNewParent(BaseTransaction
* trans
, const Id
& entry_id
,
30 const Id
& new_parent_id
) {
31 if (entry_id
.IsRoot())
33 // we have to ensure that the entry is not an ancestor of the new parent.
34 Id ancestor_id
= new_parent_id
;
35 while (!ancestor_id
.IsRoot()) {
36 if (entry_id
== ancestor_id
)
38 Entry
new_parent(trans
, GET_BY_ID
, ancestor_id
);
39 if (!SyncAssert(new_parent
.good(),
44 ancestor_id
= new_parent
.GetParentId();
49 void ChangeEntryIDAndUpdateChildren(
50 BaseWriteTransaction
* trans
,
51 ModelNeutralMutableEntry
* entry
,
53 Id old_id
= entry
->GetId();
54 if (!entry
->PutId(new_id
)) {
55 Entry
old_entry(trans
, GET_BY_ID
, new_id
);
56 CHECK(old_entry
.good());
57 LOG(FATAL
) << "Attempt to change ID to " << new_id
58 << " conflicts with existing entry.\n\n"
59 << *entry
<< "\n\n" << old_entry
;
61 if (entry
->GetIsDir()) {
62 // Get all child entries of the old id.
63 Directory::Metahandles children
;
64 trans
->directory()->GetChildHandlesById(trans
, old_id
, &children
);
65 Directory::Metahandles::iterator i
= children
.begin();
66 while (i
!= children
.end()) {
67 ModelNeutralMutableEntry
child_entry(trans
, GET_BY_HANDLE
, *i
++);
68 CHECK(child_entry
.good());
69 // Use the unchecked setter here to avoid touching the child's
70 // UNIQUE_POSITION field. In this case, UNIQUE_POSITION among the
71 // children will be valid after the loop, since we update all the children
73 child_entry
.PutParentIdPropertyOnly(new_id
);
78 // Function to handle runtime failures on syncable code. Rather than crashing,
79 // if the |condition| is false the following will happen:
80 // 1. Sets unrecoverable error on transaction.
82 bool SyncAssert(bool condition
,
83 const tracked_objects::Location
& location
,
85 BaseTransaction
* trans
) {
87 trans
->OnUnrecoverableError(location
, msg
);
93 std::string
GenerateSyncableHash(
94 ModelType model_type
, const std::string
& client_tag
) {
95 // Blank PB with just the field in it has termination symbol,
96 // handy for delimiter.
97 sync_pb::EntitySpecifics serialized_type
;
98 AddDefaultFieldValue(model_type
, &serialized_type
);
99 std::string hash_input
;
100 serialized_type
.AppendToString(&hash_input
);
101 hash_input
.append(client_tag
);
103 std::string encode_output
;
104 base::Base64Encode(base::SHA1HashString(hash_input
), &encode_output
);
105 return encode_output
;
108 std::string
GenerateSyncableBookmarkHash(
109 const std::string
& originator_cache_guid
,
110 const std::string
& originator_client_item_id
) {
111 return syncable::GenerateSyncableHash(
112 BOOKMARKS
, originator_cache_guid
+ originator_client_item_id
);
115 } // namespace syncable
116 } // namespace syncer