1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2017 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BASE_MONITORING_H_
17*14675a02SAndroid Build Coastguard Worker #define FCP_BASE_MONITORING_H_
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include <string>
20*14675a02SAndroid Build Coastguard Worker #include <utility>
21*14675a02SAndroid Build Coastguard Worker
22*14675a02SAndroid Build Coastguard Worker #include "fcp/base/new.h"
23*14675a02SAndroid Build Coastguard Worker
24*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/string_stream.h"
26*14675a02SAndroid Build Coastguard Worker #else
27*14675a02SAndroid Build Coastguard Worker #include <cstdlib>
28*14675a02SAndroid Build Coastguard Worker #include <iostream>
29*14675a02SAndroid Build Coastguard Worker #include <ostream>
30*14675a02SAndroid Build Coastguard Worker #include <sstream>
31*14675a02SAndroid Build Coastguard Worker
32*14675a02SAndroid Build Coastguard Worker #include "absl/base/attributes.h"
33*14675a02SAndroid Build Coastguard Worker #include "absl/base/log_severity.h"
34*14675a02SAndroid Build Coastguard Worker #include "absl/base/optimization.h"
35*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h"
36*14675a02SAndroid Build Coastguard Worker #include "absl/status/statusor.h"
37*14675a02SAndroid Build Coastguard Worker #endif // FCP_BAREMETAL
38*14675a02SAndroid Build Coastguard Worker
39*14675a02SAndroid Build Coastguard Worker namespace fcp {
40*14675a02SAndroid Build Coastguard Worker
41*14675a02SAndroid Build Coastguard Worker // General Definitions
42*14675a02SAndroid Build Coastguard Worker // ===================
43*14675a02SAndroid Build Coastguard Worker
44*14675a02SAndroid Build Coastguard Worker /**
45*14675a02SAndroid Build Coastguard Worker * Indicates to run the functionality in this file in debugging mode. This
46*14675a02SAndroid Build Coastguard Worker * creates more exhaustive diagnostics in some cases, as documented case by
47*14675a02SAndroid Build Coastguard Worker * case.
48*14675a02SAndroid Build Coastguard Worker *
49*14675a02SAndroid Build Coastguard Worker * We may want to make this a flag if this turns out to be often needed.
50*14675a02SAndroid Build Coastguard Worker */
51*14675a02SAndroid Build Coastguard Worker constexpr bool fcp_debug = false;
52*14675a02SAndroid Build Coastguard Worker
53*14675a02SAndroid Build Coastguard Worker // Logging and Assertions
54*14675a02SAndroid Build Coastguard Worker // ======================
55*14675a02SAndroid Build Coastguard Worker
56*14675a02SAndroid Build Coastguard Worker /**
57*14675a02SAndroid Build Coastguard Worker * Defines a subset of Google style logging. Use FCP_LOG(INFO),
58*14675a02SAndroid Build Coastguard Worker * FCP_LOG(WARNING), FCP_LOG(ERROR) or FCP_LOG(FATAL) to stream log messages.
59*14675a02SAndroid Build Coastguard Worker * Example:
60*14675a02SAndroid Build Coastguard Worker *
61*14675a02SAndroid Build Coastguard Worker * FCP_LOG(INFO) << "some info log";
62*14675a02SAndroid Build Coastguard Worker */
63*14675a02SAndroid Build Coastguard Worker // TODO(team): adapt to absl logging once available
64*14675a02SAndroid Build Coastguard Worker #define FCP_LOG(severity) _FCP_LOG_##severity
65*14675a02SAndroid Build Coastguard Worker
66*14675a02SAndroid Build Coastguard Worker #define FCP_LOG_IF(severity, condition) \
67*14675a02SAndroid Build Coastguard Worker !(condition) ? (void)0 \
68*14675a02SAndroid Build Coastguard Worker : ::fcp::internal::LogMessageVoidify() & _FCP_LOG_##severity
69*14675a02SAndroid Build Coastguard Worker
70*14675a02SAndroid Build Coastguard Worker /**
71*14675a02SAndroid Build Coastguard Worker * Log Severity
72*14675a02SAndroid Build Coastguard Worker */
73*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
74*14675a02SAndroid Build Coastguard Worker enum class LogSeverity : int {
75*14675a02SAndroid Build Coastguard Worker kInfo = 0,
76*14675a02SAndroid Build Coastguard Worker kWarning = 1,
77*14675a02SAndroid Build Coastguard Worker kError = 2,
78*14675a02SAndroid Build Coastguard Worker kFatal = 3,
79*14675a02SAndroid Build Coastguard Worker };
80*14675a02SAndroid Build Coastguard Worker #else
81*14675a02SAndroid Build Coastguard Worker using LogSeverity = absl::LogSeverity;
82*14675a02SAndroid Build Coastguard Worker #endif // FCP_BAREMETAL
83*14675a02SAndroid Build Coastguard Worker
84*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_INFO \
85*14675a02SAndroid Build Coastguard Worker ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kInfo)
86*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_WARNING \
87*14675a02SAndroid Build Coastguard Worker ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kWarning)
88*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_ERROR \
89*14675a02SAndroid Build Coastguard Worker ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kError)
90*14675a02SAndroid Build Coastguard Worker #define _FCP_LOG_FATAL \
91*14675a02SAndroid Build Coastguard Worker ::fcp::internal::LogMessage(__FILE__, __LINE__, ::fcp::LogSeverity::kFatal)
92*14675a02SAndroid Build Coastguard Worker
93*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
94*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_FALSE(x) (x)
95*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_TRUE(x) (x)
96*14675a02SAndroid Build Coastguard Worker #else
97*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_FALSE(x) ABSL_PREDICT_FALSE(x)
98*14675a02SAndroid Build Coastguard Worker #define FCP_PREDICT_TRUE(x) ABSL_PREDICT_TRUE(x)
99*14675a02SAndroid Build Coastguard Worker #endif
100*14675a02SAndroid Build Coastguard Worker
101*14675a02SAndroid Build Coastguard Worker /**
102*14675a02SAndroid Build Coastguard Worker * Check that the condition holds, otherwise die. Any additional messages can
103*14675a02SAndroid Build Coastguard Worker * be streamed into the invocation. Example:
104*14675a02SAndroid Build Coastguard Worker *
105*14675a02SAndroid Build Coastguard Worker * FCP_CHECK(condition) << "stuff went wrong";
106*14675a02SAndroid Build Coastguard Worker */
107*14675a02SAndroid Build Coastguard Worker #define FCP_CHECK(condition) \
108*14675a02SAndroid Build Coastguard Worker FCP_LOG_IF(FATAL, FCP_PREDICT_FALSE(!(condition))) \
109*14675a02SAndroid Build Coastguard Worker << ("Check failed: " #condition ". ")
110*14675a02SAndroid Build Coastguard Worker
111*14675a02SAndroid Build Coastguard Worker /**
112*14675a02SAndroid Build Coastguard Worker * Check that the expression generating a status code is OK, otherwise die.
113*14675a02SAndroid Build Coastguard Worker * Any additional messages can be streamed into the invocation.
114*14675a02SAndroid Build Coastguard Worker */
115*14675a02SAndroid Build Coastguard Worker #define FCP_CHECK_STATUS(status) \
116*14675a02SAndroid Build Coastguard Worker for (auto __check_status = (status); \
117*14675a02SAndroid Build Coastguard Worker __check_status.code() != ::fcp::StatusCode::kOk;) \
118*14675a02SAndroid Build Coastguard Worker FCP_LOG_IF(FATAL, __check_status.code() != ::fcp::StatusCode::kOk) \
119*14675a02SAndroid Build Coastguard Worker << "status not OK: " << __check_status
120*14675a02SAndroid Build Coastguard Worker
121*14675a02SAndroid Build Coastguard Worker // Logging Implementation Details
122*14675a02SAndroid Build Coastguard Worker // ==============================
123*14675a02SAndroid Build Coastguard Worker
124*14675a02SAndroid Build Coastguard Worker namespace internal {
125*14675a02SAndroid Build Coastguard Worker
126*14675a02SAndroid Build Coastguard Worker /**
127*14675a02SAndroid Build Coastguard Worker * An object which implements a logger sink. The default sink sends log
128*14675a02SAndroid Build Coastguard Worker * messages to stderr.
129*14675a02SAndroid Build Coastguard Worker */
130*14675a02SAndroid Build Coastguard Worker class Logger {
131*14675a02SAndroid Build Coastguard Worker public:
132*14675a02SAndroid Build Coastguard Worker virtual ~Logger() = default;
133*14675a02SAndroid Build Coastguard Worker
134*14675a02SAndroid Build Coastguard Worker /**
135*14675a02SAndroid Build Coastguard Worker * Basic log function.
136*14675a02SAndroid Build Coastguard Worker *
137*14675a02SAndroid Build Coastguard Worker * @param file The name of the associated file.
138*14675a02SAndroid Build Coastguard Worker * @param line The line in this file.
139*14675a02SAndroid Build Coastguard Worker * @param severity Severity of the log message.
140*14675a02SAndroid Build Coastguard Worker * @param message The message to log.
141*14675a02SAndroid Build Coastguard Worker */
142*14675a02SAndroid Build Coastguard Worker virtual void Log(const char* file, int line, LogSeverity severity,
143*14675a02SAndroid Build Coastguard Worker const char* message);
144*14675a02SAndroid Build Coastguard Worker };
145*14675a02SAndroid Build Coastguard Worker
146*14675a02SAndroid Build Coastguard Worker /**
147*14675a02SAndroid Build Coastguard Worker * Gets/sets the active logger object.
148*14675a02SAndroid Build Coastguard Worker */
149*14675a02SAndroid Build Coastguard Worker Logger* logger();
150*14675a02SAndroid Build Coastguard Worker void set_logger(Logger* logger);
151*14675a02SAndroid Build Coastguard Worker
152*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BAREMETAL
153*14675a02SAndroid Build Coastguard Worker using StringStream = std::ostringstream;
154*14675a02SAndroid Build Coastguard Worker #endif // FCP_BAREMETAL
155*14675a02SAndroid Build Coastguard Worker
156*14675a02SAndroid Build Coastguard Worker /**
157*14675a02SAndroid Build Coastguard Worker * Object allowing to construct a log message by streaming into it. This is
158*14675a02SAndroid Build Coastguard Worker * used by the macro LOG(severity).
159*14675a02SAndroid Build Coastguard Worker */
160*14675a02SAndroid Build Coastguard Worker class LogMessage {
161*14675a02SAndroid Build Coastguard Worker public:
LogMessage(const char * file,int line,LogSeverity severity)162*14675a02SAndroid Build Coastguard Worker LogMessage(const char* file, int line, LogSeverity severity)
163*14675a02SAndroid Build Coastguard Worker : file_(file), line_(line), severity_(severity) {}
164*14675a02SAndroid Build Coastguard Worker
165*14675a02SAndroid Build Coastguard Worker template <typename T>
166*14675a02SAndroid Build Coastguard Worker LogMessage& operator<<(const T& x) {
167*14675a02SAndroid Build Coastguard Worker message_ << x;
168*14675a02SAndroid Build Coastguard Worker return *this;
169*14675a02SAndroid Build Coastguard Worker }
170*14675a02SAndroid Build Coastguard Worker
171*14675a02SAndroid Build Coastguard Worker #ifndef FCP_BAREMETAL
172*14675a02SAndroid Build Coastguard Worker LogMessage& operator<<(std::ostream& (*pf)(std::ostream&)) {
173*14675a02SAndroid Build Coastguard Worker message_ << pf;
174*14675a02SAndroid Build Coastguard Worker return *this;
175*14675a02SAndroid Build Coastguard Worker }
176*14675a02SAndroid Build Coastguard Worker #endif
177*14675a02SAndroid Build Coastguard Worker
~LogMessage()178*14675a02SAndroid Build Coastguard Worker ~LogMessage() {
179*14675a02SAndroid Build Coastguard Worker logger()->Log(file_, line_, severity_, message_.str().c_str());
180*14675a02SAndroid Build Coastguard Worker if (severity_ == LogSeverity::kFatal) {
181*14675a02SAndroid Build Coastguard Worker abort();
182*14675a02SAndroid Build Coastguard Worker }
183*14675a02SAndroid Build Coastguard Worker }
184*14675a02SAndroid Build Coastguard Worker
185*14675a02SAndroid Build Coastguard Worker private:
186*14675a02SAndroid Build Coastguard Worker const char* file_;
187*14675a02SAndroid Build Coastguard Worker int line_;
188*14675a02SAndroid Build Coastguard Worker LogSeverity severity_;
189*14675a02SAndroid Build Coastguard Worker StringStream message_;
190*14675a02SAndroid Build Coastguard Worker };
191*14675a02SAndroid Build Coastguard Worker
192*14675a02SAndroid Build Coastguard Worker /**
193*14675a02SAndroid Build Coastguard Worker * This class is used to cast a LogMessage instance to void within a ternary
194*14675a02SAndroid Build Coastguard Worker * expression in the expansion of FCP_LOG_IF. The cast is necessary so
195*14675a02SAndroid Build Coastguard Worker * that the types of the expressions on either side of the : match, and the &
196*14675a02SAndroid Build Coastguard Worker * operator is used because its precedence is lower than << but higher than
197*14675a02SAndroid Build Coastguard Worker * ?:.
198*14675a02SAndroid Build Coastguard Worker */
199*14675a02SAndroid Build Coastguard Worker class LogMessageVoidify {
200*14675a02SAndroid Build Coastguard Worker public:
201*14675a02SAndroid Build Coastguard Worker void operator&(LogMessage&) {} // NOLINT
202*14675a02SAndroid Build Coastguard Worker };
203*14675a02SAndroid Build Coastguard Worker
204*14675a02SAndroid Build Coastguard Worker } // namespace internal
205*14675a02SAndroid Build Coastguard Worker
206*14675a02SAndroid Build Coastguard Worker // Status and StatusOr
207*14675a02SAndroid Build Coastguard Worker // ===================
208*14675a02SAndroid Build Coastguard Worker
209*14675a02SAndroid Build Coastguard Worker /**
210*14675a02SAndroid Build Coastguard Worker * Constructor for a status. A status message can be streamed into it. This
211*14675a02SAndroid Build Coastguard Worker * captures the current file and line position and includes it into the status
212*14675a02SAndroid Build Coastguard Worker * message if the status code is not OK.
213*14675a02SAndroid Build Coastguard Worker *
214*14675a02SAndroid Build Coastguard Worker * Use as in:
215*14675a02SAndroid Build Coastguard Worker *
216*14675a02SAndroid Build Coastguard Worker * FCP_STATUS(OK); // signal success
217*14675a02SAndroid Build Coastguard Worker * FCP_STATUS(code) << message; // signal failure
218*14675a02SAndroid Build Coastguard Worker *
219*14675a02SAndroid Build Coastguard Worker * FCP_STATUS can be used in places which either expect a Status or a
220*14675a02SAndroid Build Coastguard Worker * StatusOr<T>.
221*14675a02SAndroid Build Coastguard Worker *
222*14675a02SAndroid Build Coastguard Worker * You can configure the constructed status to also emit a log entry if the
223*14675a02SAndroid Build Coastguard Worker * status is not OK by using LogInfo, LogWarning, LogError, or LogFatal as
224*14675a02SAndroid Build Coastguard Worker * below:
225*14675a02SAndroid Build Coastguard Worker *
226*14675a02SAndroid Build Coastguard Worker * FCP_STATUS(code).LogInfo() << message;
227*14675a02SAndroid Build Coastguard Worker *
228*14675a02SAndroid Build Coastguard Worker * If the constant rx_debug is true, by default, all FCP_STATUS invocations
229*14675a02SAndroid Build Coastguard Worker * will be logged on INFO level.
230*14675a02SAndroid Build Coastguard Worker */
231*14675a02SAndroid Build Coastguard Worker #define FCP_STATUS(code) \
232*14675a02SAndroid Build Coastguard Worker ::fcp::internal::MakeStatusBuilder(code, __FILE__, __LINE__)
233*14675a02SAndroid Build Coastguard Worker
234*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
235*14675a02SAndroid Build Coastguard Worker #define FCP_MUST_USE_RESULT __attribute__((warn_unused_result))
236*14675a02SAndroid Build Coastguard Worker #else
237*14675a02SAndroid Build Coastguard Worker #define FCP_MUST_USE_RESULT ABSL_MUST_USE_RESULT
238*14675a02SAndroid Build Coastguard Worker #endif
239*14675a02SAndroid Build Coastguard Worker
240*14675a02SAndroid Build Coastguard Worker #ifdef FCP_BAREMETAL
241*14675a02SAndroid Build Coastguard Worker
242*14675a02SAndroid Build Coastguard Worker // The bare-metal implementation doesn't depend on Abseil library and
243*14675a02SAndroid Build Coastguard Worker // provides its own implementations of StatusCode, Status and StatusOr that are
244*14675a02SAndroid Build Coastguard Worker // source code compatible with absl::StatusCode, absl::Status,
245*14675a02SAndroid Build Coastguard Worker // and absl::StatusOr.
246*14675a02SAndroid Build Coastguard Worker
247*14675a02SAndroid Build Coastguard Worker // See absl::StatusCode for details.
248*14675a02SAndroid Build Coastguard Worker enum StatusCode : int {
249*14675a02SAndroid Build Coastguard Worker kOk = 0,
250*14675a02SAndroid Build Coastguard Worker kCancelled = 1,
251*14675a02SAndroid Build Coastguard Worker kUnknown = 2,
252*14675a02SAndroid Build Coastguard Worker kInvalidArgument = 3,
253*14675a02SAndroid Build Coastguard Worker kDeadlineExceeded = 4,
254*14675a02SAndroid Build Coastguard Worker kNotFound = 5,
255*14675a02SAndroid Build Coastguard Worker kAlreadyExists = 6,
256*14675a02SAndroid Build Coastguard Worker kPermissionDenied = 7,
257*14675a02SAndroid Build Coastguard Worker kResourceExhausted = 8,
258*14675a02SAndroid Build Coastguard Worker kFailedPrecondition = 9,
259*14675a02SAndroid Build Coastguard Worker kAborted = 10,
260*14675a02SAndroid Build Coastguard Worker kOutOfRange = 11,
261*14675a02SAndroid Build Coastguard Worker kUnimplemented = 12,
262*14675a02SAndroid Build Coastguard Worker kInternal = 13,
263*14675a02SAndroid Build Coastguard Worker kUnavailable = 14,
264*14675a02SAndroid Build Coastguard Worker kDataLoss = 15,
265*14675a02SAndroid Build Coastguard Worker kUnauthenticated = 16,
266*14675a02SAndroid Build Coastguard Worker };
267*14675a02SAndroid Build Coastguard Worker
268*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT Status final {
269*14675a02SAndroid Build Coastguard Worker public:
Status()270*14675a02SAndroid Build Coastguard Worker Status() : code_(StatusCode::kOk) {}
Status(StatusCode code,const std::string & message)271*14675a02SAndroid Build Coastguard Worker Status(StatusCode code, const std::string& message)
272*14675a02SAndroid Build Coastguard Worker : code_(code), message_(message) {}
273*14675a02SAndroid Build Coastguard Worker
274*14675a02SAndroid Build Coastguard Worker // Status is copyable and moveable.
275*14675a02SAndroid Build Coastguard Worker Status(const Status&) = default;
276*14675a02SAndroid Build Coastguard Worker Status& operator=(const Status&) = default;
277*14675a02SAndroid Build Coastguard Worker Status(Status&&) = default;
278*14675a02SAndroid Build Coastguard Worker Status& operator=(Status&&) = default;
279*14675a02SAndroid Build Coastguard Worker
280*14675a02SAndroid Build Coastguard Worker // Tests whether this status is OK.
ok()281*14675a02SAndroid Build Coastguard Worker bool ok() const { return code_ == StatusCode::kOk; }
282*14675a02SAndroid Build Coastguard Worker
283*14675a02SAndroid Build Coastguard Worker // Gets this status code.
code()284*14675a02SAndroid Build Coastguard Worker StatusCode code() const { return code_; }
285*14675a02SAndroid Build Coastguard Worker
286*14675a02SAndroid Build Coastguard Worker // Gets this status message.
message()287*14675a02SAndroid Build Coastguard Worker const std::string& message() const { return message_; }
288*14675a02SAndroid Build Coastguard Worker
289*14675a02SAndroid Build Coastguard Worker private:
290*14675a02SAndroid Build Coastguard Worker StatusCode code_;
291*14675a02SAndroid Build Coastguard Worker std::string message_;
292*14675a02SAndroid Build Coastguard Worker };
293*14675a02SAndroid Build Coastguard Worker
294*14675a02SAndroid Build Coastguard Worker template <typename T>
295*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT StatusOr final {
296*14675a02SAndroid Build Coastguard Worker public:
297*14675a02SAndroid Build Coastguard Worker // Default constructor initializes StatusOr with kUnknown code.
StatusOr()298*14675a02SAndroid Build Coastguard Worker explicit StatusOr() : StatusOr(StatusCode::kUnknown) {}
299*14675a02SAndroid Build Coastguard Worker
300*14675a02SAndroid Build Coastguard Worker // Constructs a StatusOr from a failed status. The passed status must not be
301*14675a02SAndroid Build Coastguard Worker // OK. This constructor is expected to be implicitly called.
StatusOr(Status status)302*14675a02SAndroid Build Coastguard Worker StatusOr(Status status) // NOLINT
303*14675a02SAndroid Build Coastguard Worker : status_(std::move(status)) {
304*14675a02SAndroid Build Coastguard Worker FCP_CHECK(!this->status().ok());
305*14675a02SAndroid Build Coastguard Worker }
306*14675a02SAndroid Build Coastguard Worker
307*14675a02SAndroid Build Coastguard Worker // Constructs a StatusOr from a status code.
StatusOr(StatusCode code)308*14675a02SAndroid Build Coastguard Worker explicit StatusOr(StatusCode code) : StatusOr(code, "") {}
309*14675a02SAndroid Build Coastguard Worker
310*14675a02SAndroid Build Coastguard Worker // Constructs a StatusOr from a status code and a message.
StatusOr(StatusCode code,const std::string & message)311*14675a02SAndroid Build Coastguard Worker StatusOr(StatusCode code, const std::string& message)
312*14675a02SAndroid Build Coastguard Worker : status_(Status(code, message)) {
313*14675a02SAndroid Build Coastguard Worker FCP_CHECK(!this->status().ok());
314*14675a02SAndroid Build Coastguard Worker }
315*14675a02SAndroid Build Coastguard Worker
316*14675a02SAndroid Build Coastguard Worker // Construct a StatusOr from a value.
StatusOr(const T & value)317*14675a02SAndroid Build Coastguard Worker StatusOr(const T& value) // NOLINT
318*14675a02SAndroid Build Coastguard Worker : value_(value) {}
319*14675a02SAndroid Build Coastguard Worker
320*14675a02SAndroid Build Coastguard Worker // Construct a StatusOr from an R-value.
StatusOr(T && value)321*14675a02SAndroid Build Coastguard Worker StatusOr(T&& value) // NOLINT
322*14675a02SAndroid Build Coastguard Worker : value_(std::move(value)) {}
323*14675a02SAndroid Build Coastguard Worker
324*14675a02SAndroid Build Coastguard Worker // StatusOr is copyable and moveable.
StatusOr(const StatusOr & other)325*14675a02SAndroid Build Coastguard Worker StatusOr(const StatusOr& other) : status_(other.status_) {
326*14675a02SAndroid Build Coastguard Worker if (ok()) {
327*14675a02SAndroid Build Coastguard Worker AssignValue(other.value_);
328*14675a02SAndroid Build Coastguard Worker }
329*14675a02SAndroid Build Coastguard Worker }
330*14675a02SAndroid Build Coastguard Worker
StatusOr(StatusOr && other)331*14675a02SAndroid Build Coastguard Worker StatusOr(StatusOr&& other) : status_(std::move(other.status_)) {
332*14675a02SAndroid Build Coastguard Worker if (ok()) {
333*14675a02SAndroid Build Coastguard Worker AssignValue(std::move(other.value_));
334*14675a02SAndroid Build Coastguard Worker }
335*14675a02SAndroid Build Coastguard Worker }
336*14675a02SAndroid Build Coastguard Worker
337*14675a02SAndroid Build Coastguard Worker StatusOr& operator=(const StatusOr& other) {
338*14675a02SAndroid Build Coastguard Worker if (this != &other) {
339*14675a02SAndroid Build Coastguard Worker ClearValue();
340*14675a02SAndroid Build Coastguard Worker if (other.ok()) {
341*14675a02SAndroid Build Coastguard Worker AssignValue(other.value_);
342*14675a02SAndroid Build Coastguard Worker }
343*14675a02SAndroid Build Coastguard Worker status_ = other.status_;
344*14675a02SAndroid Build Coastguard Worker }
345*14675a02SAndroid Build Coastguard Worker return *this;
346*14675a02SAndroid Build Coastguard Worker }
347*14675a02SAndroid Build Coastguard Worker
348*14675a02SAndroid Build Coastguard Worker StatusOr& operator=(StatusOr&& other) {
349*14675a02SAndroid Build Coastguard Worker if (this != &other) {
350*14675a02SAndroid Build Coastguard Worker ClearValue();
351*14675a02SAndroid Build Coastguard Worker if (other.ok()) {
352*14675a02SAndroid Build Coastguard Worker AssignValue(std::move(other.value_));
353*14675a02SAndroid Build Coastguard Worker }
354*14675a02SAndroid Build Coastguard Worker status_ = std::move(other.status_);
355*14675a02SAndroid Build Coastguard Worker }
356*14675a02SAndroid Build Coastguard Worker return *this;
357*14675a02SAndroid Build Coastguard Worker }
358*14675a02SAndroid Build Coastguard Worker
~StatusOr()359*14675a02SAndroid Build Coastguard Worker ~StatusOr() { ClearValue(); }
360*14675a02SAndroid Build Coastguard Worker
361*14675a02SAndroid Build Coastguard Worker // Tests whether this StatusOr is OK and has a value.
ok()362*14675a02SAndroid Build Coastguard Worker bool ok() const { return status_.ok(); }
363*14675a02SAndroid Build Coastguard Worker
364*14675a02SAndroid Build Coastguard Worker // Returns the status.
status()365*14675a02SAndroid Build Coastguard Worker const Status& status() const { return status_; }
366*14675a02SAndroid Build Coastguard Worker
367*14675a02SAndroid Build Coastguard Worker // Returns the value if the StatusOr is OK.
value()368*14675a02SAndroid Build Coastguard Worker const T& value() const& {
369*14675a02SAndroid Build Coastguard Worker CheckOk();
370*14675a02SAndroid Build Coastguard Worker return value_;
371*14675a02SAndroid Build Coastguard Worker }
value()372*14675a02SAndroid Build Coastguard Worker T& value() & {
373*14675a02SAndroid Build Coastguard Worker CheckOk();
374*14675a02SAndroid Build Coastguard Worker return value_;
375*14675a02SAndroid Build Coastguard Worker }
value()376*14675a02SAndroid Build Coastguard Worker T&& value() && {
377*14675a02SAndroid Build Coastguard Worker CheckOk();
378*14675a02SAndroid Build Coastguard Worker return std::move(value_);
379*14675a02SAndroid Build Coastguard Worker }
380*14675a02SAndroid Build Coastguard Worker
381*14675a02SAndroid Build Coastguard Worker // Operator *
382*14675a02SAndroid Build Coastguard Worker const T& operator*() const& { return value(); }
383*14675a02SAndroid Build Coastguard Worker T& operator*() & { return value(); }
384*14675a02SAndroid Build Coastguard Worker T&& operator*() && { return std::move(value()); }
385*14675a02SAndroid Build Coastguard Worker
386*14675a02SAndroid Build Coastguard Worker // Operator ->
387*14675a02SAndroid Build Coastguard Worker const T* operator->() const { return &value(); }
388*14675a02SAndroid Build Coastguard Worker T* operator->() { return &value(); }
389*14675a02SAndroid Build Coastguard Worker
390*14675a02SAndroid Build Coastguard Worker // Used to explicitly ignore a StatusOr (avoiding unused-result warnings).
Ignore()391*14675a02SAndroid Build Coastguard Worker void Ignore() const {}
392*14675a02SAndroid Build Coastguard Worker
393*14675a02SAndroid Build Coastguard Worker private:
CheckOk()394*14675a02SAndroid Build Coastguard Worker void CheckOk() const { FCP_CHECK(ok()) << "StatusOr has no value"; }
395*14675a02SAndroid Build Coastguard Worker
396*14675a02SAndroid Build Coastguard Worker // This is used to assign the value in place without invoking the assignment
397*14675a02SAndroid Build Coastguard Worker // operator. Using the assignment operator wouldn't work in case the value_
398*14675a02SAndroid Build Coastguard Worker // wasn't previously initialized. For example the value_ object might try
399*14675a02SAndroid Build Coastguard Worker // to clear its previous value.
400*14675a02SAndroid Build Coastguard Worker template <typename Arg>
AssignValue(Arg && arg)401*14675a02SAndroid Build Coastguard Worker void AssignValue(Arg&& arg) {
402*14675a02SAndroid Build Coastguard Worker new (&unused_) T(std::forward<Arg>(arg));
403*14675a02SAndroid Build Coastguard Worker }
404*14675a02SAndroid Build Coastguard Worker
405*14675a02SAndroid Build Coastguard Worker // Destroy the current value if it was initialized.
ClearValue()406*14675a02SAndroid Build Coastguard Worker void ClearValue() {
407*14675a02SAndroid Build Coastguard Worker if (ok()) value_.~T();
408*14675a02SAndroid Build Coastguard Worker }
409*14675a02SAndroid Build Coastguard Worker
410*14675a02SAndroid Build Coastguard Worker Status status_;
411*14675a02SAndroid Build Coastguard Worker
412*14675a02SAndroid Build Coastguard Worker // Using the union allows to avoid initializing the value_ field when
413*14675a02SAndroid Build Coastguard Worker // StatusOr is constructed with Status.
414*14675a02SAndroid Build Coastguard Worker struct Unused {};
415*14675a02SAndroid Build Coastguard Worker union {
416*14675a02SAndroid Build Coastguard Worker Unused unused_;
417*14675a02SAndroid Build Coastguard Worker T value_;
418*14675a02SAndroid Build Coastguard Worker };
419*14675a02SAndroid Build Coastguard Worker };
420*14675a02SAndroid Build Coastguard Worker
421*14675a02SAndroid Build Coastguard Worker #else
422*14675a02SAndroid Build Coastguard Worker
423*14675a02SAndroid Build Coastguard Worker // By default absl::Status and absl::StatusOr classes are used.
424*14675a02SAndroid Build Coastguard Worker using Status = absl::Status;
425*14675a02SAndroid Build Coastguard Worker using StatusCode = absl::StatusCode;
426*14675a02SAndroid Build Coastguard Worker template <typename T>
427*14675a02SAndroid Build Coastguard Worker using StatusOr = absl::StatusOr<T>;
428*14675a02SAndroid Build Coastguard Worker
429*14675a02SAndroid Build Coastguard Worker #endif // FCP_BAREMETAL
430*14675a02SAndroid Build Coastguard Worker
431*14675a02SAndroid Build Coastguard Worker constexpr auto OK = StatusCode::kOk;
432*14675a02SAndroid Build Coastguard Worker constexpr auto CANCELLED = StatusCode::kCancelled;
433*14675a02SAndroid Build Coastguard Worker constexpr auto UNKNOWN = StatusCode::kUnknown;
434*14675a02SAndroid Build Coastguard Worker constexpr auto INVALID_ARGUMENT = StatusCode::kInvalidArgument;
435*14675a02SAndroid Build Coastguard Worker constexpr auto DEADLINE_EXCEEDED = StatusCode::kDeadlineExceeded;
436*14675a02SAndroid Build Coastguard Worker constexpr auto NOT_FOUND = StatusCode::kNotFound;
437*14675a02SAndroid Build Coastguard Worker constexpr auto ALREADY_EXISTS = StatusCode::kAlreadyExists;
438*14675a02SAndroid Build Coastguard Worker constexpr auto PERMISSION_DENIED = StatusCode::kPermissionDenied;
439*14675a02SAndroid Build Coastguard Worker constexpr auto RESOURCE_EXHAUSTED = StatusCode::kResourceExhausted;
440*14675a02SAndroid Build Coastguard Worker constexpr auto FAILED_PRECONDITION = StatusCode::kFailedPrecondition;
441*14675a02SAndroid Build Coastguard Worker constexpr auto ABORTED = StatusCode::kAborted;
442*14675a02SAndroid Build Coastguard Worker constexpr auto OUT_OF_RANGE = StatusCode::kOutOfRange;
443*14675a02SAndroid Build Coastguard Worker constexpr auto UNIMPLEMENTED = StatusCode::kUnimplemented;
444*14675a02SAndroid Build Coastguard Worker constexpr auto INTERNAL = StatusCode::kInternal;
445*14675a02SAndroid Build Coastguard Worker constexpr auto UNAVAILABLE = StatusCode::kUnavailable;
446*14675a02SAndroid Build Coastguard Worker constexpr auto DATA_LOSS = StatusCode::kDataLoss;
447*14675a02SAndroid Build Coastguard Worker constexpr auto UNAUTHENTICATED = StatusCode::kUnauthenticated;
448*14675a02SAndroid Build Coastguard Worker
449*14675a02SAndroid Build Coastguard Worker namespace internal {
450*14675a02SAndroid Build Coastguard Worker /** Functions to assist with FCP_RETURN_IF_ERROR() */
AsStatus(const Status & status)451*14675a02SAndroid Build Coastguard Worker inline const Status AsStatus(const Status& status) { return status; }
452*14675a02SAndroid Build Coastguard Worker template <typename T>
AsStatus(const StatusOr<T> & status_or)453*14675a02SAndroid Build Coastguard Worker inline const Status AsStatus(const StatusOr<T>& status_or) {
454*14675a02SAndroid Build Coastguard Worker return status_or.status();
455*14675a02SAndroid Build Coastguard Worker }
456*14675a02SAndroid Build Coastguard Worker } // namespace internal
457*14675a02SAndroid Build Coastguard Worker
458*14675a02SAndroid Build Coastguard Worker /**
459*14675a02SAndroid Build Coastguard Worker * Macro which allows to check for a Status (or StatusOr) and return from the
460*14675a02SAndroid Build Coastguard Worker * current method if not OK. Example:
461*14675a02SAndroid Build Coastguard Worker *
462*14675a02SAndroid Build Coastguard Worker * Status DoSomething() {
463*14675a02SAndroid Build Coastguard Worker * FCP_RETURN_IF_ERROR(Step1());
464*14675a02SAndroid Build Coastguard Worker * FCP_RETURN_IF_ERROR(Step2ReturningStatusOr().status());
465*14675a02SAndroid Build Coastguard Worker * return FCP_STATUS(OK);
466*14675a02SAndroid Build Coastguard Worker * }
467*14675a02SAndroid Build Coastguard Worker */
468*14675a02SAndroid Build Coastguard Worker #define FCP_RETURN_IF_ERROR(expr) \
469*14675a02SAndroid Build Coastguard Worker do { \
470*14675a02SAndroid Build Coastguard Worker ::fcp::Status __status = ::fcp::internal::AsStatus(expr); \
471*14675a02SAndroid Build Coastguard Worker if (__status.code() != ::fcp::StatusCode::kOk) { \
472*14675a02SAndroid Build Coastguard Worker return (__status); \
473*14675a02SAndroid Build Coastguard Worker } \
474*14675a02SAndroid Build Coastguard Worker } while (false)
475*14675a02SAndroid Build Coastguard Worker
476*14675a02SAndroid Build Coastguard Worker /**
477*14675a02SAndroid Build Coastguard Worker * Macro which allows to check for a StatusOr and return it's status if not OK,
478*14675a02SAndroid Build Coastguard Worker * otherwise assign the value in the StatusOr to variable or declaration. Usage:
479*14675a02SAndroid Build Coastguard Worker *
480*14675a02SAndroid Build Coastguard Worker * StatusOr<bool> DoSomething() {
481*14675a02SAndroid Build Coastguard Worker * FCP_ASSIGN_OR_RETURN(auto value, TryComputeSomething());
482*14675a02SAndroid Build Coastguard Worker * if (!value) {
483*14675a02SAndroid Build Coastguard Worker * FCP_ASSIGN_OR_RETURN(value, TryComputeSomethingElse());
484*14675a02SAndroid Build Coastguard Worker * }
485*14675a02SAndroid Build Coastguard Worker * return value;
486*14675a02SAndroid Build Coastguard Worker * }
487*14675a02SAndroid Build Coastguard Worker */
488*14675a02SAndroid Build Coastguard Worker #define FCP_ASSIGN_OR_RETURN(lhs, expr) \
489*14675a02SAndroid Build Coastguard Worker _FCP_ASSIGN_OR_RETURN_1( \
490*14675a02SAndroid Build Coastguard Worker _FCP_ASSIGN_OR_RETURN_CONCAT(statusor_for_aor, __LINE__), lhs, expr)
491*14675a02SAndroid Build Coastguard Worker
492*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_1(statusor, lhs, expr) \
493*14675a02SAndroid Build Coastguard Worker auto statusor = (expr); \
494*14675a02SAndroid Build Coastguard Worker if (!statusor.ok()) { \
495*14675a02SAndroid Build Coastguard Worker return statusor.status(); \
496*14675a02SAndroid Build Coastguard Worker } \
497*14675a02SAndroid Build Coastguard Worker lhs = std::move(statusor).value()
498*14675a02SAndroid Build Coastguard Worker
499*14675a02SAndroid Build Coastguard Worker // See https://goo.gl/x3iba2 for the reason of this construction.
500*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_CONCAT(x, y) \
501*14675a02SAndroid Build Coastguard Worker _FCP_ASSIGN_OR_RETURN_CONCAT_INNER(x, y)
502*14675a02SAndroid Build Coastguard Worker #define _FCP_ASSIGN_OR_RETURN_CONCAT_INNER(x, y) x##y
503*14675a02SAndroid Build Coastguard Worker
504*14675a02SAndroid Build Coastguard Worker // Status Implementation Details
505*14675a02SAndroid Build Coastguard Worker // =============================
506*14675a02SAndroid Build Coastguard Worker
507*14675a02SAndroid Build Coastguard Worker namespace internal {
508*14675a02SAndroid Build Coastguard Worker
509*14675a02SAndroid Build Coastguard Worker /**
510*14675a02SAndroid Build Coastguard Worker * Helper class which allows to construct a status with message by streaming
511*14675a02SAndroid Build Coastguard Worker * into it. Implicitly converts to Status and StatusOr so can be used as a drop
512*14675a02SAndroid Build Coastguard Worker * in replacement when those types are expected.
513*14675a02SAndroid Build Coastguard Worker */
514*14675a02SAndroid Build Coastguard Worker class FCP_MUST_USE_RESULT StatusBuilder {
515*14675a02SAndroid Build Coastguard Worker public:
516*14675a02SAndroid Build Coastguard Worker /** Construct a StatusBuilder from status code. */
517*14675a02SAndroid Build Coastguard Worker StatusBuilder(StatusCode code, const char* file, int line);
518*14675a02SAndroid Build Coastguard Worker
519*14675a02SAndroid Build Coastguard Worker /**
520*14675a02SAndroid Build Coastguard Worker * Copy constructor for status builder. Most of the time not needed because of
521*14675a02SAndroid Build Coastguard Worker * copy ellision. */
522*14675a02SAndroid Build Coastguard Worker StatusBuilder(StatusBuilder const& other);
523*14675a02SAndroid Build Coastguard Worker
524*14675a02SAndroid Build Coastguard Worker /** Return true if the constructed status will be OK. */
ok()525*14675a02SAndroid Build Coastguard Worker inline bool ok() const { return code_ == OK; }
526*14675a02SAndroid Build Coastguard Worker
527*14675a02SAndroid Build Coastguard Worker /** Returns the code of the constructed status. */
code()528*14675a02SAndroid Build Coastguard Worker inline StatusCode code() const { return code_; }
529*14675a02SAndroid Build Coastguard Worker
530*14675a02SAndroid Build Coastguard Worker /** Stream into status message of this builder. */
531*14675a02SAndroid Build Coastguard Worker template <typename T>
532*14675a02SAndroid Build Coastguard Worker StatusBuilder& operator<<(T x) {
533*14675a02SAndroid Build Coastguard Worker message_ << x;
534*14675a02SAndroid Build Coastguard Worker return *this;
535*14675a02SAndroid Build Coastguard Worker }
536*14675a02SAndroid Build Coastguard Worker
537*14675a02SAndroid Build Coastguard Worker /** Mark this builder to emit a log message when the result is constructed. */
LogInfo()538*14675a02SAndroid Build Coastguard Worker inline StatusBuilder& LogInfo() {
539*14675a02SAndroid Build Coastguard Worker log_severity_ = LogSeverity::kInfo;
540*14675a02SAndroid Build Coastguard Worker return *this;
541*14675a02SAndroid Build Coastguard Worker }
542*14675a02SAndroid Build Coastguard Worker
543*14675a02SAndroid Build Coastguard Worker /** Mark this builder to emit a log message when the result is constructed. */
LogWarning()544*14675a02SAndroid Build Coastguard Worker inline StatusBuilder& LogWarning() {
545*14675a02SAndroid Build Coastguard Worker log_severity_ = LogSeverity::kWarning;
546*14675a02SAndroid Build Coastguard Worker return *this;
547*14675a02SAndroid Build Coastguard Worker }
548*14675a02SAndroid Build Coastguard Worker
549*14675a02SAndroid Build Coastguard Worker /** Mark this builder to emit a log message when the result is constructed. */
LogError()550*14675a02SAndroid Build Coastguard Worker inline StatusBuilder& LogError() {
551*14675a02SAndroid Build Coastguard Worker log_severity_ = LogSeverity::kError;
552*14675a02SAndroid Build Coastguard Worker return *this;
553*14675a02SAndroid Build Coastguard Worker }
554*14675a02SAndroid Build Coastguard Worker
555*14675a02SAndroid Build Coastguard Worker /** Mark this builder to emit a log message when the result is constructed. */
LogFatal()556*14675a02SAndroid Build Coastguard Worker inline StatusBuilder& LogFatal() {
557*14675a02SAndroid Build Coastguard Worker log_severity_ = LogSeverity::kFatal;
558*14675a02SAndroid Build Coastguard Worker return *this;
559*14675a02SAndroid Build Coastguard Worker }
560*14675a02SAndroid Build Coastguard Worker
561*14675a02SAndroid Build Coastguard Worker /** Implicit conversion to Status. */
562*14675a02SAndroid Build Coastguard Worker operator Status(); // NOLINT
563*14675a02SAndroid Build Coastguard Worker
564*14675a02SAndroid Build Coastguard Worker /** Implicit conversion to StatusOr. */
565*14675a02SAndroid Build Coastguard Worker template <typename T>
566*14675a02SAndroid Build Coastguard Worker inline operator StatusOr<T>() { // NOLINT
567*14675a02SAndroid Build Coastguard Worker return StatusOr<T>(static_cast<Status>(*this));
568*14675a02SAndroid Build Coastguard Worker }
569*14675a02SAndroid Build Coastguard Worker
570*14675a02SAndroid Build Coastguard Worker private:
571*14675a02SAndroid Build Coastguard Worker static constexpr LogSeverity kNoLog = static_cast<LogSeverity>(-1);
572*14675a02SAndroid Build Coastguard Worker const char* const file_;
573*14675a02SAndroid Build Coastguard Worker const int line_;
574*14675a02SAndroid Build Coastguard Worker const StatusCode code_;
575*14675a02SAndroid Build Coastguard Worker StringStream message_;
576*14675a02SAndroid Build Coastguard Worker LogSeverity log_severity_ = fcp_debug ? LogSeverity::kInfo : kNoLog;
577*14675a02SAndroid Build Coastguard Worker };
578*14675a02SAndroid Build Coastguard Worker
MakeStatusBuilder(StatusCode code,const char * file,int line)579*14675a02SAndroid Build Coastguard Worker inline StatusBuilder MakeStatusBuilder(StatusCode code, const char* file,
580*14675a02SAndroid Build Coastguard Worker int line) {
581*14675a02SAndroid Build Coastguard Worker return StatusBuilder(code, file, line);
582*14675a02SAndroid Build Coastguard Worker }
583*14675a02SAndroid Build Coastguard Worker
584*14675a02SAndroid Build Coastguard Worker } // namespace internal
585*14675a02SAndroid Build Coastguard Worker } // namespace fcp
586*14675a02SAndroid Build Coastguard Worker
587*14675a02SAndroid Build Coastguard Worker #endif // FCP_BASE_MONITORING_H_
588