1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements.  See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership.  The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License.  You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing,
12 // software distributed under the License is distributed on an
13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, either express or implied.  See the License for the
15 // specific language governing permissions and limitations
16 // under the License.
17 
18 #pragma once
19 
20 #ifdef GANDIVA_IR
21 
22 // The LLVM IR code doesn't have an NDEBUG mode. And, it shouldn't include references to
23 // streams or stdc++. So, making the DCHECK calls void in that case.
24 
25 #define ARROW_IGNORE_EXPR(expr) ((void)(expr))
26 
27 #define DCHECK(condition) ARROW_IGNORE_EXPR(condition)
28 #define DCHECK_OK(status) ARROW_IGNORE_EXPR(status)
29 #define DCHECK_EQ(val1, val2) ARROW_IGNORE_EXPR(val1)
30 #define DCHECK_NE(val1, val2) ARROW_IGNORE_EXPR(val1)
31 #define DCHECK_LE(val1, val2) ARROW_IGNORE_EXPR(val1)
32 #define DCHECK_LT(val1, val2) ARROW_IGNORE_EXPR(val1)
33 #define DCHECK_GE(val1, val2) ARROW_IGNORE_EXPR(val1)
34 #define DCHECK_GT(val1, val2) ARROW_IGNORE_EXPR(val1)
35 
36 #else  // !GANDIVA_IR
37 
38 #include <memory>
39 #include <ostream>
40 #include <string>
41 
42 #include "arrow/util/macros.h"
43 #include "arrow/util/visibility.h"
44 
45 namespace arrow {
46 namespace util {
47 
48 enum class ArrowLogLevel : int {
49   ARROW_DEBUG = -1,
50   ARROW_INFO = 0,
51   ARROW_WARNING = 1,
52   ARROW_ERROR = 2,
53   ARROW_FATAL = 3
54 };
55 
56 #define ARROW_LOG_INTERNAL(level) ::arrow::util::ArrowLog(__FILE__, __LINE__, level)
57 #define ARROW_LOG(level) ARROW_LOG_INTERNAL(::arrow::util::ArrowLogLevel::ARROW_##level)
58 
59 #define ARROW_IGNORE_EXPR(expr) ((void)(expr))
60 
61 #define ARROW_CHECK(condition)                                               \
62   ARROW_PREDICT_TRUE(condition)                                              \
63   ? ARROW_IGNORE_EXPR(0)                                                     \
64   : ::arrow::util::Voidify() &                                               \
65           ::arrow::util::ArrowLog(__FILE__, __LINE__,                        \
66                                   ::arrow::util::ArrowLogLevel::ARROW_FATAL) \
67               << " Check failed: " #condition " "
68 
69 // If 'to_call' returns a bad status, CHECK immediately with a logged message
70 // of 'msg' followed by the status.
71 #define ARROW_CHECK_OK_PREPEND(to_call, msg)                                         \
72   do {                                                                               \
73     ::arrow::Status _s = (to_call);                                                  \
74     ARROW_CHECK(_s.ok()) << "Operation failed: " << ARROW_STRINGIFY(to_call) << "\n" \
75                          << (msg) << ": " << _s.ToString();                          \
76   } while (false)
77 
78 // If the status is bad, CHECK immediately, appending the status to the
79 // logged message.
80 #define ARROW_CHECK_OK(s) ARROW_CHECK_OK_PREPEND(s, "Bad status")
81 
82 #define ARROW_CHECK_EQ(val1, val2) ARROW_CHECK((val1) == (val2))
83 #define ARROW_CHECK_NE(val1, val2) ARROW_CHECK((val1) != (val2))
84 #define ARROW_CHECK_LE(val1, val2) ARROW_CHECK((val1) <= (val2))
85 #define ARROW_CHECK_LT(val1, val2) ARROW_CHECK((val1) < (val2))
86 #define ARROW_CHECK_GE(val1, val2) ARROW_CHECK((val1) >= (val2))
87 #define ARROW_CHECK_GT(val1, val2) ARROW_CHECK((val1) > (val2))
88 
89 #ifdef NDEBUG
90 #define ARROW_DFATAL ::arrow::util::ArrowLogLevel::ARROW_WARNING
91 
92 // CAUTION: DCHECK_OK() always evaluates its argument, but other DCHECK*() macros
93 // only do so in debug mode.
94 
95 #define ARROW_DCHECK(condition)               \
96   while (false) ARROW_IGNORE_EXPR(condition); \
97   while (false) ::arrow::util::detail::NullLog()
98 #define ARROW_DCHECK_OK(s) \
99   ARROW_IGNORE_EXPR(s);    \
100   while (false) ::arrow::util::detail::NullLog()
101 #define ARROW_DCHECK_EQ(val1, val2)      \
102   while (false) ARROW_IGNORE_EXPR(val1); \
103   while (false) ARROW_IGNORE_EXPR(val2); \
104   while (false) ::arrow::util::detail::NullLog()
105 #define ARROW_DCHECK_NE(val1, val2)      \
106   while (false) ARROW_IGNORE_EXPR(val1); \
107   while (false) ARROW_IGNORE_EXPR(val2); \
108   while (false) ::arrow::util::detail::NullLog()
109 #define ARROW_DCHECK_LE(val1, val2)      \
110   while (false) ARROW_IGNORE_EXPR(val1); \
111   while (false) ARROW_IGNORE_EXPR(val2); \
112   while (false) ::arrow::util::detail::NullLog()
113 #define ARROW_DCHECK_LT(val1, val2)      \
114   while (false) ARROW_IGNORE_EXPR(val1); \
115   while (false) ARROW_IGNORE_EXPR(val2); \
116   while (false) ::arrow::util::detail::NullLog()
117 #define ARROW_DCHECK_GE(val1, val2)      \
118   while (false) ARROW_IGNORE_EXPR(val1); \
119   while (false) ARROW_IGNORE_EXPR(val2); \
120   while (false) ::arrow::util::detail::NullLog()
121 #define ARROW_DCHECK_GT(val1, val2)      \
122   while (false) ARROW_IGNORE_EXPR(val1); \
123   while (false) ARROW_IGNORE_EXPR(val2); \
124   while (false) ::arrow::util::detail::NullLog()
125 
126 #else
127 #define ARROW_DFATAL ::arrow::util::ArrowLogLevel::ARROW_FATAL
128 
129 #define ARROW_DCHECK ARROW_CHECK
130 #define ARROW_DCHECK_OK ARROW_CHECK_OK
131 #define ARROW_DCHECK_EQ ARROW_CHECK_EQ
132 #define ARROW_DCHECK_NE ARROW_CHECK_NE
133 #define ARROW_DCHECK_LE ARROW_CHECK_LE
134 #define ARROW_DCHECK_LT ARROW_CHECK_LT
135 #define ARROW_DCHECK_GE ARROW_CHECK_GE
136 #define ARROW_DCHECK_GT ARROW_CHECK_GT
137 
138 #endif  // NDEBUG
139 
140 #define DCHECK ARROW_DCHECK
141 #define DCHECK_OK ARROW_DCHECK_OK
142 #define DCHECK_EQ ARROW_DCHECK_EQ
143 #define DCHECK_NE ARROW_DCHECK_NE
144 #define DCHECK_LE ARROW_DCHECK_LE
145 #define DCHECK_LT ARROW_DCHECK_LT
146 #define DCHECK_GE ARROW_DCHECK_GE
147 #define DCHECK_GT ARROW_DCHECK_GT
148 
149 // This code is adapted from
150 // https://github.com/ray-project/ray/blob/master/src/ray/util/logging.h.
151 
152 // To make the logging lib pluggable with other logging libs and make
153 // the implementation unawared by the user, ArrowLog is only a declaration
154 // which hide the implementation into logging.cc file.
155 // In logging.cc, we can choose different log libs using different macros.
156 
157 // This is also a null log which does not output anything.
158 class ARROW_EXPORT ArrowLogBase {
159  public:
~ArrowLogBase()160   virtual ~ArrowLogBase() {}
161 
IsEnabled()162   virtual bool IsEnabled() const { return false; }
163 
164   template <typename T>
165   ArrowLogBase& operator<<(const T& t) {
166     if (IsEnabled()) {
167       Stream() << t;
168     }
169     return *this;
170   }
171 
172  protected:
173   virtual std::ostream& Stream() = 0;
174 };
175 
176 class ARROW_EXPORT ArrowLog : public ArrowLogBase {
177  public:
178   ArrowLog(const char* file_name, int line_number, ArrowLogLevel severity);
179   ~ArrowLog() override;
180 
181   /// Return whether or not current logging instance is enabled.
182   ///
183   /// \return True if logging is enabled and false otherwise.
184   bool IsEnabled() const override;
185 
186   /// The init function of arrow log for a program which should be called only once.
187   ///
188   /// \param appName The app name which starts the log.
189   /// \param severity_threshold Logging threshold for the program.
190   /// \param logDir Logging output file name. If empty, the log won't output to file.
191   static void StartArrowLog(const std::string& appName,
192                             ArrowLogLevel severity_threshold = ArrowLogLevel::ARROW_INFO,
193                             const std::string& logDir = "");
194 
195   /// The shutdown function of arrow log, it should be used with StartArrowLog as a pair.
196   static void ShutDownArrowLog();
197 
198   /// Install the failure signal handler to output call stack when crash.
199   /// If glog is not installed, this function won't do anything.
200   static void InstallFailureSignalHandler();
201 
202   /// Uninstall the signal actions installed by InstallFailureSignalHandler.
203   static void UninstallSignalAction();
204 
205   /// Return whether or not the log level is enabled in current setting.
206   ///
207   /// \param log_level The input log level to test.
208   /// \return True if input log level is not lower than the threshold.
209   static bool IsLevelEnabled(ArrowLogLevel log_level);
210 
211  private:
212   ARROW_DISALLOW_COPY_AND_ASSIGN(ArrowLog);
213 
214   // Hide the implementation of log provider by void *.
215   // Otherwise, lib user may define the same macro to use the correct header file.
216   void* logging_provider_;
217   /// True if log messages should be logged and false if they should be ignored.
218   bool is_enabled_;
219 
220   static ArrowLogLevel severity_threshold_;
221 
222  protected:
223   std::ostream& Stream() override;
224 };
225 
226 // This class make ARROW_CHECK compilation pass to change the << operator to void.
227 // This class is copied from glog.
228 class ARROW_EXPORT Voidify {
229  public:
Voidify()230   Voidify() {}
231   // This has to be an operator with a precedence lower than << but
232   // higher than ?:
233   void operator&(ArrowLogBase&) {}
234 };
235 
236 namespace detail {
237 
238 /// @brief A helper for the nil log sink.
239 ///
240 /// Using this helper is analogous to sending log messages to /dev/null:
241 /// nothing gets logged.
242 class NullLog {
243  public:
244   /// The no-op output operator.
245   ///
246   /// @param [in] t
247   ///   The object to send into the nil sink.
248   /// @return Reference to the updated object.
249   template <class T>
250   NullLog& operator<<(const T& t) {
251     return *this;
252   }
253 };
254 
255 }  // namespace detail
256 }  // namespace util
257 }  // namespace arrow
258 
259 #endif  // GANDIVA_IR
260