| OLD | NEW |
| 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 kDeleteDir, | 117 kDeleteDir, |
| 118 kGetFileSize, | 118 kGetFileSize, |
| 119 kRenamefile, | 119 kRenamefile, |
| 120 kLockFile, | 120 kLockFile, |
| 121 kUnlockFile, | 121 kUnlockFile, |
| 122 kGetTestDirectory, | 122 kGetTestDirectory, |
| 123 kNewLogger, | 123 kNewLogger, |
| 124 kNumEntries | 124 kNumEntries |
| 125 }; | 125 }; |
| 126 | 126 |
| 127 void LogToUMA(UmaEntry entry) { | 127 class UMALogger { |
| 128 UMA_HISTOGRAM_ENUMERATION("LevelDBEnv.IOError", entry, kNumEntries); | 128 public: |
| 129 UMALogger(std::string uma_title); |
| 130 void RecordErrorAt(UmaEntry entry) const; |
| 131 void LogRandomAccessFileError(base::PlatformFileError error_code) const; |
| 132 |
| 133 private: |
| 134 std::string uma_title_; |
| 135 }; |
| 136 |
| 137 UMALogger::UMALogger(std::string uma_title) : uma_title_(uma_title) {} |
| 138 |
| 139 void UMALogger::RecordErrorAt(UmaEntry entry) const { |
| 140 std::string uma_name(uma_title_); |
| 141 uma_name.append(".IOError"); |
| 142 UMA_HISTOGRAM_ENUMERATION(uma_name, entry, kNumEntries); |
| 129 } | 143 } |
| 130 | 144 |
| 131 void LogRandomAccessFileError(base::PlatformFileError error_code) { | 145 void UMALogger::LogRandomAccessFileError(base::PlatformFileError error_code) |
| 146 const { |
| 132 DCHECK(error_code < 0); | 147 DCHECK(error_code < 0); |
| 133 UMA_HISTOGRAM_ENUMERATION("LevelDBEnv.IOError.RandomAccessFile", | 148 std::string uma_name(uma_title_); |
| 149 uma_name.append(".IOError.RandomAccessFile"); |
| 150 UMA_HISTOGRAM_ENUMERATION(uma_name, |
| 134 -error_code, | 151 -error_code, |
| 135 -base::PLATFORM_FILE_ERROR_MAX); | 152 -base::PLATFORM_FILE_ERROR_MAX); |
| 136 } | 153 } |
| 137 | 154 |
| 138 } // namespace | 155 } // namespace |
| 139 | 156 |
| 140 namespace leveldb { | 157 namespace leveldb { |
| 141 | 158 |
| 142 namespace { | 159 namespace { |
| 143 | 160 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 NOTREACHED(); | 201 NOTREACHED(); |
| 185 } | 202 } |
| 186 NOTIMPLEMENTED(); | 203 NOTIMPLEMENTED(); |
| 187 return "Unknown error."; | 204 return "Unknown error."; |
| 188 } | 205 } |
| 189 | 206 |
| 190 class ChromiumSequentialFile: public SequentialFile { | 207 class ChromiumSequentialFile: public SequentialFile { |
| 191 private: | 208 private: |
| 192 std::string filename_; | 209 std::string filename_; |
| 193 FILE* file_; | 210 FILE* file_; |
| 211 const UMALogger* uma_logger_; |
| 194 | 212 |
| 195 public: | 213 public: |
| 196 ChromiumSequentialFile(const std::string& fname, FILE* f) | 214 ChromiumSequentialFile(const std::string& fname, FILE* f, |
| 197 : filename_(fname), file_(f) { } | 215 const UMALogger* uma_logger) |
| 216 : filename_(fname), file_(f), uma_logger_(uma_logger) { } |
| 198 virtual ~ChromiumSequentialFile() { fclose(file_); } | 217 virtual ~ChromiumSequentialFile() { fclose(file_); } |
| 199 | 218 |
| 200 virtual Status Read(size_t n, Slice* result, char* scratch) { | 219 virtual Status Read(size_t n, Slice* result, char* scratch) { |
| 201 Status s; | 220 Status s; |
| 202 size_t r = fread_unlocked(scratch, 1, n, file_); | 221 size_t r = fread_unlocked(scratch, 1, n, file_); |
| 203 *result = Slice(scratch, r); | 222 *result = Slice(scratch, r); |
| 204 if (r < n) { | 223 if (r < n) { |
| 205 if (feof(file_)) { | 224 if (feof(file_)) { |
| 206 // We leave status as ok if we hit the end of the file | 225 // We leave status as ok if we hit the end of the file |
| 207 } else { | 226 } else { |
| 208 // A partial read with an error: return a non-ok status | 227 // A partial read with an error: return a non-ok status |
| 209 s = Status::IOError(filename_, strerror(errno)); | 228 s = Status::IOError(filename_, strerror(errno)); |
| 210 LogToUMA(kSequentialFileRead); | 229 uma_logger_->RecordErrorAt(kSequentialFileRead); |
| 211 } | 230 } |
| 212 } | 231 } |
| 213 return s; | 232 return s; |
| 214 } | 233 } |
| 215 | 234 |
| 216 virtual Status Skip(uint64_t n) { | 235 virtual Status Skip(uint64_t n) { |
| 217 if (fseek(file_, n, SEEK_CUR)) { | 236 if (fseek(file_, n, SEEK_CUR)) { |
| 218 LogToUMA(kSequentialFileSkip); | 237 uma_logger_->RecordErrorAt(kSequentialFileSkip); |
| 219 return Status::IOError(filename_, strerror(errno)); | 238 return Status::IOError(filename_, strerror(errno)); |
| 220 } | 239 } |
| 221 return Status::OK(); | 240 return Status::OK(); |
| 222 } | 241 } |
| 223 }; | 242 }; |
| 224 | 243 |
| 225 class ChromiumRandomAccessFile: public RandomAccessFile { | 244 class ChromiumRandomAccessFile: public RandomAccessFile { |
| 226 private: | 245 private: |
| 227 std::string filename_; | 246 std::string filename_; |
| 228 ::base::PlatformFile file_; | 247 ::base::PlatformFile file_; |
| 248 const UMALogger* uma_logger_; |
| 229 | 249 |
| 230 public: | 250 public: |
| 231 ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file) | 251 ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file, |
| 232 : filename_(fname), file_(file) { } | 252 const UMALogger* uma_logger) |
| 253 : filename_(fname), file_(file), uma_logger_(uma_logger) { } |
| 233 virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } | 254 virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } |
| 234 | 255 |
| 235 virtual Status Read(uint64_t offset, size_t n, Slice* result, | 256 virtual Status Read(uint64_t offset, size_t n, Slice* result, |
| 236 char* scratch) const { | 257 char* scratch) const { |
| 237 Status s; | 258 Status s; |
| 238 int r = ::base::ReadPlatformFile(file_, offset, scratch, n); | 259 int r = ::base::ReadPlatformFile(file_, offset, scratch, n); |
| 239 *result = Slice(scratch, (r < 0) ? 0 : r); | 260 *result = Slice(scratch, (r < 0) ? 0 : r); |
| 240 if (r < 0) { | 261 if (r < 0) { |
| 241 // An error: return a non-ok status | 262 // An error: return a non-ok status |
| 242 s = Status::IOError(filename_, "Could not perform read"); | 263 s = Status::IOError(filename_, "Could not perform read"); |
| 243 LogToUMA(kRandomAccessFileRead); | 264 uma_logger_->RecordErrorAt(kRandomAccessFileRead); |
| 244 } | 265 } |
| 245 return s; | 266 return s; |
| 246 } | 267 } |
| 247 }; | 268 }; |
| 248 | 269 |
| 249 class ChromiumWritableFile : public WritableFile { | 270 class ChromiumWritableFile : public WritableFile { |
| 250 private: | 271 private: |
| 251 std::string filename_; | 272 std::string filename_; |
| 252 FILE* file_; | 273 FILE* file_; |
| 274 const UMALogger* uma_logger_; |
| 253 | 275 |
| 254 public: | 276 public: |
| 255 ChromiumWritableFile(const std::string& fname, FILE* f) | 277 ChromiumWritableFile(const std::string& fname, FILE* f, |
| 256 : filename_(fname), file_(f) { } | 278 const UMALogger* uma_logger) |
| 279 : filename_(fname), file_(f), uma_logger_(uma_logger) { } |
| 257 | 280 |
| 258 ~ChromiumWritableFile() { | 281 ~ChromiumWritableFile() { |
| 259 if (file_ != NULL) { | 282 if (file_ != NULL) { |
| 260 // Ignoring any potential errors | 283 // Ignoring any potential errors |
| 261 fclose(file_); | 284 fclose(file_); |
| 262 } | 285 } |
| 263 } | 286 } |
| 264 | 287 |
| 265 virtual Status Append(const Slice& data) { | 288 virtual Status Append(const Slice& data) { |
| 266 size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); | 289 size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); |
| 267 Status result; | 290 Status result; |
| 268 if (r != data.size()) { | 291 if (r != data.size()) { |
| 269 result = Status::IOError(filename_, strerror(errno)); | 292 result = Status::IOError(filename_, strerror(errno)); |
| 270 LogToUMA(kWritableFileAppend); | 293 uma_logger_->RecordErrorAt(kWritableFileAppend); |
| 271 } | 294 } |
| 272 return result; | 295 return result; |
| 273 } | 296 } |
| 274 | 297 |
| 275 virtual Status Close() { | 298 virtual Status Close() { |
| 276 Status result; | 299 Status result; |
| 277 if (fclose(file_) != 0) { | 300 if (fclose(file_) != 0) { |
| 278 result = Status::IOError(filename_, strerror(errno)); | 301 result = Status::IOError(filename_, strerror(errno)); |
| 279 LogToUMA(kWritableFileClose); | 302 uma_logger_->RecordErrorAt(kWritableFileClose); |
| 280 } | 303 } |
| 281 file_ = NULL; | 304 file_ = NULL; |
| 282 return result; | 305 return result; |
| 283 } | 306 } |
| 284 | 307 |
| 285 virtual Status Flush() { | 308 virtual Status Flush() { |
| 286 Status result; | 309 Status result; |
| 287 if (fflush_unlocked(file_) != 0) { | 310 if (fflush_unlocked(file_) != 0) { |
| 288 result = Status::IOError(filename_, strerror(errno)); | 311 result = Status::IOError(filename_, strerror(errno)); |
| 289 LogToUMA(kWritableFileFlush); | 312 uma_logger_->RecordErrorAt(kWritableFileFlush); |
| 290 } | 313 } |
| 291 return result; | 314 return result; |
| 292 } | 315 } |
| 293 | 316 |
| 294 virtual Status Sync() { | 317 virtual Status Sync() { |
| 295 Status result; | 318 Status result; |
| 296 int error = 0; | 319 int error = 0; |
| 297 | 320 |
| 298 if (fflush_unlocked(file_)) | 321 if (fflush_unlocked(file_)) |
| 299 error = errno; | 322 error = errno; |
| 300 // Sync even if fflush gave an error; perhaps the data actually got out, | 323 // Sync even if fflush gave an error; perhaps the data actually got out, |
| 301 // even though something went wrong. | 324 // even though something went wrong. |
| 302 if (fdatasync(fileno(file_)) && !error) | 325 if (fdatasync(fileno(file_)) && !error) |
| 303 error = errno; | 326 error = errno; |
| 304 // Report the first error we found. | 327 // Report the first error we found. |
| 305 if (error) { | 328 if (error) { |
| 306 result = Status::IOError(filename_, strerror(error)); | 329 result = Status::IOError(filename_, strerror(error)); |
| 307 LogToUMA(kWritableFileSync); | 330 uma_logger_->RecordErrorAt(kWritableFileSync); |
| 308 } | 331 } |
| 309 return result; | 332 return result; |
| 310 } | 333 } |
| 311 }; | 334 }; |
| 312 | 335 |
| 313 class ChromiumFileLock : public FileLock { | 336 class ChromiumFileLock : public FileLock { |
| 314 public: | 337 public: |
| 315 ::base::PlatformFile file_; | 338 ::base::PlatformFile file_; |
| 316 }; | 339 }; |
| 317 | 340 |
| 318 class ChromiumEnv : public Env { | 341 class ChromiumEnv : public Env { |
| 319 public: | 342 public: |
| 320 ChromiumEnv(); | 343 ChromiumEnv(); |
| 321 virtual ~ChromiumEnv() { | 344 virtual ~ChromiumEnv() { |
| 322 NOTREACHED(); | 345 NOTREACHED(); |
| 323 } | 346 } |
| 324 | 347 |
| 325 virtual Status NewSequentialFile(const std::string& fname, | 348 virtual Status NewSequentialFile(const std::string& fname, |
| 326 SequentialFile** result) { | 349 SequentialFile** result) { |
| 327 FILE* f = fopen_internal(fname.c_str(), "rb"); | 350 FILE* f = fopen_internal(fname.c_str(), "rb"); |
| 328 if (f == NULL) { | 351 if (f == NULL) { |
| 329 *result = NULL; | 352 *result = NULL; |
| 330 LogToUMA(kNewSequentialFile); | 353 uma_logger_->RecordErrorAt(kNewSequentialFile); |
| 331 return Status::IOError(fname, strerror(errno)); | 354 return Status::IOError(fname, strerror(errno)); |
| 332 } else { | 355 } else { |
| 333 *result = new ChromiumSequentialFile(fname, f); | 356 *result = new ChromiumSequentialFile(fname, f, uma_logger_.get()); |
| 334 return Status::OK(); | 357 return Status::OK(); |
| 335 } | 358 } |
| 336 } | 359 } |
| 337 | 360 |
| 338 virtual Status NewRandomAccessFile(const std::string& fname, | 361 virtual Status NewRandomAccessFile(const std::string& fname, |
| 339 RandomAccessFile** result) { | 362 RandomAccessFile** result) { |
| 340 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; | 363 int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; |
| 341 bool created; | 364 bool created; |
| 342 ::base::PlatformFileError error_code; | 365 ::base::PlatformFileError error_code; |
| 343 ::base::PlatformFile file = ::base::CreatePlatformFile( | 366 ::base::PlatformFile file = ::base::CreatePlatformFile( |
| 344 CreateFilePath(fname), flags, &created, &error_code); | 367 CreateFilePath(fname), flags, &created, &error_code); |
| 345 if (error_code != ::base::PLATFORM_FILE_OK) { | 368 if (error_code != ::base::PLATFORM_FILE_OK) { |
| 346 *result = NULL; | 369 *result = NULL; |
| 347 LogToUMA(kNewRandomAccessFile); | 370 uma_logger_->RecordErrorAt(kNewRandomAccessFile); |
| 348 LogRandomAccessFileError(error_code); | 371 uma_logger_->LogRandomAccessFileError(error_code); |
| 349 return Status::IOError(fname, PlatformFileErrorString(error_code)); | 372 return Status::IOError(fname, PlatformFileErrorString(error_code)); |
| 350 } | 373 } |
| 351 *result = new ChromiumRandomAccessFile(fname, file); | 374 *result = new ChromiumRandomAccessFile(fname, file, uma_logger_.get()); |
| 352 return Status::OK(); | 375 return Status::OK(); |
| 353 } | 376 } |
| 354 | 377 |
| 355 virtual Status NewWritableFile(const std::string& fname, | 378 virtual Status NewWritableFile(const std::string& fname, |
| 356 WritableFile** result) { | 379 WritableFile** result) { |
| 357 *result = NULL; | 380 *result = NULL; |
| 358 FILE* f = fopen_internal(fname.c_str(), "wb"); | 381 FILE* f = fopen_internal(fname.c_str(), "wb"); |
| 359 if (f == NULL) { | 382 if (f == NULL) { |
| 360 LogToUMA(kNewWritableFile); | 383 uma_logger_->RecordErrorAt(kNewWritableFile); |
| 361 return Status::IOError(fname, strerror(errno)); | 384 return Status::IOError(fname, strerror(errno)); |
| 362 } else { | 385 } else { |
| 363 if (!sync_parent(fname)) { | 386 if (!sync_parent(fname)) { |
| 364 fclose(f); | 387 fclose(f); |
| 365 return Status::IOError(fname, strerror(errno)); | 388 return Status::IOError(fname, strerror(errno)); |
| 366 } | 389 } |
| 367 *result = new ChromiumWritableFile(fname, f); | 390 *result = new ChromiumWritableFile(fname, f, uma_logger_.get()); |
| 368 return Status::OK(); | 391 return Status::OK(); |
| 369 } | 392 } |
| 370 } | 393 } |
| 371 | 394 |
| 372 virtual bool FileExists(const std::string& fname) { | 395 virtual bool FileExists(const std::string& fname) { |
| 373 return ::file_util::PathExists(CreateFilePath(fname)); | 396 return ::file_util::PathExists(CreateFilePath(fname)); |
| 374 } | 397 } |
| 375 | 398 |
| 376 virtual Status GetChildren(const std::string& dir, | 399 virtual Status GetChildren(const std::string& dir, |
| 377 std::vector<std::string>* result) { | 400 std::vector<std::string>* result) { |
| 378 result->clear(); | 401 result->clear(); |
| 379 ::file_util::FileEnumerator iter( | 402 ::file_util::FileEnumerator iter( |
| 380 CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES); | 403 CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES); |
| 381 ::FilePath current = iter.Next(); | 404 ::FilePath current = iter.Next(); |
| 382 while (!current.empty()) { | 405 while (!current.empty()) { |
| 383 result->push_back(FilePathToString(current.BaseName())); | 406 result->push_back(FilePathToString(current.BaseName())); |
| 384 current = iter.Next(); | 407 current = iter.Next(); |
| 385 } | 408 } |
| 386 // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so | 409 // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so |
| 387 // we'll always return OK. Maybe manually check for error | 410 // we'll always return OK. Maybe manually check for error |
| 388 // conditions like the file not existing? | 411 // conditions like the file not existing? |
| 389 return Status::OK(); | 412 return Status::OK(); |
| 390 } | 413 } |
| 391 | 414 |
| 392 virtual Status DeleteFile(const std::string& fname) { | 415 virtual Status DeleteFile(const std::string& fname) { |
| 393 Status result; | 416 Status result; |
| 394 // TODO(jorlow): Should we assert this is a file? | 417 // TODO(jorlow): Should we assert this is a file? |
| 395 if (!::file_util::Delete(CreateFilePath(fname), false)) { | 418 if (!::file_util::Delete(CreateFilePath(fname), false)) { |
| 396 result = Status::IOError(fname, "Could not delete file."); | 419 result = Status::IOError(fname, "Could not delete file."); |
| 397 LogToUMA(kDeleteFile); | 420 uma_logger_->RecordErrorAt(kDeleteFile); |
| 398 } | 421 } |
| 399 return result; | 422 return result; |
| 400 }; | 423 }; |
| 401 | 424 |
| 402 virtual Status CreateDir(const std::string& name) { | 425 virtual Status CreateDir(const std::string& name) { |
| 403 Status result; | 426 Status result; |
| 404 if (!::file_util::CreateDirectory(CreateFilePath(name))) { | 427 if (!::file_util::CreateDirectory(CreateFilePath(name))) { |
| 405 result = Status::IOError(name, "Could not create directory."); | 428 result = Status::IOError(name, "Could not create directory."); |
| 406 LogToUMA(kCreateDir); | 429 uma_logger_->RecordErrorAt(kCreateDir); |
| 407 } | 430 } |
| 408 return result; | 431 return result; |
| 409 }; | 432 }; |
| 410 | 433 |
| 411 virtual Status DeleteDir(const std::string& name) { | 434 virtual Status DeleteDir(const std::string& name) { |
| 412 Status result; | 435 Status result; |
| 413 // TODO(jorlow): Should we assert this is a directory? | 436 // TODO(jorlow): Should we assert this is a directory? |
| 414 if (!::file_util::Delete(CreateFilePath(name), false)) { | 437 if (!::file_util::Delete(CreateFilePath(name), false)) { |
| 415 result = Status::IOError(name, "Could not delete directory."); | 438 result = Status::IOError(name, "Could not delete directory."); |
| 416 LogToUMA(kDeleteDir); | 439 uma_logger_->RecordErrorAt(kDeleteDir); |
| 417 } | 440 } |
| 418 return result; | 441 return result; |
| 419 }; | 442 }; |
| 420 | 443 |
| 421 virtual Status GetFileSize(const std::string& fname, uint64_t* size) { | 444 virtual Status GetFileSize(const std::string& fname, uint64_t* size) { |
| 422 Status s; | 445 Status s; |
| 423 int64_t signed_size; | 446 int64_t signed_size; |
| 424 if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { | 447 if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { |
| 425 *size = 0; | 448 *size = 0; |
| 426 s = Status::IOError(fname, "Could not determine file size."); | 449 s = Status::IOError(fname, "Could not determine file size."); |
| 427 LogToUMA(kGetFileSize); | 450 uma_logger_->RecordErrorAt(kGetFileSize); |
| 428 } else { | 451 } else { |
| 429 *size = static_cast<uint64_t>(signed_size); | 452 *size = static_cast<uint64_t>(signed_size); |
| 430 } | 453 } |
| 431 return s; | 454 return s; |
| 432 } | 455 } |
| 433 | 456 |
| 434 virtual Status RenameFile(const std::string& src, const std::string& dst) { | 457 virtual Status RenameFile(const std::string& src, const std::string& dst) { |
| 435 Status result; | 458 Status result; |
| 436 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { | 459 if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { |
| 437 result = Status::IOError(src, "Could not rename file."); | 460 result = Status::IOError(src, "Could not rename file."); |
| 438 LogToUMA(kRenamefile); | 461 uma_logger_->RecordErrorAt(kRenamefile); |
| 439 } else { | 462 } else { |
| 440 sync_parent(dst); | 463 sync_parent(dst); |
| 441 if (src != dst) | 464 if (src != dst) |
| 442 sync_parent(src); | 465 sync_parent(src); |
| 443 } | 466 } |
| 444 return result; | 467 return result; |
| 445 } | 468 } |
| 446 | 469 |
| 447 virtual Status LockFile(const std::string& fname, FileLock** lock) { | 470 virtual Status LockFile(const std::string& fname, FileLock** lock) { |
| 448 *lock = NULL; | 471 *lock = NULL; |
| 449 Status result; | 472 Status result; |
| 450 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | | 473 int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | |
| 451 ::base::PLATFORM_FILE_READ | | 474 ::base::PLATFORM_FILE_READ | |
| 452 ::base::PLATFORM_FILE_WRITE | | 475 ::base::PLATFORM_FILE_WRITE | |
| 453 ::base::PLATFORM_FILE_EXCLUSIVE_READ | | 476 ::base::PLATFORM_FILE_EXCLUSIVE_READ | |
| 454 ::base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 477 ::base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
| 455 bool created; | 478 bool created; |
| 456 ::base::PlatformFileError error_code; | 479 ::base::PlatformFileError error_code; |
| 457 ::base::PlatformFile file = ::base::CreatePlatformFile( | 480 ::base::PlatformFile file = ::base::CreatePlatformFile( |
| 458 CreateFilePath(fname), flags, &created, &error_code); | 481 CreateFilePath(fname), flags, &created, &error_code); |
| 459 if (error_code != ::base::PLATFORM_FILE_OK) { | 482 if (error_code != ::base::PLATFORM_FILE_OK) { |
| 460 result = Status::IOError(fname, PlatformFileErrorString(error_code)); | 483 result = Status::IOError(fname, PlatformFileErrorString(error_code)); |
| 461 LogToUMA(kLockFile); | 484 uma_logger_->RecordErrorAt(kLockFile); |
| 462 } else { | 485 } else { |
| 463 ChromiumFileLock* my_lock = new ChromiumFileLock; | 486 ChromiumFileLock* my_lock = new ChromiumFileLock; |
| 464 my_lock->file_ = file; | 487 my_lock->file_ = file; |
| 465 *lock = my_lock; | 488 *lock = my_lock; |
| 466 } | 489 } |
| 467 return result; | 490 return result; |
| 468 } | 491 } |
| 469 | 492 |
| 470 virtual Status UnlockFile(FileLock* lock) { | 493 virtual Status UnlockFile(FileLock* lock) { |
| 471 ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); | 494 ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); |
| 472 Status result; | 495 Status result; |
| 473 if (!::base::ClosePlatformFile(my_lock->file_)) { | 496 if (!::base::ClosePlatformFile(my_lock->file_)) { |
| 474 result = Status::IOError("Could not close lock file."); | 497 result = Status::IOError("Could not close lock file."); |
| 475 LogToUMA(kUnlockFile); | 498 uma_logger_->RecordErrorAt(kUnlockFile); |
| 476 } | 499 } |
| 477 delete my_lock; | 500 delete my_lock; |
| 478 return result; | 501 return result; |
| 479 } | 502 } |
| 480 | 503 |
| 481 virtual void Schedule(void (*function)(void*), void* arg); | 504 virtual void Schedule(void (*function)(void*), void* arg); |
| 482 | 505 |
| 483 virtual void StartThread(void (*function)(void* arg), void* arg); | 506 virtual void StartThread(void (*function)(void* arg), void* arg); |
| 484 | 507 |
| 485 virtual std::string UserIdentifier() { | 508 virtual std::string UserIdentifier() { |
| 486 #if defined(OS_WIN) | 509 #if defined(OS_WIN) |
| 487 std::wstring user_sid; | 510 std::wstring user_sid; |
| 488 bool ret = ::base::win::GetUserSidString(&user_sid); | 511 bool ret = ::base::win::GetUserSidString(&user_sid); |
| 489 DCHECK(ret); | 512 DCHECK(ret); |
| 490 return UTF16ToUTF8(user_sid); | 513 return UTF16ToUTF8(user_sid); |
| 491 #else | 514 #else |
| 492 char buf[100]; | 515 char buf[100]; |
| 493 snprintf(buf, sizeof(buf), "%d", int(geteuid())); | 516 snprintf(buf, sizeof(buf), "%d", int(geteuid())); |
| 494 return buf; | 517 return buf; |
| 495 #endif | 518 #endif |
| 496 } | 519 } |
| 497 | 520 |
| 498 virtual Status GetTestDirectory(std::string* path) { | 521 virtual Status GetTestDirectory(std::string* path) { |
| 499 mu_.Acquire(); | 522 mu_.Acquire(); |
| 500 if (test_directory_.empty()) { | 523 if (test_directory_.empty()) { |
| 501 if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, | 524 if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, |
| 502 &test_directory_)) { | 525 &test_directory_)) { |
| 503 mu_.Release(); | 526 mu_.Release(); |
| 504 LogToUMA(kGetTestDirectory); | 527 uma_logger_->RecordErrorAt(kGetTestDirectory); |
| 505 return Status::IOError("Could not create temp directory."); | 528 return Status::IOError("Could not create temp directory."); |
| 506 } | 529 } |
| 507 } | 530 } |
| 508 *path = FilePathToString(test_directory_); | 531 *path = FilePathToString(test_directory_); |
| 509 mu_.Release(); | 532 mu_.Release(); |
| 510 return Status::OK(); | 533 return Status::OK(); |
| 511 } | 534 } |
| 512 | 535 |
| 513 virtual Status NewLogger(const std::string& fname, Logger** result) { | 536 virtual Status NewLogger(const std::string& fname, Logger** result) { |
| 514 FILE* f = fopen_internal(fname.c_str(), "w"); | 537 FILE* f = fopen_internal(fname.c_str(), "w"); |
| 515 if (f == NULL) { | 538 if (f == NULL) { |
| 516 *result = NULL; | 539 *result = NULL; |
| 517 LogToUMA(kNewLogger); | 540 uma_logger_->RecordErrorAt(kNewLogger); |
| 518 return Status::IOError(fname, strerror(errno)); | 541 return Status::IOError(fname, strerror(errno)); |
| 519 } else { | 542 } else { |
| 520 if (!sync_parent(fname)) { | 543 if (!sync_parent(fname)) { |
| 521 fclose(f); | 544 fclose(f); |
| 522 return Status::IOError(fname, strerror(errno)); | 545 return Status::IOError(fname, strerror(errno)); |
| 523 } | 546 } |
| 524 *result = new ChromiumLogger(f); | 547 *result = new ChromiumLogger(f); |
| 525 return Status::OK(); | 548 return Status::OK(); |
| 526 } | 549 } |
| 527 } | 550 } |
| 528 | 551 |
| 529 virtual uint64_t NowMicros() { | 552 virtual uint64_t NowMicros() { |
| 530 return ::base::TimeTicks::Now().ToInternalValue(); | 553 return ::base::TimeTicks::Now().ToInternalValue(); |
| 531 } | 554 } |
| 532 | 555 |
| 533 virtual void SleepForMicroseconds(int micros) { | 556 virtual void SleepForMicroseconds(int micros) { |
| 534 // Round up to the next millisecond. | 557 // Round up to the next millisecond. |
| 535 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); | 558 ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); |
| 536 } | 559 } |
| 537 | 560 |
| 561 protected: |
| 562 scoped_ptr<UMALogger> uma_logger_; |
| 563 |
| 538 private: | 564 private: |
| 539 // BGThread() is the body of the background thread | 565 // BGThread() is the body of the background thread |
| 540 void BGThread(); | 566 void BGThread(); |
| 541 static void BGThreadWrapper(void* arg) { | 567 static void BGThreadWrapper(void* arg) { |
| 542 reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); | 568 reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); |
| 543 } | 569 } |
| 544 | 570 |
| 545 FilePath test_directory_; | 571 FilePath test_directory_; |
| 546 | 572 |
| 547 size_t page_size_; | 573 size_t page_size_; |
| 548 ::base::Lock mu_; | 574 ::base::Lock mu_; |
| 549 ::base::ConditionVariable bgsignal_; | 575 ::base::ConditionVariable bgsignal_; |
| 550 bool started_bgthread_; | 576 bool started_bgthread_; |
| 551 | 577 |
| 552 // Entry per Schedule() call | 578 // Entry per Schedule() call |
| 553 struct BGItem { void* arg; void (*function)(void*); }; | 579 struct BGItem { void* arg; void (*function)(void*); }; |
| 554 typedef std::deque<BGItem> BGQueue; | 580 typedef std::deque<BGItem> BGQueue; |
| 555 BGQueue queue_; | 581 BGQueue queue_; |
| 556 }; | 582 }; |
| 557 | 583 |
| 558 ChromiumEnv::ChromiumEnv() | 584 ChromiumEnv::ChromiumEnv() |
| 559 : page_size_(::base::SysInfo::VMAllocationGranularity()), | 585 : page_size_(::base::SysInfo::VMAllocationGranularity()), |
| 560 bgsignal_(&mu_), | 586 bgsignal_(&mu_), |
| 561 started_bgthread_(false) { | 587 started_bgthread_(false), |
| 588 uma_logger_(new UMALogger("LevelDBEnv")) { |
| 562 } | 589 } |
| 563 | 590 |
| 564 class Thread : public ::base::PlatformThread::Delegate { | 591 class Thread : public ::base::PlatformThread::Delegate { |
| 565 public: | 592 public: |
| 566 Thread(void (*function)(void* arg), void* arg) | 593 Thread(void (*function)(void* arg), void* arg) |
| 567 : function_(function), arg_(arg) { | 594 : function_(function), arg_(arg) { |
| 568 ::base::PlatformThreadHandle handle; | 595 ::base::PlatformThreadHandle handle; |
| 569 bool success = ::base::PlatformThread::Create(0, this, &handle); | 596 bool success = ::base::PlatformThread::Create(0, this, &handle); |
| 570 DCHECK(success); | 597 DCHECK(success); |
| 571 } | 598 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 | 644 |
| 618 mu_.Release(); | 645 mu_.Release(); |
| 619 (*function)(arg); | 646 (*function)(arg); |
| 620 } | 647 } |
| 621 } | 648 } |
| 622 | 649 |
| 623 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { | 650 void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { |
| 624 new Thread(function, arg); // Will self-delete. | 651 new Thread(function, arg); // Will self-delete. |
| 625 } | 652 } |
| 626 | 653 |
| 654 class IDBEnv : public ChromiumEnv { |
| 655 public: |
| 656 IDBEnv() : ChromiumEnv() { |
| 657 uma_logger_.reset(new UMALogger("LevelDBEnv.IDB")); |
| 658 } |
| 659 }; |
| 660 |
| 661 ::base::LazyInstance<IDBEnv>::Leaky |
| 662 idb_env = LAZY_INSTANCE_INITIALIZER; |
| 663 |
| 627 ::base::LazyInstance<ChromiumEnv>::Leaky | 664 ::base::LazyInstance<ChromiumEnv>::Leaky |
| 628 default_env = LAZY_INSTANCE_INITIALIZER; | 665 default_env = LAZY_INSTANCE_INITIALIZER; |
| 629 | 666 |
| 630 } | 667 } |
| 631 | 668 |
| 669 Env* IDBEnv() { |
| 670 return idb_env.Pointer(); |
| 671 } |
| 672 |
| 632 Env* Env::Default() { | 673 Env* Env::Default() { |
| 633 return default_env.Pointer(); | 674 return default_env.Pointer(); |
| 634 } | 675 } |
| 635 | 676 |
| 636 } | 677 } |
| OLD | NEW |