1 // Copyright (c) 2012 The Chromium 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. 4 5 #ifndef THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_ 6 #define THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_ 7 8 #include <stdio.h> 9 10 #include <algorithm> 11 12 #include "base/format_macros.h" 13 #include "base/strings/string_util.h" 14 #include "base/time/time.h" 15 #include "third_party/leveldatabase/src/include/leveldb/env.h" 16 17 namespace leveldb { 18 19 class ChromiumLogger : public Logger { 20 public: 21 explicit ChromiumLogger(FILE* f) : file_(f) {} 22 virtual ~ChromiumLogger() { 23 fclose(file_); 24 } 25 virtual void Logv(const char* format, va_list ap) { 26 const base::PlatformThreadId thread_id = 27 ::base::PlatformThread::CurrentId(); 28 29 // We try twice: the first time with a fixed-size stack allocated buffer, 30 // and the second time with a much larger dynamically allocated buffer. 31 char buffer[500]; 32 for (int iter = 0; iter < 2; iter++) { 33 char* base; 34 int bufsize; 35 if (iter == 0) { 36 bufsize = sizeof(buffer); 37 base = buffer; 38 } else { 39 bufsize = 30000; 40 base = new char[bufsize]; 41 } 42 char* p = base; 43 char* limit = base + bufsize; 44 45 ::base::Time::Exploded t; 46 ::base::Time::Now().LocalExplode(&t); 47 48 p += ::base::snprintf(p, limit - p, 49 "%04d/%02d/%02d-%02d:%02d:%02d.%03d %" PRIu64 " ", 50 t.year, 51 t.month, 52 t.day_of_month, 53 t.hour, 54 t.minute, 55 t.second, 56 t.millisecond, 57 static_cast<uint64>(thread_id)); 58 59 // Print the message 60 if (p < limit) { 61 va_list backup_ap; 62 GG_VA_COPY(backup_ap, ap); 63 p += vsnprintf(p, limit - p, format, backup_ap); 64 va_end(backup_ap); 65 } 66 67 // Truncate to available space if necessary 68 if (p >= limit) { 69 if (iter == 0) { 70 continue; // Try again with larger buffer 71 } else { 72 p = limit - 1; 73 } 74 } 75 76 // Add newline if necessary 77 if (p == base || p[-1] != '\n') { 78 *p++ = '\n'; 79 } 80 81 assert(p <= limit); 82 fwrite(base, 1, p - base, file_); 83 fflush(file_); 84 if (base != buffer) { 85 delete[] base; 86 } 87 break; 88 } 89 } 90 91 private: 92 FILE* file_; 93 }; 94 95 } // namespace leveldb 96 97 #endif // THIRD_PARTY_LEVELDATABASE_CHROMIUM_LOGGER_H_ 98