LCOV - code coverage report
Current view: top level - src/leveldb/util - posix_logger.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 62 0.0 %
Date: 2022-04-21 14:51:19 Functions: 0 3 0.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 0 16 0.0 %

           Branch data     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 <sys/time.h>
#      12                 :            : 
#      13                 :            : #include <cassert>
#      14                 :            : #include <cstdarg>
#      15                 :            : #include <cstdio>
#      16                 :            : #include <ctime>
#      17                 :            : #include <sstream>
#      18                 :            : #include <thread>
#      19                 :            : 
#      20                 :            : #include "leveldb/env.h"
#      21                 :            : 
#      22                 :            : namespace leveldb {
#      23                 :            : 
#      24                 :            : class PosixLogger final : public Logger {
#      25                 :            :  public:
#      26                 :            :   // Creates a logger that writes to the given file.
#      27                 :            :   //
#      28                 :            :   // The PosixLogger instance takes ownership of the file handle.
#      29                 :          0 :   explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); }
#      30                 :            : 
#      31                 :          0 :   ~PosixLogger() override { std::fclose(fp_); }
#      32                 :            : 
#      33                 :          0 :   void Logv(const char* format, va_list arguments) override {
#      34                 :            :     // Record the time as close to the Logv() call as possible.
#      35                 :          0 :     struct ::timeval now_timeval;
#      36                 :          0 :     ::gettimeofday(&now_timeval, nullptr);
#      37                 :          0 :     const std::time_t now_seconds = now_timeval.tv_sec;
#      38                 :          0 :     struct std::tm now_components;
#      39                 :          0 :     ::localtime_r(&now_seconds, &now_components);
#      40                 :            : 
#      41                 :            :     // Record the thread ID.
#      42                 :          0 :     constexpr const int kMaxThreadIdSize = 32;
#      43                 :          0 :     std::ostringstream thread_stream;
#      44                 :          0 :     thread_stream << std::this_thread::get_id();
#      45                 :          0 :     std::string thread_id = thread_stream.str();
#      46         [ #  # ]:          0 :     if (thread_id.size() > kMaxThreadIdSize) {
#      47                 :          0 :       thread_id.resize(kMaxThreadIdSize);
#      48                 :          0 :     }
#      49                 :            : 
#      50                 :            :     // We first attempt to print into a stack-allocated buffer. If this attempt
#      51                 :            :     // fails, we make a second attempt with a dynamically allocated buffer.
#      52                 :          0 :     constexpr const int kStackBufferSize = 512;
#      53                 :          0 :     char stack_buffer[kStackBufferSize];
#      54                 :          0 :     static_assert(sizeof(stack_buffer) == static_cast<size_t>(kStackBufferSize),
#      55                 :          0 :                   "sizeof(char) is expected to be 1 in C++");
#      56                 :            : 
#      57                 :          0 :     int dynamic_buffer_size = 0;  // Computed in the first iteration.
#      58         [ #  # ]:          0 :     for (int iteration = 0; iteration < 2; ++iteration) {
#      59                 :          0 :       const int buffer_size =
#      60         [ #  # ]:          0 :           (iteration == 0) ? kStackBufferSize : dynamic_buffer_size;
#      61                 :          0 :       char* const buffer =
#      62         [ #  # ]:          0 :           (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size];
#      63                 :            : 
#      64                 :            :       // Print the header into the buffer.
#      65                 :          0 :       int buffer_offset = snprintf(
#      66                 :          0 :           buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ",
#      67                 :          0 :           now_components.tm_year + 1900, now_components.tm_mon + 1,
#      68                 :          0 :           now_components.tm_mday, now_components.tm_hour, now_components.tm_min,
#      69                 :          0 :           now_components.tm_sec, static_cast<int>(now_timeval.tv_usec),
#      70                 :          0 :           thread_id.c_str());
#      71                 :            : 
#      72                 :            :       // The header can be at most 28 characters (10 date + 15 time +
#      73                 :            :       // 3 delimiters) plus the thread ID, which should fit comfortably into the
#      74                 :            :       // static buffer.
#      75                 :          0 :       assert(buffer_offset <= 28 + kMaxThreadIdSize);
#      76                 :          0 :       static_assert(28 + kMaxThreadIdSize < kStackBufferSize,
#      77                 :          0 :                     "stack-allocated buffer may not fit the message header");
#      78                 :          0 :       assert(buffer_offset < buffer_size);
#      79                 :            : 
#      80                 :            :       // Print the message into the buffer.
#      81                 :          0 :       std::va_list arguments_copy;
#      82                 :          0 :       va_copy(arguments_copy, arguments);
#      83                 :          0 :       buffer_offset +=
#      84                 :          0 :           std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset,
#      85                 :          0 :                          format, arguments_copy);
#      86                 :          0 :       va_end(arguments_copy);
#      87                 :            : 
#      88                 :            :       // The code below may append a newline at the end of the buffer, which
#      89                 :            :       // requires an extra character.
#      90         [ #  # ]:          0 :       if (buffer_offset >= buffer_size - 1) {
#      91                 :            :         // The message did not fit into the buffer.
#      92         [ #  # ]:          0 :         if (iteration == 0) {
#      93                 :            :           // Re-run the loop and use a dynamically-allocated buffer. The buffer
#      94                 :            :           // will be large enough for the log message, an extra newline and a
#      95                 :            :           // null terminator.
#      96                 :          0 :           dynamic_buffer_size = buffer_offset + 2;
#      97                 :          0 :           continue;
#      98                 :          0 :         }
#      99                 :            : 
#     100                 :            :         // The dynamically-allocated buffer was incorrectly sized. This should
#     101                 :            :         // not happen, assuming a correct implementation of (v)snprintf. Fail
#     102                 :            :         // in tests, recover by truncating the log message in production.
#     103                 :          0 :         assert(false);
#     104                 :          0 :         buffer_offset = buffer_size - 1;
#     105                 :          0 :       }
#     106                 :            : 
#     107                 :            :       // Add a newline if necessary.
#     108         [ #  # ]:          0 :       if (buffer[buffer_offset - 1] != '\n') {
#     109                 :          0 :         buffer[buffer_offset] = '\n';
#     110                 :          0 :         ++buffer_offset;
#     111                 :          0 :       }
#     112                 :            : 
#     113                 :          0 :       assert(buffer_offset <= buffer_size);
#     114                 :          0 :       std::fwrite(buffer, 1, buffer_offset, fp_);
#     115                 :          0 :       std::fflush(fp_);
#     116                 :            : 
#     117         [ #  # ]:          0 :       if (iteration != 0) {
#     118                 :          0 :         delete[] buffer;
#     119                 :          0 :       }
#     120                 :          0 :       break;
#     121                 :          0 :     }
#     122                 :          0 :   }
#     123                 :            : 
#     124                 :            :  private:
#     125                 :            :   std::FILE* const fp_;
#     126                 :            : };
#     127                 :            : 
#     128                 :            : }  // namespace leveldb
#     129                 :            : 
#     130                 :            : #endif  // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a