1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/sync/syncable/directory_manager.h" 6 7#include <map> 8#include <set> 9#include <iterator> 10 11#include "base/logging.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/port.h" 14#include "base/string_util.h" 15#include "chrome/browser/sync/syncable/syncable.h" 16#include "chrome/common/deprecated/event_sys-inl.h" 17 18using browser_sync::Cryptographer; 19 20namespace syncable { 21 22static const FilePath::CharType kSyncDataDatabaseFilename[] = 23 FILE_PATH_LITERAL("SyncData.sqlite3"); 24 25DirectoryManagerEvent DirectoryManagerShutdownEvent() { 26 DirectoryManagerEvent event; 27 event.what_happened = DirectoryManagerEvent::SHUTDOWN; 28 return event; 29} 30 31// static 32const FilePath DirectoryManager::GetSyncDataDatabaseFilename() { 33 return FilePath(kSyncDataDatabaseFilename); 34} 35 36const FilePath DirectoryManager::GetSyncDataDatabasePath() const { 37 return root_path_.Append(GetSyncDataDatabaseFilename()); 38} 39 40DirectoryManager::DirectoryManager(const FilePath& path) 41 : root_path_(path), 42 managed_directory_(NULL), 43 channel_(new Channel(DirectoryManagerShutdownEvent())), 44 cryptographer_(new Cryptographer) { 45} 46 47DirectoryManager::~DirectoryManager() { 48 base::AutoLock lock(lock_); 49 DCHECK_EQ(managed_directory_, static_cast<Directory*>(NULL)) 50 << "Dir " << managed_directory_->name() << " not closed!"; 51 delete channel_; 52} 53 54bool DirectoryManager::Open(const std::string& name) { 55 bool was_open = false; 56 const DirOpenResult result = OpenImpl(name, 57 GetSyncDataDatabasePath(), &was_open); 58 return syncable::OPENED == result; 59} 60 61// Opens a directory. Returns false on error. 62DirOpenResult DirectoryManager::OpenImpl(const std::string& name, 63 const FilePath& path, 64 bool* was_open) { 65 bool opened = false; 66 { 67 base::AutoLock lock(lock_); 68 // Check to see if it's already open. 69 if (managed_directory_) { 70 DCHECK_EQ(base::strcasecmp(name.c_str(), 71 managed_directory_->name().c_str()), 0) 72 << "Can't open more than one directory."; 73 opened = *was_open = true; 74 } 75 } 76 77 if (opened) 78 return syncable::OPENED; 79 // Otherwise, open it. 80 81 scoped_ptr<Directory> dir(new Directory); 82 const DirOpenResult result = dir->Open(path, name); 83 if (syncable::OPENED == result) { 84 base::AutoLock lock(lock_); 85 managed_directory_ = dir.release(); 86 } 87 return result; 88} 89 90// Marks a directory as closed. It might take a while until all the file 91// handles and resources are freed by other threads. 92void DirectoryManager::Close(const std::string& name) { 93 // Erase from mounted and opened directory lists. 94 { 95 base::AutoLock lock(lock_); 96 if (!managed_directory_ || 97 base::strcasecmp(name.c_str(), 98 managed_directory_->name().c_str()) != 0) { 99 // It wasn't open. 100 return; 101 } 102 } 103 104 // TODO(timsteele): No lock?! 105 // Notify listeners. 106 managed_directory_->channel()->NotifyListeners(DIRECTORY_CLOSED); 107 DirectoryManagerEvent event = { DirectoryManagerEvent::CLOSED, name }; 108 channel_->NotifyListeners(event); 109 110 delete managed_directory_; 111 managed_directory_ = NULL; 112} 113 114void DirectoryManager::FinalSaveChangesForAll() { 115 base::AutoLock lock(lock_); 116 if (managed_directory_) 117 managed_directory_->SaveChanges(); 118} 119 120void DirectoryManager::GetOpenDirectories(DirNames* result) { 121 result->clear(); 122 base::AutoLock lock(lock_); 123 if (managed_directory_) 124 result->push_back(managed_directory_->name()); 125} 126 127ScopedDirLookup::ScopedDirLookup(DirectoryManager* dirman, 128 const std::string& name) : dirman_(dirman) { 129 dir_ = dirman->managed_directory_ && 130 (base::strcasecmp(name.c_str(), 131 dirman->managed_directory_->name().c_str()) == 0) ? 132 dirman->managed_directory_ : NULL; 133 good_ = dir_ != NULL; 134 good_checked_ = false; 135} 136 137ScopedDirLookup::~ScopedDirLookup() { } 138 139Directory* ScopedDirLookup::operator -> () const { 140 CHECK(good_checked_); 141 DCHECK(good_); 142 return dir_; 143} 144 145ScopedDirLookup::operator Directory* () const { 146 CHECK(good_checked_); 147 DCHECK(good_); 148 return dir_; 149} 150 151} // namespace syncable 152