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 |