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