Home | History | Annotate | Download | only in syncable
      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