aboutsummaryrefslogtreecommitdiffstats
path: root/CommonLibs/Configuration.cpp
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-01-09 15:09:08 +0100
committerPau Espin Pedrol <pespin@sysmocom.de>2018-01-09 15:26:50 +0100
commitcaf2abc58fb72da9ec25cbf141e642268816f08f (patch)
treedc876e10e509db2a679dd71fb7c8e534baeb562d /CommonLibs/Configuration.cpp
parentde1685f6d7f169225bba4d1dd5fd767c5ff93b82 (diff)
Remove Configuration module and libsqlite dependency
Diffstat (limited to 'CommonLibs/Configuration.cpp')
-rw-r--r--CommonLibs/Configuration.cpp1160
1 files changed, 0 insertions, 1160 deletions
diff --git a/CommonLibs/Configuration.cpp b/CommonLibs/Configuration.cpp
deleted file mode 100644
index 4661903..0000000
--- a/CommonLibs/Configuration.cpp
+++ /dev/null
@@ -1,1160 +0,0 @@
-/*
-* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
-* Copyright 2010 Kestrel Signal Processing, Inc.
-* Copyright 2011, 2012 Range Networks, Inc.
-*
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-#include "Configuration.h"
-#include "Logger.h"
-#include <fstream>
-#include <iostream>
-#include <string.h>
-
-#ifdef DEBUG_CONFIG
-#define debugLogEarly gLogEarly
-#else
-#define debugLogEarly(x,y,z)
-#endif
-
-
-using namespace std;
-
-char gCmdName[20] = {0}; // Use a char* to avoid avoid static initialization of string, and race at startup.
-
-static const char* createConfigTable = {
- "CREATE TABLE IF NOT EXISTS CONFIG ("
- "KEYSTRING TEXT UNIQUE NOT NULL, "
- "VALUESTRING TEXT, "
- "STATIC INTEGER DEFAULT 0, "
- "OPTIONAL INTEGER DEFAULT 0, "
- "COMMENTS TEXT DEFAULT ''"
- ")"
-};
-
-static std::string replaceAll(const std::string input, const std::string search, const std::string replace)
-{
- std::string output = input;
- size_t index = 0;
-
- while (true) {
- index = output.find(search, index);
- if (index == std::string::npos) {
- break;
- }
-
- output.replace(index, replace.length(), replace);
- index += replace.length();
- }
-
- return output;
-}
-
-
-float ConfigurationRecord::floatNumber() const
-{
- float val;
- sscanf(mValue.c_str(),"%f",&val);
- return val;
-}
-
-
-ConfigurationTable::ConfigurationTable(const char* filename, const char *wCmdName, ConfigurationKeyMap wSchema)
-{
- gLogEarly(LOG_INFO, "opening configuration table from path %s", filename);
- // Connect to the database.
- int rc = sqlite3_open(filename,&mDB);
- // (pat) When I used malloc here, sqlite3 sporadically crashes.
- if (wCmdName) {
- strncpy(gCmdName,wCmdName,18);
- gCmdName[18] = 0;
- strcat(gCmdName,":");
- }
- if (rc) {
- gLogEarly(LOG_EMERG, "cannot open configuration database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
- sqlite3_close(mDB);
- mDB = NULL;
- return;
- }
- // Create the table, if needed.
- if (!sqlite3_command(mDB,createConfigTable)) {
- gLogEarly(LOG_EMERG, "cannot create configuration table in database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
- }
-
- // Build CommonLibs schema
- ConfigurationKey *tmp;
- tmp = new ConfigurationKey("Log.File","",
- "",
- ConfigurationKey::DEVELOPER,
- ConfigurationKey::FILEPATH_OPT,// audited
- "",
- false,
- "Path to use for textfile based logging. "
- "By default, this feature is disabled. "
- "To enable, specify an absolute path to the file you wish to use, eg: /tmp/my-debug.log. "
- "To disable again, execute \"unconfig Log.File\"."
- );
- mSchema[tmp->getName()] = *tmp;
- delete tmp;
-
- tmp = new ConfigurationKey("Log.Level","NOTICE",
- "",
- ConfigurationKey::CUSTOMER,
- ConfigurationKey::CHOICE,
- "EMERG|EMERGENCY - report serious faults associated with service failure or hardware damage,"
- "ALERT|ALERT - report likely service disruption caused by misconfiguration or poor connectivity,"
- "CRIT|CRITICAL - report anomalous events that are likely to degrade service,"
- "ERR|ERROR - report internal errors of the software that may result in degradation of service in unusual circumstances,"
- "WARNING|WARNING - report anomalous events that may indicate a degradation of normal service,"
- "NOTICE|NOTICE - report anomalous events that probably do not affect service but may be of interest to network operators,"
- "INFO|INFORMATION - report normal events,"
- "DEBUG|DEBUG - only for use by developers and will degrade system performance",
- false,
- "Default logging level when no other level is defined for a file."
- );
- mSchema[tmp->getName()] = *tmp;
- delete tmp;
-
- // Add application specific schema
- mSchema.insert(wSchema.begin(), wSchema.end());
-
- // Init the cross checking callback to something predictable
- mCrossCheck = NULL;
-}
-
-string ConfigurationTable::getDefaultSQL(const std::string& program, const std::string& version)
-{
- stringstream ss;
- ConfigurationKeyMap::iterator mp;
-
- ss << "--" << endl;
- ss << "-- This file was generated using: " << program << " --gensql" << endl;
- ss << "-- binary version: " << version << endl;
- ss << "--" << endl;
- ss << "-- Future changes should not be put in this file directly but" << endl;
- ss << "-- rather in the program's ConfigurationKey schema." << endl;
- ss << "--" << endl;
- ss << "PRAGMA foreign_keys=OFF;" << endl;
- ss << "BEGIN TRANSACTION;" << endl;
- ss << "CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');" << endl;
-
- mp = mSchema.begin();
- while (mp != mSchema.end()) {
- ss << "INSERT INTO \"CONFIG\" VALUES(";
- // name
- ss << "'" << mp->first << "',";
- // default
- ss << "'" << mp->second.getDefaultValue() << "',";
- // static
- if (mp->second.isStatic()) {
- ss << "1";
- } else {
- ss << "0";
- }
- ss << ",";
- // optional
- ss << "0,";
- // description
- ss << "'";
- if (mp->second.getType() == ConfigurationKey::BOOLEAN) {
- ss << "1=enabled, 0=disabled - ";
- }
- ss << mp->second.getDescription();
- if (mp->second.isStatic()) {
- ss << " Static.";
- }
- ss << "'";
- ss << ");" << endl;
- mp++;
- }
-
- ss << "COMMIT;" << endl;
- ss << endl;
-
- return ss.str();
-}
-
-string ConfigurationTable::getTeX(const std::string& program, const std::string& version)
-{
- stringstream ss;
- ConfigurationKeyMap::iterator mp;
-
- ss << "% START AUTO-GENERATED CONTENT" << endl;
- ss << "% -- these sections were generated using: " << program << " --gentex" << endl;
- ss << "% -- binary version: " << version << endl;
-
- ss << "\\subsection{Customer Site Parameters}" << endl;
- ss << "These parameters must be changed to fit your site." << endl;
- ss << "\\begin{itemize}" << endl;
- mp = mSchema.begin();
- while (mp != mSchema.end()) {
- if (mp->second.getVisibility() == ConfigurationKey::CUSTOMERSITE) {
- ss << " \\item ";
- // name
- ss << mp->first << " -- ";
- // description
- ss << mp->second.getDescription();
- ss << endl;
- }
- mp++;
- }
- ss << "\\end{itemize}" << endl;
- ss << endl;
-
- ss << "\\subsection{Customer Tuneable Parameters}" << endl;
- ss << "These parameters can be changed to optimize your site." << endl;
- ss << "\\begin{itemize}" << endl;
- mp = mSchema.begin();
- while (mp != mSchema.end()) {
- if (mp->second.getVisibility() != ConfigurationKey::CUSTOMERSITE &&
- (
- mp->second.getVisibility() == ConfigurationKey::CUSTOMER ||
- mp->second.getVisibility() == ConfigurationKey::CUSTOMERTUNE ||
- mp->second.getVisibility() == ConfigurationKey::CUSTOMERWARN
- )) {
- ss << " \\item ";
- // name
- ss << mp->first << " -- ";
- // description
- ss << mp->second.getDescription();
- ss << endl;
- }
- mp++;
- }
- ss << "\\end{itemize}" << endl;
- ss << endl;
-
- ss << "\\subsection{Developer/Factory Parameters}" << endl;
- ss << "These parameters should only be changed by when developing new code." << endl;
- ss << "\\begin{itemize}" << endl;
- mp = mSchema.begin();
- while (mp != mSchema.end()) {
- if (mp->second.getVisibility() == ConfigurationKey::FACTORY ||
- mp->second.getVisibility() == ConfigurationKey::DEVELOPER) {
- ss << " \\item ";
- // name
- ss << mp->first << " -- ";
- // description
- ss << mp->second.getDescription();
- ss << endl;
- }
- mp++;
- }
- ss << "\\end{itemize}" << endl;
- ss << "% END AUTO-GENERATED CONTENT" << endl;
- ss << endl;
-
- string tmp = replaceAll(ss.str(), "^", "\\^");
- return replaceAll(tmp, "_", "\\_");
-}
-
-bool ConfigurationTable::defines(const string& key)
-{
- try {
- ScopedLock lock(mLock);
- return lookup(key).defined();
- } catch (ConfigurationTableKeyNotFound) {
- debugLogEarly(LOG_ALERT, "configuration parameter %s not found", key.c_str());
- return false;
- }
-}
-
-bool ConfigurationTable::keyDefinedInSchema(const std::string& name)
-{
- return mSchema.find(name) == mSchema.end() ? false : true;
-}
-
-bool ConfigurationTable::isValidValue(const std::string& name, const std::string& val) {
- bool ret = false;
-
- ConfigurationKey key = mSchema[name];
-
- switch (key.getType()) {
- case ConfigurationKey::BOOLEAN: {
- if (val == "1" || val == "0") {
- ret = true;
- }
- break;
- }
-
- case ConfigurationKey::CHOICE_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::CHOICE: {
- int startPos = -1;
- uint endPos = 0;
-
- std::string tmp = key.getValidValues();
-
- do {
- startPos++;
- if ((endPos = tmp.find('|', startPos)) != std::string::npos) {
- if (val == tmp.substr(startPos, endPos-startPos)) {
- ret = true;
- break;
- }
- } else {
- if (val == tmp.substr(startPos, tmp.find(',', startPos)-startPos)) {
- ret = true;
- break;
- }
- }
-
- } while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);
- break;
- }
-
- case ConfigurationKey::CIDR_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::CIDR: {
- uint delimiter;
- std::string ip;
- int cidr = -1;
-
- delimiter = val.find('/');
- if (delimiter != std::string::npos) {
- ip = val.substr(0, delimiter);
- std::stringstream(val.substr(delimiter+1)) >> cidr;
- if (ConfigurationKey::isValidIP(ip) && 0 <= cidr && cidr <= 32) {
- ret = true;
- }
- }
- break;
- }
-
- case ConfigurationKey::FILEPATH_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::FILEPATH: {
- regex_t r;
- const char* expression = "^[a-zA-Z0-9/_.-]+$";
- int result = regcomp(&r, expression, REG_EXTENDED);
- if (result) {
- char msg[256];
- regerror(result,&r,msg,255);
- break;//abort();
- }
- if (regexec(&r, val.c_str(), 0, NULL, 0)==0) {
- ret = true;
- }
- regfree(&r);
- break;
- }
-
- case ConfigurationKey::IPADDRESS_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::IPADDRESS: {
- ret = ConfigurationKey::isValidIP(val);
- break;
- }
-
- case ConfigurationKey::IPANDPORT: {
- uint delimiter;
- std::string ip;
- int port = -1;
-
- delimiter = val.find(':');
- if (delimiter != std::string::npos) {
- ip = val.substr(0, delimiter);
- std::stringstream(val.substr(delimiter+1)) >> port;
- if (ConfigurationKey::isValidIP(ip) && 1 <= port && port <= 65535) {
- ret = true;
- }
- }
- break;
- }
-
- case ConfigurationKey::MIPADDRESS_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::MIPADDRESS: {
- int startPos = -1;
- uint endPos = 0;
-
- do {
- startPos++;
- endPos = val.find(' ', startPos);
- if (ConfigurationKey::isValidIP(val.substr(startPos, endPos-startPos))) {
- ret = true;
- } else {
- ret = false;
- break;
- }
-
- } while ((startPos = endPos) != (int)std::string::npos);
- break;
- }
-
- case ConfigurationKey::PORT_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::PORT: {
- int intVal;
-
- std::stringstream(val) >> intVal;
-
- if (1 <= intVal && intVal <= 65535) {
- ret = true;
- }
- break;
- }
-
- case ConfigurationKey::REGEX_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::REGEX: {
- regex_t r;
- const char* expression = val.c_str();
- int result = regcomp(&r, expression, REG_EXTENDED);
- if (result) {
- char msg[256];
- regerror(result,&r,msg,255);
- } else {
- ret = true;
- }
- regfree(&r);
- break;
- }
-
- case ConfigurationKey::STRING_OPT: {
- if (val.length() == 0) {
- ret = true;
- break;
- }
- }
- case ConfigurationKey::STRING: {
- regex_t r;
- const char* expression = key.getValidValues().c_str();
- int result = regcomp(&r, expression, REG_EXTENDED);
- if (result) {
- char msg[256];
- regerror(result,&r,msg,255);
- break;//abort();
- }
- if (regexec(&r, val.c_str(), 0, NULL, 0)==0) {
- ret = true;
- }
- regfree(&r);
- break;
- }
-
- case ConfigurationKey::VALRANGE: {
- regex_t r;
- int result;
- if (key.getValidValues().find('.') != std::string::npos) {
- result = regcomp(&r, "^[0-9.-]+$", REG_EXTENDED);
- } else {
- result = regcomp(&r, "^[0-9-]+$", REG_EXTENDED);
- }
- if (result) {
- char msg[256];
- regerror(result,&r,msg,255);
- break;//abort();
- }
- if (regexec(&r, val.c_str(), 0, NULL, 0)!=0) {
- ret = false;
- } else if (key.getValidValues().find('.') != std::string::npos) {
- ret = ConfigurationKey::isInValRange<float>(key, val, false);
- } else {
- ret = ConfigurationKey::isInValRange<int>(key, val, true);
- }
-
- regfree(&r);
- break;
- }
- }
-
- return ret;
-}
-
-ConfigurationKeyMap ConfigurationTable::getSimilarKeys(const std::string& snippet) {
- ConfigurationKeyMap tmp;
-
- ConfigurationKeyMap::const_iterator mp = mSchema.begin();
- while (mp != mSchema.end()) {
- if (mp->first.find(snippet) != std::string::npos) {
- tmp[mp->first] = mp->second;
- }
- mp++;
- }
-
- return tmp;
-}
-
-const ConfigurationRecord& ConfigurationTable::lookup(const string& key)
-{
- assert(mDB);
- checkCacheAge();
- // We assume the caller holds mLock.
- // So it is OK to return a reference into the cache.
-
- // Check the cache.
- // This is cheap.
- ConfigurationMap::const_iterator where = mCache.find(key);
- if (where!=mCache.end()) {
- if (where->second.defined()) return where->second;
- throw ConfigurationTableKeyNotFound(key);
- }
-
- // Check the database.
- // This is more expensive.
- char *value = NULL;
- sqlite3_single_lookup(mDB,"CONFIG",
- "KEYSTRING",key.c_str(),"VALUESTRING",value);
-
- // value found, cache the result
- if (value) {
- mCache[key] = ConfigurationRecord(value);
- // key definition found, cache the default
- } else if (keyDefinedInSchema(key)) {
- mCache[key] = ConfigurationRecord(mSchema[key].getDefaultValue());
- // total miss, cache the error
- } else {
- mCache[key] = ConfigurationRecord(false);
- throw ConfigurationTableKeyNotFound(key);
- }
-
- free(value);
-
- // Leave mLock locked. The caller holds it still.
- return mCache[key];
-}
-
-
-
-bool ConfigurationTable::isStatic(const string& key)
-{
- if (keyDefinedInSchema(key)) {
- return mSchema[key].isStatic();
- } else {
- return false;
- }
-}
-
-
-
-
-string ConfigurationTable::getStr(const string& key)
-{
- // We need the lock because rec is a reference into the cache.
- try {
- ScopedLock lock(mLock);
- return lookup(key).value();
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-}
-
-
-bool ConfigurationTable::getBool(const string& key)
-{
- try {
- return getNum(key) != 0;
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-}
-
-
-long ConfigurationTable::getNum(const string& key)
-{
- // We need the lock because rec is a reference into the cache.
- try {
- ScopedLock lock(mLock);
- return lookup(key).number();
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-}
-
-
-float ConfigurationTable::getFloat(const string& key)
-{
- try {
- ScopedLock lock(mLock);
- return lookup(key).floatNumber();
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-}
-
-std::vector<string> ConfigurationTable::getVectorOfStrings(const string& key)
-{
- // Look up the string.
- char *line=NULL;
- try {
- ScopedLock lock(mLock);
- const ConfigurationRecord& rec = lookup(key);
- line = strdup(rec.value().c_str());
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-
- assert(line);
- char *lp = line;
-
- // Parse the string.
- std::vector<string> retVal;
- while (lp) {
- while (*lp==' ') lp++;
- if (*lp == '\0') break;
- char *tp = strsep(&lp," ");
- if (!tp) break;
- retVal.push_back(tp);
- }
- free(line);
- return retVal;
-}
-
-
-std::vector<unsigned> ConfigurationTable::getVector(const string& key)
-{
- // Look up the string.
- char *line=NULL;
- try {
- ScopedLock lock(mLock);
- const ConfigurationRecord& rec = lookup(key);
- line = strdup(rec.value().c_str());
- } catch (ConfigurationTableKeyNotFound) {
- // Raise an alert and re-throw the exception.
- debugLogEarly(LOG_ALERT, "configuration parameter %s has no defined value", key.c_str());
- throw ConfigurationTableKeyNotFound(key);
- }
-
- assert(line);
- char *lp = line;
-
- // Parse the string.
- std::vector<unsigned> retVal;
- while (lp) {
- // Watch for multiple or trailing spaces.
- while (*lp==' ') lp++;
- if (*lp=='\0') break;
- retVal.push_back(strtol(lp,NULL,0));
- strsep(&lp," ");
- }
- free(line);
- return retVal;
-}
-
-
-bool ConfigurationTable::remove(const string& key)
-{
- assert(mDB);
-
- ScopedLock lock(mLock);
- // Clear the cache entry and the database.
- ConfigurationMap::iterator where = mCache.find(key);
- if (where!=mCache.end()) mCache.erase(where);
- // Really remove it.
- string cmd = "DELETE FROM CONFIG WHERE KEYSTRING=='"+key+"'";
- return sqlite3_command(mDB,cmd.c_str());
-}
-
-
-
-void ConfigurationTable::find(const string& pat, ostream& os) const
-{
- // Prepare the statement.
- string cmd = "SELECT KEYSTRING,VALUESTRING FROM CONFIG WHERE KEYSTRING LIKE \"%" + pat + "%\"";
- sqlite3_stmt *stmt;
- if (sqlite3_prepare_statement(mDB,&stmt,cmd.c_str())) return;
- // Read the result.
- int src = sqlite3_run_query(mDB,stmt);
- while (src==SQLITE_ROW) {
- const char* value = (const char*)sqlite3_column_text(stmt,1);
- os << sqlite3_column_text(stmt,0) << " ";
- int len = 0;
- if (value) {
- len = strlen(value);
- }
- if (len && value) os << value << endl;
- else os << "(disabled)" << endl;
- src = sqlite3_run_query(mDB,stmt);
- }
- sqlite3_finalize(stmt);
-}
-
-
-ConfigurationRecordMap ConfigurationTable::getAllPairs() const
-{
- ConfigurationRecordMap tmp;
-
- // Prepare the statement.
- string cmd = "SELECT KEYSTRING,VALUESTRING FROM CONFIG";
- sqlite3_stmt *stmt;
- if (sqlite3_prepare_statement(mDB,&stmt,cmd.c_str())) return tmp;
- // Read the result.
- int src = sqlite3_run_query(mDB,stmt);
- while (src==SQLITE_ROW) {
- const char* key = (const char*)sqlite3_column_text(stmt,0);
- const char* value = (const char*)sqlite3_column_text(stmt,1);
- if (key && value) {
- tmp[string(key)] = ConfigurationRecord(value);
- } else if (key && !value) {
- tmp[string(key)] = ConfigurationRecord(false);
- }
- src = sqlite3_run_query(mDB,stmt);
- }
- sqlite3_finalize(stmt);
-
- return tmp;
-}
-
-bool ConfigurationTable::set(const string& key, const string& value)
-{
- assert(mDB);
- ScopedLock lock(mLock);
- string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",\"" + value + "\",1)";
- bool success = sqlite3_command(mDB,cmd.c_str());
- // Cache the result.
- if (success) mCache[key] = ConfigurationRecord(value);
- return success;
-}
-
-bool ConfigurationTable::set(const string& key, long value)
-{
- char buffer[30];
- sprintf(buffer,"%ld",value);
- return set(key,buffer);
-}
-
-
-bool ConfigurationTable::set(const string& key)
-{
- assert(mDB);
- ScopedLock lock(mLock);
- string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",NULL,1)";
- bool success = sqlite3_command(mDB,cmd.c_str());
- if (success) mCache[key] = ConfigurationRecord(true);
- return success;
-}
-
-
-void ConfigurationTable::checkCacheAge()
-{
- // mLock is set by caller
- static time_t timeOfLastPurge = 0;
- time_t now = time(NULL);
- // purge every 3 seconds
- // purge period cannot be configuration parameter
- if (now - timeOfLastPurge < 3) return;
- timeOfLastPurge = now;
- // this is purge() without the lock
- ConfigurationMap::iterator mp = mCache.begin();
- while (mp != mCache.end()) {
- ConfigurationMap::iterator prev = mp;
- mp++;
- mCache.erase(prev);
- }
-}
-
-
-void ConfigurationTable::purge()
-{
- ScopedLock lock(mLock);
- ConfigurationMap::iterator mp = mCache.begin();
- while (mp != mCache.end()) {
- ConfigurationMap::iterator prev = mp;
- mp++;
- mCache.erase(prev);
- }
-}
-
-
-void ConfigurationTable::setUpdateHook(void(*func)(void *,int ,char const *,char const *,sqlite3_int64))
-{
- assert(mDB);
- sqlite3_update_hook(mDB,func,NULL);
-}
-
-
-void ConfigurationTable::setCrossCheckHook(vector<string> (*wCrossCheck)(const string&))
-{
- mCrossCheck = wCrossCheck;
-}
-
-
-vector<string> ConfigurationTable::crossCheck(const string& key) {
- vector<string> ret;
-
- if (mCrossCheck != NULL) {
- ret = mCrossCheck(key);
- }
-
- return ret;
-}
-
-void HashString::computeHash()
-{
- // FIXME -- Someone needs to review this hash function.
- const char* cstr = c_str();
- mHash = 0;
- for (unsigned i=0; i<size(); i++) {
- mHash = mHash ^ (mHash >> 32);
- mHash = mHash*127 + cstr[i];
- }
-}
-
-
-void SimpleKeyValue::addItem(const char* pair_orig)
-{
- char *pair = strdup(pair_orig);
- char *key = pair;
- char *mark = strchr(pair,'=');
- if (!mark) return;
- *mark = '\0';
- char *value = mark+1;
- mMap[key] = value;
- free(pair);
-}
-
-
-
-const char* SimpleKeyValue::get(const char* key) const
-{
- HashStringMap::const_iterator p = mMap.find(key);
- if (p==mMap.end()) return NULL;
- return p->second.c_str();
-}
-
-
-void SimpleKeyValue::addItems(const char* pairs_orig)
-{
- char *pairs = strdup(pairs_orig);
- char *thisPair;
- while ((thisPair=strsep(&pairs," "))!=NULL) {
- addItem(thisPair);
- }
- free(pairs);
-}
-
-
-bool ConfigurationKey::isValidIP(const std::string& ip) {
- struct sockaddr_in sa;
- return inet_pton(AF_INET, ip.c_str(), &(sa.sin_addr)) != 0;
-}
-
-
-void ConfigurationKey::getMinMaxStepping(const ConfigurationKey &key, std::string &min, std::string &max, std::string &stepping) {
- uint delimiter;
- int startPos;
- uint endPos;
-
- std::string tmp = key.getValidValues();
- stepping = "1";
-
- // grab steps if they're defined
- startPos = tmp.find('(');
- if (startPos != (int)std::string::npos) {
- endPos = tmp.find(')');
- stepping = tmp.substr(startPos+1, endPos-startPos-1);
- tmp = tmp.substr(0, startPos);
- }
- startPos = 0;
-
- delimiter = tmp.find(':', startPos);
- min = tmp.substr(startPos, delimiter-startPos);
- max = tmp.substr(delimiter+1, tmp.find(',', delimiter)-delimiter-1);
-}
-
-
-template<class T> bool ConfigurationKey::isInValRange(const ConfigurationKey &key, const std::string& val, const bool isInteger) {
- bool ret = false;
-
- T convVal;
- T min;
- T max;
- T steps;
- std::string strMin;
- std::string strMax;
- std::string strSteps;
-
- std::stringstream(val) >> convVal;
-
- ConfigurationKey::getMinMaxStepping(key, strMin, strMax, strSteps);
- std::stringstream(strMin) >> min;
- std::stringstream(strMax) >> max;
- std::stringstream(strSteps) >> steps;
-
- // TODO : only ranges checked, steps not enforced
- if (isInteger) {
- if (val.find('.') == std::string::npos && min <= convVal && convVal <= max) {
- ret = true;
- }
- } else {
- if (min <= convVal && convVal <= max) {
- ret = true;
- }
- }
-
- return ret;
-}
-
-const std::string ConfigurationKey::getARFCNsString() {
- stringstream ss;
- int i;
- float downlink;
- float uplink;
-
- // 128:251 GSM850
- downlink = 869.2;
- uplink = 824.2;
- for (i = 128; i <= 251; i++) {
- ss << i << "|GSM850 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
- downlink += 0.2;
- uplink += 0.2;
- }
-
- // 1:124 PGSM900
- downlink = 935.2;
- uplink = 890.2;
- for (i = 1; i <= 124; i++) {
- ss << i << "|PGSM900 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
- downlink += 0.2;
- uplink += 0.2;
- }
-
- // 512:885 DCS1800
- downlink = 1805.2;
- uplink = 1710.2;
- for (i = 512; i <= 885; i++) {
- ss << i << "|DCS1800 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
- downlink += 0.2;
- uplink += 0.2;
- }
-
- // 512:810 PCS1900
- downlink = 1930.2;
- uplink = 1850.2;
- for (i = 512; i <= 810; i++) {
- ss << i << "|PCS1900 #" << i << " : " << downlink << " MHz downlink / " << uplink << " MHz uplink,";
- downlink += 0.2;
- uplink += 0.2;
- }
-
- ss << endl;
-
- return ss.str();
-}
-
-const std::string ConfigurationKey::visibilityLevelToString(const ConfigurationKey::VisibilityLevel& visibility) {
- std::string ret = "UNKNOWN ERROR";
-
- switch (visibility) {
- case ConfigurationKey::CUSTOMER:
- ret = "customer - can be freely changed by the customer without any detriment to their system";
- break;
- case ConfigurationKey::CUSTOMERSITE:
- ret = "customer site - these values are different for each BTS and should not be left default";
- break;
- case ConfigurationKey::CUSTOMERTUNE:
- ret = "customer tune - should only be changed to tune an installation to better suit the physical environment or MS usage pattern";
- break;
- case ConfigurationKey::CUSTOMERWARN:
- ret = "customer warn - a warning will be presented and confirmation required before changing this sensitive setting";
- break;
- case ConfigurationKey::DEVELOPER:
- ret = "developer - should only be changed by developers to debug/optimize the implementation";
- break;
- case ConfigurationKey::FACTORY:
- ret = "factory - set once at the factory, should never be changed";
- break;
- }
-
- return ret;
-}
-
-const std::string ConfigurationKey::typeToString(const ConfigurationKey::Type& type) {
- std::string ret = "UNKNOWN ERROR";
-
- switch (type) {
- case BOOLEAN:
- ret = "boolean";
- break;
- case CHOICE_OPT:
- ret = "multiple choice (optional)";
- break;
- case CHOICE:
- ret = "multiple choice";
- break;
- case CIDR_OPT:
- ret = "CIDR notation (optional)";
- break;
- case CIDR:
- ret = "CIDR notation";
- break;
- case FILEPATH_OPT:
- ret = "file path (optional)";
- break;
- case FILEPATH:
- ret = "file path";
- break;
- case IPADDRESS_OPT:
- ret = "IP address (optional)";
- break;
- case IPADDRESS:
- ret = "IP address";
- break;
- case IPANDPORT:
- ret = "IP address and port";
- break;
- case MIPADDRESS_OPT:
- ret = "space-separated list of IP addresses (optional)";
- break;
- case MIPADDRESS:
- ret = "space-separated list of IP addresses";
- break;
- case PORT_OPT:
- ret = "IP port (optional)";
- break;
- case PORT:
- ret = "IP port";
- break;
- case REGEX_OPT:
- ret = "regular expression (optional)";
- break;
- case REGEX:
- ret = "regular expression";
- break;
- case STRING_OPT:
- ret = "string (optional)";
- break;
- case STRING:
- ret = "string";
- break;
- case VALRANGE:
- ret = "value range";
- break;
- }
-
- return ret;
-}
-
-void ConfigurationKey::printKey(const ConfigurationKey &key, const std::string& currentValue, ostream& os) {
- os << key.getName() << " ";
- if (!currentValue.length()) {
- os << "(disabled)";
- } else {
- os << currentValue;
- }
- if (currentValue.compare(key.getDefaultValue()) == 0) {
- os << " [default]";
- }
- os << endl;
-}
-
-void ConfigurationKey::printDescription(const ConfigurationKey &key, ostream& os) {
- std::string tmp;
-
- os << " - description: " << key.getDescription() << std::endl;
- if (key.getUnits().length()) {
- os << " - units: " << key.getUnits() << std::endl;
- }
- os << " - type: " << ConfigurationKey::typeToString(key.getType()) << std::endl;
- if (key.getDefaultValue().length()) {
- os << " - default value: " << key.getDefaultValue() << std::endl;
- }
- os << " - visibility level: " << ConfigurationKey::visibilityLevelToString(key.getVisibility()) << std::endl;
- os << " - static: " << key.isStatic() << std::endl;
-
- tmp = key.getValidValues();
- if (key.getType() == ConfigurationKey::VALRANGE) {
- int startPos = tmp.find('(');
- uint delimiter = 0;
- if (startPos != (int)std::string::npos) {
- tmp = tmp.substr(0, startPos);
- }
- startPos = -1;
-
- do {
- startPos++;
- delimiter = tmp.find(':', startPos);
- os << " - valid values: " << "from " << tmp.substr(startPos, delimiter-startPos) << " to "
- << tmp.substr(delimiter+1, tmp.find(',', delimiter)-delimiter-1) << std::endl;
-
- } while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);
-
- } else if (key.getType() == ConfigurationKey::CHOICE) {
- int startPos = -1;
- uint endPos = 0;
-
- do {
- startPos++;
- if ((endPos = tmp.find('|', startPos)) != std::string::npos) {
- os << " - valid values: " << tmp.substr(startPos, endPos-startPos);
- os << " = " << tmp.substr(endPos+1, tmp.find(',', endPos)-endPos-1) << std::endl;
- } else {
- os << " - valid values: " << tmp.substr(startPos, tmp.find(',', startPos)-startPos) << std::endl;
- }
-
- } while ((startPos = tmp.find(',', startPos)) != (int)std::string::npos);
-
- } else if (key.getType() == ConfigurationKey::BOOLEAN) {
- os << " - valid values: 0 = disabled" << std::endl;
- os << " - valid values: 1 = enabled" << std::endl;
-
- } else if (key.getType() == ConfigurationKey::STRING) {
- os << " - valid val regex: " << tmp << std::endl;
-
- } else if (key.getValidValues().length()) {
- os << " - raw valid values: " << tmp << std::endl;
- }
-}
-
-
-// vim: ts=4 sw=4