12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <algorithm> 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <iterator> 97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base64.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "sync/internal_api/public/base/attachment_id_proto.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/internal_api/public/base/unique_position.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/unrecoverable_error_handler.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry_kernel.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/in_memory_directory_backing_store.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/on_disk_directory_backing_store.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sync/syncable/scoped_kernel_lock.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/syncable/scoped_parent_child_index_updater.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable-inl.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_base_transaction.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_changes_version.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_read_transaction.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_util.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_write_transaction.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType Directory::kSyncDatabaseFilename[] = 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("SyncData.sqlite3"); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::PersistedKernelInfo::PersistedKernelInfo() 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_id(0) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet protocol_types = ProtocolTypes(); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Inc()) { 44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ResetDownloadProgress(iter.Get()); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transaction_version[iter.Get()] = 0; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::PersistedKernelInfo::~PersistedKernelInfo() {} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid Directory::PersistedKernelInfo::ResetDownloadProgress( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type) { 53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Clear everything except the data type id field. 54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch download_progress[model_type].Clear(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_progress[model_type].set_data_type_id( 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSpecificsFieldNumberFromModelType(model_type)); 57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Explicitly set an empty token field to denote no progress. 59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch download_progress[model_type].set_token(""); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool Directory::PersistedKernelInfo::HasEmptyDownloadProgress( 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ModelType model_type) { 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const sync_pb::DataTypeProgressMarker& progress_marker = 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) download_progress[model_type]; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return progress_marker.token().empty(); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::SaveChangesSnapshot::SaveChangesSnapshot() 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kernel_info_status(KERNEL_SHARE_INFO_INVALID) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Directory::SaveChangesSnapshot::~SaveChangesSnapshot() { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&dirty_metas); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&delete_journals); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Kernel::Kernel( 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const KernelLoadInfo& info, DirectoryChangeDelegate* delegate, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& transaction_observer) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_write_transaction_id(0), 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name(name), 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_status(Directory::KERNEL_SHARE_INFO_VALID), 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) persisted_info(info.kernel_info), 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_guid(info.cache_guid), 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_metahandle(info.max_metahandle + 1), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate(delegate), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transaction_observer(transaction_observer) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transaction_observer.IsInitialized()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Kernel::~Kernel() { 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) STLDeleteContainerPairSecondPointers(metahandles_map.begin(), 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) metahandles_map.end()); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Directory( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryBackingStore* store, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnrecoverableErrorHandler* unrecoverable_error_handler, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportUnrecoverableErrorFunction report_unrecoverable_error_function, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NigoriHandler* nigori_handler, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Cryptographer* cryptographer) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kernel_(NULL), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_(store), 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_handler_(unrecoverable_error_handler), 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_unrecoverable_error_function_( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_unrecoverable_error_function), 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_set_(false), 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nigori_handler_(nigori_handler), 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cryptographer_(cryptographer), 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invariant_check_level_(VERIFY_CHANGES) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::~Directory() { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirOpenResult Directory::Open( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& name, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryChangeDelegate* delegate, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& transaction_observer) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("sync", "SyncDatabaseOpen"); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DirOpenResult result = 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenImpl(name, delegate, transaction_observer); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OPENED != result) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::InitializeIndices(MetahandlesMap* handles_map) { 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ScopedKernelLock lock(this); 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.swap(*handles_map); 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ParentChildIndex::ShouldInclude(entry)) 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Insert(entry); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 metahandle = entry->ref(META_HANDLE); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->ref(IS_UNSYNCED)) 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.insert(metahandle); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->ref(IS_UNAPPLIED_UPDATE)) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = entry->GetServerModelType(); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->unapplied_update_metahandles[type].insert(metahandle); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.end()) 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "Unexpected duplicate use of client tag"; 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.end()) 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "Unexpected duplicate use of server tag"; 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map[entry->ref(ID).value()] = entry; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!entry->is_dirty()); 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddToAttachmentIndex(lock, metahandle, entry->ref(ATTACHMENT_METADATA)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirOpenResult Directory::OpenImpl( 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& name, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryChangeDelegate* delegate, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transaction_observer) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KernelLoadInfo info; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temporary indices before kernel_ initialized in case Load fails. We 0(1) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // swap these later. 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::MetahandlesMap tmp_handles_map; 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Avoids mem leaks on failure. Harmlessly deletes the empty hash map after 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the swap in the success case. 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) STLValueDeleter<Directory::MetahandlesMap> deleter(&tmp_handles_map); 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JournalIndex delete_journals; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DirOpenResult result = 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) store_->Load(&tmp_handles_map, &delete_journals, &info); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OPENED != result) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_ = new Kernel(name, info, delegate, transaction_observer); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_.reset(new DeleteJournal(&delete_journals)); 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InitializeIndices(&tmp_handles_map); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write back the share info to reserve some space in 'next_id'. This will 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prevent local ID reuse in the case of an early crash. See the comments in 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TakeSnapshotForSaveChanges() or crbug.com/142987 for more information. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SaveChanges()) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FAILED_INITIAL_WRITE; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OPENED; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeleteJournal* Directory::delete_journal() { 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(delete_journal_.get()); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return delete_journal_.get(); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::Close() { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_.reset(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete kernel_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_ = NULL; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::OnUnrecoverableError(const BaseTransaction* trans, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& location, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string & message) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(trans != NULL); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_set_ = true; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_handler_->OnUnrecoverableError(location, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryById(const Id& id) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetEntryById(lock, id); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryKernel* Directory::GetEntryById(const ScopedKernelLock& lock, 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Id& id) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find it in the in memory ID index. 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) IdsMap::iterator id_found = kernel_->ids_map.find(id.value()); 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (id_found != kernel_->ids_map.end()) { 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return id_found->second; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByClientTag(const string& tag) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TagsMap::iterator it = kernel_->client_tags_map.find(tag); 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it != kernel_->client_tags_map.end()) { 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return it->second; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByServerTag(const string& tag) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TagsMap::iterator it = kernel_->server_tags_map.find(tag); 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it != kernel_->server_tags_map.end()) { 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return it->second; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByHandle(int64 metahandle) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetEntryByHandle(lock, metahandle); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciEntryKernel* Directory::GetEntryByHandle(const ScopedKernelLock& lock, 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 metahandle) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look up in memory 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find(metahandle); 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (found != kernel_->metahandles_map.end()) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found it in memory. Easy. 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return found->second; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::GetChildHandlesById( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseTransaction* trans, const Id& parent_id, 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::Metahandles* result) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(this == trans->directory(), FROM_HERE, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Directories don't match", trans)) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendChildHandles(lock, parent_id, result); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int Directory::GetTotalNodeCount( 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BaseTransaction* trans, 295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* kernel) const { 296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(this == trans->directory(), FROM_HERE, 297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Directories don't match", trans)) 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int count = 1; 301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::deque<const OrderedChildSet*> child_sets; 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetChildSetForKernel(trans, kernel, &child_sets); 304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (!child_sets.empty()) { 305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OrderedChildSet* set = child_sets.front(); 306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_sets.pop_front(); 307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (OrderedChildSet::const_iterator it = set->begin(); 308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != set->end(); ++it) { 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) count++; 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetChildSetForKernel(trans, *it, &child_sets); 311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return count; 315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::GetChildSetForKernel( 318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BaseTransaction* trans, 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* kernel, 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::deque<const OrderedChildSet*>* child_sets) const { 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!kernel->ref(IS_DIR)) 322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; // Not a directory => no children. 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OrderedChildSet* descendants = 325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(kernel->ref(ID)); 326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!descendants) 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; // This directory has no children. 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Add our children to the list of items to be traversed. 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_sets->push_back(descendants); 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int Directory::GetPositionIndex( 3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BaseTransaction* trans, 3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EntryKernel* kernel) const { 3367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const OrderedChildSet* siblings = 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kernel_->parent_child_index.GetChildren(kernel->ref(PARENT_ID)); 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) OrderedChildSet::const_iterator it = siblings->find(kernel); 3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return std::distance(siblings->begin(), it); 3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return InsertEntry(lock, trans, entry); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool Directory::InsertEntry(const ScopedKernelLock& lock, 3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BaseWriteTransaction* trans, 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryKernel* entry) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(NULL != entry, FROM_HERE, "Entry is null", trans)) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char error[] = "Entry already in memory index."; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert( 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.insert( 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::make_pair(entry->ref(META_HANDLE), entry)).second, 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error, 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) trans)) { 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert( 365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map.insert( 366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::make_pair(entry->ref(ID).value(), entry)).second, 367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error, 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) trans)) { 370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ParentChildIndex::ShouldInclude(entry)) { 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(kernel_->parent_child_index.Insert(entry), 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error, 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 380010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) AddToAttachmentIndex( 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci lock, entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA)); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Should NEVER be created with a client tag or server tag. 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Server tag should be empty", trans)) { 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Client tag should be empty", trans)) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::ReindexId(BaseWriteTransaction* trans, 3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EntryKernel* const entry, 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const Id& new_id) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (NULL != GetEntryById(lock, new_id)) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the indices that depend on the ID field. 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedParentChildIndexUpdater updater_b(lock, entry, 405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &kernel_->parent_child_index); 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1U, num_erased); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->put(ID, new_id); 409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map[entry->ref(ID).value()] = entry; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::ReindexParentId(BaseWriteTransaction* trans, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EntryKernel* const entry, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Id& new_parent_id) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the indices that depend on the PARENT_ID field. 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedParentChildIndexUpdater index_updater(lock, entry, 422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &kernel_->parent_child_index); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->put(PARENT_ID, new_parent_id); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void Directory::RemoveFromAttachmentIndex( 4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ScopedKernelLock& lock, 430010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int64 metahandle, 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const sync_pb::AttachmentMetadata& attachment_metadata) { 432010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (int i = 0; i < attachment_metadata.record_size(); ++i) { 433010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) AttachmentIdUniqueId unique_id = 434010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) attachment_metadata.record(i).id().unique_id(); 435010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) IndexByAttachmentId::iterator iter = 436010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kernel_->index_by_attachment_id.find(unique_id); 437010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (iter != kernel_->index_by_attachment_id.end()) { 438010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) iter->second.erase(metahandle); 439010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (iter->second.empty()) { 440010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kernel_->index_by_attachment_id.erase(iter); 441010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 442010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 443010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 444010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 445010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 446010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void Directory::AddToAttachmentIndex( 4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ScopedKernelLock& lock, 448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int64 metahandle, 4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const sync_pb::AttachmentMetadata& attachment_metadata) { 450010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for (int i = 0; i < attachment_metadata.record_size(); ++i) { 451010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) AttachmentIdUniqueId unique_id = 452010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) attachment_metadata.record(i).id().unique_id(); 453010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) IndexByAttachmentId::iterator iter = 454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kernel_->index_by_attachment_id.find(unique_id); 455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (iter == kernel_->index_by_attachment_id.end()) { 456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) iter = kernel_->index_by_attachment_id.insert(std::make_pair( 457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) unique_id, 458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MetahandleSet())).first; 459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) iter->second.insert(metahandle); 461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 462010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 463010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 464010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void Directory::UpdateAttachmentIndex( 465010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const int64 metahandle, 466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const sync_pb::AttachmentMetadata& old_metadata, 467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const sync_pb::AttachmentMetadata& new_metadata) { 468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ScopedKernelLock lock(this); 4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RemoveFromAttachmentIndex(lock, metahandle, old_metadata); 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AddToAttachmentIndex(lock, metahandle, new_metadata); 471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void Directory::GetMetahandlesByAttachmentId( 474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BaseTransaction* trans, 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const sync_pb::AttachmentIdProto& attachment_id_proto, 476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Metahandles* result) { 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(result); 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result->clear(); 479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedKernelLock lock(this); 480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IndexByAttachmentId::const_iterator index_iter = 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kernel_->index_by_attachment_id.find(attachment_id_proto.unique_id()); 482cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (index_iter == kernel_->index_by_attachment_id.end()) 483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const MetahandleSet& metahandle_set = index_iter->second; 485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::copy( 486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metahandle_set.begin(), metahandle_set.end(), back_inserter(*result)); 487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(trans != NULL); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return unrecoverable_error_set_; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Directory::ClearDirtyMetahandles(const ScopedKernelLock& lock) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->dirty_metahandles.clear(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::SafeToPurgeFromMemory(WriteTransaction* trans, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EntryKernel* const entry) const { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool safe = entry->ref(IS_DEL) && !entry->is_dirty() && 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !entry->ref(SYNCING) && !entry->ref(IS_UNAPPLIED_UPDATE) && 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !entry->ref(IS_UNSYNCED); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (safe) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = entry->GetServerModelType(); 508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(kernel_->dirty_metahandles.count(handle) == 0U, 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Dirty metahandles should be empty", trans)) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tim): Bug 49278. 513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(!kernel_->unsynced_metahandles.count(handle), 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Unsynced handles should be empty", 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!kernel_->unapplied_update_metahandles[type].count(handle), 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Unapplied metahandles should be empty", 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return safe; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) { 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReadTransaction trans(FROM_HERE, this); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is an unrecoverable error then just bail out. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unrecoverable_error_set(&trans)) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deep copy dirty entries from kernel_->metahandles_index into snapshot and 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clear dirty flags. 538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandleSet::const_iterator i = kernel_->dirty_metahandles.begin(); 539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) i != kernel_->dirty_metahandles.end(); ++i) { 5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryKernel* entry = GetEntryByHandle(lock, *i); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip over false positives; it happens relatively infrequently. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry->is_dirty()) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new EntryKernel(*entry)); 548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1U, kernel_->dirty_metahandles.count(*i)); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't bother removing from the index here as we blow the entire thing 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a moment, and it unnecessarily complicates iteration. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->clear_dirty(NULL); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ClearDirtyMetahandles(lock); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set purged handles. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(snapshot->metahandles_to_purge.empty()); 557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill kernel_info_status and kernel_info. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info = kernel_->persisted_info; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid duplicates when the process crashes, we record the next_id to be 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // greater magnitude than could possibly be reached before the next save 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changes. In other words, it's effectively impossible for the user to 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // generate 65536 new bookmarks in 3 seconds. 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info.next_id -= 65536; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info_status = kernel_->info_status; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This one we reset on failure. 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_VALID; 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->TakeSnapshotAndClear( 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &trans, &snapshot->delete_journals, &snapshot->delete_journals_to_purge); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::SaveChanges() { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(kernel_->save_changes_mutex); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Snapshot and save. 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveChangesSnapshot snapshot; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TakeSnapshotForSaveChanges(&snapshot); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = store_->SaveChanges(snapshot); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle success or failure. 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = VacuumAfterSaveChanges(snapshot); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSaveChangesFailure(snapshot); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (snapshot.dirty_metas.empty()) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need a write transaction as we are about to permanently purge entries. 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now drop everything we can out of memory. 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != snapshot.dirty_metas.end(); ++i) { 602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); 604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = (found == kernel_->metahandles_map.end() ? 605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NULL : found->second); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry && SafeToPurgeFromMemory(&trans, entry)) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We now drop deleted metahandles that are up to date on both the client 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and the server. 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num_erased = 0; 610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); 617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); 622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Deleted entry still present", 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (&trans))) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 629010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RemoveFromAttachmentIndex( 6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci lock, entry->ref(META_HANDLE), entry->ref(ATTACHMENT_METADATA)); 631010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete entry; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trans.unrecoverable_error_set()) 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::UnapplyEntry(EntryKernel* entry) { 641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics( 643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->ref(SERVER_SPECIFICS)); 644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Clear enough so that on the next sync cycle all local data will 646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // be overwritten. 647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Note: do not modify the root node in order to preserve the 648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // initial sync ended bit for this type (else on the next restart 649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // this type will be treated as disabled and therefore fully purged). 650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (IsRealDataType(server_type) && 651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeToRootTag(server_type) == entry->ref(UNIQUE_SERVER_TAG)) { 652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Set the unapplied bit if this item has server data. 656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (IsRealDataType(server_type) && !entry->ref(IS_UNAPPLIED_UPDATE)) { 657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_UNAPPLIED_UPDATE, true); 658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unapplied_update_metahandles[server_type].insert(handle); 659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Unset the unsynced bit. 663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(IS_UNSYNCED)) { 664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.erase(handle); 665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_UNSYNCED, false); 666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Mark the item as locally deleted. No deleted items are allowed in the 670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // parent child index. 671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(IS_DEL)) { 672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Remove(entry); 673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_DEL, true); 674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Set the version to the "newly created" version. 678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(BASE_VERSION) != CHANGES_VERSION) { 679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(BASE_VERSION, CHANGES_VERSION); 680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // At this point locally created items that aren't synced will become locally 684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // deleted items, and purged on the next snapshot. All other items will match 685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the state they would have had if they were just created via a server 686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). 687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Directory::DeleteEntry(const ScopedKernelLock& lock, 6901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool save_to_journal, 691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry, 6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryKernelSet* entries_to_journal) { 693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics( 695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->ref(SERVER_SPECIFICS)); 696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 697868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_to_purge.insert(handle); 698868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_erased = 0; 700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); 701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 702868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->unsynced_metahandles.erase(handle); 705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); 706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unapplied_update_metahandles[server_type].erase(handle); 708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); 709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (kernel_->parent_child_index.Contains(entry)) 710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Remove(entry); 711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); 715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); 720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RemoveFromAttachmentIndex(lock, handle, entry->ref(ATTACHMENT_METADATA)); 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (save_to_journal) { 725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_to_journal->insert(entry); 726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete entry; 728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, 732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeSet types_to_journal, 733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeSet types_to_unapply) { 734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) disabled_types.RemoveAll(ProxyTypes()); 735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (disabled_types.Empty()) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EntryKernelSet entries_to_journal; 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLElementDeleter<EntryKernelSet> journal_deleter(&entries_to_journal); 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool found_progress = false; 7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (ModelTypeSet::Iterator iter = disabled_types.First(); iter.Good(); 7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) iter.Inc()) { 7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!kernel_->persisted_info.HasEmptyDownloadProgress(iter.Get())) 7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) found_progress = true; 7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If none of the disabled types have progress markers, there's nothing to 7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // purge. 7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!found_progress) 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // We iterate in two passes to avoid a bug in STLport (which is used in 761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the Android build). There are some versions of that library where a 762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // hash_map's iterators can be invalidated when an item is erased from the 763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // hash_map. 764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // See http://sourceforge.net/p/stlport/bugs/239/. 765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::set<EntryKernel*> to_purge; 767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 769868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it->second->ref(SPECIFICS); 771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 772868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it->second->ref(SERVER_SPECIFICS); 773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType local_type = GetModelTypeFromSpecifics(local_specifics); 774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics(server_specifics); 775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((IsRealDataType(local_type) && disabled_types.Has(local_type)) || 777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (IsRealDataType(server_type) && disabled_types.Has(server_type))) { 778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) to_purge.insert(it->second); 779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (std::set<EntryKernel*>::iterator it = to_purge.begin(); 783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != to_purge.end(); ++it) { 784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = *it; 785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (*it)->ref(SPECIFICS); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->ref(SERVER_SPECIFICS); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType local_type = GetModelTypeFromSpecifics(local_specifics); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics(server_specifics); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (types_to_unapply.Has(local_type) || 794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) types_to_unapply.Has(server_type)) { 795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UnapplyEntry(entry); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool save_to_journal = 798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (types_to_journal.Has(local_type) || 799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) types_to_journal.Has(server_type)) && 800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (delete_journal_->IsDeleteJournalEnabled(local_type) || 801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete_journal_->IsDeleteJournalEnabled(server_type)); 8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DeleteEntry(lock, save_to_journal, entry, &entries_to_journal); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->AddJournalBatch(&trans, entries_to_journal); 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Ensure meta tracking for these data types reflects the purged state. 809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (ModelTypeSet::Iterator it = disabled_types.First(); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Good(); it.Inc()) { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.transaction_version[it.Get()] = 0; 812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 813a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Don't discard progress markers or context for unapplied types. 814a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (!types_to_unapply.Has(it.Get())) { 815a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kernel_->persisted_info.ResetDownloadProgress(it.Get()); 816a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kernel_->persisted_info.datatype_context[it.Get()].Clear(); 817a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 819a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 820a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 826c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool Directory::ResetVersionsForType(BaseWriteTransaction* trans, 827c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ModelType type) { 828c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!ProtocolTypes().Has(type)) 829c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 830c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK_NE(type, BOOKMARKS) << "Only non-hierarchical types are supported"; 831c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 832c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EntryKernel* type_root = GetEntryByServerTag(ModelTypeToRootTag(type)); 833c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!type_root) 834c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return false; 835c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 836c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ScopedKernelLock lock(this); 837c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const Id& type_root_id = type_root->ref(ID); 838c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch Directory::Metahandles children; 839c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch AppendChildHandles(lock, type_root_id, &children); 840c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 841c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch for (Metahandles::iterator it = children.begin(); it != children.end(); 842c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ++it) { 8431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryKernel* entry = GetEntryByHandle(lock, *it); 844c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!entry) 845c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch continue; 846c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (entry->ref(BASE_VERSION) > 1) 847c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->put(BASE_VERSION, 1); 848c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (entry->ref(SERVER_VERSION) > 1) 849c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->put(SERVER_VERSION, 1); 850c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 851c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Note that we do not unset IS_UNSYNCED or IS_UNAPPLIED_UPDATE in order 852c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // to ensure no in-transit data is lost. 853c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 854c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch entry->mark_dirty(&kernel_->dirty_metahandles); 855c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 856c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 857c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return true; 858c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 859c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 860010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool Directory::IsAttachmentLinked( 861010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const sync_pb::AttachmentIdProto& attachment_id_proto) const { 862010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ScopedKernelLock lock(this); 863010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) IndexByAttachmentId::const_iterator iter = 864010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kernel_->index_by_attachment_id.find(attachment_id_proto.unique_id()); 865010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (iter != kernel_->index_by_attachment_id.end() && !iter->second.empty()) { 866010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return true; 867010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 868010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 869010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 870010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because we optimistically cleared the dirty bit on the real entries when 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // taking the snapshot, we must restore it on failure. Not doing this could 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause lost data, if no other changes are made to the in-memory entries 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that would cause the dirty bit to get set again. Setting the bit ensures 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that SaveChanges will at least try again later. 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != snapshot.dirty_metas.end(); ++i) { 883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 884868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); 885868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (found != kernel_->metahandles_map.end()) { 886868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) found->second->mark_dirty(&kernel_->dirty_metahandles); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 890868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_to_purge.insert(snapshot.metahandles_to_purge.begin(), 891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snapshot.metahandles_to_purge.end()); 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Restore delete journals. 8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->AddJournalBatch(&trans, snapshot.delete_journals); 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->PurgeDeleteJournals(&trans, 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot.delete_journals_to_purge); 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetDownloadProgress( 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::DataTypeProgressMarker* value_out) const { 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value_out->CopyFrom( 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type]); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetDownloadProgressAsString( 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* value_out) const { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type].SerializeToString( 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_out); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Directory::GetEntriesCount() const { 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->metahandles_map.size(); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::SetDownloadProgress( 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::DataTypeProgressMarker& new_progress) { 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type].CopyFrom(new_progress); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::GetTransactionVersion(ModelType type) const { 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.transaction_version[type]; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::IncrementTransactionVersion(ModelType type) { 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.transaction_version[type]++; 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 938c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid Directory::GetDataTypeContext(BaseTransaction* trans, 939c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ModelType type, 940c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch sync_pb::DataTypeContext* context) const { 941c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ScopedKernelLock lock(this); 942c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch context->CopyFrom(kernel_->persisted_info.datatype_context[type]); 943c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 944c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 945c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid Directory::SetDataTypeContext( 946c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BaseWriteTransaction* trans, 947c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ModelType type, 948c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const sync_pb::DataTypeContext& context) { 949c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ScopedKernelLock lock(this); 950c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kernel_->persisted_info.datatype_context[type].CopyFrom(context); 951c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 952c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 953c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ModelTypeSet Directory::InitialSyncEndedTypes() { 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet protocol_types = ProtocolTypes(); 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet initial_sync_ended_types; 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator i = protocol_types.First(); i.Good(); i.Inc()) { 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (InitialSyncEndedForType(&trans, i.Get())) { 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initial_sync_ended_types.Put(i.Get()); 9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initial_sync_ended_types; 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Directory::InitialSyncEndedForType(ModelType type) { 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return InitialSyncEndedForType(&trans, type); 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Directory::InitialSyncEndedForType( 9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BaseTransaction* trans, ModelType type) { 9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // True iff the type's root node has been received and applied. 97446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) syncable::Entry entry(trans, syncable::GET_TYPE_ROOT, type); 975d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return entry.good() && entry.GetBaseVersion() != CHANGES_VERSION; 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::store_birthday() const { 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.store_birthday; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::set_store_birthday(const string& store_birthday) { 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_->persisted_info.store_birthday == store_birthday) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.store_birthday = store_birthday; 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::bag_of_chips() const { 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.bag_of_chips; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::set_bag_of_chips(const string& bag_of_chips) { 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_->persisted_info.bag_of_chips == bag_of_chips) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.bag_of_chips = bag_of_chips; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::cache_guid() const { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to lock since nothing ever writes to it after load. 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->cache_guid; 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NigoriHandler* Directory::GetNigoriHandler() { 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nigori_handler_; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Cryptographer* Directory::GetCryptographer(const BaseTransaction* trans) { 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(this, trans->directory()); 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cryptographer_; 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetAllMetaHandles(BaseTransaction* trans, 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet* result) { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1023868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator i = kernel_->metahandles_map.begin(); 1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) i != kernel_->metahandles_map.end(); ++i) { 1025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->insert(i->first); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetUnsyncedMetaHandles(BaseTransaction* trans, 1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Metahandles* result) { 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1033868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) copy(kernel_->unsynced_metahandles.begin(), 1034868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.end(), back_inserter(*result)); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::unsynced_entity_count() const { 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1039868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->unsynced_metahandles.size(); 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Directory::TypeHasUnappliedUpdates(ModelType type) { 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return !kernel_->unapplied_update_metahandles[type].empty(); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetUnappliedUpdateMetaHandles( 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseTransaction* trans, 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FullModelTypeSet server_types, 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int64>* result) { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = UNSPECIFIED; i < MODEL_TYPE_COUNT; ++i) { 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = ModelTypeFromInt(i); 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_types.Has(type)) { 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy(kernel_->unapplied_update_metahandles[type].begin(), 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->unapplied_update_metahandles[type].end(), 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) back_inserter(*result)); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1063a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void Directory::GetMetaHandlesOfType(BaseTransaction* trans, 1064a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ModelType type, 1065a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<int64>* result) { 1066a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScopedKernelLock lock(this); 10671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetMetaHandlesOfType(lock, trans, type, result); 10681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 10691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 10701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Directory::GetMetaHandlesOfType(const ScopedKernelLock& lock, 10711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BaseTransaction* trans, 10721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ModelType type, 10731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<int64>* result) { 10741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci result->clear(); 1075a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 1076a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 1077a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EntryKernel* entry = it->second; 1078a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ModelType entry_type = 1079a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetModelTypeFromSpecifics(entry->ref(SPECIFICS)); 1080a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (entry_type == type) 1081a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) result->push_back(it->first); 1082a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1083a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1084a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Directory::CollectMetaHandleCounts( 10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int>* num_entries_by_type, 10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int>* num_to_delete_entries_by_type) { 10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedKernelLock lock(this); 10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1091868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 1092868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ModelType type = GetModelTypeFromSpecifics(entry->ref(SPECIFICS)); 10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*num_entries_by_type)[type]++; 1096868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(IS_DEL)) 10972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*num_to_delete_entries_by_type)[type]++; 10982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochscoped_ptr<base::ListValue> Directory::GetNodeDetailsForType( 1102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch BaseTransaction* trans, 1103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ModelType type) { 11045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> nodes(new base::ListValue()); 11055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedKernelLock lock(this); 11075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 11085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 1109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (GetModelTypeFromSpecifics(it->second->ref(SPECIFICS)) != type) { 1110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch continue; 1111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 1112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 11135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EntryKernel* kernel = it->second; 11145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> node( 11155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kernel->ToValue(GetCryptographer(trans))); 11165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Add the position index if appropriate. This must be done here (and not 11185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // in EntryKernel) because the EntryKernel does not have access to its 11195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // siblings. 11205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (kernel->ShouldMaintainPosition() && !kernel->ref(IS_DEL)) { 11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node->SetInteger("positionIndex", GetPositionIndex(trans, kernel)); 11225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nodes->Append(node.release()); 11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 11265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return nodes.Pass(); 11285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::CheckInvariantsOnTransactionClose( 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncable::BaseTransaction* trans, 11324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MetahandleSet& modified_handles) { 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: The trans may be in the process of being destructed. Be careful if 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // you wish to call any of its virtual methods. 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (invariant_check_level_) { 11364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case FULL_DB_VERIFICATION: { 11374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MetahandleSet all_handles; 11384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetAllMetaHandles(trans, &all_handles); 11394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CheckTreeInvariants(trans, all_handles); 11404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 11414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case VERIFY_CHANGES: { 11424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CheckTreeInvariants(trans, modified_handles); 11434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 11444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case OFF: { 11454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOTREACHED(); 11494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::FullyCheckTreeInvariants(syncable::BaseTransaction* trans) { 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet handles; 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAllMetaHandles(trans, &handles); 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CheckTreeInvariants(trans, handles); 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::CheckTreeInvariants(syncable::BaseTransaction* trans, 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MetahandleSet& handles) { 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet::const_iterator i; 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = handles.begin() ; i != handles.end() ; ++i) { 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = *i; 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry e(trans, GET_BY_HANDLE, metahandle); 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(e.good(), FROM_HERE, "Entry is bad", trans)) 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) syncable::Id id = e.GetId(); 1167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) syncable::Id parentid = e.GetParentId(); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id.IsRoot()) { 1170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsDir(), FROM_HERE, 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be a directory", 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(parentid.IsRoot(), FROM_HERE, 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be root", 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1178d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!e.GetIsUnsynced(), FROM_HERE, 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be sycned", 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!e.GetIsDel()) { 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id != parentid, FROM_HERE, 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Id should be different from parent id.", 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!e.GetNonUniqueName().empty(), FROM_HERE, 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Non unique name should not be empty.", 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int safety_count = handles.size() + 1; 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!parentid.IsRoot()) { 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry parent(trans, GET_BY_ID, parentid); 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(parent.good(), FROM_HERE, 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent entry is not valid.", 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (handles.end() == handles.find(parent.GetMetahandle())) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Skip further checking if parent was unmodified. 1203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(parent.GetIsDir(), FROM_HERE, 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should be a directory", 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!parent.GetIsDel(), FROM_HERE, 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should not have been marked for deletion.", 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(handles.end() != handles.find(parent.GetMetahandle()), 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should be in the index.", 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) parentid = parent.GetParentId(); 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(--safety_count > 0, FROM_HERE, 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Count should be greater than zero.", 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 base_version = e.GetBaseVersion(); 1224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 server_version = e.GetServerVersion(); 1225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool using_unique_client_tag = !e.GetUniqueClientTag().empty(); 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CHANGES_VERSION == base_version || 0 == base_version) { 1227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (e.GetIsUnappliedUpdate()) { 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must be a new item, or a de-duplicated unique client tag 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that was created both locally and remotely. 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!using_unique_client_tag) { 1231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsDel(), FROM_HERE, 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The entry should not have been deleted.", 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It came from the server, so it must have a server ID. 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id.ServerKnows(), FROM_HERE, 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The id should be from a server.", 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (e.GetIsDir()) { 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(chron): Implement this mode if clients ever need it. 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, you can't combine a client tag and a directory. 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!using_unique_client_tag, FROM_HERE, 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Directory cannot have a client tag.", 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be an uncomitted item, or a successfully deleted one. 1251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!e.GetIsDel()) { 1252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsUnsynced(), FROM_HERE, 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The item should be unsynced.", 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the next check failed, it would imply that an item exists 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the server, isn't waiting for application locally, but either 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is an unsynced create or a sucessful delete in the local copy. 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either way, that's a mismatch. 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(0 == server_version, FROM_HERE, 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Server version should be zero.", 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Items that aren't using the unique client tag should have a zero 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base version only if they have a local ID. Items with unique client 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tags are allowed to use the zero base version for undeletion and 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // de-duplication; the unique client tag trumps the server ID. 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!using_unique_client_tag) { 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!id.ServerKnows(), FROM_HERE, 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Should be a client only id.", 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id.ServerKnows(), 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Should be a server id.", 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Server-unknown items that are locally deleted should not be sent up to 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the server. They must be !IS_UNSYNCED. 1285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!(!id.ServerKnows() && e.GetIsDel() && e.GetIsUnsynced()), 1286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FROM_HERE, 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Locally deleted item must not be unsynced.", 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) { 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::SetInvariantCheckLevel(InvariantCheckLevel check_level) { 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invariant_check_level_ = check_level; 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::NextMetahandle() { 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = (kernel_->next_metahandle)++; 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return metahandle; 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Always returns a client ID that is the string representation of a negative 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number. 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Id Directory::NextId() { 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 result; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = (kernel_->persisted_info.next_id)--; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(result, 0); 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Id::CreateFromClientString(base::Int64ToString(result)); 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::HasChildren(BaseTransaction* trans, const Id& id) { 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->parent_child_index.GetChildren(id) != NULL; 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Id Directory::GetFirstChildId(BaseTransaction* trans, 1324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const EntryKernel* parent) { 1325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parent); 1326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parent->ref(IS_DIR)); 1327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(parent->ref(ID)); 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We're expected to return root if there are no children. 1333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!children) 1334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*children->begin())->ref(ID); 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)syncable::Id Directory::GetPredecessorId(EntryKernel* e) { 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(ParentChildIndex::ShouldInclude(e)); 1343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(children && !children->empty()); 1346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator i = children->find(e); 1347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(i != children->end()); 1348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (i == children->begin()) { 1350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i--; 1353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*i)->ref(ID); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)syncable::Id Directory::GetSuccessorId(EntryKernel* e) { 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(ParentChildIndex::ShouldInclude(e)); 1361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(children && !children->empty()); 1364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator i = children->find(e); 1365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(i != children->end()); 1366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i++; 1368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (i == children->end()) { 1369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*i)->ref(ID); 1372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(rlarocque): Remove all support for placing ShouldMaintainPosition() 1376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// items as siblings of items that do not maintain postions. It is required 1377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// only for tests. See crbug.com/178282. 1378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void Directory::PutPredecessor(EntryKernel* e, EntryKernel* predecessor) { 1379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!e->ref(IS_DEL)); 1380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!e->ShouldMaintainPosition()) { 1381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!e->ref(UNIQUE_POSITION).IsValid()); 1382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string suffix = e->ref(UNIQUE_BOOKMARK_TAG); 1385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!suffix.empty()); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove our item from the ParentChildIndex and remember to re-add it later. 1388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedKernelLock lock(this); 1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ScopedParentChildIndexUpdater updater(lock, e, &kernel_->parent_child_index); 1390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note: The ScopedParentChildIndexUpdater will update this set for us as we 1392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // leave this function. 1393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* siblings = 1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!siblings) { 1397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This parent currently has no other children. 1398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(predecessor->ref(ID).IsRoot()); 1399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::InitialPosition(suffix); 1400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (predecessor->ref(ID).IsRoot()) { 1405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We have at least one sibling, and we're inserting to the left of them. 1406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition successor_pos = (*siblings->begin())->ref(UNIQUE_POSITION); 1407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos; 1409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!successor_pos.IsValid()) { 1410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If all our successors are of non-positionable types, just create an 1411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // initial position. We arbitrarily choose to sort invalid positions to 1412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the right of the valid positions. 1413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 1414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We really shouldn't need to support this. See TODO above. 1415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pos = UniquePosition::InitialPosition(suffix); 1416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!siblings->empty()); 1418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pos = UniquePosition::Before(successor_pos, suffix); 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We can't support placing an item after an invalid position. Fortunately, 1426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the tests don't exercise this particular case. We should not support 1427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // siblings with invalid positions at all. See TODO above. 1428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(predecessor->ref(UNIQUE_POSITION).IsValid()); 1429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator neighbour = siblings->find(predecessor); 1431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(neighbour != siblings->end()); 1432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++neighbour; 1434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (neighbour == siblings->end()) { 1435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Inserting at the end of the list. 1436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::After( 1437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) predecessor->ref(UNIQUE_POSITION), 1438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) suffix); 1439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EntryKernel* successor = *neighbour; 1444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Another mixed valid and invalid position case. This one could be supported 1446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // in theory, but we're trying to deprecate support for siblings with and 1447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // without valid positions. See TODO above. 1448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(successor->ref(UNIQUE_POSITION).IsValid()); 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Finally, the normal case: inserting between two elements. 1451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::Between( 1452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) predecessor->ref(UNIQUE_POSITION), 1453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successor->ref(UNIQUE_POSITION), 1454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) suffix); 1455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(rlarocque): Avoid this indirection. Just return the set. 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::AppendChildHandles(const ScopedKernelLock& lock, 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Id& parent_id, 1462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::Metahandles* result) { 1463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(parent_id); 1465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!children) 1466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (OrderedChildSet::const_iterator i = children->begin(); 1469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i != children->end(); ++i) { 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back((*i)->ref(META_HANDLE)); 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid Directory::UnmarkDirtyEntry(WriteTransaction* trans, Entry* entry) { 1476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(trans); 1477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch entry->kernel_->clear_dirty(&kernel_->dirty_metahandles); 1478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 1479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 14801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid Directory::GetAttachmentIdsToUpload(BaseTransaction* trans, 14811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ModelType type, 14821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentIdSet* id_set) { 14831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(maniscalco): Maintain an index by ModelType and rewrite this method to 14841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // use it. The approach below is likely very expensive because it iterates 14851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // all entries (bug 415199). 14861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(trans); 14871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(id_set); 14881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci id_set->clear(); 14891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentIdSet on_server_id_set; 14901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentIdSet not_on_server_id_set; 14911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<int64> metahandles; 14921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci { 14931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ScopedKernelLock lock(this); 14941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetMetaHandlesOfType(lock, trans, type, &metahandles); 14951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<int64>::const_iterator iter = metahandles.begin(); 14961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<int64>::const_iterator end = metahandles.end(); 14971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // For all of this type's entries... 14981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (; iter != end; ++iter) { 14991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EntryKernel* entry = GetEntryByHandle(lock, *iter); 15001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(entry); 15011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const sync_pb::AttachmentMetadata metadata = 15021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry->ref(ATTACHMENT_METADATA); 15031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // for each of this entry's attachments... 15041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (int i = 0; i < metadata.record_size(); ++i) { 15051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentId id = 15061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AttachmentId::CreateFromProto(metadata.record(i).id()); 15071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // if this attachment is known to be on the server, remember it for 15081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // later, 15091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (metadata.record(i).is_on_server()) { 15101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci on_server_id_set.insert(id); 15111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 15121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // otherwise, add it to id_set. 15131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci not_on_server_id_set.insert(id); 15141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 15181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Why did we bother keeping a set of ids known to be on the server? The 15191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // is_on_server flag is stored denormalized so we can end up with two entries 15201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // with the same attachment id where one says it's on the server and the other 15211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // says it's not. When this happens, we trust the one that says it's on the 15221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // server. To avoid re-uploading the same attachment mulitple times, we 15231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // remove any ids known to be on the server from the id_set we are about to 15241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // return. 15251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 15261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(maniscalco): Eliminate redundant metadata storage (bug 415203). 15271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::set_difference(not_on_server_id_set.begin(), 15281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci not_on_server_id_set.end(), 15291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci on_server_id_set.begin(), 15301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci on_server_id_set.end(), 15311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::inserter(*id_set, id_set->end())); 15321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 15331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncable 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 1536