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

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

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

Powered by Google App Engine
This is Rietveld 408576698