Home | History | Annotate | Download | only in syncable
      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