directory.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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) 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <iterator> 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base64.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/internal_api/public/base/unique_position.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/unrecoverable_error_handler.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry_kernel.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/in_memory_directory_backing_store.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/on_disk_directory_backing_store.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sync/syncable/scoped_kernel_lock.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "sync/syncable/scoped_parent_child_index_updater.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable-inl.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_base_transaction.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_changes_version.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_read_transaction.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_util.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_write_transaction.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType Directory::kSyncDatabaseFilename[] = 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("SyncData.sqlite3"); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::PersistedKernelInfo::PersistedKernelInfo() 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_id(0) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet protocol_types = ProtocolTypes(); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter.Inc()) { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reset_download_progress(iter.Get()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) transaction_version[iter.Get()] = 0; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::PersistedKernelInfo::~PersistedKernelInfo() {} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::PersistedKernelInfo::reset_download_progress( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_progress[model_type].set_data_type_id( 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSpecificsFieldNumberFromModelType(model_type)); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An empty-string token indicates no prior knowledge. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_progress[model_type].set_token(std::string()); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::SaveChangesSnapshot::SaveChangesSnapshot() 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kernel_info_status(KERNEL_SHARE_INFO_INVALID) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Directory::SaveChangesSnapshot::~SaveChangesSnapshot() { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&dirty_metas); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLDeleteElements(&delete_journals); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Kernel::Kernel( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const KernelLoadInfo& info, DirectoryChangeDelegate* delegate, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& transaction_observer) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_write_transaction_id(0), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name(name), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_status(Directory::KERNEL_SHARE_INFO_VALID), 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) persisted_info(info.kernel_info), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cache_guid(info.cache_guid), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_metahandle(info.max_metahandle + 1), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate(delegate), 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transaction_observer(transaction_observer) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transaction_observer.IsInitialized()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Kernel::~Kernel() { 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) STLDeleteContainerPairSecondPointers(metahandles_map.begin(), 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) metahandles_map.end()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::Directory( 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryBackingStore* store, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnrecoverableErrorHandler* unrecoverable_error_handler, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportUnrecoverableErrorFunction report_unrecoverable_error_function, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NigoriHandler* nigori_handler, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Cryptographer* cryptographer) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kernel_(NULL), 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_(store), 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_handler_(unrecoverable_error_handler), 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_unrecoverable_error_function_( 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) report_unrecoverable_error_function), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_set_(false), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nigori_handler_(nigori_handler), 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cryptographer_(cryptographer), 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invariant_check_level_(VERIFY_CHANGES) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory::~Directory() { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirOpenResult Directory::Open( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& name, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryChangeDelegate* delegate, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& transaction_observer) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("sync", "SyncDatabaseOpen"); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DirOpenResult result = 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OpenImpl(name, delegate, transaction_observer); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OPENED != result) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::InitializeIndices(MetahandlesMap* handles_map) { 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.swap(*handles_map); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::const_iterator it = kernel_->metahandles_map.begin(); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ParentChildIndex::ShouldInclude(entry)) 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Insert(entry); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int64 metahandle = entry->ref(META_HANDLE); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->ref(IS_UNSYNCED)) 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.insert(metahandle); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->ref(IS_UNAPPLIED_UPDATE)) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = entry->GetServerModelType(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->unapplied_update_metahandles[type].insert(metahandle); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.end()) 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "Unexpected duplicate use of client tag"; 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map[entry->ref(UNIQUE_SERVER_TAG)] = entry; 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->server_tags_map.find(entry->ref(UNIQUE_SERVER_TAG)) == 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.end()) 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "Unexpected duplicate use of server tag"; 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map[entry->ref(UNIQUE_CLIENT_TAG)] = entry; 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(kernel_->ids_map.find(entry->ref(ID).value()) == 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map.end()) << "Unexpected duplicate use of ID"; 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map[entry->ref(ID).value()] = entry; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!entry->is_dirty()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DirOpenResult Directory::OpenImpl( 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string& name, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirectoryChangeDelegate* delegate, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WeakHandle<TransactionObserver>& 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transaction_observer) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KernelLoadInfo info; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Temporary indices before kernel_ initialized in case Load fails. We 0(1) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // swap these later. 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::MetahandlesMap tmp_handles_map; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JournalIndex delete_journals; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DirOpenResult result = 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) store_->Load(&tmp_handles_map, &delete_journals, &info); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OPENED != result) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_ = new Kernel(name, info, delegate, transaction_observer); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_.reset(new DeleteJournal(&delete_journals)); 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InitializeIndices(&tmp_handles_map); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write back the share info to reserve some space in 'next_id'. This will 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prevent local ID reuse in the case of an early crash. See the comments in 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TakeSnapshotForSaveChanges() or crbug.com/142987 for more information. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SaveChanges()) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FAILED_INITIAL_WRITE; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OPENED; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DeleteJournal* Directory::delete_journal() { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(delete_journal_.get()); 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return delete_journal_.get(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::Close() { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) store_.reset(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete kernel_; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_ = NULL; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::OnUnrecoverableError(const BaseTransaction* trans, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const tracked_objects::Location& location, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string & message) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(trans != NULL); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_set_ = true; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unrecoverable_error_handler_->OnUnrecoverableError(location, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryById(const Id& id) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetEntryById(id, &lock); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryById(const Id& id, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock* const lock) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find it in the in memory ID index. 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) IdsMap::iterator id_found = kernel_->ids_map.find(id.value()); 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (id_found != kernel_->ids_map.end()) { 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return id_found->second; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByClientTag(const string& tag) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TagsMap::iterator it = kernel_->client_tags_map.find(tag); 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it != kernel_->client_tags_map.end()) { 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return it->second; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByServerTag(const string& tag) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kernel_); 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TagsMap::iterator it = kernel_->server_tags_map.find(tag); 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it != kernel_->server_tags_map.end()) { 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return it->second; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByHandle(int64 metahandle) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetEntryByHandle(metahandle, &lock); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetEntryByHandle(int64 metahandle, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock* lock) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Look up in memory 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find(metahandle); 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (found != kernel_->metahandles_map.end()) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found it in memory. Easy. 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return found->second; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::GetChildHandlesById( 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseTransaction* trans, const Id& parent_id, 263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::Metahandles* result) { 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(this == trans->directory(), FROM_HERE, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Directories don't match", trans)) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppendChildHandles(lock, parent_id, result); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int Directory::GetTotalNodeCount( 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BaseTransaction* trans, 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* kernel) const { 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(this == trans->directory(), FROM_HERE, 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Directories don't match", trans)) 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int count = 1; 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::deque<const OrderedChildSet*> child_sets; 283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetChildSetForKernel(trans, kernel, &child_sets); 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (!child_sets.empty()) { 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OrderedChildSet* set = child_sets.front(); 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_sets.pop_front(); 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (OrderedChildSet::const_iterator it = set->begin(); 289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != set->end(); ++it) { 290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) count++; 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetChildSetForKernel(trans, *it, &child_sets); 292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return count; 296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::GetChildSetForKernel( 299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BaseTransaction* trans, 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* kernel, 301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::deque<const OrderedChildSet*>* child_sets) const { 302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!kernel->ref(IS_DIR)) 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; // Not a directory => no children. 304868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const OrderedChildSet* descendants = 306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(kernel->ref(ID)); 307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!descendants) 308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; // This directory has no children. 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Add our children to the list of items to be traversed. 311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) child_sets->push_back(descendants); 312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int Directory::GetPositionIndex( 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) BaseTransaction* trans, 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) EntryKernel* kernel) const { 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const OrderedChildSet* siblings = 3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) kernel_->parent_child_index.GetChildren(kernel->ref(PARENT_ID)); 3197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) OrderedChildSet::const_iterator it = siblings->find(kernel); 3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return std::distance(siblings->begin(), it); 3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EntryKernel* Directory::GetRootEntry() { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetEntryById(Id()); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::InsertEntry(BaseWriteTransaction* trans, EntryKernel* entry) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InsertEntry(trans, entry, &lock); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::InsertEntry(BaseWriteTransaction* trans, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EntryKernel* entry, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock* lock) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(NULL != lock); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(NULL != entry, FROM_HERE, "Entry is null", trans)) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char error[] = "Entry already in memory index."; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert( 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.insert( 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::make_pair(entry->ref(META_HANDLE), entry)).second, 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error, 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) trans)) { 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert( 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map.insert( 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::make_pair(entry->ref(ID).value(), entry)).second, 353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error, 355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) trans)) { 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ParentChildIndex::ShouldInclude(entry)) { 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(kernel_->parent_child_index.Insert(entry), 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Should NEVER be created with a client tag or server tag. 368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(entry->ref(UNIQUE_SERVER_TAG).empty(), FROM_HERE, 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Server tag should be empty", trans)) { 370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(entry->ref(UNIQUE_CLIENT_TAG).empty(), FROM_HERE, 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Client tag should be empty", trans)) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::ReindexId(BaseWriteTransaction* trans, 3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EntryKernel* const entry, 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const Id& new_id) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != GetEntryById(new_id, &lock)) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the indices that depend on the ID field. 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedParentChildIndexUpdater updater_b(lock, entry, 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &kernel_->parent_child_index); 390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1U, num_erased); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->put(ID, new_id); 393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->ids_map[entry->ref(ID).value()] = entry; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool Directory::ReindexParentId(BaseWriteTransaction* trans, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EntryKernel* const entry, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Id& new_parent_id) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the indices that depend on the PARENT_ID field. 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedParentChildIndexUpdater index_updater(lock, entry, 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &kernel_->parent_child_index); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->put(PARENT_ID, new_parent_id); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::unrecoverable_error_set(const BaseTransaction* trans) const { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(trans != NULL); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return unrecoverable_error_set_; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::ClearDirtyMetahandles() { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->dirty_metahandles.clear(); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::SafeToPurgeFromMemory(WriteTransaction* trans, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const EntryKernel* const entry) const { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool safe = entry->ref(IS_DEL) && !entry->is_dirty() && 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !entry->ref(SYNCING) && !entry->ref(IS_UNAPPLIED_UPDATE) && 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !entry->ref(IS_UNSYNCED); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (safe) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = entry->GetServerModelType(); 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(kernel_->dirty_metahandles.count(handle) == 0U, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Dirty metahandles should be empty", trans)) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tim): Bug 49278. 436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(!kernel_->unsynced_metahandles.count(handle), 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Unsynced handles should be empty", 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!kernel_->unapplied_update_metahandles[type].count(handle), 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Unapplied metahandles should be empty", 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return safe; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::TakeSnapshotForSaveChanges(SaveChangesSnapshot* snapshot) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReadTransaction trans(FROM_HERE, this); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is an unrecoverable error then just bail out. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unrecoverable_error_set(&trans)) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deep copy dirty entries from kernel_->metahandles_index into snapshot and 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clear dirty flags. 461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandleSet::const_iterator i = kernel_->dirty_metahandles.begin(); 462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) i != kernel_->dirty_metahandles.end(); ++i) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EntryKernel* entry = GetEntryByHandle(*i, &lock); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip over false positives; it happens relatively infrequently. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!entry->is_dirty()) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot->dirty_metas.insert(snapshot->dirty_metas.end(), 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new EntryKernel(*entry)); 471868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1U, kernel_->dirty_metahandles.count(*i)); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't bother removing from the index here as we blow the entire thing 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a moment, and it unnecessarily complicates iteration. 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->clear_dirty(NULL); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearDirtyMetahandles(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set purged handles. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(snapshot->metahandles_to_purge.empty()); 480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snapshot->metahandles_to_purge.swap(kernel_->metahandles_to_purge); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill kernel_info_status and kernel_info. 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info = kernel_->persisted_info; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To avoid duplicates when the process crashes, we record the next_id to be 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // greater magnitude than could possibly be reached before the next save 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changes. In other words, it's effectively impossible for the user to 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // generate 65536 new bookmarks in 3 seconds. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info.next_id -= 65536; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snapshot->kernel_info_status = kernel_->info_status; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This one we reset on failure. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_VALID; 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->TakeSnapshotAndClear( 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &trans, &snapshot->delete_journals, &snapshot->delete_journals_to_purge); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::SaveChanges() { 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = false; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock scoped_lock(kernel_->save_changes_mutex); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Snapshot and save. 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveChangesSnapshot snapshot; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TakeSnapshotForSaveChanges(&snapshot); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = store_->SaveChanges(snapshot); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle success or failure. 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = VacuumAfterSaveChanges(snapshot); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandleSaveChangesFailure(snapshot); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return success; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::VacuumAfterSaveChanges(const SaveChangesSnapshot& snapshot) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (snapshot.dirty_metas.empty()) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need a write transaction as we are about to permanently purge entries. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTransaction trans(FROM_HERE, VACUUM_AFTER_SAVE, this); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now drop everything we can out of memory. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != snapshot.dirty_metas.end(); ++i) { 525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); 527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = (found == kernel_->metahandles_map.end() ? 528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NULL : found->second); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry && SafeToPurgeFromMemory(&trans, entry)) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We now drop deleted metahandles that are up to date on both the client 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and the server. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num_erased = 0; 533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); 540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); 545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!SyncAssert(!kernel_->parent_child_index.Contains(entry), 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Deleted entry still present", 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (&trans))) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete entry; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trans.unrecoverable_error_set()) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::UnapplyEntry(EntryKernel* entry) { 561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics( 563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->ref(SERVER_SPECIFICS)); 564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Clear enough so that on the next sync cycle all local data will 566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // be overwritten. 567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Note: do not modify the root node in order to preserve the 568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // initial sync ended bit for this type (else on the next restart 569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // this type will be treated as disabled and therefore fully purged). 570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (IsRealDataType(server_type) && 571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeToRootTag(server_type) == entry->ref(UNIQUE_SERVER_TAG)) { 572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Set the unapplied bit if this item has server data. 576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (IsRealDataType(server_type) && !entry->ref(IS_UNAPPLIED_UPDATE)) { 577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_UNAPPLIED_UPDATE, true); 578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unapplied_update_metahandles[server_type].insert(handle); 579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Unset the unsynced bit. 583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(IS_UNSYNCED)) { 584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.erase(handle); 585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_UNSYNCED, false); 586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Mark the item as locally deleted. No deleted items are allowed in the 590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // parent child index. 591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(IS_DEL)) { 592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Remove(entry); 593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(IS_DEL, true); 594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Set the version to the "newly created" version. 598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(BASE_VERSION) != CHANGES_VERSION) { 599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->put(BASE_VERSION, CHANGES_VERSION); 600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->mark_dirty(&kernel_->dirty_metahandles); 601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // At this point locally created items that aren't synced will become locally 604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // deleted items, and purged on the next snapshot. All other items will match 605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the state they would have had if they were just created via a server 606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // update. See MutableEntry::MutableEntry(.., CreateNewUpdateItem, ..). 607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Directory::DeleteEntry(bool save_to_journal, 610868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry, 611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernelSet* entries_to_journal) { 612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64 handle = entry->ref(META_HANDLE); 613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics( 614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entry->ref(SERVER_SPECIFICS)); 615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_to_purge.insert(handle); 617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 618868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_erased = 0; 619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->metahandles_map.erase(entry->ref(META_HANDLE)); 620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->ids_map.erase(entry->ref(ID).value()); 622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 623868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = kernel_->unsynced_metahandles.erase(handle); 624868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(entry->ref(IS_UNSYNCED), num_erased > 0); 625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unapplied_update_metahandles[server_type].erase(handle); 627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(entry->ref(IS_UNAPPLIED_UPDATE), num_erased > 0); 628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (kernel_->parent_child_index.Contains(entry)) 629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.Remove(entry); 630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_CLIENT_TAG).empty()) { 632868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->client_tags_map.erase(entry->ref(UNIQUE_CLIENT_TAG)); 634868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 635868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 636868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!entry->ref(UNIQUE_SERVER_TAG).empty()) { 637868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) num_erased = 638868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->server_tags_map.erase(entry->ref(UNIQUE_SERVER_TAG)); 639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_EQ(1u, num_erased); 640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (save_to_journal) { 643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) entries_to_journal->insert(entry); 644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete entry; 646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 649868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool Directory::PurgeEntriesWithTypeIn(ModelTypeSet disabled_types, 650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeSet types_to_journal, 651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelTypeSet types_to_unapply) { 652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) disabled_types.RemoveAll(ProxyTypes()); 653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (disabled_types.Empty()) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTransaction trans(FROM_HERE, PURGE_ENTRIES, this); 6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EntryKernelSet entries_to_journal; 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STLElementDeleter<EntryKernelSet> journal_deleter(&entries_to_journal); 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // We iterate in two passes to avoid a bug in STLport (which is used in 667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the Android build). There are some versions of that library where a 668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // hash_map's iterators can be invalidated when an item is erased from the 669868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // hash_map. 670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // See http://sourceforge.net/p/stlport/bugs/239/. 671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::set<EntryKernel*> to_purge; 673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it->second->ref(SPECIFICS); 677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it->second->ref(SERVER_SPECIFICS); 679868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType local_type = GetModelTypeFromSpecifics(local_specifics); 680868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics(server_specifics); 681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 682868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((IsRealDataType(local_type) && disabled_types.Has(local_type)) || 683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (IsRealDataType(server_type) && disabled_types.Has(server_type))) { 684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) to_purge.insert(it->second); 685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 686868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (std::set<EntryKernel*>::iterator it = to_purge.begin(); 689868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != to_purge.end(); ++it) { 690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = *it; 691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 692868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const sync_pb::EntitySpecifics& local_specifics = 693868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (*it)->ref(SPECIFICS); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::EntitySpecifics& server_specifics = 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*it)->ref(SERVER_SPECIFICS); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType local_type = GetModelTypeFromSpecifics(local_specifics); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType server_type = GetModelTypeFromSpecifics(server_specifics); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (types_to_unapply.Has(local_type) || 700868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) types_to_unapply.Has(server_type)) { 701868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UnapplyEntry(entry); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 703868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool save_to_journal = 704868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (types_to_journal.Has(local_type) || 705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) types_to_journal.Has(server_type)) && 706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (delete_journal_->IsDeleteJournalEnabled(local_type) || 707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete_journal_->IsDeleteJournalEnabled(server_type)); 708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DeleteEntry(save_to_journal, entry, &entries_to_journal); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->AddJournalBatch(&trans, entries_to_journal); 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Ensure meta tracking for these data types reflects the purged state. 715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (ModelTypeSet::Iterator it = disabled_types.First(); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Good(); it.Inc()) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.transaction_version[it.Get()] = 0; 718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Don't discard progress markers for unapplied types. 720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!types_to_unapply.Has(it.Get())) 721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->persisted_info.reset_download_progress(it.Get()); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::HandleSaveChangesFailure(const SaveChangesSnapshot& snapshot) { 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WriteTransaction trans(FROM_HERE, HANDLE_SAVE_FAILURE, this); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because we optimistically cleared the dirty bit on the real entries when 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // taking the snapshot, we must restore it on failure. Not doing this could 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause lost data, if no other changes are made to the in-memory entries 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that would cause the dirty bit to get set again. Setting the bit ensures 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that SaveChanges will at least try again later. 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (EntryKernelSet::const_iterator i = snapshot.dirty_metas.begin(); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != snapshot.dirty_metas.end(); ++i) { 740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MetahandlesMap::iterator found = 741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_map.find((*i)->ref(META_HANDLE)); 742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (found != kernel_->metahandles_map.end()) { 743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) found->second->mark_dirty(&kernel_->dirty_metahandles); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->metahandles_to_purge.insert(snapshot.metahandles_to_purge.begin(), 748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snapshot.metahandles_to_purge.end()); 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Restore delete journals. 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->AddJournalBatch(&trans, snapshot.delete_journals); 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_journal_->PurgeDeleteJournals(&trans, 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) snapshot.delete_journals_to_purge); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetDownloadProgress( 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sync_pb::DataTypeProgressMarker* value_out) const { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value_out->CopyFrom( 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type]); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetDownloadProgressAsString( 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* value_out) const { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type].SerializeToString( 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_out); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Directory::GetEntriesCount() const { 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->metahandles_map.size(); 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::SetDownloadProgress( 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ModelType model_type, 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const sync_pb::DataTypeProgressMarker& new_progress) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.download_progress[model_type].CopyFrom(new_progress); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::GetTransactionVersion(ModelType type) const { 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.transaction_version[type]; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::IncrementTransactionVersion(ModelType type) { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->transaction_mutex.AssertAcquired(); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.transaction_version[type]++; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ModelTypeSet Directory::InitialSyncEndedTypes() { 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet protocol_types = ProtocolTypes(); 7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeSet initial_sync_ended_types; 7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (ModelTypeSet::Iterator i = protocol_types.First(); i.Good(); i.Inc()) { 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (InitialSyncEndedForType(&trans, i.Get())) { 8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initial_sync_ended_types.Put(i.Get()); 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return initial_sync_ended_types; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Directory::InitialSyncEndedForType(ModelType type) { 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return InitialSyncEndedForType(&trans, type); 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool Directory::InitialSyncEndedForType( 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BaseTransaction* trans, ModelType type) { 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // True iff the type's root node has been received and applied. 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::Entry entry(trans, 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::GET_BY_SERVER_TAG, 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ModelTypeToRootTag(type)); 818d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return entry.good() && entry.GetBaseVersion() != CHANGES_VERSION; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::store_birthday() const { 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.store_birthday; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::set_store_birthday(const string& store_birthday) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_->persisted_info.store_birthday == store_birthday) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.store_birthday = store_birthday; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::bag_of_chips() const { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->persisted_info.bag_of_chips; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::set_bag_of_chips(const string& bag_of_chips) { 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kernel_->persisted_info.bag_of_chips == bag_of_chips) 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->persisted_info.bag_of_chips = bag_of_chips; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string Directory::cache_guid() const { 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to lock since nothing ever writes to it after load. 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kernel_->cache_guid; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NigoriHandler* Directory::GetNigoriHandler() { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nigori_handler_; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Cryptographer* Directory::GetCryptographer(const BaseTransaction* trans) { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(this, trans->directory()); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cryptographer_; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetAllMetaHandles(BaseTransaction* trans, 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet* result) { 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator i = kernel_->metahandles_map.begin(); 867868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) i != kernel_->metahandles_map.end(); ++i) { 868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result->insert(i->first); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetUnsyncedMetaHandles(BaseTransaction* trans, 873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Metahandles* result) { 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) copy(kernel_->unsynced_metahandles.begin(), 877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->unsynced_metahandles.end(), back_inserter(*result)); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::unsynced_entity_count() const { 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 882868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->unsynced_metahandles.size(); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool Directory::TypeHasUnappliedUpdates(ModelType type) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 887a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return !kernel_->unapplied_update_metahandles[type].empty(); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::GetUnappliedUpdateMetaHandles( 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BaseTransaction* trans, 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FullModelTypeSet server_types, 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int64>* result) { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = UNSPECIFIED; i < MODEL_TYPE_COUNT; ++i) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ModelType type = ModelTypeFromInt(i); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_types.Has(type)) { 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy(kernel_->unapplied_update_metahandles[type].begin(), 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->unapplied_update_metahandles[type].end(), 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) back_inserter(*result)); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Directory::CollectMetaHandleCounts( 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int>* num_entries_by_type, 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<int>* num_to_delete_entries_by_type) { 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syncable::ReadTransaction trans(FROM_HERE, this); 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedKernelLock lock(this); 9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EntryKernel* entry = it->second; 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ModelType type = GetModelTypeFromSpecifics(entry->ref(SPECIFICS)); 9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*num_entries_by_type)[type]++; 917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (entry->ref(IS_DEL)) 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*num_to_delete_entries_by_type)[type]++; 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)scoped_ptr<base::ListValue> Directory::GetAllNodeDetails( 9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BaseTransaction* trans) { 9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> nodes(new base::ListValue()); 9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedKernelLock lock(this); 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (MetahandlesMap::iterator it = kernel_->metahandles_map.begin(); 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != kernel_->metahandles_map.end(); ++it) { 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EntryKernel* kernel = it->second; 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> node( 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kernel->ToValue(GetCryptographer(trans))); 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Add the position index if appropriate. This must be done here (and not 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // in EntryKernel) because the EntryKernel does not have access to its 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // siblings. 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (kernel->ShouldMaintainPosition() && !kernel->ref(IS_DEL)) { 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) node->SetInteger("positionIndex", GetPositionIndex(trans, kernel)); 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nodes->Append(node.release()); 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return nodes.Pass(); 9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::CheckInvariantsOnTransactionClose( 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncable::BaseTransaction* trans, 9484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MetahandleSet& modified_handles) { 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: The trans may be in the process of being destructed. Be careful if 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // you wish to call any of its virtual methods. 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (invariant_check_level_) { 9524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case FULL_DB_VERIFICATION: { 9534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MetahandleSet all_handles; 9544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GetAllMetaHandles(trans, &all_handles); 9554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CheckTreeInvariants(trans, all_handles); 9564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 9574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case VERIFY_CHANGES: { 9584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return CheckTreeInvariants(trans, modified_handles); 9594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 9604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case OFF: { 9614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOTREACHED(); 9654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::FullyCheckTreeInvariants(syncable::BaseTransaction* trans) { 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet handles; 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAllMetaHandles(trans, &handles); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CheckTreeInvariants(trans, handles); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::CheckTreeInvariants(syncable::BaseTransaction* trans, 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const MetahandleSet& handles) { 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MetahandleSet::const_iterator i; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = handles.begin() ; i != handles.end() ; ++i) { 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = *i; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry e(trans, GET_BY_HANDLE, metahandle); 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(e.good(), FROM_HERE, "Entry is bad", trans)) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 982d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) syncable::Id id = e.GetId(); 983d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) syncable::Id parentid = e.GetParentId(); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id.IsRoot()) { 986d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsDir(), FROM_HERE, 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be a directory", 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(parentid.IsRoot(), FROM_HERE, 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be root", 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 994d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!e.GetIsUnsynced(), FROM_HERE, 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Entry should be sycned", 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1001d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!e.GetIsDel()) { 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id != parentid, FROM_HERE, 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Id should be different from parent id.", 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1006d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!e.GetNonUniqueName().empty(), FROM_HERE, 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Non unique name should not be empty.", 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int safety_count = handles.size() + 1; 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!parentid.IsRoot()) { 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Entry parent(trans, GET_BY_ID, parentid); 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(parent.good(), FROM_HERE, 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent entry is not valid.", 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1017d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (handles.end() == handles.find(parent.GetMetahandle())) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Skip further checking if parent was unmodified. 1019d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(parent.GetIsDir(), FROM_HERE, 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should be a directory", 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1023d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!parent.GetIsDel(), FROM_HERE, 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should not have been marked for deletion.", 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1027d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(handles.end() != handles.find(parent.GetMetahandle()), 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Parent should be in the index.", 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1032d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) parentid = parent.GetParentId(); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(--safety_count > 0, FROM_HERE, 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Count should be greater than zero.", 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1039d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 base_version = e.GetBaseVersion(); 1040d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int64 server_version = e.GetServerVersion(); 1041d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool using_unique_client_tag = !e.GetUniqueClientTag().empty(); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CHANGES_VERSION == base_version || 0 == base_version) { 1043d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (e.GetIsUnappliedUpdate()) { 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must be a new item, or a de-duplicated unique client tag 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that was created both locally and remotely. 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!using_unique_client_tag) { 1047d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsDel(), FROM_HERE, 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The entry should not have been deleted.", 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It came from the server, so it must have a server ID. 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id.ServerKnows(), FROM_HERE, 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The id should be from a server.", 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1058d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (e.GetIsDir()) { 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(chron): Implement this mode if clients ever need it. 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, you can't combine a client tag and a directory. 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!using_unique_client_tag, FROM_HERE, 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Directory cannot have a client tag.", 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be an uncomitted item, or a successfully deleted one. 1067d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!e.GetIsDel()) { 1068d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(e.GetIsUnsynced(), FROM_HERE, 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The item should be unsynced.", 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the next check failed, it would imply that an item exists 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the server, isn't waiting for application locally, but either 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is an unsynced create or a sucessful delete in the local copy. 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either way, that's a mismatch. 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(0 == server_version, FROM_HERE, 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Server version should be zero.", 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Items that aren't using the unique client tag should have a zero 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // base version only if they have a local ID. Items with unique client 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tags are allowed to use the zero base version for undeletion and 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // de-duplication; the unique client tag trumps the server ID. 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!using_unique_client_tag) { 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(!id.ServerKnows(), FROM_HERE, 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Should be a client only id.", 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SyncAssert(id.ServerKnows(), 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Should be a server id.", 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Server-unknown items that are locally deleted should not be sent up to 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the server. They must be !IS_UNSYNCED. 1101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!SyncAssert(!(!id.ServerKnows() && e.GetIsDel() && e.GetIsUnsynced()), 1102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FROM_HERE, 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Locally deleted item must not be unsynced.", 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trans)) { 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::SetInvariantCheckLevel(InvariantCheckLevel check_level) { 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invariant_check_level_ = check_level; 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Directory::NextMetahandle() { 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 metahandle = (kernel_->next_metahandle)++; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return metahandle; 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Always returns a client ID that is the string representation of a negative 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number. 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Id Directory::NextId() { 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 result; 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = (kernel_->persisted_info.next_id)--; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kernel_->info_status = KERNEL_SHARE_INFO_DIRTY; 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(result, 0); 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Id::CreateFromClientString(base::Int64ToString(result)); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Directory::HasChildren(BaseTransaction* trans, const Id& id) { 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return kernel_->parent_child_index.GetChildren(id) != NULL; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Id Directory::GetFirstChildId(BaseTransaction* trans, 1140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const EntryKernel* parent) { 1141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parent); 1142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parent->ref(IS_DIR)); 1143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 1145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(parent->ref(ID)); 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We're expected to return root if there are no children. 1149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!children) 1150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*children->begin())->ref(ID); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)syncable::Id Directory::GetPredecessorId(EntryKernel* e) { 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(ParentChildIndex::ShouldInclude(e)); 1159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(children && !children->empty()); 1162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator i = children->find(e); 1163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(i != children->end()); 1164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (i == children->begin()) { 1166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i--; 1169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*i)->ref(ID); 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)syncable::Id Directory::GetSuccessorId(EntryKernel* e) { 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedKernelLock lock(this); 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(ParentChildIndex::ShouldInclude(e)); 1177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(children && !children->empty()); 1180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator i = children->find(e); 1181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(i != children->end()); 1182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i++; 1184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (i == children->end()) { 1185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Id(); 1186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (*i)->ref(ID); 1188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(rlarocque): Remove all support for placing ShouldMaintainPosition() 1192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// items as siblings of items that do not maintain postions. It is required 1193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// only for tests. See crbug.com/178282. 1194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void Directory::PutPredecessor(EntryKernel* e, EntryKernel* predecessor) { 1195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!e->ref(IS_DEL)); 1196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!e->ShouldMaintainPosition()) { 1197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!e->ref(UNIQUE_POSITION).IsValid()); 1198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string suffix = e->ref(UNIQUE_BOOKMARK_TAG); 1201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!suffix.empty()); 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove our item from the ParentChildIndex and remember to re-add it later. 1204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScopedKernelLock lock(this); 1205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ScopedParentChildIndexUpdater updater(lock, e, &kernel_->parent_child_index); 1206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Note: The ScopedParentChildIndexUpdater will update this set for us as we 1208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // leave this function. 1209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* siblings = 1210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(e->ref(PARENT_ID)); 1211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!siblings) { 1213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This parent currently has no other children. 1214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(predecessor->ref(ID).IsRoot()); 1215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::InitialPosition(suffix); 1216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (predecessor->ref(ID).IsRoot()) { 1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We have at least one sibling, and we're inserting to the left of them. 1222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition successor_pos = (*siblings->begin())->ref(UNIQUE_POSITION); 1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos; 1225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!successor_pos.IsValid()) { 1226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If all our successors are of non-positionable types, just create an 1227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // initial position. We arbitrarily choose to sort invalid positions to 1228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the right of the valid positions. 1229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 1230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We really shouldn't need to support this. See TODO above. 1231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pos = UniquePosition::InitialPosition(suffix); 1232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 1233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!siblings->empty()); 1234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pos = UniquePosition::Before(successor_pos, suffix); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We can't support placing an item after an invalid position. Fortunately, 1242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the tests don't exercise this particular case. We should not support 1243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // siblings with invalid positions at all. See TODO above. 1244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(predecessor->ref(UNIQUE_POSITION).IsValid()); 1245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OrderedChildSet::const_iterator neighbour = siblings->find(predecessor); 1247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(neighbour != siblings->end()); 1248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++neighbour; 1250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (neighbour == siblings->end()) { 1251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Inserting at the end of the list. 1252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::After( 1253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) predecessor->ref(UNIQUE_POSITION), 1254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) suffix); 1255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EntryKernel* successor = *neighbour; 1260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Another mixed valid and invalid position case. This one could be supported 1262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // in theory, but we're trying to deprecate support for siblings with and 1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // without valid positions. See TODO above. 1264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(successor->ref(UNIQUE_POSITION).IsValid()); 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Finally, the normal case: inserting between two elements. 1267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) UniquePosition pos = UniquePosition::Between( 1268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) predecessor->ref(UNIQUE_POSITION), 1269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successor->ref(UNIQUE_POSITION), 1270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) suffix); 1271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) e->put(UNIQUE_POSITION, pos); 1272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(rlarocque): Avoid this indirection. Just return the set. 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Directory::AppendChildHandles(const ScopedKernelLock& lock, 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Id& parent_id, 1278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Directory::Metahandles* result) { 1279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const OrderedChildSet* children = 1280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kernel_->parent_child_index.GetChildren(parent_id); 1281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!children) 1282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 1283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (OrderedChildSet::const_iterator i = children->begin(); 1285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) i != children->end(); ++i) { 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(parent_id, (*i)->ref(PARENT_ID)); 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back((*i)->ref(META_HANDLE)); 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncable 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace syncer 1293