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 DCHECK(!entry_id
.IsNull());
32 DCHECK(!new_parent_id
.IsNull());
33 if (entry_id
.IsRoot())
35 // we have to ensure that the entry is not an ancestor of the new parent.
36 Id ancestor_id
= new_parent_id
;
37 while (!ancestor_id
.IsRoot()) {
38 if (entry_id
== ancestor_id
)
40 Entry
new_parent(trans
, GET_BY_ID
, ancestor_id
);
41 if (!SyncAssert(new_parent
.good(),
46 ancestor_id
= new_parent
.GetParentId();
51 void ChangeEntryIDAndUpdateChildren(
52 BaseWriteTransaction
* trans
,
53 ModelNeutralMutableEntry
* entry
,
55 Id old_id
= entry
->GetId();
56 if (!entry
->PutId(new_id
)) {
57 Entry
old_entry(trans
, GET_BY_ID
, new_id
);
58 CHECK(old_entry
.good());
59 LOG(FATAL
) << "Attempt to change ID to " << new_id
60 << " conflicts with existing entry.\n\n"
61 << *entry
<< "\n\n" << old_entry
;
63 if (entry
->GetIsDir()) {
64 // Get all child entries of the old id.
65 Directory::Metahandles children
;
66 trans
->directory()->GetChildHandlesById(trans
, old_id
, &children
);
67 Directory::Metahandles::iterator i
= children
.begin();
68 while (i
!= children
.end()) {
69 ModelNeutralMutableEntry
child_entry(trans
, GET_BY_HANDLE
, *i
++);
70 CHECK(child_entry
.good());
71 // Change the parent ID of the entry unless it was unset (implicit)
72 if (!child_entry
.GetParentId().IsNull()) {
73 // Use the unchecked setter here to avoid touching the child's
74 // UNIQUE_POSITION field. In this case, UNIQUE_POSITION among the
75 // children will be valid after the loop, since we update all the
77 child_entry
.PutParentIdPropertyOnly(new_id
);
83 // Function to handle runtime failures on syncable code. Rather than crashing,
84 // if the |condition| is false the following will happen:
85 // 1. Sets unrecoverable error on transaction.
87 bool SyncAssert(bool condition
,
88 const tracked_objects::Location
& location
,
90 BaseTransaction
* trans
) {
92 trans
->OnUnrecoverableError(location
, msg
);
98 std::string
GenerateSyncableHash(
99 ModelType model_type
, const std::string
& client_tag
) {
100 // Blank PB with just the field in it has termination symbol,
101 // handy for delimiter.
102 sync_pb::EntitySpecifics serialized_type
;
103 AddDefaultFieldValue(model_type
, &serialized_type
);
104 std::string hash_input
;
105 serialized_type
.AppendToString(&hash_input
);
106 hash_input
.append(client_tag
);
108 std::string encode_output
;
109 base::Base64Encode(base::SHA1HashString(hash_input
), &encode_output
);
110 return encode_output
;
113 std::string
GenerateSyncableBookmarkHash(
114 const std::string
& originator_cache_guid
,
115 const std::string
& originator_client_item_id
) {
116 return syncable::GenerateSyncableHash(
117 BOOKMARKS
, originator_cache_guid
+ originator_client_item_id
);
120 } // namespace syncable
121 } // namespace syncer