directory_manager.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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