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
DirectoryManagerShutdownEvent()25 DirectoryManagerEvent DirectoryManagerShutdownEvent() {
26 DirectoryManagerEvent event;
27 event.what_happened = DirectoryManagerEvent::SHUTDOWN;
28 return event;
29 }
30
31 // static
GetSyncDataDatabaseFilename()32 const FilePath DirectoryManager::GetSyncDataDatabaseFilename() {
33 return FilePath(kSyncDataDatabaseFilename);
34 }
35
GetSyncDataDatabasePath() const36 const FilePath DirectoryManager::GetSyncDataDatabasePath() const {
37 return root_path_.Append(GetSyncDataDatabaseFilename());
38 }
39
DirectoryManager(const FilePath & path)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
~DirectoryManager()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
Open(const std::string & name)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.
OpenImpl(const std::string & name,const FilePath & path,bool * was_open)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.
Close(const std::string & name)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
FinalSaveChangesForAll()114 void DirectoryManager::FinalSaveChangesForAll() {
115 base::AutoLock lock(lock_);
116 if (managed_directory_)
117 managed_directory_->SaveChanges();
118 }
119
GetOpenDirectories(DirNames * result)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
ScopedDirLookup(DirectoryManager * dirman,const std::string & name)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
~ScopedDirLookup()137 ScopedDirLookup::~ScopedDirLookup() { }
138
operator ->() const139 Directory* ScopedDirLookup::operator -> () const {
140 CHECK(good_checked_);
141 DCHECK(good_);
142 return dir_;
143 }
144
operator Directory*() const145 ScopedDirLookup::operator Directory* () const {
146 CHECK(good_checked_);
147 DCHECK(good_);
148 return dir_;
149 }
150
151 } // namespace syncable
152