]>
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.
13 #include "port/win/win_logger.h"
14 #include "port/win/io_win.h"
22 #include "rocksdb/env.h"
24 #include "monitoring/iostats_context_imp.h"
25 #include "port/sys_time.h"
31 WinLogger::WinLogger(uint64_t (*gettid
)(), Env
* env
, HANDLE file
,
32 const InfoLogLevel log_level
)
37 last_flush_micros_(0),
39 flush_pending_(false) {
40 assert(file_
!= NULL
);
41 assert(file_
!= INVALID_HANDLE_VALUE
);
44 void WinLogger::DebugWriter(const char* str
, int len
) {
45 assert(file_
!= INVALID_HANDLE_VALUE
);
46 DWORD bytesWritten
= 0;
47 BOOL ret
= WriteFile(file_
, str
, len
, &bytesWritten
, NULL
);
49 std::string errSz
= GetWindowsErrSz(GetLastError());
50 fprintf(stderr
, errSz
.c_str());
54 WinLogger::~WinLogger() {
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() ",
71 ret
= CloseHandle(file_
);
72 // On error the return value is zero
73 if (ret
== 0 && s
.ok()) {
74 auto lastError
= GetLastError();
75 s
= IOErrorFromWindowsError("Failed to flush LOG on Close() ",
78 file_
= INVALID_HANDLE_VALUE
;
84 void WinLogger::Flush() {
85 assert(file_
!= INVALID_HANDLE_VALUE
);
87 flush_pending_
= false;
88 // With Windows API writes go to OS buffers directly so no fflush needed
89 // unlike with C runtime API. We don't flush all the way to disk
93 last_flush_micros_
= env_
->NowMicros();
96 void WinLogger::Logv(const char* format
, va_list ap
) {
97 IOSTATS_TIMER_GUARD(logger_nanos
);
98 assert(file_
!= INVALID_HANDLE_VALUE
);
100 const uint64_t thread_id
= (*gettid_
)();
102 // We try twice: the first time with a fixed-size stack allocated buffer,
103 // and the second time with a much larger dynamically allocated buffer.
105 std::unique_ptr
<char[]> largeBuffer
;
106 for (int iter
= 0; iter
< 2; ++iter
) {
110 bufsize
= sizeof(buffer
);
114 largeBuffer
.reset(new char[bufsize
]);
115 base
= largeBuffer
.get();
119 char* limit
= base
+ bufsize
;
121 struct timeval now_tv
;
122 gettimeofday(&now_tv
, nullptr);
123 const time_t seconds
= now_tv
.tv_sec
;
125 localtime_s(&t
, &seconds
);
126 p
+= snprintf(p
, limit
- p
, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
127 t
.tm_year
+ 1900, t
.tm_mon
+ 1, t
.tm_mday
, t
.tm_hour
,
128 t
.tm_min
, t
.tm_sec
, static_cast<int>(now_tv
.tv_usec
),
129 static_cast<long long unsigned int>(thread_id
));
134 va_copy(backup_ap
, ap
);
135 int done
= vsnprintf(p
, limit
- p
, format
, backup_ap
);
144 // Truncate to available space if necessary
147 continue; // Try again with larger buffer
153 // Add newline if necessary
154 if (p
== base
|| p
[-1] != '\n') {
159 const size_t write_size
= p
- base
;
161 DWORD bytesWritten
= 0;
162 BOOL ret
= WriteFile(file_
, base
, static_cast<DWORD
>(write_size
),
163 &bytesWritten
, NULL
);
165 std::string errSz
= GetWindowsErrSz(GetLastError());
166 fprintf(stderr
, errSz
.c_str());
169 flush_pending_
= true;
170 assert((bytesWritten
== write_size
) || (ret
== FALSE
));
171 if (bytesWritten
> 0) {
172 log_size_
+= write_size
;
175 uint64_t now_micros
=
176 static_cast<uint64_t>(now_tv
.tv_sec
) * 1000000 + now_tv
.tv_usec
;
177 if (now_micros
- last_flush_micros_
>= flush_every_seconds_
* 1000000) {
178 flush_pending_
= false;
179 // With Windows API writes go to OS buffers directly so no fflush needed
180 // unlike with C runtime API. We don't flush all the way to disk
182 last_flush_micros_
= now_micros
;
188 size_t WinLogger::GetLogFileSize() const { return log_size_
; }
192 } // namespace rocksdb