// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/sync/syncable/directory_manager.h" #include <map> #include <set> #include <iterator> #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/port.h" #include "base/string_util.h" #include "chrome/browser/sync/syncable/syncable.h" #include "chrome/common/deprecated/event_sys-inl.h" using browser_sync::Cryptographer; namespace syncable { static const FilePath::CharType kSyncDataDatabaseFilename[] = FILE_PATH_LITERAL("SyncData.sqlite3"); DirectoryManagerEvent DirectoryManagerShutdownEvent() { DirectoryManagerEvent event; event.what_happened = DirectoryManagerEvent::SHUTDOWN; return event; } // static const FilePath DirectoryManager::GetSyncDataDatabaseFilename() { return FilePath(kSyncDataDatabaseFilename); } const FilePath DirectoryManager::GetSyncDataDatabasePath() const { return root_path_.Append(GetSyncDataDatabaseFilename()); } DirectoryManager::DirectoryManager(const FilePath& path) : root_path_(path), managed_directory_(NULL), channel_(new Channel(DirectoryManagerShutdownEvent())), cryptographer_(new Cryptographer) { } DirectoryManager::~DirectoryManager() { base::AutoLock lock(lock_); DCHECK_EQ(managed_directory_, static_cast<Directory*>(NULL)) << "Dir " << managed_directory_->name() << " not closed!"; delete channel_; } bool DirectoryManager::Open(const std::string& name) { bool was_open = false; const DirOpenResult result = OpenImpl(name, GetSyncDataDatabasePath(), &was_open); return syncable::OPENED == result; } // Opens a directory. Returns false on error. DirOpenResult DirectoryManager::OpenImpl(const std::string& name, const FilePath& path, bool* was_open) { bool opened = false; { base::AutoLock lock(lock_); // Check to see if it's already open. if (managed_directory_) { DCHECK_EQ(base::strcasecmp(name.c_str(), managed_directory_->name().c_str()), 0) << "Can't open more than one directory."; opened = *was_open = true; } } if (opened) return syncable::OPENED; // Otherwise, open it. scoped_ptr<Directory> dir(new Directory); const DirOpenResult result = dir->Open(path, name); if (syncable::OPENED == result) { base::AutoLock lock(lock_); managed_directory_ = dir.release(); } return result; } // Marks a directory as closed. It might take a while until all the file // handles and resources are freed by other threads. void DirectoryManager::Close(const std::string& name) { // Erase from mounted and opened directory lists. { base::AutoLock lock(lock_); if (!managed_directory_ || base::strcasecmp(name.c_str(), managed_directory_->name().c_str()) != 0) { // It wasn't open. return; } } // TODO(timsteele): No lock?! // Notify listeners. managed_directory_->channel()->NotifyListeners(DIRECTORY_CLOSED); DirectoryManagerEvent event = { DirectoryManagerEvent::CLOSED, name }; channel_->NotifyListeners(event); delete managed_directory_; managed_directory_ = NULL; } void DirectoryManager::FinalSaveChangesForAll() { base::AutoLock lock(lock_); if (managed_directory_) managed_directory_->SaveChanges(); } void DirectoryManager::GetOpenDirectories(DirNames* result) { result->clear(); base::AutoLock lock(lock_); if (managed_directory_) result->push_back(managed_directory_->name()); } ScopedDirLookup::ScopedDirLookup(DirectoryManager* dirman, const std::string& name) : dirman_(dirman) { dir_ = dirman->managed_directory_ && (base::strcasecmp(name.c_str(), dirman->managed_directory_->name().c_str()) == 0) ? dirman->managed_directory_ : NULL; good_ = dir_ != NULL; good_checked_ = false; } ScopedDirLookup::~ScopedDirLookup() { } Directory* ScopedDirLookup::operator -> () const { CHECK(good_checked_); DCHECK(good_); return dir_; } ScopedDirLookup::operator Directory* () const { CHECK(good_checked_); DCHECK(good_); return dir_; } } // namespace syncable