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. 4 5 #include "sync/syncable/entry.h" 6 7 #include <iomanip> 8 9 #include "base/json/string_escape.h" 10 #include "base/strings/string_util.h" 11 #include "sync/syncable/blob.h" 12 #include "sync/syncable/directory.h" 13 #include "sync/syncable/syncable_base_transaction.h" 14 #include "sync/syncable/syncable_columns.h" 15 16 using std::string; 17 18 namespace syncer { 19 namespace syncable { 20 21 Entry::Entry(BaseTransaction* trans, GetById, const Id& id) 22 : basetrans_(trans) { 23 kernel_ = trans->directory()->GetEntryById(id); 24 } 25 26 Entry::Entry(BaseTransaction* trans, GetByClientTag, const string& tag) 27 : basetrans_(trans) { 28 kernel_ = trans->directory()->GetEntryByClientTag(tag); 29 } 30 31 Entry::Entry(BaseTransaction* trans, GetByServerTag, const string& tag) 32 : basetrans_(trans) { 33 kernel_ = trans->directory()->GetEntryByServerTag(tag); 34 } 35 36 Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle) 37 : basetrans_(trans) { 38 kernel_ = trans->directory()->GetEntryByHandle(metahandle); 39 } 40 41 Directory* Entry::dir() const { 42 return basetrans_->directory(); 43 } 44 45 base::DictionaryValue* Entry::ToValue(Cryptographer* cryptographer) const { 46 base::DictionaryValue* entry_info = new base::DictionaryValue(); 47 entry_info->SetBoolean("good", good()); 48 if (good()) { 49 entry_info->Set("kernel", kernel_->ToValue(cryptographer)); 50 entry_info->Set("modelType", 51 ModelTypeToValue(GetModelType())); 52 entry_info->SetBoolean("existsOnClientBecauseNameIsNonEmpty", 53 ExistsOnClientBecauseNameIsNonEmpty()); 54 entry_info->SetBoolean("isRoot", IsRoot()); 55 } 56 return entry_info; 57 } 58 59 const string& Entry::Get(StringField field) const { 60 DCHECK(kernel_); 61 return kernel_->ref(field); 62 } 63 64 ModelType Entry::GetServerModelType() const { 65 ModelType specifics_type = kernel_->GetServerModelType(); 66 if (specifics_type != UNSPECIFIED) 67 return specifics_type; 68 69 // Otherwise, we don't have a server type yet. That should only happen 70 // if the item is an uncommitted locally created item. 71 // It's possible we'll need to relax these checks in the future; they're 72 // just here for now as a safety measure. 73 DCHECK(Get(IS_UNSYNCED)); 74 DCHECK_EQ(Get(SERVER_VERSION), 0); 75 DCHECK(Get(SERVER_IS_DEL)); 76 // Note: can't enforce !Get(ID).ServerKnows() here because that could 77 // actually happen if we hit AttemptReuniteLostCommitResponses. 78 return UNSPECIFIED; 79 } 80 81 ModelType Entry::GetModelType() const { 82 ModelType specifics_type = GetModelTypeFromSpecifics(Get(SPECIFICS)); 83 if (specifics_type != UNSPECIFIED) 84 return specifics_type; 85 if (IsRoot()) 86 return TOP_LEVEL_FOLDER; 87 // Loose check for server-created top-level folders that aren't 88 // bound to a particular model type. 89 if (!Get(UNIQUE_SERVER_TAG).empty() && Get(IS_DIR)) 90 return TOP_LEVEL_FOLDER; 91 92 return UNSPECIFIED; 93 } 94 95 Id Entry::GetPredecessorId() const { 96 return dir()->GetPredecessorId(kernel_); 97 } 98 99 Id Entry::GetSuccessorId() const { 100 return dir()->GetSuccessorId(kernel_); 101 } 102 103 Id Entry::GetFirstChildId() const { 104 return dir()->GetFirstChildId(basetrans_, kernel_); 105 } 106 107 void Entry::GetChildHandles(std::vector<int64>* result) const { 108 dir()->GetChildHandlesById(basetrans_, Get(ID), result); 109 } 110 111 int Entry::GetTotalNodeCount() const { 112 return dir()->GetTotalNodeCount(basetrans_, kernel_); 113 } 114 115 int Entry::GetPositionIndex() const { 116 return dir()->GetPositionIndex(basetrans_, kernel_); 117 } 118 119 bool Entry::ShouldMaintainPosition() const { 120 return kernel_->ShouldMaintainPosition(); 121 } 122 123 std::ostream& operator<<(std::ostream& s, const Blob& blob) { 124 for (Blob::const_iterator i = blob.begin(); i != blob.end(); ++i) 125 s << std::hex << std::setw(2) 126 << std::setfill('0') << static_cast<unsigned int>(*i); 127 return s << std::dec; 128 } 129 130 std::ostream& operator<<(std::ostream& os, const Entry& entry) { 131 int i; 132 EntryKernel* const kernel = entry.kernel_; 133 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) { 134 os << g_metas_columns[i].name << ": " 135 << kernel->ref(static_cast<Int64Field>(i)) << ", "; 136 } 137 for ( ; i < TIME_FIELDS_END; ++i) { 138 os << g_metas_columns[i].name << ": " 139 << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", "; 140 } 141 for ( ; i < ID_FIELDS_END; ++i) { 142 os << g_metas_columns[i].name << ": " 143 << kernel->ref(static_cast<IdField>(i)) << ", "; 144 } 145 os << "Flags: "; 146 for ( ; i < BIT_FIELDS_END; ++i) { 147 if (kernel->ref(static_cast<BitField>(i))) 148 os << g_metas_columns[i].name << ", "; 149 } 150 for ( ; i < STRING_FIELDS_END; ++i) { 151 const std::string& field = kernel->ref(static_cast<StringField>(i)); 152 os << g_metas_columns[i].name << ": " << field << ", "; 153 } 154 for ( ; i < PROTO_FIELDS_END; ++i) { 155 std::string escaped_str; 156 base::JsonDoubleQuote( 157 kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(), 158 false, 159 &escaped_str); 160 os << g_metas_columns[i].name << ": " << escaped_str << ", "; 161 } 162 for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) { 163 os << g_metas_columns[i].name << ": " 164 << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString() 165 << ", "; 166 } 167 os << "TempFlags: "; 168 for ( ; i < BIT_TEMPS_END; ++i) { 169 if (kernel->ref(static_cast<BitTemp>(i))) 170 os << "#" << i - BIT_TEMPS_BEGIN << ", "; 171 } 172 return os; 173 } 174 175 } // namespace syncable 176 } // namespace syncer 177