static char *cache_log;
static int rotateNumber;
static int Levels[MAX_DEBUG_SECTIONS];
- static int level;
+ static int level; ///< minimum debugging level required by debugs() call
+ static int sectionLevel; ///< maximum debugging level allowed now
static int override_X;
static int log_stderr;
static bool log_syslog;
#define debugs(SECTION, LEVEL, CONTENT) \
do { \
if ((Debug::level = (LEVEL)) <= Debug::Levels[SECTION]) { \
+ Debug::sectionLevel = Debug::Levels[SECTION]; \
std::ostream &_dbo=Debug::getDebugOut(); \
if (Debug::level > DBG_IMPORTANT) \
_dbo << SkipBuildPrefix(__FILE__)<<"("<<__LINE__<<") "<<__FUNCTION__<<": "; \
void _db_set_syslog(const char *facility);
void _db_rotate_log(void);
+
+/// Prints raw and/or non-terminated data safely, efficiently, and beautifully.
+/// Allows raw data debugging in debugs() statements with low debugging levels
+/// by printing only if higher section debugging levels are configured:
+/// debugs(11, DBG_IMPORTANT, "always printed" << Raw(may be printed...));
+class Raw {
+public:
+ Raw(const char *label, const char *data, const size_t size):
+ level(-1), label_(label), data_(data), size_(size) {}
+
+ /// limit data printing to at least the given debugging level
+ Raw &minLevel(const int aLevel) { level = aLevel; return *this; }
+
+ /// If debugging is prohibited by the current debugs() or section level,
+ /// prints nothing. Otherwise, dumps data using one of these formats:
+ /// " label[size]=data" if label was set and data size is positive
+ /// " label[0]" if label was set and data size is zero
+ /// " data" if label was not set and data size is positive
+ /// "" (i.e., prints nothing) if label was not set and data size is zero
+ std::ostream &print(std::ostream &os) const;
+
+ /// Minimum section debugging level necessary for printing. By default,
+ /// small strings are always printed while large strings are only printed
+ /// if DBG_DATA debugging level is enabled.
+ int level;
+
+private:
+ const char *label_; ///< optional data name or ID; triggers size printing
+ const char *data_; ///< raw data to be printed
+ size_t size_; ///< data length
+};
+
+inline
+std::ostream &operator <<(std::ostream &os, const Raw &raw)
+{
+ return raw.print(os);
+}
+
#endif /* SQUID_DEBUG_H */
bool Debug::log_syslog = false;
int Debug::Levels[MAX_DEBUG_SECTIONS];
int Debug::level;
+int Debug::sectionLevel;
char *Debug::cache_log = NULL;
int Debug::rotateNumber = -1;
FILE *debug_log = NULL;
return path+BuildPrefixLength;
}
+
+std::ostream &
+Raw::print(std::ostream &os) const
+{
+ if (label_)
+ os << ' ' << label_ << '[' << size_ << ']';
+
+ if (!size_)
+ return os;
+
+ // finalize debugging level if no level was set explicitly via minLevel()
+ const int finalLevel = (level >= 0) ? level :
+ (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
+ if (finalLevel <= Debug::sectionLevel) {
+ os << (label_ ? '=' : ' ');
+ if (data_)
+ os.write(data_, size_);
+ else
+ os << "[null]";
+ }
+
+ return os;
+}
int Debug::rotateNumber = 0;
int Debug::Levels[MAX_DEBUG_SECTIONS];
int Debug::level;
+int Debug::sectionLevel;
int Debug::override_X = 0;
int Debug::log_stderr = 1;
bool Debug::log_syslog = false;
{
return path;
}
+
+std::ostream &
+Raw::print(std::ostream &os) const
+{
+ if (label_)
+ os << ' ' << label_ << '[' << size_ << ']';
+
+ if (!size_)
+ return os;
+
+ // finalize debugging level if no level was set explicitly via minLevel()
+ const int finalLevel = (level >= 0) ? level :
+ (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
+ if (finalLevel <= Debug::sectionLevel) {
+ os << (label_ ? '=' : ' ');
+ os.write(data_, size_);
+ }
+
+ return os;
+}