Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(112)

Side by Side Diff: components/leveldb/env_mojo.cc

Issue 2722293002: Fix lifetime of leveldb::MojoEnv instances. (Closed)
Patch Set: minor cleanups Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 std::string filename_; 211 std::string filename_;
209 base::File file_; 212 base::File file_;
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
221 base::LazyInstance<std::vector<MojoEnv*>>::Leaky g_mojo_envs =
222 LAZY_INSTANCE_INITIALIZER;
223
218 } // namespace 224 } // namespace
219 225
220 MojoEnv::MojoEnv(const std::string& name, 226 // static
221 scoped_refptr<LevelDBMojoProxy> file_thread, 227 MojoEnv* MojoEnv::Get(
222 LevelDBMojoProxy::OpaqueDir* dir) 228 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) {
223 : ChromiumEnv(name), thread_(file_thread), dir_(dir) {} 229 auto* envs = g_mojo_envs.Pointer();
230 for (MojoEnv* env : *envs) {
231 if (env->thread_->task_runner() == file_task_runner)
michaeln 2017/03/27 20:24:10 I think this does ptr comparison, do we seen multi
Marijn Kruisselbrink 2017/03/31 23:26:24 Part of the confusion/complication is because of h
232 return env;
233 }
234 MojoEnv* env = new MojoEnv(std::move(file_task_runner));
235 envs->push_back(env);
236 return env;
237 }
224 238
225 MojoEnv::~MojoEnv() { 239 std::string MojoEnv::RegisterDirectory(
michaeln 2017/03/27 20:24:10 This function/class is not thread safe (dirs_), do
226 thread_->UnregisterDirectory(dir_); 240 filesystem::mojom::DirectoryPtr directory) {
241 LevelDBMojoProxy::OpaqueDir* dir =
242 thread_->RegisterDirectory(std::move(directory));
243 int dir_id = dirs_.Add(dir);
244 return base::StringPrintf("%d:", dir_id);
245 }
246
247 void MojoEnv::UnregisterDirectory(base::StringPiece prefix) {
248 DCHECK(!prefix.empty());
249 DCHECK_EQ(prefix.back(), ':');
250 prefix.remove_suffix(1);
251 int dir_id;
252 bool result = base::StringToInt(prefix, &dir_id);
253 DCHECK(result) << "Invalid directory id '" << prefix << "'";
254 LevelDBMojoProxy::OpaqueDir* dir = dirs_.Lookup(dir_id);
255 DCHECK(dir) << "Invalid directory id " << dir_id;
256 dirs_.Remove(dir_id);
257 thread_->UnregisterDirectory(dir);
227 } 258 }
228 259
229 Status MojoEnv::NewSequentialFile(const std::string& fname, 260 Status MojoEnv::NewSequentialFile(const std::string& fname,
230 SequentialFile** result) { 261 SequentialFile** result) {
231 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname); 262 TRACE_EVENT1("leveldb", "MojoEnv::NewSequentialFile", "fname", fname);
263 LevelDBMojoProxy::OpaqueDir* dir;
264 std::string path;
265 ParsePath(fname, &dir, &path);
266
232 base::File f = thread_->OpenFileHandle( 267 base::File f = thread_->OpenFileHandle(
233 dir_, fname, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead); 268 dir, path, filesystem::mojom::kFlagOpen | filesystem::mojom::kFlagRead);
234 if (!f.IsValid()) { 269 if (!f.IsValid()) {
235 *result = nullptr; 270 *result = nullptr;
236 return MakeIOError(fname, "Unable to create sequential file", 271 return MakeIOError(fname, "Unable to create sequential file",
237 leveldb_env::kNewSequentialFile, f.error_details()); 272 leveldb_env::kNewSequentialFile, f.error_details());
238 } 273 }
239 274
240 *result = new MojoSequentialFile(fname, std::move(f)); 275 *result = new MojoSequentialFile(fname, std::move(f));
241 return Status::OK(); 276 return Status::OK();
242 } 277 }
243 278
244 Status MojoEnv::NewRandomAccessFile(const std::string& fname, 279 Status MojoEnv::NewRandomAccessFile(const std::string& fname,
245 RandomAccessFile** result) { 280 RandomAccessFile** result) {
246 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname); 281 TRACE_EVENT1("leveldb", "MojoEnv::NewRandomAccessFile", "fname", fname);
282 LevelDBMojoProxy::OpaqueDir* dir;
283 std::string path;
284 ParsePath(fname, &dir, &path);
285
247 base::File f = thread_->OpenFileHandle( 286 base::File f = thread_->OpenFileHandle(
248 dir_, fname, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen); 287 dir, path, filesystem::mojom::kFlagRead | filesystem::mojom::kFlagOpen);
249 if (!f.IsValid()) { 288 if (!f.IsValid()) {
250 *result = nullptr; 289 *result = nullptr;
251 base::File::Error error_code = f.error_details(); 290 base::File::Error error_code = f.error_details();
252 return MakeIOError(fname, FileErrorString(error_code), 291 return MakeIOError(path, FileErrorString(error_code),
253 leveldb_env::kNewRandomAccessFile, error_code); 292 leveldb_env::kNewRandomAccessFile, error_code);
254 } 293 }
255 294
256 *result = new MojoRandomAccessFile(fname, std::move(f)); 295 *result = new MojoRandomAccessFile(path, std::move(f));
257 return Status::OK(); 296 return Status::OK();
258 } 297 }
259 298
260 Status MojoEnv::NewWritableFile(const std::string& fname, 299 Status MojoEnv::NewWritableFile(const std::string& fname,
261 WritableFile** result) { 300 WritableFile** result) {
262 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname); 301 TRACE_EVENT1("leveldb", "MojoEnv::NewWritableFile", "fname", fname);
263 base::File f = 302 LevelDBMojoProxy::OpaqueDir* dir;
264 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kCreateAlways | 303 std::string path;
265 filesystem::mojom::kFlagWrite); 304 ParsePath(fname, &dir, &path);
305
306 base::File f = thread_->OpenFileHandle(
307 dir, path,
308 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite);
266 if (!f.IsValid()) { 309 if (!f.IsValid()) {
267 *result = nullptr; 310 *result = nullptr;
268 return MakeIOError(fname, "Unable to create writable file", 311 return MakeIOError(path, "Unable to create writable file",
269 leveldb_env::kNewWritableFile, f.error_details()); 312 leveldb_env::kNewWritableFile, f.error_details());
270 } 313 }
271 314
272 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); 315 *result = new MojoWritableFile(dir, path, std::move(f), thread_);
273 return Status::OK(); 316 return Status::OK();
274 } 317 }
275 318
276 Status MojoEnv::NewAppendableFile(const std::string& fname, 319 Status MojoEnv::NewAppendableFile(const std::string& fname,
277 WritableFile** result) { 320 WritableFile** result) {
278 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname); 321 TRACE_EVENT1("leveldb", "MojoEnv::NewAppendableFile", "fname", fname);
279 base::File f = 322 LevelDBMojoProxy::OpaqueDir* dir;
280 thread_->OpenFileHandle(dir_, fname, filesystem::mojom::kFlagOpenAlways | 323 std::string path;
281 filesystem::mojom::kFlagAppend); 324 ParsePath(fname, &dir, &path);
325
326 base::File f = thread_->OpenFileHandle(
327 dir, path,
328 filesystem::mojom::kFlagOpenAlways | filesystem::mojom::kFlagAppend);
282 if (!f.IsValid()) { 329 if (!f.IsValid()) {
283 *result = nullptr; 330 *result = nullptr;
284 return MakeIOError(fname, "Unable to create appendable file", 331 return MakeIOError(path, "Unable to create appendable file",
285 leveldb_env::kNewAppendableFile, f.error_details()); 332 leveldb_env::kNewAppendableFile, f.error_details());
286 } 333 }
287 334
288 *result = new MojoWritableFile(dir_, fname, std::move(f), thread_); 335 *result = new MojoWritableFile(dir, path, std::move(f), thread_);
289 return Status::OK(); 336 return Status::OK();
290 } 337 }
291 338
292 bool MojoEnv::FileExists(const std::string& fname) { 339 bool MojoEnv::FileExists(const std::string& fname) {
293 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname); 340 TRACE_EVENT1("leveldb", "MojoEnv::FileExists", "fname", fname);
294 return thread_->FileExists(dir_, fname); 341 LevelDBMojoProxy::OpaqueDir* dir;
342 std::string path;
343 ParsePath(fname, &dir, &path);
344
345 return thread_->FileExists(dir, path);
295 } 346 }
296 347
297 Status MojoEnv::GetChildren(const std::string& path, 348 Status MojoEnv::GetChildren(const std::string& dirname,
298 std::vector<std::string>* result) { 349 std::vector<std::string>* result) {
299 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "path", path); 350 TRACE_EVENT1("leveldb", "MojoEnv::GetChildren", "dirname", dirname);
300 return FilesystemErrorToStatus(thread_->GetChildren(dir_, path, result), path, 351 LevelDBMojoProxy::OpaqueDir* dir;
352 std::string path;
353 ParsePath(dirname, &dir, &path);
354
355 return FilesystemErrorToStatus(thread_->GetChildren(dir, path, result), path,
301 leveldb_env::kGetChildren); 356 leveldb_env::kGetChildren);
302 } 357 }
303 358
304 Status MojoEnv::DeleteFile(const std::string& fname) { 359 Status MojoEnv::DeleteFile(const std::string& fname) {
305 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname); 360 TRACE_EVENT1("leveldb", "MojoEnv::DeleteFile", "fname", fname);
306 return FilesystemErrorToStatus(thread_->Delete(dir_, fname, 0), fname, 361 LevelDBMojoProxy::OpaqueDir* dir;
362 std::string path;
363 ParsePath(fname, &dir, &path);
364
365 return FilesystemErrorToStatus(thread_->Delete(dir, path, 0), path,
307 leveldb_env::kDeleteFile); 366 leveldb_env::kDeleteFile);
308 } 367 }
309 368
310 Status MojoEnv::CreateDir(const std::string& dirname) { 369 Status MojoEnv::CreateDir(const std::string& dirname) {
311 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname); 370 TRACE_EVENT1("leveldb", "MojoEnv::CreateDir", "dirname", dirname);
312 return FilesystemErrorToStatus(thread_->CreateDir(dir_, dirname), dirname, 371 LevelDBMojoProxy::OpaqueDir* dir;
372 std::string path;
373 ParsePath(dirname, &dir, &path);
374
375 return FilesystemErrorToStatus(thread_->CreateDir(dir, path), path,
313 leveldb_env::kCreateDir); 376 leveldb_env::kCreateDir);
314 } 377 }
315 378
316 Status MojoEnv::DeleteDir(const std::string& dirname) { 379 Status MojoEnv::DeleteDir(const std::string& dirname) {
317 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname); 380 TRACE_EVENT1("leveldb", "MojoEnv::DeleteDir", "dirname", dirname);
381 LevelDBMojoProxy::OpaqueDir* dir;
382 std::string path;
383 ParsePath(dirname, &dir, &path);
384
318 return FilesystemErrorToStatus( 385 return FilesystemErrorToStatus(
319 thread_->Delete(dir_, dirname, filesystem::mojom::kDeleteFlagRecursive), 386 thread_->Delete(dir, path, filesystem::mojom::kDeleteFlagRecursive), path,
320 dirname, leveldb_env::kDeleteDir); 387 leveldb_env::kDeleteDir);
321 } 388 }
322 389
323 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) { 390 Status MojoEnv::GetFileSize(const std::string& fname, uint64_t* file_size) {
324 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname); 391 TRACE_EVENT1("leveldb", "MojoEnv::GetFileSize", "fname", fname);
325 return FilesystemErrorToStatus(thread_->GetFileSize(dir_, fname, file_size), 392 LevelDBMojoProxy::OpaqueDir* dir;
326 fname, 393 std::string path;
327 leveldb_env::kGetFileSize); 394 ParsePath(fname, &dir, &path);
395
396 return FilesystemErrorToStatus(thread_->GetFileSize(dir, path, file_size),
397 path, leveldb_env::kGetFileSize);
328 } 398 }
329 399
330 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) { 400 Status MojoEnv::RenameFile(const std::string& src, const std::string& target) {
331 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target); 401 TRACE_EVENT2("leveldb", "MojoEnv::RenameFile", "src", src, "target", target);
332 return FilesystemErrorToStatus(thread_->RenameFile(dir_, src, target), src, 402 LevelDBMojoProxy::OpaqueDir* src_dir;
333 leveldb_env::kRenameFile); 403 std::string src_path;
404 ParsePath(src, &src_dir, &src_path);
405 LevelDBMojoProxy::OpaqueDir* target_dir;
406 std::string target_path;
407 ParsePath(target, &target_dir, &target_path);
408 DCHECK_EQ(src_dir, target_dir);
409
410 return FilesystemErrorToStatus(
411 thread_->RenameFile(src_dir, src_path, target_path), src_path,
412 leveldb_env::kRenameFile);
334 } 413 }
335 414
336 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) { 415 Status MojoEnv::LockFile(const std::string& fname, FileLock** lock) {
337 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname); 416 TRACE_EVENT1("leveldb", "MojoEnv::LockFile", "fname", fname);
417 LevelDBMojoProxy::OpaqueDir* dir;
418 std::string path;
419 ParsePath(fname, &dir, &path);
338 420
339 std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p = 421 std::pair<filesystem::mojom::FileError, LevelDBMojoProxy::OpaqueLock*> p =
340 thread_->LockFile(dir_, fname); 422 thread_->LockFile(dir, path);
341 423
342 if (p.second) 424 if (p.second)
343 *lock = new MojoFileLock(p.second, fname); 425 *lock = new MojoFileLock(p.second, fname);
344 426
345 return FilesystemErrorToStatus(p.first, fname, leveldb_env::kLockFile); 427 return FilesystemErrorToStatus(p.first, path, leveldb_env::kLockFile);
346 } 428 }
347 429
348 Status MojoEnv::UnlockFile(FileLock* lock) { 430 Status MojoEnv::UnlockFile(FileLock* lock) {
349 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock); 431 MojoFileLock* my_lock = reinterpret_cast<MojoFileLock*>(lock);
350 432
351 std::string fname = my_lock ? my_lock->name() : "(invalid)"; 433 std::string fname = my_lock ? my_lock->name() : "(invalid)";
352 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname); 434 TRACE_EVENT1("leveldb", "MojoEnv::UnlockFile", "fname", fname);
353 435
354 filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock()); 436 filesystem::mojom::FileError err = thread_->UnlockFile(my_lock->TakeLock());
355 delete my_lock; 437 delete my_lock;
356 return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile); 438 return FilesystemErrorToStatus(err, fname, leveldb_env::kUnlockFile);
357 } 439 }
358 440
359 Status MojoEnv::GetTestDirectory(std::string* path) { 441 Status MojoEnv::GetTestDirectory(std::string* path) {
360 // TODO(erg): This method is actually only used from the test harness in 442 // 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 443 // leveldb. And when we go and port that test stuff to a
362 // service_manager::ServiceTest, 444 // service_manager::ServiceTest,
363 // we probably won't use it since the mojo filesystem actually handles 445 // we probably won't use it since the mojo filesystem actually handles
364 // temporary filesystems just fine. 446 // temporary filesystems just fine.
365 NOTREACHED(); 447 NOTREACHED();
366 return Status::OK(); 448 return Status::OK();
367 } 449 }
368 450
369 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) { 451 Status MojoEnv::NewLogger(const std::string& fname, Logger** result) {
370 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname); 452 TRACE_EVENT1("leveldb", "MojoEnv::NewLogger", "fname", fname);
453 LevelDBMojoProxy::OpaqueDir* dir;
454 std::string path;
455 ParsePath(fname, &dir, &path);
456
371 base::File f(thread_->OpenFileHandle( 457 base::File f(thread_->OpenFileHandle(
372 dir_, fname, 458 dir, path,
373 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite)); 459 filesystem::mojom::kCreateAlways | filesystem::mojom::kFlagWrite));
374 if (!f.IsValid()) { 460 if (!f.IsValid()) {
375 *result = NULL; 461 *result = NULL;
376 return MakeIOError(fname, "Unable to create log file", 462 return MakeIOError(path, "Unable to create log file",
377 leveldb_env::kNewLogger, f.error_details()); 463 leveldb_env::kNewLogger, f.error_details());
378 } else { 464 } else {
379 *result = new leveldb::ChromiumLogger(std::move(f)); 465 *result = new leveldb::ChromiumLogger(std::move(f));
380 return Status::OK(); 466 return Status::OK();
381 } 467 }
382 } 468 }
383 469
470 void MojoEnv::ParsePath(const std::string& path,
471 LevelDBMojoProxy::OpaqueDir** out_dir,
472 std::string* out_path) {
473 size_t colon_pos = path.find(':');
474 DCHECK_NE(colon_pos, std::string::npos);
475
476 int dir_id;
477 bool result = base::StringToInt(
478 base::StringPiece(path.begin(), path.begin() + colon_pos), &dir_id);
479 DCHECK(result) << "Invalid directory id in path '" << path << "'";
480 *out_dir = dirs_.Lookup(dir_id);
481 DCHECK(*out_dir) << "Invalid directory id " << dir_id;
482
483 *out_path = std::string(path.begin() + colon_pos + 1, path.end());
484 }
485
486 MojoEnv::MojoEnv(scoped_refptr<base::SingleThreadTaskRunner> file_task_runner)
487 : ChromiumEnv("LevelDBEnv.Mojo"),
488 thread_(new LevelDBMojoProxy(std::move(file_task_runner))) {}
489
490 MojoEnv::~MojoEnv() {}
491
384 } // namespace leveldb 492 } // namespace leveldb
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698