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

Side by Side Diff: third_party/leveldatabase/env_chromium.cc

Issue 11445030: Add sync of parent directory when creating or renaming a file. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 1 // Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors. 3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 4
5 #include <deque> 5 #include <deque>
6 #include <errno.h> 6 #include <errno.h>
7 #include <stdio.h> 7 #include <stdio.h>
8 #include "base/at_exit.h" 8 #include "base/at_exit.h"
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 12 matching lines...) Expand all
23 #include "leveldb/env.h" 23 #include "leveldb/env.h"
24 #include "leveldb/slice.h" 24 #include "leveldb/slice.h"
25 #include "port/port.h" 25 #include "port/port.h"
26 #include "util/logging.h" 26 #include "util/logging.h"
27 27
28 #if defined(OS_WIN) 28 #if defined(OS_WIN)
29 #include <io.h> 29 #include <io.h>
30 #include "base/win/win_util.h" 30 #include "base/win/win_util.h"
31 #endif 31 #endif
32 32
33 #if !defined(OS_WIN)
34 #include <fcntl.h>
dgrogan 2012/12/06 23:17:38 Oh yeah, what's this for?
ericu 2012/12/10 18:31:12 O_WRONLY
35 #endif
36
33 namespace { 37 namespace {
34 38
35 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) || \ 39 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) || \
36 defined(OS_OPENBSD) 40 defined(OS_OPENBSD)
37 // The following are glibc-specific 41 // The following are glibc-specific
38 42
39 size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) { 43 size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) {
40 return fread(ptr, size, n, file); 44 return fread(ptr, size, n, file);
41 } 45 }
42 46
(...skipping 16 matching lines...) Expand all
59 #endif 63 #endif
60 64
61 #endif 65 #endif
62 66
63 // Wide-char safe fopen wrapper. 67 // Wide-char safe fopen wrapper.
64 FILE* fopen_internal(const char* fname, const char* mode) { 68 FILE* fopen_internal(const char* fname, const char* mode) {
65 #if defined(OS_WIN) 69 #if defined(OS_WIN)
66 return _wfopen(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str()); 70 return _wfopen(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str());
67 #else 71 #else
68 return fopen(fname, mode); 72 return fopen(fname, mode);
73 }
dgrogan 2012/12/06 23:15:41 This won't compile on windows, will it?
ericu 2012/12/10 18:31:12 Fixed. However, I'm having trouble uploading a ne
dgrogan 2012/12/10 21:53:46 Editing it here should work, env_chromium.cc lives
69 #endif 74 #endif
70 }
71
72 } // namespace
73
74 namespace leveldb {
75
76 namespace {
77
78 class Thread;
79
80 static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[]
81 = FILE_PATH_LITERAL("leveldb-test-");
82 75
83 ::FilePath CreateFilePath(const std::string& file_path) { 76 ::FilePath CreateFilePath(const std::string& file_path) {
84 #if defined(OS_WIN) 77 #if defined(OS_WIN)
85 return FilePath(UTF8ToUTF16(file_path)); 78 return FilePath(UTF8ToUTF16(file_path));
86 #else 79 #else
87 return FilePath(file_path); 80 return FilePath(file_path);
88 #endif 81 #endif
89 } 82 }
90 83
91 std::string FilePathToString(const ::FilePath& file_path) { 84 std::string FilePathToString(const ::FilePath& file_path) {
92 #if defined(OS_WIN) 85 #if defined(OS_WIN)
93 return UTF16ToUTF8(file_path.value()); 86 return UTF16ToUTF8(file_path.value());
94 #else 87 #else
95 return file_path.value(); 88 return file_path.value();
96 #endif 89 #endif
97 } 90 }
98 91
92 bool sync_parent(const std::string& fname) {
93 #if !defined(OS_WIN)
94 FilePath parent_dir = CreateFilePath(fname).DirName();
95 int parent_fd = open(FilePathToString(parent_dir).c_str(), O_WRONLY);
96 if (parent_fd < 0)
97 return false;
98 fsync(parent_fd);
99 close(parent_fd);
100 #endif
101 return true;
102 }
103
104 } // namespace
105
106 namespace leveldb {
107
108 namespace {
109
110 class Thread;
111
112 static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[]
113 = FILE_PATH_LITERAL("leveldb-test-");
114
99 // TODO(jorlow): This should be moved into Chromium's base. 115 // TODO(jorlow): This should be moved into Chromium's base.
100 const char* PlatformFileErrorString(const ::base::PlatformFileError& error) { 116 const char* PlatformFileErrorString(const ::base::PlatformFileError& error) {
101 switch (error) { 117 switch (error) {
102 case ::base::PLATFORM_FILE_ERROR_FAILED: 118 case ::base::PLATFORM_FILE_ERROR_FAILED:
103 return "Opening file failed."; 119 return "Opening file failed.";
104 case ::base::PLATFORM_FILE_ERROR_IN_USE: 120 case ::base::PLATFORM_FILE_ERROR_IN_USE:
105 return "File currently in use."; 121 return "File currently in use.";
106 case ::base::PLATFORM_FILE_ERROR_EXISTS: 122 case ::base::PLATFORM_FILE_ERROR_EXISTS:
107 return "File already exists."; 123 return "File already exists.";
108 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: 124 case ::base::PLATFORM_FILE_ERROR_NOT_FOUND:
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 return Status::OK(); 299 return Status::OK();
284 } 300 }
285 301
286 virtual Status NewWritableFile(const std::string& fname, 302 virtual Status NewWritableFile(const std::string& fname,
287 WritableFile** result) { 303 WritableFile** result) {
288 *result = NULL; 304 *result = NULL;
289 FILE* f = fopen_internal(fname.c_str(), "wb"); 305 FILE* f = fopen_internal(fname.c_str(), "wb");
290 if (f == NULL) { 306 if (f == NULL) {
291 return Status::IOError(fname, strerror(errno)); 307 return Status::IOError(fname, strerror(errno));
292 } else { 308 } else {
309 if (!sync_parent(fname)) {
310 fclose(f);
311 return Status::IOError(fname, strerror(errno));
312 }
293 *result = new ChromiumWritableFile(fname, f); 313 *result = new ChromiumWritableFile(fname, f);
294 return Status::OK(); 314 return Status::OK();
295 } 315 }
296 } 316 }
297 317
298 virtual bool FileExists(const std::string& fname) { 318 virtual bool FileExists(const std::string& fname) {
299 return ::file_util::PathExists(CreateFilePath(fname)); 319 return ::file_util::PathExists(CreateFilePath(fname));
300 } 320 }
301 321
302 virtual Status GetChildren(const std::string& dir, 322 virtual Status GetChildren(const std::string& dir,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } else { 370 } else {
351 *size = static_cast<uint64_t>(signed_size); 371 *size = static_cast<uint64_t>(signed_size);
352 } 372 }
353 return s; 373 return s;
354 } 374 }
355 375
356 virtual Status RenameFile(const std::string& src, const std::string& dst) { 376 virtual Status RenameFile(const std::string& src, const std::string& dst) {
357 Status result; 377 Status result;
358 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { 378 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) {
359 result = Status::IOError(src, "Could not rename file."); 379 result = Status::IOError(src, "Could not rename file.");
380 } else {
381 sync_parent(dst);
dgrogan 2012/12/06 23:15:41 Was ignoring the return value an oversight or cons
ericu 2012/12/10 18:31:12 Conscious choice. There's nothing we can do about
382 if (src != dst)
383 sync_parent(src);
360 } 384 }
361 return result; 385 return result;
362 } 386 }
363 387
364 virtual Status LockFile(const std::string& fname, FileLock** lock) { 388 virtual Status LockFile(const std::string& fname, FileLock** lock) {
365 *lock = NULL; 389 *lock = NULL;
366 Status result; 390 Status result;
367 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | 391 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS |
368 ::base::PLATFORM_FILE_READ | 392 ::base::PLATFORM_FILE_READ |
369 ::base::PLATFORM_FILE_WRITE | 393 ::base::PLATFORM_FILE_WRITE |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 mu_.Release(); 447 mu_.Release();
424 return Status::OK(); 448 return Status::OK();
425 } 449 }
426 450
427 virtual Status NewLogger(const std::string& fname, Logger** result) { 451 virtual Status NewLogger(const std::string& fname, Logger** result) {
428 FILE* f = fopen_internal(fname.c_str(), "w"); 452 FILE* f = fopen_internal(fname.c_str(), "w");
429 if (f == NULL) { 453 if (f == NULL) {
430 *result = NULL; 454 *result = NULL;
431 return Status::IOError(fname, strerror(errno)); 455 return Status::IOError(fname, strerror(errno));
432 } else { 456 } else {
457 if (!sync_parent(fname)) {
458 fclose(f);
459 return Status::IOError(fname, strerror(errno));
460 }
433 *result = new ChromiumLogger(f); 461 *result = new ChromiumLogger(f);
434 return Status::OK(); 462 return Status::OK();
435 } 463 }
436 } 464 }
437 465
438 virtual uint64_t NowMicros() { 466 virtual uint64_t NowMicros() {
439 return ::base::TimeTicks::Now().ToInternalValue(); 467 return ::base::TimeTicks::Now().ToInternalValue();
440 } 468 }
441 469
442 virtual void SleepForMicroseconds(int micros) { 470 virtual void SleepForMicroseconds(int micros) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 ::base::LazyInstance<ChromiumEnv>::Leaky 568 ::base::LazyInstance<ChromiumEnv>::Leaky
541 default_env = LAZY_INSTANCE_INITIALIZER; 569 default_env = LAZY_INSTANCE_INITIALIZER;
542 570
543 } 571 }
544 572
545 Env* Env::Default() { 573 Env* Env::Default() {
546 return default_env.Pointer(); 574 return default_env.Pointer();
547 } 575 }
548 576
549 } 577 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698