Line data Source code
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 384 : PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
25 384 : virtual ~PosixLogger() {
26 192 : fclose(file_);
27 192 : }
28 695 : virtual void Logv(const char* format, va_list ap) {
29 695 : 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 695 : for (int iter = 0; iter < 2; iter++) {
35 : char* base;
36 : int bufsize;
37 695 : if (iter == 0) {
38 : bufsize = sizeof(buffer);
39 : base = buffer;
40 : } else {
41 0 : bufsize = 30000;
42 0 : base = new char[bufsize];
43 : }
44 695 : char* p = base;
45 695 : char* limit = base + bufsize;
46 :
47 : struct timeval now_tv;
48 695 : gettimeofday(&now_tv, NULL);
49 695 : const time_t seconds = now_tv.tv_sec;
50 : struct tm t;
51 695 : localtime_r(&seconds, &t);
52 1390 : 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 2085 : static_cast<long long unsigned int>(thread_id));
62 :
63 : // Print the message
64 695 : if (p < limit) {
65 : va_list backup_ap;
66 695 : va_copy(backup_ap, ap);
67 1390 : p += vsnprintf(p, limit - p, format, backup_ap);
68 695 : va_end(backup_ap);
69 : }
70 :
71 : // Truncate to available space if necessary
72 695 : if (p >= limit) {
73 0 : if (iter == 0) {
74 0 : continue; // Try again with larger buffer
75 : } else {
76 0 : p = limit - 1;
77 : }
78 : }
79 :
80 : // Add newline if necessary
81 695 : if (p == base || p[-1] != '\n') {
82 373 : *p++ = '\n';
83 : }
84 :
85 695 : assert(p <= limit);
86 695 : fwrite(base, 1, p - base, file_);
87 695 : fflush(file_);
88 695 : if (base != buffer) {
89 0 : delete[] base;
90 : }
91 695 : break;
92 : }
93 695 : }
94 : };
95 :
96 : } // namespace leveldb
97 :
98 : #endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
|