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 |