aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llerror.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llcommon/llerror.h404
1 files changed, 202 insertions, 202 deletions
diff --git a/linden/indra/llcommon/llerror.h b/linden/indra/llcommon/llerror.h
index 04e8eee..1285491 100644
--- a/linden/indra/llcommon/llerror.h
+++ b/linden/indra/llcommon/llerror.h
@@ -1,8 +1,9 @@
1/** 1/**
2 * @file llerror.h 2 * @file llerror.h
3 * @brief Constants, functions, and macros for logging and runtime errors. 3 * @date December 2006
4 * @brief error message system
4 * 5 *
5 * Copyright (c) 2001-2007, Linden Research, Inc. 6 * Copyright (c) 2006-2007, Linden Research, Inc.
6 * 7 *
7 * The source code in this file ("Source Code") is provided by Linden Lab 8 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0 9 * to you under the terms of the GNU General Public License, version 2.0
@@ -29,209 +30,208 @@
29#define LL_LLERROR_H 30#define LL_LLERROR_H
30 31
31#include <sstream> 32#include <sstream>
32#include <stdio.h> 33#include <typeinfo>
33#include <stdarg.h> 34
34 35#include "llerrorlegacy.h"
35#include "llerrorstream.h" 36
36#include "llerrorbuffer.h" 37
37 38/* Error Logging Facility
38// Specific error codes 39
39const S32 LL_ERR_NOERR = 0; 40 Information for most users:
40const S32 LL_ERR_ASSET_REQUEST_FAILED = -1; 41
41//const S32 LL_ERR_ASSET_REQUEST_INVALID = -2; 42 Code can log messages with constuctions like this:
42const S32 LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3; 43
43const S32 LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4; 44 llinfos << "request to fizzbip agent " << agent_id
44const S32 LL_ERR_INSUFFICIENT_PERMISSIONS = -5; 45 << " denied due to timeout" << llendl;
45const S32 LL_ERR_EOF = -39; 46
46const S32 LL_ERR_CANNOT_OPEN_FILE = -42; 47 Messages can be logged to one of four increasing levels of concern,
47const S32 LL_ERR_FILE_NOT_FOUND = -43; 48 using one of four "streams":
48const S32 LL_ERR_FILE_EMPTY = -44; 49
49const S32 LL_ERR_TCP_TIMEOUT = -23016; 50 lldebugs - debug messages that are normally supressed
50const S32 LL_ERR_CIRCUIT_GONE = -23017; 51 llinfos - informational messages that are normall shown
51 52 llwarns - warning messages that singal a problem
52// Error types 53 llerrs - error messages that are major, unrecoverable failures
53 54
54#define LLERR_IMAGE (1 << 1) // Image requests 55 The later (llerrs) automatically crashes the process after the message
55#define LLERR_MESSAGE (1 << 2) // Messaging 56 is logged.
56#define LLERR_PERF (1 << 3) // Performance 57
57#define LLERR_SQL (1 << 4) // SQL statements 58 Note that these "streams" are actually #define magic. Rules for use:
58#define LLERR_DOUG (1 << 5) // Doug's debugging 59 * they cannot be used as normal streams, only to start a message
59#define LLERR_USER_INPUT (1 << 6) // Keyboard and mouse 60 * messages written to them MUST be terminated with llendl
60#define LLERR_TIMING (1 << 7) // Verbose time info 61 * between the opening and closing, the << operator is indeed
61#define LLERR_TASK (1 << 8) // Tracking tasks 62 writing onto a std::ostream, so all conversions and stream
62#define LLERR_MSG_HANDLER (1 << 9) // 63 formating are available
63#define LLERR_CIRCUIT_INFO (1 << 10) // Message system circuit info 64
64#define LLERR_PHYSICS (1 << 11) // physics 65 These messages are automatically logged with function name, and (if enabled)
65#define LLERR_VFS (1 << 12) // VFS 66 file and line of the message. (Note: Existing messages that already include
66const U32 LLERR_ALL = 0xffff; 67 the function name don't get name printed twice.)
67const U32 LLERR_NONE = 0x0; 68
68 69 If you have a class, adding LOG_CLASS line to the declaration will cause
69// Define one of these for different error levels in release... 70 all messages emitted from member functions (normal and static) to be tagged
70// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output. 71 with the proper class name as well as the function name:
71#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output 72
72#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output. 73 class LLFoo
73 74 {
74 75 LOG_CLASS(LLFoo);
75////////////////////////////////////////// 76 public:
76// 77 ...
77// Implementation - ignore 78 };
78// 79
79// 80 void LLFoo::doSomething(int i)
80#ifdef _DEBUG 81 {
81#define SHOW_DEBUG 82 if (i > 100)
82#define SHOW_WARN 83 {
83#define SHOW_INFO 84 llwanrs << "called with a big value for i: " << i << llendl;
84#define SHOW_ASSERT 85 }
85#else // _DEBUG 86 ...
86 87 }
87#ifdef RELEASE_SHOW_DEBUG 88
88#define SHOW_DEBUG 89 will result in messages like:
89#endif 90
90 91 WARN: LLFoo::doSomething: called with a big value for i: 283
91#ifdef RELEASE_SHOW_WARN 92
92#define SHOW_WARN 93 Which messages are logged and which are supressed can be controled at run
93#endif 94 time from the live file logcontrol.xml based on function, class and/or
94 95 source file. See etc/logcontrol-dev.xml for details.
95#ifdef RELEASE_SHOW_INFO 96
96#define SHOW_INFO 97 Lastly, logging is now very efficient in both compiled code and execution
97#endif 98 when skipped. There is no need to wrap messages, even debugging ones, in
98 99 #ifdef _DEBUG constructs. lldebugs messages are compiled into all builds,
99#ifdef RELEASE_SHOW_ASSERT 100 even release. Which means you can use them to help debug even when deployed
100#define SHOW_ASSERT 101 to a real grid.
101#endif 102*/
102 103
103#endif // _DEBUG 104namespace LLError
104
105
106extern LLErrorStream gErrorStream;
107
108
109// LL Error macros
110//
111// Usage:
112//
113// llerrs << "An error, oh my!" << variable << endl;
114// llwarns << "Another error, fuck me!" << variable << endl;
115// llwarnst(LLERR_IMAGE) << "Debug, mother fucker" << endl;
116//
117// NOTE: The output format of filename(lineno): is so that MS DevStudio
118// can parse the output and automatically jump to that location
119
120inline std::string llerrno_string(int errnum)
121{ 105{
122 std::stringstream res; 106 enum ELevel
123 res << "error(" << errnum << "):" << strerror(errnum) << " "; 107 {
124 return res.str(); 108 LEVEL_ALL = 0,
109 // used to indicate that all messagess should be logged
110
111 LEVEL_DEBUG = 0,
112 LEVEL_INFO = 1,
113 LEVEL_WARN = 2,
114 LEVEL_ERROR = 3, // used to be called FATAL
115
116 LEVEL_NONE = 4
117 // not really a level
118 // used to indicate that no messages should be logged
119 };
120
121 /* Macro support
122 The classes CallSite and Log are used by the logging macros below.
123 They are not intended for general use.
124 */
125
126 class CallSite;
127
128 class Log
129 {
130 public:
131 static bool shouldLog(CallSite&);
132 static std::ostringstream* out();
133 static void flush(std::ostringstream*, const CallSite&);
134 };
135
136 class CallSite
137 {
138 // Represents a specific place in the code where a message is logged
139 // This is public because it is used by the macros below. It is not
140 // intended for public use.
141 public:
142 CallSite(ELevel, const char* file, int line,
143 const std::type_info& class_info, const char* function);
144
145 bool shouldLog()
146 { return mCached ? mShouldLog : Log::shouldLog(*this); }
147 // this member function needs to be in-line for efficiency
148
149 void invalidate();
150
151 private:
152 // these describe the call site and never change
153 const ELevel mLevel;
154 const char* const mFile;
155 const int mLine;
156 const std::type_info& mClassInfo;
157 const char* const mFunction;
158
159 // these implement a cache of the call to shouldLog()
160 bool mCached;
161 bool mShouldLog;
162
163 friend class Log;
164 };
165
166
167 class End { };
168 inline std::ostream& operator<<(std::ostream& s, const End&)
169 { return s; }
170 // used to indicate the end of a message
171
172 class NoClassInfo { };
173 // used to indicate no class info known for logging
125} 174}
126 175
127inline std::string llerror_file_line(const char* file, S32 line)
128{
129 std::stringstream res;
130 res << file << "(" <<line << ")";
131 return res.str();
132}
133 176
134// Used to throw an error which is always causes a system halt.
135#define llerrs if (gErrorStream.isEnabledFor(LLErrorBuffer::FATAL)) \
136 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::FATAL; \
137 llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : error\n"; \
138 llerror_oss << "ERROR: " << llerror_file_line(__FILE__, __LINE__) << " "
139
140// Used to show warnings
141#define llwarns if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
142 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
143 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : WARNING: "; \
144 else llerror_oss << "WARNING: "; \
145 llerror_oss
146
147// Alerts are for serious non-fatal situations that are not supposed to happen and need to alert someone
148#define llalerts if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
149 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
150 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : ALERT: "; \
151 else llerror_oss << "ALERT: "; \
152 llerror_oss
153
154// Used to show informational messages that don't get disabled
155#define llinfos if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO)) \
156 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
157 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
158 else llerror_oss << "INFO: "; \
159 llerror_oss
160
161#define llinfost(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO, type)) \
162 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
163 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
164 else llerror_oss << "INFO: [" << #type << "] "; \
165 llerror_oss
166
167// Used for general debugging output
168#define lldebugs if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG)) \
169 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
170 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
171 else llerror_oss << "DEBUG: "; \
172 llerror_oss
173
174#define lldebugst(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG, type)) \
175 { std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
176 if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
177 else llerror_oss << "DEBUG: [" << #type << "] "; \
178 llerror_oss
179
180#define llendl std::endl; gErrorStream.crashOnError(llerror_oss, llerror_level); }
181#define llendflush std::endl << std::flush; gErrorStream.crashOnError(llerror_oss, llerror_level); }
182#define llcont llerror_oss
183
184#define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl;
185
186#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
187
188#ifdef SHOW_ASSERT
189#define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
190#else
191#define llassert(func)
192#endif
193#define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
194
195#ifdef SHOW_ASSERT
196#define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
197#else
198#define llverify(func) (func); // get rid of warning C4189
199#endif
200
201// handy compile-time assert - enforce those template parameters!
202#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1]
203
204// Makes the app go down in flames, but on purpose!
205void _llcrash_and_loop();
206
207// Use as follows:
208// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
209//
210// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
211// should perhaps be replaced with boost::format.
212inline std::string llformat(const char *fmt, ...)
213{
214 char tstr[1024]; /* Flawfinder: ignore */
215 va_list va;
216 va_start(va, fmt);
217#if LL_WINDOWS
218 _vsnprintf(tstr, 1024, fmt, va);
219#else
220 vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
221#endif
222 va_end(va);
223 return std::string(tstr);
224}
225 177
226// Helper class to temporarily change error level for the current scope. 178/*
227class LLScopedErrorLevel 179 Class type information for logging
228{ 180 */
229public: 181
230 LLScopedErrorLevel(LLErrorBuffer::ELevel error_level); 182#define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG
231 ~LLScopedErrorLevel(); 183 // Declares class to tag logged messages with.
232 184 // See top of file for example of how to use this
233private: 185
234 LLErrorBuffer::ELevel mOrigErrorLevel; 186typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
235}; 187 // Outside a class declartion, or in class without LOG_CLASS(), this
236 188 // typedef causes the messages to not be associated with any class.
189
190
191
192
193
194/*
195 Error Logging Macros
196 See top of file for common usage.
197*/
198
199#define lllog(level) \
200 { \
201 static LLError::CallSite _site( \
202 level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__);\
203 if (_site.shouldLog()) \
204 { \
205 std::ostringstream* _out = LLError::Log::out(); \
206 (*_out)
207
208#define llendl \
209 LLError::End(); \
210 LLError::Log::flush(_out, _site); \
211 } \
212 }
213
214#define llinfos lllog(LLError::LEVEL_INFO)
215#define lldebugs lllog(LLError::LEVEL_DEBUG)
216#define llwarns lllog(LLError::LEVEL_WARN)
217#define llerrs lllog(LLError::LEVEL_ERROR)
218
219#define llcont (*_out)
220 /*
221 Use this construct if you need to do computation in the middle of a
222 message:
223
224 llinfos << "the agent " << agend_id;
225 switch (f)
226 {
227 case FOP_SHRUGS: llcont << "shrugs"; break;
228 case FOP_TAPS: llcont << "points at " << who; break;
229 case FOP_SAYS: llcont << "says " << message; break;
230 }
231 llcont << " for " << t << " seconds" << llendl;
232
233 Such computation is done iff the message will be logged.
234 */
235
236
237#endif // LL_LLERROR_H 237#endif // LL_LLERROR_H