blob: e1271bf0b602cc69e53be9dc9e7340f2bc6da45a [file] [log] [blame]
[email protected]c9ce60b2012-12-19 23:16:081// Copyright 2012 The Chromium Authors. All rights reserved.
[email protected]15732672012-06-20 18:58:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "sync/syncable/syncable_util.h"
6
avi4856ced02015-12-22 03:14:107#include <stdint.h>
8
[email protected]b2bf91a12012-12-21 20:54:289#include "base/base64.h"
[email protected]15732672012-06-20 18:58:2610#include "base/location.h"
[email protected]4f3837872012-06-29 20:28:0711#include "base/logging.h"
[email protected]b2bf91a12012-12-21 20:54:2812#include "base/sha1.h"
[email protected]15732672012-06-20 18:58:2613#include "sync/syncable/directory.h"
14#include "sync/syncable/entry.h"
15#include "sync/syncable/mutable_entry.h"
16#include "sync/syncable/syncable_id.h"
[email protected]c9ce60b2012-12-19 23:16:0817#include "sync/syncable/syncable_write_transaction.h"
[email protected]15732672012-06-20 18:58:2618
[email protected]9cfc7c702012-07-02 22:54:1719namespace syncer {
[email protected]15732672012-06-20 18:58:2620namespace syncable {
21
[email protected]4f3837872012-06-29 20:28:0722// Returns the number of unsynced entries.
avi4856ced02015-12-22 03:14:1023int GetUnsyncedEntries(BaseTransaction* trans, std::vector<int64_t>* handles) {
[email protected]4f3837872012-06-29 20:28:0724 trans->directory()->GetUnsyncedMetaHandles(trans, handles);
25 DVLOG_IF(1, !handles->empty()) << "Have " << handles->size()
26 << " unsynced items.";
27 return handles->size();
28}
29
[email protected]15732672012-06-20 18:58:2630bool IsLegalNewParent(BaseTransaction* trans, const Id& entry_id,
31 const Id& new_parent_id) {
stanisc8d4046a2015-01-30 20:20:3132 DCHECK(!entry_id.IsNull());
33 DCHECK(!new_parent_id.IsNull());
[email protected]15732672012-06-20 18:58:2634 if (entry_id.IsRoot())
35 return false;
36 // we have to ensure that the entry is not an ancestor of the new parent.
37 Id ancestor_id = new_parent_id;
38 while (!ancestor_id.IsRoot()) {
39 if (entry_id == ancestor_id)
40 return false;
41 Entry new_parent(trans, GET_BY_ID, ancestor_id);
42 if (!SyncAssert(new_parent.good(),
43 FROM_HERE,
44 "Invalid new parent",
45 trans))
46 return false;
[email protected]65824a12013-09-13 20:26:3147 ancestor_id = new_parent.GetParentId();
[email protected]15732672012-06-20 18:58:2648 }
49 return true;
50}
51
[email protected]15732672012-06-20 18:58:2652void ChangeEntryIDAndUpdateChildren(
[email protected]9da02fd2013-09-26 21:59:1953 BaseWriteTransaction* trans,
54 ModelNeutralMutableEntry* entry,
[email protected]4f3837872012-06-29 20:28:0755 const Id& new_id) {
[email protected]65824a12013-09-13 20:26:3156 Id old_id = entry->GetId();
57 if (!entry->PutId(new_id)) {
[email protected]15732672012-06-20 18:58:2658 Entry old_entry(trans, GET_BY_ID, new_id);
59 CHECK(old_entry.good());
60 LOG(FATAL) << "Attempt to change ID to " << new_id
61 << " conflicts with existing entry.\n\n"
62 << *entry << "\n\n" << old_entry;
63 }
[email protected]65824a12013-09-13 20:26:3164 if (entry->GetIsDir()) {
[email protected]15732672012-06-20 18:58:2665 // Get all child entries of the old id.
[email protected]560009e2013-06-07 14:13:2366 Directory::Metahandles children;
[email protected]15732672012-06-20 18:58:2667 trans->directory()->GetChildHandlesById(trans, old_id, &children);
[email protected]560009e2013-06-07 14:13:2368 Directory::Metahandles::iterator i = children.begin();
[email protected]15732672012-06-20 18:58:2669 while (i != children.end()) {
[email protected]9da02fd2013-09-26 21:59:1970 ModelNeutralMutableEntry child_entry(trans, GET_BY_HANDLE, *i++);
[email protected]15732672012-06-20 18:58:2671 CHECK(child_entry.good());
stanisc8d4046a2015-01-30 20:20:3172 // Change the parent ID of the entry unless it was unset (implicit)
73 if (!child_entry.GetParentId().IsNull()) {
74 // Use the unchecked setter here to avoid touching the child's
75 // UNIQUE_POSITION field. In this case, UNIQUE_POSITION among the
76 // children will be valid after the loop, since we update all the
77 // children at once.
78 child_entry.PutParentIdPropertyOnly(new_id);
79 }
[email protected]15732672012-06-20 18:58:2680 }
81 }
[email protected]15732672012-06-20 18:58:2682}
83
84// Function to handle runtime failures on syncable code. Rather than crashing,
85// if the |condition| is false the following will happen:
86// 1. Sets unrecoverable error on transaction.
87// 2. Returns false.
88bool SyncAssert(bool condition,
89 const tracked_objects::Location& location,
90 const char* msg,
91 BaseTransaction* trans) {
92 if (!condition) {
93 trans->OnUnrecoverableError(location, msg);
94 return false;
95 }
96 return true;
97}
98
[email protected]b2bf91a12012-12-21 20:54:2899std::string GenerateSyncableHash(
100 ModelType model_type, const std::string& client_tag) {
101 // Blank PB with just the field in it has termination symbol,
102 // handy for delimiter.
103 sync_pb::EntitySpecifics serialized_type;
104 AddDefaultFieldValue(model_type, &serialized_type);
105 std::string hash_input;
106 serialized_type.AppendToString(&hash_input);
107 hash_input.append(client_tag);
108
109 std::string encode_output;
[email protected]33fca122013-12-11 01:48:50110 base::Base64Encode(base::SHA1HashString(hash_input), &encode_output);
[email protected]b2bf91a12012-12-21 20:54:28111 return encode_output;
112}
113
[email protected]457eaeb2013-04-02 04:08:20114std::string GenerateSyncableBookmarkHash(
[email protected]f7c5c882013-08-22 00:55:06115 const std::string& originator_cache_guid,
116 const std::string& originator_client_item_id) {
[email protected]457eaeb2013-04-02 04:08:20117 return syncable::GenerateSyncableHash(
118 BOOKMARKS, originator_cache_guid + originator_client_item_id);
119}
120
[email protected]15732672012-06-20 18:58:26121} // namespace syncable
[email protected]9cfc7c702012-07-02 22:54:17122} // namespace syncer