clang 23.0.0git
AtomicLineLogger.cpp
Go to the documentation of this file.
1//===- AtomicLineLogger.cpp -----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the implementation of an AtomicLineLogger and the relevant
10// supporting classes.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/StringRef.h"
16#include "llvm/Support/Errno.h"
17#include "llvm/Support/FileSystem.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/Process.h"
20#include "llvm/Support/Threading.h"
21#ifndef _WIN32
22#include <unistd.h>
23#endif
24#ifdef __APPLE__
25#include <sys/time.h>
26#endif
27
28using namespace clang;
29
30static uint64_t getTimestampMillis() {
31#ifdef __APPLE__
32 // Using chrono is roughly 50% slower.
33 struct timeval T;
34 gettimeofday(&T, 0);
35 return T.tv_sec * 1000 + T.tv_usec / 1000;
36#else
37 auto Time = std::chrono::system_clock::now();
38 auto Millis = std::chrono::duration_cast<std::chrono::milliseconds>(
39 Time.time_since_epoch());
40 return Millis.count();
41#endif
42}
43
44// Writes the whole line into an FD that is opened with OF_Append.
45// This function only does one write (up to retry due to interrupts), and the
46// single write is blocking and atomic on POSIX systems.
47static bool writeLineToFD(int FD, const char *Data, size_t Size) {
48#ifndef _WIN32
49 ssize_t Written = llvm::sys::RetryAfterSignal(-1, write, FD, Data, Size);
50 return Written >= 0 && (static_cast<size_t>(Written) == Size);
51#else
52 (void)FD, (void)Data, (void)Size;
53 llvm_unreachable("Logging not supported on Windows!");
54 return false;
55#endif
56}
57
58LogLine::LogLine(int FD, std::atomic<uint64_t> *DroppedLines)
59 : FormattingOS(Buffer), FD(FD), DroppedLines(DroppedLines) {
60 auto Millis = getTimestampMillis();
61 *FormattingOS << llvm::format("[%lld.%0.3lld]", Millis / 1000, Millis % 1000);
62 *FormattingOS << ' ' << llvm::sys::Process::getProcessId() << ' '
63 << llvm::get_threadid() << ": ";
64}
65
67 : Buffer(std::move(Other.Buffer)), FD(Other.FD),
68 DroppedLines(Other.DroppedLines) {
69 if (Other.FormattingOS)
70 FormattingOS.emplace(Buffer);
71
72 // Destroy the info in Other so its destructor does not write out the line.
73 Other.FormattingOS.reset();
74 Other.FD = -1;
75 Other.DroppedLines = nullptr;
76}
77
79 if (!FormattingOS)
80 return;
81 *FormattingOS << "\n";
82 if (!writeLineToFD(FD, Buffer.data(), Buffer.size()))
83 DroppedLines->fetch_add(1, std::memory_order_relaxed);
84}
85
87 : LogPath(LogFilePath.str()) {
88#ifndef _WIN32
89 if (LogFilePath.empty())
90 return;
91
92 std::error_code EC = llvm::sys::fs::openFileForWrite(
93 LogFilePath, FD, llvm::sys::fs::CD_OpenAlways, llvm::sys::fs::OF_Append);
94 if (EC) {
95 llvm::errs() << "warning: unable to open log file '" << LogFilePath
96 << "': " << EC.message() << "\n";
97 FD = -1;
98 return;
99 }
100#endif
101 // Write to files opened with OF_Append may not be guaranteed to be atomic
102 // on Windows, so we do not enable logging on Windows.
103}
104
106 if (FD != -1)
107 return LogLine(FD, &DroppedLines);
108 return LogLine();
109}
110
112 if (FD == -1)
113 return;
114 if (uint64_t Dropped = DroppedLines.load(std::memory_order_relaxed))
115 llvm::errs() << "warning: log '" << LogPath
116 << "' is incomplete: " << Dropped
117 << " line(s) dropped due to write errors\n";
118 llvm::sys::Process::SafelyCloseFileDescriptor(FD);
119}
static bool writeLineToFD(int FD, const char *Data, size_t Size)
static uint64_t getTimestampMillis()
Defines a logger where each line is written atomically to the file.
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ Other
Other implicit parameter.
Definition Decl.h:1774