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