OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/leveldb/env_mojo.h" | 5 #include "components/leveldb/env_mojo.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 | 10 |
| 11 #include "base/lazy_instance.h" |
| 12 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/stringprintf.h" |
12 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
13 #include "third_party/leveldatabase/chromium_logger.h" | 16 #include "third_party/leveldatabase/chromium_logger.h" |
14 #include "third_party/leveldatabase/src/include/leveldb/status.h" | 17 #include "third_party/leveldatabase/src/include/leveldb/status.h" |
15 | 18 |
16 namespace leveldb { | 19 namespace leveldb { |
17 | 20 |
18 namespace { | 21 namespace { |
19 | 22 |
20 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); | 23 const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); |
21 | 24 |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 Type file_type_; | 213 Type file_type_; |
211 LevelDBMojoProxy::OpaqueDir* dir_; | 214 LevelDBMojoProxy::OpaqueDir* dir_; |
212 std::string parent_dir_; | 215 std::string parent_dir_; |
213 scoped_refptr<LevelDBMojoProxy> thread_; | 216 scoped_refptr<LevelDBMojoProxy> thread_; |
214 | 217 |
215 DISALLOW_COPY_AND_ASSIGN(MojoWritableFile); | 218 DISALLOW_COPY_AND_ASSIGN(MojoWritableFile); |
216 }; | 219 }; |
217 | 220 |
218 } // namespace | 221 } // namespace |
219 | 222 |
220 MojoEnv::MojoEnv(const std::string& name, | 223 MojoEnv::Directory::~Directory() { |
221 scoped_refptr<LevelDBMojoProxy> file_thread, | 224 env_->UnregisterDirectory(prefix_); |
222 LevelDBMojoProxy::OpaqueDir* dir) | 225 } |
223 : ChromiumEnv(name), thread_(file_thread), dir_(dir) {} | |
224 | 226 |
225 MojoEnv::~MojoEnv() { | 227 MojoEnv::Directory::Directory(MojoEnv* env, std::string prefix) |
226 thread_->UnregisterDirectory(dir_); | 228 : env_(env), prefix_(std::move(prefix)) {} |
| 229 |
| 230 MojoEnv::MojoEnv(scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) |
| 231 : ChromiumEnv("LevelDBEnv.Mojo"), |
| 232 thread_(new LevelDBMojoProxy(std::move(file_task_runner))) {} |
| 233 |
| 234 std::unique_ptr<MojoEnv::Directory> MojoEnv::RegisterDirectory( |
| 235 filesystem::mojom::DirectoryPtr directory) { |
| 236 LevelDBMojoProxy::OpaqueDir* dir = |
| 237 thread_->RegisterDirectory(std::move(directory)); |
| 238 int dir_id = dirs_.Add(dir); |
| 239 std::string prefix = base::StringPrintf("%d:", dir_id); |
| 240 return base::WrapUnique(new Directory(this, prefix)); |
227 } | 241 } |
228 | 242 |
229 Status MojoEnv::NewSequentialFile(const std::string& fname, | 243 Status MojoEnv::NewSequentialFile(const std::string& fname, |
230 SequentialFile** result) { | 244 SequentialFile** result) { |
231 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname); | 245 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname); |
| 246 LevelDBMojoProxy::OpaqueDir* dir; |
| 247 std::string path; |
| 248 ParsePath(fname, &dir, &path); |
| 249 |
232 base::File f = thread_->OpenFileHandle( | 250 base::File f = thread_->OpenFileHandle( |
233 dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); | 251 dir, path, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); |
234 if (!f.IsValid()) { | 252 if (!f.IsValid()) { |
235 *result = nullptr; | 253 *result = nullptr; |
236 return MakeIOError(fname, "Unable to create sequential file", | 254 return MakeIOError(fname, "Unable to create sequential file", |
237 leveldb_env::kNewSequentialFile, f.error_details()); | 255 leveldb_env::kNewSequentialFile, f.error_details()); |
238 } | 256 } |
239 | 257 |
240 *result = new MojoSequentialFile(fname, std::move(f)); | 258 *result = new MojoSequentialFile(fname, std::move(f)); |
241 return Status::OK(); | 259 return Status::OK(); |
242 } | 260 } |
243 | 261 |
244 Status MojoEnv::NewRandomAccessFile(const std::string& fname, | 262 Status MojoEnv::NewRandomAccessFile(const std::string& fname, |
245 RandomAccessFile** result) { | 263 RandomAccessFile** result) { |
246 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname); | 264 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname); |
| 265 LevelDBMojoProxy::OpaqueDir* dir; |
| 266 std::string path; |
| 267 ParsePath(fname, &dir, &path); |
| 268 |
247 base::File f = thread_->OpenFileHandle( | 269 base::File f = thread_->OpenFileHandle( |
248 dir_, fname, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen); | 270 dir, path, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen); |
249 if (!f.IsValid()) { | 271 if (!f.IsValid()) { |
250 *result = nullptr; | 272 *result = nullptr; |
251 base::File::Error error_code = f.error_details(); | 273 base::File::Error error_code = f.error_details(); |
252 return MakeIOError(fname, FileErrorString(error_code), | 274 return MakeIOError(path, FileErrorString(error_code), |
253 leveldb_env::kNewRandomAccessFile, error_code); | 275 leveldb_env::kNewRandomAccessFile, error_code); |
254 } | 276 } |
255 | 277 |
256 *result = new MojoRandomAccessFile(fname, std::move(f)); | 278 *result = new MojoRandomAccessFile(path, std::move(f)); |
257 return Status::OK(); | 279 return Status::OK(); |
258 } | 280 } |
259 | 281 |
260 Status MojoEnv::NewWritableFile(const std::string& fname, | 282 Status MojoEnv::NewWritableFile(const std::string& fname, |
261 WritableFile** result) { | 283 WritableFile** result) { |
262 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); | 284 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); |
263 base::File f = | 285 LevelDBMojoProxy::OpaqueDir* dir; |
264 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways | | 286 std::string path; |
265 filesystem::mojom::kFlagWrite); | 287 ParsePath(fname, &dir, &path); |
| 288 |
| 289 base::File f = thread_->OpenFileHandle( |
| 290 dir, path, |
| 291 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite); |
266 if (!f.IsValid()) { | 292 if (!f.IsValid()) { |
267 *result = nullptr; | 293 *result = nullptr; |
268 return MakeIOError(fname, "Unable to create writable file", | 294 return MakeIOError(path, "Unable to create writable file", |
269 leveldb_env::kNewWritableFile, f.error_details()); | 295 leveldb_env::kNewWritableFile, f.error_details()); |
270 } | 296 } |
271 | 297 |
272 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); | 298 *result = new MojoWritableFile(dir, path, std::move(f), thread_); |
273 return Status::OK(); | 299 return Status::OK(); |
274 } | 300 } |
275 | 301 |
276 Status MojoEnv::NewAppendableFile(const std::string& fname, | 302 Status MojoEnv::NewAppendableFile(const std::string& fname, |
277 WritableFile** result) { | 303 WritableFile** result) { |
278 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); | 304 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); |
279 base::File f = | 305 LevelDBMojoProxy::OpaqueDir* dir; |
280 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways | | 306 std::string path; |
281 filesystem::mojom::kFlagAppend); | 307 ParsePath(fname, &dir, &path); |
| 308 |
| 309 base::File f = thread_->OpenFileHandle( |
| 310 dir, path, |
| 311 filesystem::mojom::kFlagOpenAlways | filesystem::mojom::kFlagAppend); |
282 if (!f.IsValid()) { | 312 if (!f.IsValid()) { |
283 *result = nullptr; | 313 *result = nullptr; |
284 return MakeIOError(fname, "Unable to create appendable file", | 314 return MakeIOError(path, "Unable to create appendable file", |
285 leveldb_env::kNewAppendableFile, f.error_details()); | 315 leveldb_env::kNewAppendableFile, f.error_details()); |
286 } | 316 } |
287 | 317 |
288 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); | 318 *result = new MojoWritableFile(dir, path, std::move(f), thread_); |
289 return Status::OK(); | 319 return Status::OK(); |
290 } | 320 } |
291 | 321 |
292 bool MojoEnv::FileExists(const std::string& fname) { | 322 bool MojoEnv::FileExists(const std::string& fname) { |
293 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname); | 323 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname); |
294 return thread_->FileExists(dir_, fname); | 324 LevelDBMojoProxy::OpaqueDir* dir; |
| 325 std::string path; |
| 326 ParsePath(fname, &dir, &path); |
| 327 |
| 328 return thread_->FileExists(dir, path); |
295 } | 329 } |
296 | 330 |
297 Status MojoEnv::GetChildren(const std::string& path, | 331 Status MojoEnv::GetChildren(const std::string& dirname, |
298 std::vector<std::string>* result) { | 332 std::vector<std::string>* result) { |
299 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path); | 333 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "dirname", dirname); |
300 return FilesystemErrorToStatus(thread_->GetChildren(dir_, path, result), path, | 334 LevelDBMojoProxy::OpaqueDir* dir; |
| 335 std::string path; |
| 336 ParsePath(dirname, &dir, &path); |
| 337 |
| 338 return FilesystemErrorToStatus(thread_->GetChildren(dir, path, result), path, |
301 leveldb_env::kGetChildren); | 339 leveldb_env::kGetChildren); |
302 } | 340 } |
303 | 341 |
304 Status MojoEnv::DeleteFile(const std::string& fname) { | 342 Status MojoEnv::DeleteFile(const std::string& fname) { |
305 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); | 343 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); |
306 return FilesystemErrorToStatus(thread_->Delete(dir_, fname, 0), fname, | 344 LevelDBMojoProxy::OpaqueDir* dir; |
| 345 std::string path; |
| 346 ParsePath(fname, &dir, &path); |
| 347 |
| 348 return FilesystemErrorToStatus(thread_->Delete(dir, path, 0), path, |
307 leveldb_env::kDeleteFile); | 349 leveldb_env::kDeleteFile); |
308 } | 350 } |
309 | 351 |
310 Status MojoEnv::CreateDir(const std::string& dirname) { | 352 Status MojoEnv::CreateDir(const std::string& dirname) { |
311 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); | 353 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); |
312 return FilesystemErrorToStatus(thread_->CreateDir(dir_, dirname), dirname, | 354 LevelDBMojoProxy::OpaqueDir* dir; |
| 355 std::string path; |
| 356 ParsePath(dirname, &dir, &path); |
| 357 |
| 358 return FilesystemErrorToStatus(thread_->CreateDir(dir, path), path, |
313 leveldb_env::kCreateDir); | 359 leveldb_env::kCreateDir); |
314 } | 360 } |
315 | 361 |
316 Status MojoEnv::DeleteDir(const std::string& dirname) { | 362 Status MojoEnv::DeleteDir(const std::string& dirname) { |
317 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); | 363 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); |
| 364 LevelDBMojoProxy::OpaqueDir* dir; |
| 365 std::string path; |
| 366 ParsePath(dirname, &dir, &path); |
| 367 |
318 return FilesystemErrorToStatus( | 368 return FilesystemErrorToStatus( |
319 thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive), | 369 thread_->Delete(dir, path, filesystem::mojom::kDeleteFlagRecursive), path, |
320 dirname, leveldb_env::kDeleteDir); | 370 leveldb_env::kDeleteDir); |
321 } | 371 } |
322 | 372 |
323 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { | 373 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { |
324 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); | 374 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); |
325 return FilesystemErrorToStatus(thread_->GetFileSize(dir_, fname, file_size), | 375 LevelDBMojoProxy::OpaqueDir* dir; |
326 fname, | 376 std::string path; |
327 leveldb_env::kGetFileSize); | 377 ParsePath(fname, &dir, &path); |
| 378 |
| 379 return FilesystemErrorToStatus(thread_->GetFileSize(dir, path, file_size), |
| 380 path, leveldb_env::kGetFileSize); |
328 } | 381 } |
329 | 382 |
330 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { | 383 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { |
331 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); | 384 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); |
332 return FilesystemErrorToStatus(thread_->RenameFile(dir_, src, target), src, | 385 LevelDBMojoProxy::OpaqueDir* src_dir; |
333 leveldb_env::kRenameFile); | 386 std::string src_path; |
| 387 ParsePath(src, &src_dir, &src_path); |
| 388 LevelDBMojoProxy::OpaqueDir* target_dir; |
| 389 std::string target_path; |
| 390 ParsePath(target, &target_dir, &target_path); |
| 391 DCHECK_EQ(src_dir, target_dir); |
| 392 |
| 393 return FilesystemErrorToStatus( |
| 394 thread_->RenameFile(src_dir, src_path, target_path), src_path, |
| 395 leveldb_env::kRenameFile); |
334 } | 396 } |
335 | 397 |
336 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { | 398 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { |
337 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); | 399 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); |
| 400 LevelDBMojoProxy::OpaqueDir* dir; |
| 401 std::string path; |
| 402 ParsePath(fname, &dir, &path); |
338 | 403 |
339 std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p = | 404 std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p = |
340 thread_->LockFile(dir_, fname); | 405 thread_->LockFile(dir, path); |
341 | 406 |
342 if (p.second) | 407 if (p.second) |
343 *lock = new MojoFileLock(p.second, fname); | 408 *lock = new MojoFileLock(p.second, fname); |
344 | 409 |
345 return FilesystemErrorToStatus(p.first, fname, leveldb_env::kLockFile); | 410 return FilesystemErrorToStatus(p.first, path, leveldb_env::kLockFile); |
346 } | 411 } |
347 | 412 |
348 Status MojoEnv::UnlockFile(FileLock* lock) { | 413 Status MojoEnv::UnlockFile(FileLock* lock) { |
349 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock); | 414 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock); |
350 | 415 |
351 std::string fname = my_lock ? my_lock->name() : "(invalid)"; | 416 std::string fname = my_lock ? my_lock->name() : "(invalid)"; |
352 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); | 417 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); |
353 | 418 |
354 filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock()); | 419 filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock()); |
355 delete my_lock; | 420 delete my_lock; |
356 return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile); | 421 return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile); |
357 } | 422 } |
358 | 423 |
359 Status MojoEnv::GetTestDirectory(std::string* path) { | 424 Status MojoEnv::GetTestDirectory(std::string* path) { |
360 // TODO(erg): This method is actually only used from the test harness in | 425 // TODO(erg): This method is actually only used from the test harness in |
361 // leveldb. And when we go and port that test stuff to a | 426 // leveldb. And when we go and port that test stuff to a |
362 // service_manager::ServiceTest, | 427 // service_manager::ServiceTest, |
363 // we probably won't use it since the mojo filesystem actually handles | 428 // we probably won't use it since the mojo filesystem actually handles |
364 // temporary filesystems just fine. | 429 // temporary filesystems just fine. |
365 NOTREACHED(); | 430 NOTREACHED(); |
366 return Status::OK(); | 431 return Status::OK(); |
367 } | 432 } |
368 | 433 |
369 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { | 434 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { |
370 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname); | 435 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname); |
| 436 LevelDBMojoProxy::OpaqueDir* dir; |
| 437 std::string path; |
| 438 ParsePath(fname, &dir, &path); |
| 439 |
371 base::File f(thread_->OpenFileHandle( | 440 base::File f(thread_->OpenFileHandle( |
372 dir_, fname, | 441 dir, path, |
373 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); | 442 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); |
374 if (!f.IsValid()) { | 443 if (!f.IsValid()) { |
375 *result = NULL; | 444 *result = NULL; |
376 return MakeIOError(fname, "Unable to create log file", | 445 return MakeIOError(path, "Unable to create log file", |
377 leveldb_env::kNewLogger, f.error_details()); | 446 leveldb_env::kNewLogger, f.error_details()); |
378 } else { | 447 } else { |
379 *result = new leveldb::ChromiumLogger(std::move(f)); | 448 *result = new leveldb::ChromiumLogger(std::move(f)); |
380 return Status::OK(); | 449 return Status::OK(); |
381 } | 450 } |
382 } | 451 } |
383 | 452 |
| 453 MojoEnv::~MojoEnv() {} |
| 454 |
| 455 void MojoEnv::ParsePath(const std::string& path, |
| 456 LevelDBMojoProxy::OpaqueDir** out_dir, |
| 457 std::string* out_path) { |
| 458 size_t colon_pos = path.find(':'); |
| 459 DCHECK_NE(colon_pos, std::string::npos); |
| 460 |
| 461 int dir_id; |
| 462 bool result = base::StringToInt( |
| 463 base::StringPiece(path.begin(), path.begin() + colon_pos), &dir_id); |
| 464 DCHECK(result) << "Invalid directory id in path '" << path << "'"; |
| 465 *out_dir = dirs_.Lookup(dir_id); |
| 466 DCHECK(*out_dir) << "Invalid directory id " << dir_id; |
| 467 |
| 468 *out_path = std::string(path.begin() + colon_pos + 1, path.end()); |
| 469 } |
| 470 |
| 471 void MojoEnv::UnregisterDirectory(base::StringPiece prefix) { |
| 472 DCHECK(!prefix.empty()); |
| 473 DCHECK_EQ(prefix.back(), ':'); |
| 474 prefix.remove_suffix(1); |
| 475 int dir_id; |
| 476 bool result = base::StringToInt(prefix, &dir_id); |
| 477 DCHECK(result) << "Invalid directory id '" << prefix << "'"; |
| 478 LevelDBMojoProxy::OpaqueDir* dir = dirs_.Lookup(dir_id); |
| 479 DCHECK(dir) << "Invalid directory id " << dir_id; |
| 480 dirs_.Remove(dir_id); |
| 481 thread_->UnregisterDirectory(dir); |
| 482 } |
| 483 |
384 } // namespace leveldb | 484 } // namespace leveldb |
OLD | NEW |