You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 line
2.7 KiB

  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
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. //
  5. // Logger implementation that can be shared by all environments
  6. // where enough posix functionality is available.
  7. #ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
  8. #define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
  9. #include <algorithm>
  10. #include <stdio.h>
  11. #include <sys/time.h>
  12. #include <time.h>
  13. #include "leveldb/env.h"
  14. namespace leveldb {
  15. class PosixLogger : public Logger {
  16. private:
  17. FILE* file_;
  18. uint64_t (*gettid_)(); // Return the thread id for the current thread
  19. public:
  20. PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
  21. virtual ~PosixLogger() {
  22. fclose(file_);
  23. }
  24. virtual void Logv(const char* format, va_list ap) {
  25. const uint64_t thread_id = (*gettid_)();
  26. // We try twice: the first time with a fixed-size stack allocated buffer,
  27. // and the second time with a much larger dynamically allocated buffer.
  28. char buffer[500];
  29. for (int iter = 0; iter < 2; iter++) {
  30. char* base;
  31. int bufsize;
  32. if (iter == 0) {
  33. bufsize = sizeof(buffer);
  34. base = buffer;
  35. } else {
  36. bufsize = 30000;
  37. base = new char[bufsize];
  38. }
  39. char* p = base;
  40. char* limit = base + bufsize;
  41. struct timeval now_tv;
  42. gettimeofday(&now_tv, NULL);
  43. const time_t seconds = now_tv.tv_sec;
  44. struct tm t;
  45. localtime_r(&seconds, &t);
  46. p += snprintf(p, limit - p,
  47. "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
  48. t.tm_year + 1900,
  49. t.tm_mon + 1,
  50. t.tm_mday,
  51. t.tm_hour,
  52. t.tm_min,
  53. t.tm_sec,
  54. static_cast<int>(now_tv.tv_usec),
  55. static_cast<long long unsigned int>(thread_id));
  56. // Print the message
  57. if (p < limit) {
  58. va_list backup_ap;
  59. va_copy(backup_ap, ap);
  60. p += vsnprintf(p, limit - p, format, backup_ap);
  61. va_end(backup_ap);
  62. }
  63. // Truncate to available space if necessary
  64. if (p >= limit) {
  65. if (iter == 0) {
  66. continue; // Try again with larger buffer
  67. } else {
  68. p = limit - 1;
  69. }
  70. }
  71. // Add newline if necessary
  72. if (p == base || p[-1] != '\n') {
  73. *p++ = '\n';
  74. }
  75. assert(p <= limit);
  76. fwrite(base, 1, p - base, file_);
  77. fflush(file_);
  78. if (base != buffer) {
  79. delete[] base;
  80. }
  81. break;
  82. }
  83. }
  84. };
  85. } // namespace leveldb
  86. #endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_