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

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

Issue 2722293002: Fix lifetime of leveldb::MojoEnv instances. (Closed)
Patch Set: annotate leaks Created 3 years, 8 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698