| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 #ifndef COMPONENTS_LEVELDB_LEVELDB_FILE_THREAD_H_ | |
| 6 #define COMPONENTS_LEVELDB_LEVELDB_FILE_THREAD_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <string> | |
| 10 #include <utility> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "base/files/file.h" | |
| 14 #include "base/memory/ref_counted.h" | |
| 15 #include "base/synchronization/waitable_event.h" | |
| 16 #include "base/threading/thread.h" | |
| 17 #include "components/filesystem/public/interfaces/directory.mojom.h" | |
| 18 | |
| 19 namespace leveldb { | |
| 20 | |
| 21 // The thread which services file requests from leveldb. | |
| 22 // | |
| 23 // MojoEnv is an object passed to the leveldb implementation which can be | |
| 24 // called from multiple threads. mojo pipes are bound to a single | |
| 25 // thread. Because of this mismatch, we create a thread which owns the mojo | |
| 26 // pipe, sends and receives messages. | |
| 27 // | |
| 28 // All public methods can be accessed from any thread. | |
| 29 class LevelDBFileThread : public base::Thread, | |
| 30 public base::RefCountedThreadSafe<LevelDBFileThread> { | |
| 31 public: | |
| 32 LevelDBFileThread(); | |
| 33 | |
| 34 // A private struct to hide the underlying file that holds the lock from our | |
| 35 // callers, forcing them to go through our LockFile()/UnlockFile() interface | |
| 36 // so that they don't try to use the underlying pointer from an unsafe thread. | |
| 37 struct OpaqueLock; | |
| 38 | |
| 39 // A private struct to hide the underlying root directory that we're | |
| 40 // operating in. LevelDBFileThread will want to own all the directory | |
| 41 // pointers, so while opening a database, we pass the directory to the thread | |
| 42 // it will be operated on. | |
| 43 struct OpaqueDir; | |
| 44 | |
| 45 // Passes ownership of a |directory| to the other thread, giving a reference | |
| 46 // handle back to the caller. | |
| 47 OpaqueDir* RegisterDirectory(filesystem::DirectoryPtr directory); | |
| 48 void UnregisterDirectory(OpaqueDir* dir); | |
| 49 | |
| 50 // Synchronously calls Directory.OpenFileHandle(). | |
| 51 base::File OpenFileHandle(OpaqueDir* dir, | |
| 52 const std::string& name, | |
| 53 uint32_t open_flags); | |
| 54 | |
| 55 // Synchronously flushes |directory_|. | |
| 56 filesystem::FileError SyncDirectory(OpaqueDir* dir, | |
| 57 const std::string& name); | |
| 58 | |
| 59 // Synchronously checks whether |name| exists. | |
| 60 bool FileExists(OpaqueDir* dir, | |
| 61 const std::string& name); | |
| 62 | |
| 63 // Synchronously returns the filenames of all files in |path|. | |
| 64 filesystem::FileError GetChildren(OpaqueDir* dir, | |
| 65 const std::string& path, | |
| 66 std::vector<std::string>* result); | |
| 67 | |
| 68 // Synchronously deletes |path|. | |
| 69 filesystem::FileError Delete(OpaqueDir* dir, | |
| 70 const std::string& path, | |
| 71 uint32_t delete_flags); | |
| 72 | |
| 73 // Synchronously creates |path|. | |
| 74 filesystem::FileError CreateDir(OpaqueDir* dir, | |
| 75 const std::string& path); | |
| 76 | |
| 77 // Synchronously gets the size of a file. | |
| 78 filesystem::FileError GetFileSize(OpaqueDir* dir, | |
| 79 const std::string& path, | |
| 80 uint64_t* file_size); | |
| 81 | |
| 82 // Synchronously renames a file. | |
| 83 filesystem::FileError RenameFile(OpaqueDir* dir, | |
| 84 const std::string& old_path, | |
| 85 const std::string& new_path); | |
| 86 | |
| 87 // Synchronously locks a file. Returns both the file return code, and if OK, | |
| 88 // an opaque object to the lock to enforce going through this interface to | |
| 89 // unlock the file so that unlocking happens on the correct thread. | |
| 90 std::pair<filesystem::FileError, OpaqueLock*> LockFile( | |
| 91 OpaqueDir* dir, const std::string& path); | |
| 92 | |
| 93 // Unlocks a file. LevelDBFileThread takes ownership of lock. (We don't make | |
| 94 // this a scoped_ptr because exporting the ctor/dtor for this struct publicly | |
| 95 // defeats the purpose of the struct.) | |
| 96 filesystem::FileError UnlockFile(OpaqueLock* lock); | |
| 97 | |
| 98 private: | |
| 99 friend class base::RefCountedThreadSafe<LevelDBFileThread>; | |
| 100 ~LevelDBFileThread() override; | |
| 101 | |
| 102 // Called from the beginning of most impls which take an OpaqueDir. Returns | |
| 103 // true if the directory was unbound between the time the task was posted and | |
| 104 // the task was run on this thread. If it was, no further processing should | |
| 105 // be done (and the waitable event will be Signal()ed). | |
| 106 bool RegisterDirAndWaitableEvent(OpaqueDir* dir, | |
| 107 base::WaitableEvent* done_event); | |
| 108 | |
| 109 // Cleans up internal state related to the waitable event before Signal()ing | |
| 110 // it. | |
| 111 void CompleteWaitableEvent(base::WaitableEvent* done_event); | |
| 112 | |
| 113 // Called when one of our directory or files has a connection error. This | |
| 114 // will find all the outstanding waitable events that depend on it and signal | |
| 115 // them. | |
| 116 void OnConnectionError(); | |
| 117 | |
| 118 void RegisterDirectoryImpl( | |
| 119 base::WaitableEvent* done_event, | |
| 120 mojo::InterfacePtrInfo<filesystem::Directory> directory_info, | |
| 121 OpaqueDir** out_dir); | |
| 122 void UnregisterDirectoryImpl(base::WaitableEvent* done_event, | |
| 123 OpaqueDir* dir); | |
| 124 | |
| 125 // Shared callback function which signals for the methods that only return an | |
| 126 // error code. | |
| 127 void OnSimpleComplete(base::WaitableEvent* done_event, | |
| 128 filesystem::FileError* out_error, | |
| 129 filesystem::FileError in_error); | |
| 130 | |
| 131 void OpenFileHandleImpl(OpaqueDir* dir, | |
| 132 std::string name, | |
| 133 base::WaitableEvent* done_event, | |
| 134 uint32_t open_flags, | |
| 135 base::File* out_file); | |
| 136 void OnOpenFileHandleComplete(base::WaitableEvent* done_event, | |
| 137 base::File* output_file, | |
| 138 filesystem::FileError err, | |
| 139 mojo::ScopedHandle handle); | |
| 140 | |
| 141 void SyncDirectoryImpl(OpaqueDir* dir, | |
| 142 std::string name, | |
| 143 base::WaitableEvent* done_event, | |
| 144 filesystem::FileError* out_error); | |
| 145 void OnSyncDirctoryOpened(scoped_ptr<filesystem::DirectoryPtr> dir, | |
| 146 base::WaitableEvent* done_event, | |
| 147 filesystem::FileError* out_error, | |
| 148 filesystem::FileError in_error); | |
| 149 void OnSyncDirectoryComplete(scoped_ptr<filesystem::DirectoryPtr> dir, | |
| 150 base::WaitableEvent* done_event, | |
| 151 filesystem::FileError* out_error, | |
| 152 filesystem::FileError in_error); | |
| 153 | |
| 154 void FileExistsImpl(OpaqueDir* dir, | |
| 155 std::string name, | |
| 156 base::WaitableEvent* done_event, | |
| 157 bool* exists); | |
| 158 void OnFileExistsComplete(base::WaitableEvent* done_event, | |
| 159 bool* exists, | |
| 160 filesystem::FileError err, | |
| 161 bool in_exists); | |
| 162 | |
| 163 void GetChildrenImpl(OpaqueDir* dir, | |
| 164 std::string name, | |
| 165 std::vector<std::string>* contents, | |
| 166 base::WaitableEvent* done_event, | |
| 167 filesystem::FileError* out_error); | |
| 168 void OnGetChildrenOpened(scoped_ptr<filesystem::DirectoryPtr> dir, | |
| 169 std::vector<std::string>* contents, | |
| 170 base::WaitableEvent* done_event, | |
| 171 filesystem::FileError* out_error, | |
| 172 filesystem::FileError in_error); | |
| 173 void OnGetChildrenComplete( | |
| 174 scoped_ptr<filesystem::DirectoryPtr> dir, | |
| 175 std::vector<std::string>* out_contents, | |
| 176 base::WaitableEvent* done_event, | |
| 177 filesystem::FileError* out_error, | |
| 178 filesystem::FileError in_error, | |
| 179 mojo::Array<filesystem::DirectoryEntryPtr> directory_contents); | |
| 180 | |
| 181 void DeleteImpl(OpaqueDir* dir, | |
| 182 std::string name, | |
| 183 uint32_t delete_flags, | |
| 184 base::WaitableEvent* done_event, | |
| 185 filesystem::FileError* out_error); | |
| 186 | |
| 187 void CreateDirImpl(OpaqueDir* dir, | |
| 188 std::string name, | |
| 189 base::WaitableEvent* done_event, | |
| 190 filesystem::FileError* out_error); | |
| 191 | |
| 192 void GetFileSizeImpl(OpaqueDir* dir, | |
| 193 const std::string& path, | |
| 194 uint64_t* file_size, | |
| 195 base::WaitableEvent* done_event, | |
| 196 filesystem::FileError* out_error); | |
| 197 void OnGetFileSizeImpl(uint64_t* file_size, | |
| 198 base::WaitableEvent* done_event, | |
| 199 filesystem::FileError* out_error, | |
| 200 filesystem::FileError in_error, | |
| 201 filesystem::FileInformationPtr file_info); | |
| 202 | |
| 203 void RenameFileImpl(OpaqueDir* dir, | |
| 204 const std::string& old_path, | |
| 205 const std::string& new_path, | |
| 206 base::WaitableEvent* done_event, | |
| 207 filesystem::FileError* out_error); | |
| 208 | |
| 209 void LockFileImpl(OpaqueDir* dir, | |
| 210 const std::string& path, | |
| 211 base::WaitableEvent* done_event, | |
| 212 filesystem::FileError* out_error, | |
| 213 OpaqueLock** out_lock); | |
| 214 void OnOpenLockFileComplete(scoped_ptr<filesystem::FilePtr> file, | |
| 215 base::WaitableEvent* done_event, | |
| 216 filesystem::FileError* out_error, | |
| 217 OpaqueLock** out_lock, | |
| 218 filesystem::FileError in_error); | |
| 219 void OnLockFileComplete(scoped_ptr<filesystem::FilePtr> file, | |
| 220 base::WaitableEvent* done_event, | |
| 221 filesystem::FileError* out_error, | |
| 222 OpaqueLock** out_lock, | |
| 223 filesystem::FileError in_error); | |
| 224 | |
| 225 void UnlockFileImpl(scoped_ptr<OpaqueLock> lock, | |
| 226 base::WaitableEvent* done_event, | |
| 227 filesystem::FileError* out_error); | |
| 228 void OnUnlockFileCompleted(scoped_ptr<OpaqueLock> lock, | |
| 229 base::WaitableEvent* done_event, | |
| 230 filesystem::FileError* out_error, | |
| 231 filesystem::FileError in_error); | |
| 232 | |
| 233 // Overridden from base::Thread: | |
| 234 void Init() override; | |
| 235 void CleanUp() override; | |
| 236 | |
| 237 int outstanding_opaque_dirs_; | |
| 238 | |
| 239 // When our public methods are called, we create a WaitableEvent on their | |
| 240 // thread so that we can block their thread on the LevelDBFileThread. We then | |
| 241 // need to track what DirectoryPtrs and FilePtrs, which if they get closed, | |
| 242 // should immediately trigger the waitable event. | |
| 243 struct WaitableEventDependencies; | |
| 244 std::map<base::WaitableEvent*, WaitableEventDependencies> | |
| 245 waitable_event_dependencies_; | |
| 246 | |
| 247 DISALLOW_COPY_AND_ASSIGN(LevelDBFileThread); | |
| 248 }; | |
| 249 | |
| 250 } // namespace leveldb | |
| 251 | |
| 252 #endif // COMPONENTS_LEVELDB_LEVELDB_FILE_THREAD_H_ | |
| OLD | NEW |