merge in of error-refactor-3

concludes (fixes) SL-31187
pair programmed and reviewed by markl and karen
master
Mark Lentczner 2007-02-06 00:57:33 +00:00
parent 77f04c74eb
commit d0d4670f49
29 changed files with 1640 additions and 301 deletions

View File

@ -30,6 +30,7 @@
#include "stdtypes.h"
#include "lldefs.h"
#include "llerror.h"
#include "llformat.h"
#include "llstring.h"
#include "lltimer.h"
#include "llfasttimer.h"

View File

@ -11,9 +11,11 @@
#include "llcommon.h"
#include "llapr.h"
#include "llerrorcontrol.h"
#include "llerrorthread.h"
#include "llframetimer.h"
#include "llmemory.h"
#include "lltimer.h"
//
// Signal handling
@ -174,10 +176,8 @@ LLSD LLApp::getOptionData(OptionPriority level)
void LLApp::stepFrame()
{
// Update the static frame timer.
LLFrameTimer::updateFrameTime();
// Run ready runnables
LLEventTimer::updateClass();
mRunner.run();
}
@ -544,7 +544,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
else
{
// Don't log anything, even errors - this is because this signal could happen anywhere.
gErrorStream.setLevel(LLErrorStream::NONE);
LLError::setDefaultLevel(LLError::LEVEL_NONE);
}
// Change the signal that we reraise to SIGABRT, so we generate a core dump.

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
/**
* @file llerror.h
* @brief Constants, functions, and macros for logging and runtime errors.
* @date December 2006
* @brief error message system
*
* Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
* Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
* $License$
*/
@ -10,209 +11,208 @@
#define LL_LLERROR_H
#include <sstream>
#include <stdio.h>
#include <stdarg.h>
#include <typeinfo>
#include "llerrorstream.h"
#include "llerrorbuffer.h"
// Specific error codes
const S32 LL_ERR_NOERR = 0;
const S32 LL_ERR_ASSET_REQUEST_FAILED = -1;
//const S32 LL_ERR_ASSET_REQUEST_INVALID = -2;
const S32 LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
const S32 LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
const S32 LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
const S32 LL_ERR_EOF = -39;
const S32 LL_ERR_CANNOT_OPEN_FILE = -42;
const S32 LL_ERR_FILE_NOT_FOUND = -43;
const S32 LL_ERR_FILE_EMPTY = -44;
const S32 LL_ERR_TCP_TIMEOUT = -23016;
const S32 LL_ERR_CIRCUIT_GONE = -23017;
// Error types
#define LLERR_IMAGE (1 << 1) // Image requests
#define LLERR_MESSAGE (1 << 2) // Messaging
#define LLERR_PERF (1 << 3) // Performance
#define LLERR_SQL (1 << 4) // SQL statements
#define LLERR_DOUG (1 << 5) // Doug's debugging
#define LLERR_USER_INPUT (1 << 6) // Keyboard and mouse
#define LLERR_TIMING (1 << 7) // Verbose time info
#define LLERR_TASK (1 << 8) // Tracking tasks
#define LLERR_MSG_HANDLER (1 << 9) //
#define LLERR_CIRCUIT_INFO (1 << 10) // Message system circuit info
#define LLERR_PHYSICS (1 << 11) // physics
#define LLERR_VFS (1 << 12) // VFS
const U32 LLERR_ALL = 0xffff;
const U32 LLERR_NONE = 0x0;
// Define one of these for different error levels in release...
// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
#include "llerrorlegacy.h"
//////////////////////////////////////////
//
// Implementation - ignore
//
//
#ifdef _DEBUG
#define SHOW_DEBUG
#define SHOW_WARN
#define SHOW_INFO
#define SHOW_ASSERT
#else // _DEBUG
/* Error Logging Facility
#ifdef RELEASE_SHOW_DEBUG
#define SHOW_DEBUG
#endif
Information for most users:
Code can log messages with constuctions like this:
llinfos << "request to fizzbip agent " << agent_id
<< " denied due to timeout" << llendl;
Messages can be logged to one of four increasing levels of concern,
using one of four "streams":
#ifdef RELEASE_SHOW_WARN
#define SHOW_WARN
#endif
lldebugs - debug messages that are normally supressed
llinfos - informational messages that are normall shown
llwarns - warning messages that singal a problem
llerrs - error messages that are major, unrecoverable failures
The later (llerrs) automatically crashes the process after the message
is logged.
Note that these "streams" are actually #define magic. Rules for use:
* they cannot be used as normal streams, only to start a message
* messages written to them MUST be terminated with llendl
* between the opening and closing, the << operator is indeed
writing onto a std::ostream, so all conversions and stream
formating are available
These messages are automatically logged with function name, and (if enabled)
file and line of the message. (Note: Existing messages that already include
the function name don't get name printed twice.)
If you have a class, adding LOG_CLASS line to the declaration will cause
all messages emitted from member functions (normal and static) to be tagged
with the proper class name as well as the function name:
class LLFoo
{
LOG_CLASS(LLFoo);
public:
...
};
void LLFoo::doSomething(int i)
{
if (i > 100)
{
llwanrs << "called with a big value for i: " << i << llendl;
}
...
}
will result in messages like:
WARN: LLFoo::doSomething: called with a big value for i: 283
Which messages are logged and which are supressed can be controled at run
time from the live file logcontrol.xml based on function, class and/or
source file. See etc/logcontrol-dev.xml for details.
Lastly, logging is now very efficient in both compiled code and execution
when skipped. There is no need to wrap messages, even debugging ones, in
#ifdef _DEBUG constructs. lldebugs messages are compiled into all builds,
even release. Which means you can use them to help debug even when deployed
to a real grid.
*/
#ifdef RELEASE_SHOW_INFO
#define SHOW_INFO
#endif
#ifdef RELEASE_SHOW_ASSERT
#define SHOW_ASSERT
#endif
#endif // _DEBUG
extern LLErrorStream gErrorStream;
// LL Error macros
//
// Usage:
//
// llerrs << "An error, oh my!" << variable << endl;
// llwarns << "Another error, fuck me!" << variable << endl;
// llwarnst(LLERR_IMAGE) << "Debug, mother fucker" << endl;
//
// NOTE: The output format of filename(lineno): is so that MS DevStudio
// can parse the output and automatically jump to that location
inline std::string llerrno_string(int errnum)
namespace LLError
{
std::stringstream res;
res << "error(" << errnum << "):" << strerror(errnum) << " ";
return res.str();
enum ELevel
{
LEVEL_ALL = 0,
// used to indicate that all messagess should be logged
LEVEL_DEBUG = 0,
LEVEL_INFO = 1,
LEVEL_WARN = 2,
LEVEL_ERROR = 3, // used to be called FATAL
LEVEL_NONE = 4
// not really a level
// used to indicate that no messages should be logged
};
/* Macro support
The classes CallSite and Log are used by the logging macros below.
They are not intended for general use.
*/
class CallSite;
class Log
{
public:
static bool shouldLog(CallSite&);
static std::ostringstream* out();
static void flush(std::ostringstream*, const CallSite&);
};
class CallSite
{
// Represents a specific place in the code where a message is logged
// This is public because it is used by the macros below. It is not
// intended for public use.
public:
CallSite(ELevel, const char* file, int line,
const std::type_info& class_info, const char* function);
bool shouldLog()
{ return mCached ? mShouldLog : Log::shouldLog(*this); }
// this member function needs to be in-line for efficiency
void invalidate();
private:
// these describe the call site and never change
const ELevel mLevel;
const char* const mFile;
const int mLine;
const std::type_info& mClassInfo;
const char* const mFunction;
// these implement a cache of the call to shouldLog()
bool mCached;
bool mShouldLog;
friend class Log;
};
class End { };
inline std::ostream& operator<<(std::ostream& s, const End&)
{ return s; }
// used to indicate the end of a message
class NoClassInfo { };
// used to indicate no class info known for logging
}
inline std::string llerror_file_line(const char* file, S32 line)
{
std::stringstream res;
res << file << "(" <<line << ")";
return res.str();
}
// Used to throw an error which is always causes a system halt.
#define llerrs if (gErrorStream.isEnabledFor(LLErrorBuffer::FATAL)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::FATAL; \
llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : error\n"; \
llerror_oss << "ERROR: " << llerror_file_line(__FILE__, __LINE__) << " "
// Used to show warnings
#define llwarns if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : WARNING: "; \
else llerror_oss << "WARNING: "; \
llerror_oss
/*
Class type information for logging
*/
// Alerts are for serious non-fatal situations that are not supposed to happen and need to alert someone
#define llalerts if (gErrorStream.isEnabledFor(LLErrorBuffer::WARN)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::WARN; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : ALERT: "; \
else llerror_oss << "ALERT: "; \
llerror_oss
#define LOG_CLASS(s) typedef s _LL_CLASS_TO_LOG
// Declares class to tag logged messages with.
// See top of file for example of how to use this
typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
// Outside a class declartion, or in class without LOG_CLASS(), this
// typedef causes the messages to not be associated with any class.
// Used to show informational messages that don't get disabled
#define llinfos if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
else llerror_oss << "INFO: "; \
llerror_oss
#define llinfost(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::INFO, type)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::INFO; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : INFO: "; \
else llerror_oss << "INFO: [" << #type << "] "; \
llerror_oss
// Used for general debugging output
#define lldebugs if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
else llerror_oss << "DEBUG: "; \
llerror_oss
#define lldebugst(type) if (gErrorStream.isEnabledFor(LLErrorBuffer::DEBUG, type)) \
{ std::ostringstream llerror_oss; LLErrorBuffer::ELevel llerror_level = LLErrorBuffer::DEBUG; \
if (gErrorStream.getPrintLocation()) llerror_oss << llerror_file_line(__FILE__, __LINE__) << " : DEBUG: "; \
else llerror_oss << "DEBUG: [" << #type << "] "; \
llerror_oss
#define llendl std::endl; gErrorStream.crashOnError(llerror_oss, llerror_level); }
#define llendflush std::endl << std::flush; gErrorStream.crashOnError(llerror_oss, llerror_level); }
#define llcont llerror_oss
#define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl;
/*
Error Logging Macros
See top of file for common usage.
*/
#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
#define lllog(level) \
{ \
static LLError::CallSite _site( \
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__);\
if (_site.shouldLog()) \
{ \
std::ostringstream* _out = LLError::Log::out(); \
(*_out)
#define llendl \
LLError::End(); \
LLError::Log::flush(_out, _site); \
} \
}
#ifdef SHOW_ASSERT
#define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llassert(func)
#endif
#define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#define llinfos lllog(LLError::LEVEL_INFO)
#define lldebugs lllog(LLError::LEVEL_DEBUG)
#define llwarns lllog(LLError::LEVEL_WARN)
#define llerrs lllog(LLError::LEVEL_ERROR)
#ifdef SHOW_ASSERT
#define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llverify(func) (func); // get rid of warning C4189
#endif
#define llcont (*_out)
/*
Use this construct if you need to do computation in the middle of a
message:
llinfos << "the agent " << agend_id;
switch (f)
{
case FOP_SHRUGS: llcont << "shrugs"; break;
case FOP_TAPS: llcont << "points at " << who; break;
case FOP_SAYS: llcont << "says " << message; break;
}
llcont << " for " << t << " seconds" << llendl;
Such computation is done iff the message will be logged.
*/
// handy compile-time assert - enforce those template parameters!
#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */
// Makes the app go down in flames, but on purpose!
void _llcrash_and_loop();
// Use as follows:
// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
//
// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
// should perhaps be replaced with boost::format.
inline std::string llformat(const char *fmt, ...)
{
char tstr[1024]; /* Flawfinder: ignore */
va_list va;
va_start(va, fmt);
#if LL_WINDOWS
_vsnprintf(tstr, 1024, fmt, va);
#else
vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
#endif
va_end(va);
return std::string(tstr);
}
// Helper class to temporarily change error level for the current scope.
class LLScopedErrorLevel
{
public:
LLScopedErrorLevel(LLErrorBuffer::ELevel error_level);
~LLScopedErrorLevel();
private:
LLErrorBuffer::ELevel mOrigErrorLevel;
};
#endif // LL_LLERROR_H

View File

@ -0,0 +1,123 @@
/**
* @file llerrorcontrol.h
* @date December 2006
* @brief error message system control
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#ifndef LL_LLERRORCONTROL_H
#define LL_LLERRORCONTROL_H
#include "llerror.h"
#include <string>
class LLFixedBuffer;
class LLSD;
/*
This is the part of the LLError namespace that manages the messages
produced by the logging. The logging support is defined in llerror.h.
Most files do not need to include this.
These implementations are in llerror.cpp.
*/
namespace LLError
{
void initForServer(const std::string& identity);
// resets all logging settings to defaults needed by server processes
// logs to stderr, syslog, and windows debug log
// the identity string is used for in the syslog
void initForApplication(const std::string& dir);
// resets all logging settings to defaults needed by applicaitons
// logs to stderr and windows debug log
// sets up log configuration from the file logcontrol.xml in dir
/*
Settings that control what is logged.
Setting a level means log messages at that level or above.
*/
void setPrintLocation(bool);
void setDefaultLevel(LLError::ELevel);
void setFunctionLevel(const std::string& function_name, LLError::ELevel);
void setClassLevel(const std::string& class_name, LLError::ELevel);
void setFileLevel(const std::string& file_name, LLError::ELevel);
void configure(const LLSD&);
// the LLSD can configure all of the settings
// usually read automatically from the live errorlog.xml file
/*
Control functions.
*/
typedef void (*FatalFunction)(const std::string& message);
void crashAndLoop(const std::string& message);
// Default fatal funtion: divides by zero and loops forever
void setFatalFunction(FatalFunction);
// The fatal function will be called when an message of LEVEL_ERROR
// is logged. Note: supressing a LEVEL_ERROR message from being logged
// (by, for example, setting a class level to LEVEL_NONE), will keep
// the that message from causing the fatal funciton to be invoked.
typedef std::string (*TimeFunction)();
std::string utcTime();
void setTimeFunction(TimeFunction);
// The function is use to return the current time, formatted for
// display by those error recorders that want the time included.
class Recorder
{
// An object that handles the actual output or error messages.
public:
virtual ~Recorder();
virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
// use the level for better display, not for filtering
virtual bool wantsTime(); // default returns false
// override and return true if the recorder wants the time string
// included in the text of the message
};
void addRecorder(Recorder*);
void removeRecorder(Recorder*);
// each error message is passed to each recorder via recordMessage()
void logToFile(const std::string& filename);
void logToFixedBuffer(LLFixedBuffer*);
// Utilities to add recorders for logging to a file or a fixed buffer
// A second call to the same function will remove the logger added
// with the first.
// Passing the empty string or NULL to just removes any prior.
std::string logFileName();
// returns name of current logging file, empty string if none
/*
Utilities for use by the unit tests of LLError itself.
*/
class Settings;
Settings* saveAndResetSettings();
void restoreSettings(Settings *);
std::string abbreviateFile(const std::string& filePath);
int shouldLogCallCount();
};
#endif // LL_LLERRORCONTROL_H

View File

@ -0,0 +1,98 @@
/**
* @file llerrorlegacy.h
* @date January 2007
* @brief old things from the older error system
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#ifndef LL_LLERRORLEGACY_H
#define LL_LLERRORLEGACY_H
/*
LEGACY -- DO NOT USE THIS STUFF ANYMORE
*/
// Specific error codes
const int LL_ERR_NOERR = 0;
const int LL_ERR_ASSET_REQUEST_FAILED = -1;
//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
const int LL_ERR_EOF = -39;
const int LL_ERR_CANNOT_OPEN_FILE = -42;
const int LL_ERR_FILE_NOT_FOUND = -43;
const int LL_ERR_FILE_EMPTY = -44;
const int LL_ERR_TCP_TIMEOUT = -23016;
const int LL_ERR_CIRCUIT_GONE = -23017;
// Define one of these for different error levels in release...
// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
//////////////////////////////////////////
//
// Implementation - ignore
//
//
#ifdef _DEBUG
#define SHOW_DEBUG
#define SHOW_WARN
#define SHOW_INFO
#define SHOW_ASSERT
#else // _DEBUG
#ifdef RELEASE_SHOW_DEBUG
#define SHOW_DEBUG
#endif
#ifdef RELEASE_SHOW_WARN
#define SHOW_WARN
#endif
#ifdef RELEASE_SHOW_INFO
#define SHOW_INFO
#endif
#ifdef RELEASE_SHOW_ASSERT
#define SHOW_ASSERT
#endif
#endif // _DEBUG
#define lldebugst(type) lldebugs
#define llendflush llendl
#define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl;
#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
#ifdef SHOW_ASSERT
#define llassert(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llassert(func)
#endif
#define llassert_always(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#ifdef SHOW_ASSERT
#define llverify(func) if (!(func)) llerrs << "ASSERT (" << #func << ")" << llendl;
#else
#define llverify(func) (func); // get rid of warning C4189
#endif
// handy compile-time assert - enforce those template parameters!
#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */
//XXX: used in two places in llcommon/llskipmap.h
#endif // LL_LLERRORLEGACY_H

View File

@ -178,6 +178,7 @@ void llifstream::open(const char* _Filename, /* Flawfinder: ignore */
}
llassert(_Filebuffer == NULL);
_Filebuffer = new _Myfb(filep);
_ShouldClose = true;
_Myios::init(_Filebuffer);
}
@ -189,13 +190,17 @@ bool llifstream::is_open() const
}
llifstream::~llifstream()
{
if (_ShouldClose)
{
close();
}
delete _Filebuffer;
}
llifstream::llifstream(const char *_Filename,
ios_base::openmode _Mode,
int _Prot)
: std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL)
: std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
{ // construct with named file and specified mode
open(_Filename, _Mode | ios_base::in, _Prot); /* Flawfinder: ignore */

View File

@ -68,7 +68,7 @@ public:
typedef std::basic_ios<char,std::char_traits< char > > _Myios;
llifstream()
: std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL)
: std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
{ // construct unopened
}
@ -78,7 +78,8 @@ public:
explicit llifstream(_Filet *_File)
: std::basic_istream<char,std::char_traits< char > >(NULL,true),
_Filebuffer(new _Myfb(_File))
_Filebuffer(new _Myfb(_File)),
_ShouldClose(false)
{ // construct with specified C stream
}
virtual ~llifstream();
@ -95,6 +96,7 @@ public:
private:
_Myfb* _Filebuffer; // the file buffer
bool _ShouldClose;
};

View File

@ -0,0 +1,28 @@
/**
* @file llformat.cpp
* @date January 2007
* @brief string formatting utility
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#include "linden_common.h"
#include "llformat.h"
#include <stdarg.h>
std::string llformat(const char *fmt, ...)
{
char tstr[1024]; /* Flawfinder: ignore */
va_list va;
va_start(va, fmt);
#if LL_WINDOWS
_vsnprintf(tstr, 1024, fmt, va);
#else
vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */
#endif
va_end(va);
return std::string(tstr);
}

23
indra/llcommon/llformat.h Normal file
View File

@ -0,0 +1,23 @@
/**
* @file llformat.h
* @date January 2007
* @brief string formatting utility
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#ifndef LL_LLFORMAT_H
#define LL_LLFORMAT_H
#include <string>
// Use as follows:
// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
//
// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
// should perhaps be replaced with boost::format.
std::string llformat(const char *fmt, ...);
#endif // LL_LLFORMAT_H

View File

@ -8,24 +8,56 @@
#include "linden_common.h"
#include "lllivefile.h"
#include "llframetimer.h"
#include "lltimer.h"
class LLLiveFile::Impl
{
public:
Impl(const std::string &filename, const F32 refresh_period);
~Impl();
bool check();
bool mForceCheck;
F32 mRefreshPeriod;
LLFrameTimer mRefreshTimer;
LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period) :
mForceCheck(true),
mRefreshPeriod(refresh_period),
mFilename(filename),
mLastModTime(0),
mLastExists(false)
std::string mFilename;
time_t mLastModTime;
bool mLastExists;
LLEventTimer* mEventTimer;
};
LLLiveFile::Impl::Impl(const std::string &filename, const F32 refresh_period)
: mForceCheck(true),
mRefreshPeriod(refresh_period),
mFilename(filename),
mLastModTime(0),
mLastExists(false),
mEventTimer(NULL)
{
}
LLLiveFile::Impl::~Impl()
{
delete mEventTimer;
}
LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period)
: impl(* new Impl(filename, refresh_period))
{
}
LLLiveFile::~LLLiveFile()
{
delete &impl;
}
bool LLLiveFile::checkAndReload()
bool LLLiveFile::Impl::check()
{
if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod)
{
@ -46,9 +78,8 @@ bool LLLiveFile::checkAndReload()
// broken somehow. Clear flags and return.
if (mLastExists)
{
loadFile(); // Load the file, even though it's missing to allow it to clear state.
mLastExists = false;
return true;
return true; // no longer existing is a change!
}
return false;
}
@ -68,7 +99,44 @@ bool LLLiveFile::checkAndReload()
mLastExists = true;
mLastModTime = stat_data.st_mtime;
loadFile();
return true;
}
bool LLLiveFile::checkAndReload()
{
bool changed = impl.check();
if (changed)
{
loadFile();
}
return changed;
}
std::string LLLiveFile::filename() const
{
return impl.mFilename;
}
namespace
{
class LiveFileEventTimer : public LLEventTimer
{
public:
LiveFileEventTimer(LLLiveFile& f, F32 refresh)
: LLEventTimer(refresh), mLiveFile(f)
{ }
void tick()
{ mLiveFile.checkAndReload(); }
private:
LLLiveFile& mLiveFile;
};
}
void LLLiveFile::addToEventTimer()
{
impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod);
}

View File

@ -9,7 +9,6 @@
#ifndef LL_LLLIVEFILE_H
#define LL_LLLIVEFILE_H
#include "llframetimer.h"
class LLLiveFile
{
@ -17,18 +16,22 @@ public:
LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f);
virtual ~LLLiveFile();
bool checkAndReload(); // Returns true if the file changed in any way
bool checkAndReload();
// Returns true if the file changed in any way
// Call this before using anything that was read & cached from the file
std::string filename() const;
void addToEventTimer();
// Normally, just calling checkAndReload() is enough. In some cases
// though, you may need to let the live file periodically check itself.
protected:
virtual void loadFile() = 0; // Implement this to load your file if it changed
bool mForceCheck;
F32 mRefreshPeriod;
LLFrameTimer mRefreshTimer;
std::string mFilename;
time_t mLastModTime;
bool mLastExists;
private:
class Impl;
Impl& impl;
};
#endif //LL_LLLIVEFILE_H

View File

@ -10,6 +10,7 @@
#include <math.h>
#include "../llmath/llmath.h"
#include "llformat.h"
namespace {
class ImplMap;

View File

@ -11,6 +11,7 @@
#include "stdtypes.h"
#include "llerror.h"
#include "llfile.h"
#include <algorithm>
#include <map>
#include <stdio.h>

View File

@ -10,6 +10,8 @@
#ifndef LL_STRING_TABLE_H
#define LL_STRING_TABLE_H
#include "lldefs.h"
#include "llformat.h"
#include "llstl.h"
#include <list>
#include <set>

View File

@ -4402,33 +4402,6 @@ void process_secured_template_checksum_request(LLMessageSystem* msg, void**)
send_template_reply(msg, token);
}
void process_log_control(LLMessageSystem* msg, void**)
{
U8 level;
U32 mask;
BOOL time;
BOOL location;
BOOL remote_infos;
msg->getU8Fast(_PREHASH_Options, _PREHASH_Level, level);
msg->getU32Fast(_PREHASH_Options, _PREHASH_Mask, mask);
msg->getBOOLFast(_PREHASH_Options, _PREHASH_Time, time);
msg->getBOOLFast(_PREHASH_Options, _PREHASH_Location, location);
msg->getBOOLFast(_PREHASH_Options, _PREHASH_RemoteInfos, remote_infos);
gErrorStream.setLevel(LLErrorStream::ELevel(level));
gErrorStream.setDebugMask(mask);
gErrorStream.setTime(time);
gErrorStream.setPrintLocation(location);
gErrorStream.setElevatedRemote(remote_infos);
llinfos << "Logging set to level " << gErrorStream.getLevel()
<< " mask " << std::hex << gErrorStream.getDebugMask() << std::dec
<< " time " << gErrorStream.getTime()
<< " loc " << gErrorStream.getPrintLocation()
<< llendl;
}
void process_log_messages(LLMessageSystem* msg, void**)
{
U8 log_message;
@ -4749,7 +4722,6 @@ BOOL start_messaging_system(
gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL);
gMessageSystem->setHandlerFuncFast(_PREHASH_TemplateChecksumRequest, process_template_checksum_request, NULL);
gMessageSystem->setHandlerFuncFast(_PREHASH_SecuredTemplateChecksumRequest, process_secured_template_checksum_request, NULL);
gMessageSystem->setHandlerFuncFast(_PREHASH_LogControl, process_log_control, NULL);
gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL);
gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit,
process_create_trusted_circuit,

View File

@ -187,6 +187,8 @@ class LLMessagePollInfo;
class LLMessageSystem
{
LOG_CLASS(LLMessageSystem);
public:
U8 mSendBuffer[MAX_BUFFER_SIZE];
// Encoded send buffer needs to be slightly larger since the zero
@ -757,7 +759,6 @@ BOOL start_messaging_system(
void end_messaging_system();
void null_message_callback(LLMessageSystem *msg, void **data);
void process_log_control(LLMessageSystem* msg, void**);
//
// Inlines

View File

@ -489,7 +489,6 @@ char * _PREHASH_NVPair;
char * _PREHASH_ObjectSpinStart;
char * _PREHASH_UseEstateSun;
char * _PREHASH_LogoutBlock;
char * _PREHASH_RelayLogControl;
char * _PREHASH_RegionID;
char * _PREHASH_Creator;
char * _PREHASH_ProposalText;
@ -1294,7 +1293,6 @@ char * _PREHASH_AssetBlock;
char * _PREHASH_AcceptNotices;
char * _PREHASH_SetGroupAcceptNotices;
char * _PREHASH_CloseCircuit;
char * _PREHASH_LogControl;
char * _PREHASH_TeleportFinish;
char * _PREHASH_PathRevolutions;
char * _PREHASH_ClassifiedInfoReply;
@ -1963,7 +1961,6 @@ void init_prehash_data()
_PREHASH_ObjectSpinStart = gMessageStringTable.getString("ObjectSpinStart");
_PREHASH_UseEstateSun = gMessageStringTable.getString("UseEstateSun");
_PREHASH_LogoutBlock = gMessageStringTable.getString("LogoutBlock");
_PREHASH_RelayLogControl = gMessageStringTable.getString("RelayLogControl");
_PREHASH_RegionID = gMessageStringTable.getString("RegionID");
_PREHASH_Creator = gMessageStringTable.getString("Creator");
_PREHASH_ProposalText = gMessageStringTable.getString("ProposalText");
@ -2768,7 +2765,6 @@ void init_prehash_data()
_PREHASH_AcceptNotices = gMessageStringTable.getString("AcceptNotices");
_PREHASH_SetGroupAcceptNotices = gMessageStringTable.getString("SetGroupAcceptNotices");
_PREHASH_CloseCircuit = gMessageStringTable.getString("CloseCircuit");
_PREHASH_LogControl = gMessageStringTable.getString("LogControl");
_PREHASH_TeleportFinish = gMessageStringTable.getString("TeleportFinish");
_PREHASH_PathRevolutions = gMessageStringTable.getString("PathRevolutions");
_PREHASH_ClassifiedInfoReply = gMessageStringTable.getString("ClassifiedInfoReply");

View File

@ -489,7 +489,6 @@ extern char * _PREHASH_NVPair;
extern char * _PREHASH_ObjectSpinStart;
extern char * _PREHASH_UseEstateSun;
extern char * _PREHASH_LogoutBlock;
extern char * _PREHASH_RelayLogControl;
extern char * _PREHASH_RegionID;
extern char * _PREHASH_Creator;
extern char * _PREHASH_ProposalText;
@ -1294,7 +1293,6 @@ extern char * _PREHASH_AssetBlock;
extern char * _PREHASH_AcceptNotices;
extern char * _PREHASH_SetGroupAcceptNotices;
extern char * _PREHASH_CloseCircuit;
extern char * _PREHASH_LogControl;
extern char * _PREHASH_TeleportFinish;
extern char * _PREHASH_PathRevolutions;
extern char * _PREHASH_ClassifiedInfoReply;

View File

@ -584,7 +584,7 @@ void LLButton::draw()
else
{
// no image
llalerts << "No image for button " << mName << llendl;
llwarns << "No image for button " << mName << llendl;
// draw it in pink so we can find it
gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4::pink1, FALSE);
}

View File

@ -28,6 +28,7 @@
#include "llcrypto.h"
#include "lldir.h"
#include "lleconomy.h"
#include "llerrorcontrol.h"
#include "llfiltersd2xmlrpc.h"
#include "llfocusmgr.h"
#include "imageids.h"
@ -421,7 +422,6 @@ BOOL idle_startup()
invalid_message_callback,
NULL);
gErrorStream.setUTCTimestamp(gLogUTC);
if (gSavedSettings.getBOOL("LogMessages") || gLogMessages)
{
llinfos << "Message logging activated!" << llendl;
@ -1679,7 +1679,7 @@ BOOL idle_startup()
// Move the progress view in front of the UI
gViewerWindow->moveProgressViewToFront();
gErrorStream.setFixedBuffer(gDebugView->mDebugConsolep);
LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
// set initial visibility of debug console
gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
gDebugView->mStatViewp->setVisible(gSavedSettings.getBOOL("ShowDebugStats"));

View File

@ -430,8 +430,6 @@ void handle_dump_image_list(void*);
void handle_fullscreen_debug(void*);
void handle_crash(void*);
void handle_dump_followcam(void*);
void handle_viewer_enable_circuit_log(void*);
void handle_viewer_disable_circuit_log(void*);
void handle_viewer_enable_message_log(void*);
void handle_viewer_disable_message_log(void*);
void handle_send_postcard(void*);
@ -818,10 +816,6 @@ void init_client_menu(LLMenuGL* menu)
LLMenuGL* sub = NULL;
sub = new LLMenuGL("Network");
sub->append(new LLMenuItemCallGL("Enable Circuit Log",
&handle_viewer_enable_circuit_log, NULL));
sub->append(new LLMenuItemCallGL("Disable Circuit Log",
&handle_viewer_disable_circuit_log, NULL));
sub->append(new LLMenuItemCallGL("Enable Message Log",
&handle_viewer_enable_message_log, NULL));
sub->append(new LLMenuItemCallGL("Disable Message Log",
@ -1307,11 +1301,6 @@ void init_server_menu(LLMenuGL* menu)
&handle_normal_llinfo_log, &enable_god_customer_service));
sub_menu->appendSeparator();
sub_menu->append(new LLMenuItemCallGL("Enable Circuit Log",
&handle_sim_enable_circuit_log, &enable_god_customer_service));
sub_menu->append(new LLMenuItemCallGL("Disable Circuit Log",
&handle_sim_disable_circuit_log, &enable_god_customer_service));
sub_menu->appendSeparator();
sub_menu->append(new LLMenuItemCallGL("Enable Message Log",
&handle_sim_enable_message_log, &enable_god_customer_service));
sub_menu->append(new LLMenuItemCallGL("Disable Message Log",
@ -6375,24 +6364,6 @@ void handle_dump_followcam(void*)
LLFollowCamMgr::dump();
}
void handle_viewer_enable_circuit_log(void*)
{
llinfos << "Showing circuit information every " << gMessageSystem->mCircuitPrintFreq << " seconds" << llendl;
gErrorStream.setLevel( LLErrorStream::DEBUG );
gErrorStream.setDebugFlag( LLERR_CIRCUIT_INFO );
// and dump stuff out immediately
gMessageSystem->dumpCircuitInfo();
}
void handle_viewer_disable_circuit_log(void*)
{
llinfos << "Hiding circuit information" << llendl;
#if !LL_DEBUG
gErrorStream.setLevel( LLErrorStream::INFO );
#endif
gErrorStream.clearDebugFlag( LLERR_CIRCUIT_INFO );
}
void handle_viewer_enable_message_log(void*)
{
gMessageSystem->startLogging();

View File

@ -63,8 +63,6 @@
#include "lldqueueptr.h"
#include "llendianswizzle.h"
#include "llerror.h"
#include "llerrorbuffer.h"
#include "llerrorstream.h"
#include "llfasttimer.h"
#include "llfixedbuffer.h"
#include "llframetimer.h"

View File

@ -324,9 +324,9 @@ bool LLXMLRPCTransaction::Impl::process()
if (curl_msg->data.result != CURLE_OK)
{
setCurlStatus(curl_msg->data.result);
llalerts << "LLXMLRPCTransaction CURL error "
llwarns << "LLXMLRPCTransaction CURL error "
<< mCurlCode << ": " << mCurlErrorBuffer << llendl;
llalerts << "LLXMLRPCTransaction request URI: "
llwarns << "LLXMLRPCTransaction request URI: "
<< mURI << llendl;
return true;
@ -360,11 +360,11 @@ bool LLXMLRPCTransaction::Impl::process()
{
setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
llalerts << "LLXMLRPCTransaction XMLRPC "
llwarns << "LLXMLRPCTransaction XMLRPC "
<< (hasError ? "error " : "fault ")
<< faultCode << ": "
<< faultString << llendl;
llalerts << "LLXMLRPCTransaction request URI: "
llwarns << "LLXMLRPCTransaction request URI: "
<< mURI << llendl;
}

View File

@ -16,6 +16,7 @@
#include "lltut.h"
#include "llhttpclient.h"
#include "llformat.h"
#include "llpipeutil.h"
#include "llpumpio.h"

View File

@ -12,6 +12,7 @@
#include <stdlib.h>
#include "llbufferstream.h"
#include "lldefs.h"
#include "llframetimer.h"
#include "llpumpio.h"
#include "llrand.h"

View File

@ -9,6 +9,8 @@
*/
#include "lltut.h"
#include "llformat.h"
#include "llsd.h"
namespace tut
@ -135,6 +137,20 @@ namespace tut
}
}
void ensure_ends_with(const std::string& msg,
const std::string& actual, const std::string& expectedEnd)
{
if( actual.size() < expectedEnd.size()
|| actual.rfind(expectedEnd)
!= (actual.size() - expectedEnd.size()) )
{
std::stringstream ss;
ss << msg << ": " << "expected to find " << expectedEnd
<< " at end of actual " << actual;
throw failure(ss.str().c_str());
}
}
void ensure_contains(const std::string& msg,
const std::string& actual, const std::string& expectedSubString)
{
@ -146,4 +162,16 @@ namespace tut
throw failure(ss.str().c_str());
}
}
void ensure_does_not_contain(const std::string& msg,
const std::string& actual, const std::string& expectedSubString)
{
if( actual.find(expectedSubString, 0) != std::string::npos )
{
std::stringstream ss;
ss << msg << ": " << "expected not to find " << expectedSubString
<< " in actual " << actual;
throw failure(ss.str().c_str());
}
}
}

View File

@ -68,8 +68,14 @@ namespace tut
void ensure_starts_with(const std::string& msg,
const std::string& actual, const std::string& expectedStart);
void ensure_ends_with(const std::string& msg,
const std::string& actual, const std::string& expectedEnd);
void ensure_contains(const std::string& msg,
const std::string& actual, const std::string& expectedSubString);
void ensure_does_not_contain(const std::string& msg,
const std::string& actual, const std::string& expectedSubString);
}

View File

@ -17,6 +17,7 @@
*/
#include "linden_common.h"
#include "llerrorcontrol.h"
#include "lltut.h"
#include <apr-1/apr_pools.h>
@ -159,8 +160,18 @@ void stream_groups(std::ostream& s, const char* app)
}
}
void wouldHaveCrashed(const std::string& message)
{
tut::fail("llerrs message: " + message);
}
int main(int argc, char **argv)
{
LLError::initForApplication(".");
LLError::setFatalFunction(wouldHaveCrashed);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
// *FIX: should come from error config file
#ifdef CTYPE_WORKAROUND
ctype_workaround();
#endif