summaryrefslogtreecommitdiff
path: root/qpid/cpp/src/qpid/log/Selector.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/cpp/src/qpid/log/Selector.cpp')
-rw-r--r--qpid/cpp/src/qpid/log/Selector.cpp216
1 files changed, 183 insertions, 33 deletions
diff --git a/qpid/cpp/src/qpid/log/Selector.cpp b/qpid/cpp/src/qpid/log/Selector.cpp
index 8757486d88..9f52242694 100644
--- a/qpid/cpp/src/qpid/log/Selector.cpp
+++ b/qpid/cpp/src/qpid/log/Selector.cpp
@@ -27,59 +27,209 @@ namespace log {
using namespace std;
-void Selector::enable(const string& enableStr) {
- string level, pattern;
- size_t c=enableStr.find(':');
+const char LOG_SYMBOL_DISABLE ('!');
+const char LOG_SYMBOL_SEPERATOR(':');
+const char LOG_SYMBOL_AND_ABOVE('+');
+const char LOG_SYMBOL_AND_BELOW('-');
+
+//
+// Parse an enable or disable entry into usable fields.
+// Throws if 'level' field is not recognized.
+//
+SelectorElement::SelectorElement(const std::string cliEntry) :
+ level(qpid::log::debug),
+ category(qpid::log::unspecified),
+ isDisable(false),
+ isCategory(false),
+ isLevelAndAbove(false),
+ isLevelAndBelow(false)
+{
+ if (cliEntry.empty())
+ return;
+ std::string working(cliEntry);
+ if (LOG_SYMBOL_DISABLE == working[0]) {
+ isDisable = true;
+ working = working.substr(1);
+ }
+ size_t c=working.find(LOG_SYMBOL_SEPERATOR);
if (c==string::npos) {
- level=enableStr;
+ levelStr=working;
+ } else {
+ levelStr=working.substr(0,c);
+ patternStr=working.substr(c+1);
+ }
+ if (!levelStr.empty()) {
+ if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_ABOVE) {
+ isLevelAndAbove = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ } else if (levelStr[levelStr.size()-1]==LOG_SYMBOL_AND_BELOW) {
+ isLevelAndBelow = true;
+ levelStr = levelStr.substr(0, levelStr.size()-1);
+ }
}
- else {
- level=enableStr.substr(0,c);
- pattern=enableStr.substr(c+1);
+ level = LevelTraits::level(levelStr); // throws if bad level name
+ isCategory = CategoryTraits::isCategory(patternStr);
+ if (isCategory) {
+ category = CategoryTraits::category(patternStr);
}
- bool isCat = CategoryTraits::isCategory(pattern);
- if (!level.empty() && level[level.size()-1]=='+') {
- for (int i = LevelTraits::level(level.substr(0,level.size()-1));
- i < LevelTraits::COUNT;
- ++i) {
- if (isCat) {
- enable(Level(i), CategoryTraits::category(pattern));
+}
+
+// Empty selector
+Selector::Selector() {
+ reset();
+}
+
+
+// Selector from options
+Selector::Selector(const Options& opt){
+ reset();
+ for_each(opt.selectors.begin(), opt.selectors.end(),
+ boost::bind(&Selector::enable, this, _1));
+ for_each(opt.deselectors.begin(), opt.deselectors.end(),
+ boost::bind(&Selector::disable, this, _1));
+}
+
+
+// Selector from single level
+Selector::Selector(Level l, const std::string& s) {
+ reset();
+ enable(l, s);
+}
+
+
+// Selector from single enable
+Selector::Selector(const std::string& selector) {
+ reset();
+ enable(selector);
+}
+
+
+/**
+ * Process a single CLI --log-enable option
+ */
+void Selector::enable(const string& enableStr) {
+ if (enableStr.empty())
+ return;
+ SelectorElement se(enableStr);
+ if (se.isDisable) {
+ // Disable statements are allowed in an enable string as a convenient
+ // way to process management strings that have enable/disable mixed.
+ disable(enableStr);
+ } else if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
+ } else {
+ enable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ enableFlags[lvl][se.category] = true;
} else {
- enable(Level(i), pattern);
+ enable(Level(lvl), se.patternStr);
}
}
+ } else {
+ if (se.isCategory) {
+ enableFlags[se.level][se.category] = true;
+ } else {
+ enable(se.level, se.patternStr);
+ }
}
- else {
- if (isCat) {
- enable(LevelTraits::level(level), CategoryTraits::category(pattern));
+}
+
+void Selector::disable(const string& disableStr) {
+ if (disableStr.empty())
+ return;
+ SelectorElement se(disableStr);
+ if (se.isLevelAndAbove) {
+ for (int lvl = se.level; lvl < LevelTraits::COUNT; ++lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else if (se.isLevelAndBelow) {
+ for (int lvl = se.level; lvl >= 0; --lvl) {
+ if (se.isCategory) {
+ disableFlags[lvl][se.category] = true;
+ } else {
+ disable(Level(lvl), se.patternStr);
+ }
+ }
+ } else {
+ if (se.isCategory) {
+ disableFlags[se.level][se.category] = true;
} else {
- enable(LevelTraits::level(level), pattern);
+ disable(se.level, se.patternStr);
}
}
}
-Selector::Selector(const Options& opt){
- reset();
- for_each(opt.selectors.begin(), opt.selectors.end(),
- boost::bind(&Selector::enable, this, _1));
+
+/**
+* Enable/disable messages with level in levels where the file
+* name contains substring.
+*/
+void Selector::enable(Level level, const std::string& substring) {
+ enabledFunctions[level].push_back(substring);
}
-bool Selector::isEnabled(Level level, const char* function) {
+
+void Selector::disable(Level level, const std::string& substring) {
+ disabledFunctions[level].push_back(substring);
+}
+
+
+void Selector::reset() {
+ // Initialize fields in a Selector that are not automatically set
+ for (int lt = 0; lt < LevelTraits::COUNT; ++lt)
+ for (int ct = 0; ct < CategoryTraits::COUNT; ++ct)
+ enableFlags[lt][ct] = disableFlags[lt][ct] = false;
+}
+
+
+bool Selector::lookupFuncName(Level level, const char* function, FunctionNameTable& table) {
const char* functionEnd = function+::strlen(function);
- for (std::vector<std::string>::iterator i=substrings[level].begin();
- i != substrings[level].end();
+ for (std::vector<std::string>::iterator i=table[level].begin();
+ i != table[level].end();
++i)
- {
- if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
- return true;
- }
+ {
+ if (std::search(function, functionEnd, i->begin(), i->end()) != functionEnd)
+ return true;
+ }
return false;
}
+
+bool Selector::isEnabled(Level level, const char* function) {
+ return lookupFuncName(level, function, enabledFunctions);
+}
+
+bool Selector::isDisabled(Level level, const char* function) {
+ return lookupFuncName(level, function, disabledFunctions);
+}
+
+//
+// isEnabled
+//
+// Determines if all the fields in this Selector enable or disable a
+// level/function/category set from an actual QPID_LOG Statement.
+//
bool Selector::isEnabled(Level level, const char* function, Category category) {
- if (catFlags[level][category])
- return true;
- return isEnabled(level, function);
+ if (isDisabled(level, function))
+ return false; // Disabled by function name
+ if (disableFlags[level][category])
+ return false; // Disabled by category name
+ if (isEnabled(level, function))
+ return true; // Enabled by function name
+ if (enableFlags[level][category])
+ return true; // Enabled by category name
+ else
+ return false; // Unspecified defaults to disabled
}
}} // namespace qpid::log