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 18 using browser_sync::Cryptographer; 19 20 namespace syncable { 21 22 static const FilePath::CharType kSyncDataDatabaseFilename[] = 23 FILE_PATH_LITERAL("SyncData.sqlite3"); 24 25 DirectoryManagerEvent DirectoryManagerShutdownEvent() { 26 DirectoryManagerEvent event; 27 event.what_happened = DirectoryManagerEvent::SHUTDOWN; 28 return event; 29 } 30 31 // static 32 const FilePath DirectoryManager::GetSyncDataDatabaseFilename() { 33 return FilePath(kSyncDataDatabaseFilename); 34 } 35 36 const FilePath DirectoryManager::GetSyncDataDatabasePath() const { 37 return root_path_.Append(GetSyncDataDatabaseFilename()); 38 } 39 40 DirectoryManager::DirectoryManager(const FilePath& path) 41 : root_path_(path), 42 managed_directory_(NULL), 43 channel_(new Channel(DirectoryManagerShutdownEvent())), 44 cryptographer_(new Cryptographer) { 45 } 46 47 DirectoryManager::~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 54 bool 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. 62 DirOpenResult 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. 92 void 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 114 void DirectoryManager::FinalSaveChangesForAll() { 115 base::AutoLock lock(lock_); 116 if (managed_directory_) 117 managed_directory_->SaveChanges(); 118 } 119 120 void 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 127 ScopedDirLookup::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 137 ScopedDirLookup::~ScopedDirLookup() { } 138 139 Directory* ScopedDirLookup::operator -> () const { 140 CHECK(good_checked_); 141 DCHECK(good_); 142 return dir_; 143 } 144 145 ScopedDirLookup::operator Directory* () const { 146 CHECK(good_checked_); 147 DCHECK(good_); 148 return dir_; 149 } 150 151 } // namespace syncable 152