]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/port/win/win_logger.cc
1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
6 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
7 // Use of this source code is governed by a BSD-style license that can be
8 // found in the LICENSE file. See the AUTHORS file for names of contributors.
10 // Logger implementation that can be shared by all environments
11 // where enough posix functionality is available.
15 #include "port/win/win_logger.h"
16 #include "port/win/io_win.h"
24 #include "rocksdb/env.h"
26 #include "monitoring/iostats_context_imp.h"
27 #include "port/sys_time.h"
29 namespace ROCKSDB_NAMESPACE
{
33 WinLogger::WinLogger(uint64_t (*gettid
)(), Env
* env
, HANDLE file
,
34 const InfoLogLevel log_level
)
39 last_flush_micros_(0),
41 flush_pending_(false) {
42 assert(file_
!= NULL
);
43 assert(file_
!= INVALID_HANDLE_VALUE
);
46 void WinLogger::DebugWriter(const char* str
, int len
) {
47 assert(file_
!= INVALID_HANDLE_VALUE
);
48 DWORD bytesWritten
= 0;
49 BOOL ret
= WriteFile(file_
, str
, len
, &bytesWritten
, NULL
);
51 std::string errSz
= GetWindowsErrSz(GetLastError());
52 fprintf(stderr
, "%s", errSz
.c_str());
56 WinLogger::~WinLogger() { CloseInternal(); }
58 Status
WinLogger::CloseImpl() {
59 return CloseInternal();
62 Status
WinLogger::CloseInternal() {
64 if (INVALID_HANDLE_VALUE
!= file_
) {
65 BOOL ret
= FlushFileBuffers(file_
);
67 auto lastError
= GetLastError();
68 s
= IOErrorFromWindowsError("Failed to flush LOG on Close() ", lastError
);
70 ret
= CloseHandle(file_
);
71 // On error the return value is zero
72 if (ret
== 0 && s
.ok()) {
73 auto lastError
= GetLastError();
74 s
= IOErrorFromWindowsError("Failed to flush LOG on Close() ", lastError
);
76 file_
= INVALID_HANDLE_VALUE
;
82 void WinLogger::Flush() {
83 assert(file_
!= INVALID_HANDLE_VALUE
);
85 flush_pending_
= false;
86 // With Windows API writes go to OS buffers directly so no fflush needed
87 // unlike with C runtime API. We don't flush all the way to disk
91 last_flush_micros_
= env_
->NowMicros();
94 void WinLogger::Logv(const char* format
, va_list ap
) {
95 IOSTATS_TIMER_GUARD(logger_nanos
);
96 assert(file_
!= INVALID_HANDLE_VALUE
);
98 const uint64_t thread_id
= (*gettid_
)();
100 // We try twice: the first time with a fixed-size stack allocated buffer,
101 // and the second time with a much larger dynamically allocated buffer.
103 std::unique_ptr
<char[]> largeBuffer
;
104 for (int iter
= 0; iter
< 2; ++iter
) {
108 bufsize
= sizeof(buffer
);
112 largeBuffer
.reset(new char[bufsize
]);
113 base
= largeBuffer
.get();
117 char* limit
= base
+ bufsize
;
119 struct timeval now_tv
;
120 gettimeofday(&now_tv
, nullptr);
121 const time_t seconds
= now_tv
.tv_sec
;
123 localtime_s(&t
, &seconds
);
124 p
+= snprintf(p
, limit
- p
, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
125 t
.tm_year
+ 1900, t
.tm_mon
+ 1, t
.tm_mday
, t
.tm_hour
,
126 t
.tm_min
, t
.tm_sec
, static_cast<int>(now_tv
.tv_usec
),
127 static_cast<long long unsigned int>(thread_id
));
132 va_copy(backup_ap
, ap
);
133 int done
= vsnprintf(p
, limit
- p
, format
, backup_ap
);
142 // Truncate to available space if necessary
145 continue; // Try again with larger buffer
151 // Add newline if necessary
152 if (p
== base
|| p
[-1] != '\n') {
157 const size_t write_size
= p
- base
;
159 DWORD bytesWritten
= 0;
160 BOOL ret
= WriteFile(file_
, base
, static_cast<DWORD
>(write_size
),
161 &bytesWritten
, NULL
);
163 std::string errSz
= GetWindowsErrSz(GetLastError());
164 fprintf(stderr
, "%s", errSz
.c_str());
167 flush_pending_
= true;
168 assert((bytesWritten
== write_size
) || (ret
== FALSE
));
169 if (bytesWritten
> 0) {
170 log_size_
+= write_size
;
173 uint64_t now_micros
=
174 static_cast<uint64_t>(now_tv
.tv_sec
) * 1000000 + now_tv
.tv_usec
;
175 if (now_micros
- last_flush_micros_
>= flush_every_seconds_
* 1000000) {
176 flush_pending_
= false;
177 // With Windows API writes go to OS buffers directly so no fflush needed
178 // unlike with C runtime API. We don't flush all the way to disk
180 last_flush_micros_
= now_micros
;
186 size_t WinLogger::GetLogFileSize() const { return log_size_
; }
190 } // namespace ROCKSDB_NAMESPACE