merged private Config to public: r4211:
Changes to ConfigurationTable class. Cleaner locking operations, fewer messages for normal operations, ALERT logging for truly abnormal operations. git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4348 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
parent
f60dafa4ff
commit
bcf60a8fc9
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||||
* Copyright 2010 Kestrel Signal Processing, 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.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
|
@ -33,6 +34,7 @@
|
||||||
|
|
||||||
using namespace std;
|
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 = {
|
static const char* createConfigTable = {
|
||||||
"CREATE TABLE IF NOT EXISTS CONFIG ("
|
"CREATE TABLE IF NOT EXISTS CONFIG ("
|
||||||
|
@ -45,19 +47,36 @@ static const char* createConfigTable = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
ConfigurationTable::ConfigurationTable(const char* filename)
|
|
||||||
|
float ConfigurationRecord::floatNumber() const
|
||||||
{
|
{
|
||||||
|
float val;
|
||||||
|
sscanf(mValue.c_str(),"%f",&val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ConfigurationTable::ConfigurationTable(const char* filename, const char *wCmdName, int wFacility)
|
||||||
|
:mFacility(wFacility)
|
||||||
|
{
|
||||||
|
syslog(LOG_INFO | mFacility, "opening configuration table from path %s", filename);
|
||||||
// Connect to the database.
|
// Connect to the database.
|
||||||
int rc = sqlite3_open(filename,&mDB);
|
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) {
|
if (rc) {
|
||||||
cerr << "Cannot open configuration database: " << sqlite3_errmsg(mDB);
|
syslog(LOG_EMERG | mFacility, "cannot open configuration database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
|
||||||
sqlite3_close(mDB);
|
sqlite3_close(mDB);
|
||||||
mDB = NULL;
|
mDB = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Create the table, if needed.
|
// Create the table, if needed.
|
||||||
if (!sqlite3_command(mDB,createConfigTable)) {
|
if (!sqlite3_command(mDB,createConfigTable)) {
|
||||||
cerr << "Cannot create configuration table:" << sqlite3_errmsg(mDB);
|
syslog(LOG_EMERG | mFacility, "cannot create configuration table in database at %s, error message: %s", filename, sqlite3_errmsg(mDB));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +120,6 @@ const ConfigurationRecord& ConfigurationTable::lookup(const string& key)
|
||||||
ConfigurationMap::const_iterator where = mCache.find(key);
|
ConfigurationMap::const_iterator where = mCache.find(key);
|
||||||
if (where!=mCache.end()) {
|
if (where!=mCache.end()) {
|
||||||
if (where->second.defined()) return where->second;
|
if (where->second.defined()) return where->second;
|
||||||
// Unlock the mutex before throwing the exception.
|
|
||||||
mLock.unlock();
|
|
||||||
syslog(LOG_ALERT, "configuration key %s not found", key.c_str());
|
|
||||||
throw ConfigurationTableKeyNotFound(key);
|
throw ConfigurationTableKeyNotFound(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,8 +133,6 @@ const ConfigurationRecord& ConfigurationTable::lookup(const string& key)
|
||||||
if (!value) {
|
if (!value) {
|
||||||
// Cache the failure.
|
// Cache the failure.
|
||||||
mCache[key] = ConfigurationRecord(false);
|
mCache[key] = ConfigurationRecord(false);
|
||||||
// Unlock the mutex before throwing the exception.
|
|
||||||
mLock.unlock();
|
|
||||||
throw ConfigurationTableKeyNotFound(key);
|
throw ConfigurationTableKeyNotFound(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,51 +170,134 @@ bool ConfigurationTable::isRequired(const string& key) const
|
||||||
string ConfigurationTable::getStr(const string& key)
|
string ConfigurationTable::getStr(const string& key)
|
||||||
{
|
{
|
||||||
// We need the lock because rec is a reference into the cache.
|
// We need the lock because rec is a reference into the cache.
|
||||||
ScopedLock lock(mLock);
|
try {
|
||||||
return lookup(key).value();
|
ScopedLock lock(mLock);
|
||||||
|
return lookup(key).value();
|
||||||
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
// Raise an alert and re-throw the exception.
|
||||||
|
syslog(LOG_ALERT | mFacility, "configuration parameter %s has no defined value", key.c_str());
|
||||||
|
throw ConfigurationTableKeyNotFound(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string ConfigurationTable::getStr(const string& key, const char* defaultValue)
|
string ConfigurationTable::getStr(const string& key, const char* defaultValue)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return getStr(key);
|
ScopedLock lock(mLock);
|
||||||
|
return lookup(key).value();
|
||||||
} catch (ConfigurationTableKeyNotFound) {
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
syslog(LOG_NOTICE | mFacility, "deinfing missing parameter %s with value %s", key.c_str(),defaultValue);
|
||||||
set(key,defaultValue);
|
set(key,defaultValue);
|
||||||
return string(defaultValue);
|
return string(defaultValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ConfigurationTable::getBool(const string& key)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return getNum(key) != 0;
|
||||||
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
long ConfigurationTable::getNum(const string& key)
|
long ConfigurationTable::getNum(const string& key)
|
||||||
{
|
{
|
||||||
// We need the lock because rec is a reference into the cache.
|
// We need the lock because rec is a reference into the cache.
|
||||||
ScopedLock lock(mLock);
|
try {
|
||||||
return lookup(key).number();
|
ScopedLock lock(mLock);
|
||||||
|
return lookup(key).number();
|
||||||
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
// Raise an alert and re-throw the exception.
|
||||||
|
syslog(LOG_ALERT | mFacility, "configuration parameter %s has no defined value", key.c_str());
|
||||||
|
throw ConfigurationTableKeyNotFound(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long ConfigurationTable::getNum(const string& key, long defaultValue)
|
long ConfigurationTable::getNum(const string& key, long defaultValue)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return getNum(key);
|
ScopedLock lock(mLock);
|
||||||
|
return lookup(key).number();
|
||||||
} catch (ConfigurationTableKeyNotFound) {
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
syslog(LOG_NOTICE | mFacility, "deinfing missing parameter %s with value %ld", key.c_str(),defaultValue);
|
||||||
set(key,defaultValue);
|
set(key,defaultValue);
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float ConfigurationTable::getFloat(const string& key)
|
||||||
|
{
|
||||||
|
// We need the lock because rec is a reference into the cache.
|
||||||
|
ScopedLock lock(mLock);
|
||||||
|
return lookup(key).floatNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
syslog(LOG_ALERT | mFacility, "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<string> ConfigurationTable::getVectorOfStrings(const string& key, const char* defaultValue){
|
||||||
|
try {
|
||||||
|
return getVectorOfStrings(key);
|
||||||
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
set(key,defaultValue);
|
||||||
|
return getVectorOfStrings(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<unsigned> ConfigurationTable::getVector(const string& key)
|
std::vector<unsigned> ConfigurationTable::getVector(const string& key)
|
||||||
{
|
{
|
||||||
// Look up the string.
|
// Look up the string.
|
||||||
mLock.lock();
|
char *line=NULL;
|
||||||
const ConfigurationRecord& rec = lookup(key);
|
try {
|
||||||
char* line = strdup(rec.value().c_str());
|
ScopedLock lock(mLock);
|
||||||
mLock.unlock();
|
const ConfigurationRecord& rec = lookup(key);
|
||||||
|
line = strdup(rec.value().c_str());
|
||||||
|
} catch (ConfigurationTableKeyNotFound) {
|
||||||
|
// Raise an alert and re-throw the exception.
|
||||||
|
syslog(LOG_ALERT | mFacility, "configuration parameter %s has no defined value", key.c_str());
|
||||||
|
throw ConfigurationTableKeyNotFound(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(line);
|
||||||
|
char *lp = line;
|
||||||
|
|
||||||
// Parse the string.
|
// Parse the string.
|
||||||
std::vector<unsigned> retVal;
|
std::vector<unsigned> retVal;
|
||||||
char *lp=line;
|
|
||||||
while (lp) {
|
while (lp) {
|
||||||
// Watch for multiple or trailing spaces.
|
// Watch for multiple or trailing spaces.
|
||||||
while (*lp==' ') lp++;
|
while (*lp==' ') lp++;
|
||||||
|
@ -228,6 +325,21 @@ bool ConfigurationTable::unset(const string& key)
|
||||||
return sqlite3_command(mDB,cmd.c_str());
|
return sqlite3_command(mDB,cmd.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConfigurationTable::remove(const string& key)
|
||||||
|
{
|
||||||
|
assert(mDB);
|
||||||
|
if (isRequired(key)) return false;
|
||||||
|
|
||||||
|
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
|
void ConfigurationTable::find(const string& pat, ostream& os) const
|
||||||
{
|
{
|
||||||
|
@ -252,13 +364,7 @@ bool ConfigurationTable::set(const string& key, const string& value)
|
||||||
{
|
{
|
||||||
assert(mDB);
|
assert(mDB);
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
// Is it there already?
|
string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",\"" + value + "\",1)";
|
||||||
char * oldValue = NULL;
|
|
||||||
bool exists = sqlite3_single_lookup(mDB,"CONFIG","KEYSTRING",key.c_str(),"VALUESTRING",oldValue);
|
|
||||||
// Update or insert as appropriate.
|
|
||||||
string cmd;
|
|
||||||
if (exists) cmd = "UPDATE CONFIG SET VALUESTRING=\""+value+"\" WHERE KEYSTRING==\""+key+"\"";
|
|
||||||
else cmd = "INSERT INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",\"" + value + "\",1)";
|
|
||||||
bool success = sqlite3_command(mDB,cmd.c_str());
|
bool success = sqlite3_command(mDB,cmd.c_str());
|
||||||
// Cache the result.
|
// Cache the result.
|
||||||
if (success) mCache[key] = ConfigurationRecord(value);
|
if (success) mCache[key] = ConfigurationRecord(value);
|
||||||
|
@ -277,7 +383,7 @@ bool ConfigurationTable::set(const string& key)
|
||||||
{
|
{
|
||||||
assert(mDB);
|
assert(mDB);
|
||||||
ScopedLock lock(mLock);
|
ScopedLock lock(mLock);
|
||||||
string cmd = "INSERT INTO CONFIG (KEYSTRING) VALUES (\"" + key + "\")";
|
string cmd = "INSERT OR REPLACE INTO CONFIG (KEYSTRING,VALUESTRING,OPTIONAL) VALUES (\"" + key + "\",NULL,1)";
|
||||||
bool success = sqlite3_command(mDB,cmd.c_str());
|
bool success = sqlite3_command(mDB,cmd.c_str());
|
||||||
if (success) mCache[key] = ConfigurationRecord(true);
|
if (success) mCache[key] = ConfigurationRecord(true);
|
||||||
return success;
|
return success;
|
||||||
|
@ -335,5 +441,38 @@ void HashString::computeHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// vim: ts=4 sw=4
|
// vim: ts=4 sw=4
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2009, 2010 Free Software Foundation, Inc.
|
* Copyright 2009, 2010 Free Software Foundation, Inc.
|
||||||
* Copyright 2010 Kestrel Signal Processing, Inc.
|
* Copyright 2010, 2012 Kestrel Signal Processing, Inc.
|
||||||
*
|
*
|
||||||
* This software is distributed under the terms of the GNU Affero Public License.
|
* This software is distributed under the terms of the GNU Affero Public License.
|
||||||
* See the COPYING file in the main directory for details.
|
* See the COPYING file in the main directory for details.
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
|
|
||||||
/** A class for configuration file errors. */
|
/** A class for configuration file errors. */
|
||||||
class ConfigurationTableError {};
|
class ConfigurationTableError {};
|
||||||
|
extern char gCmdName[]; // Gotta be global, gotta be char*, gotta love it.
|
||||||
|
|
||||||
/** An exception thrown when a given config key isn't found. */
|
/** An exception thrown when a given config key isn't found. */
|
||||||
class ConfigurationTableKeyNotFound : public ConfigurationTableError {
|
class ConfigurationTableKeyNotFound : public ConfigurationTableError {
|
||||||
|
@ -56,7 +58,7 @@ class ConfigurationTableKeyNotFound : public ConfigurationTableError {
|
||||||
|
|
||||||
ConfigurationTableKeyNotFound(const std::string& wKey)
|
ConfigurationTableKeyNotFound(const std::string& wKey)
|
||||||
:mKey(wKey)
|
:mKey(wKey)
|
||||||
{ std::cerr << "cannot find configuration value " << mKey << std::endl; }
|
{ }
|
||||||
|
|
||||||
const std::string& key() const { return mKey; }
|
const std::string& key() const { return mKey; }
|
||||||
|
|
||||||
|
@ -94,6 +96,8 @@ class ConfigurationRecord {
|
||||||
long number() const { return mNumber; }
|
long number() const { return mNumber; }
|
||||||
bool defined() const { return mDefined; }
|
bool defined() const { return mDefined; }
|
||||||
|
|
||||||
|
float floatNumber() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,11 +180,12 @@ class ConfigurationTable {
|
||||||
sqlite3* mDB; ///< database connection
|
sqlite3* mDB; ///< database connection
|
||||||
ConfigurationMap mCache; ///< cache of recently access configuration values
|
ConfigurationMap mCache; ///< cache of recently access configuration values
|
||||||
mutable Mutex mLock; ///< control for multithreaded access to the cache
|
mutable Mutex mLock; ///< control for multithreaded access to the cache
|
||||||
|
int mFacility;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
ConfigurationTable(const char* filename = ":memory:");
|
ConfigurationTable(const char* filename = ":memory:", const char *wCmdName = 0, int wFacility = LOG_USER);
|
||||||
|
|
||||||
/** Return true if the key is used in the table. */
|
/** Return true if the key is used in the table. */
|
||||||
bool defines(const std::string& key);
|
bool defines(const std::string& key);
|
||||||
|
@ -211,12 +216,34 @@ class ConfigurationTable {
|
||||||
*/
|
*/
|
||||||
long getNum(const std::string& key);
|
long getNum(const std::string& key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a boolean from the table.
|
||||||
|
Return false if NULL or 0, true otherwise.
|
||||||
|
*/
|
||||||
|
bool getBool(const std::string& key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a numeric parameter from the table.
|
Get a numeric parameter from the table.
|
||||||
Define the parameter to the default value if not found.
|
Define the parameter to the default value if not found.
|
||||||
*/
|
*/
|
||||||
long getNum(const std::string& key, long defaultValue);
|
long getNum(const std::string& key, long defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a vector of strings from the table.
|
||||||
|
*/
|
||||||
|
std::vector<std::string> getVectorOfStrings(const std::string& key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a vector of strings from the table, with a default value..
|
||||||
|
*/
|
||||||
|
std::vector<std::string> getVectorOfStrings(const std::string& key, const char* defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a float from the table.
|
||||||
|
Throw ConfigurationTableKeyNotFound if not found.
|
||||||
|
*/
|
||||||
|
float getFloat(const std::string& key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a numeric vector from the table.
|
Get a numeric vector from the table.
|
||||||
*/
|
*/
|
||||||
|
@ -236,13 +263,21 @@ class ConfigurationTable {
|
||||||
bool set(const std::string& key);
|
bool set(const std::string& key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove a key from the table.
|
Set a corresponding value to NULL.
|
||||||
Will not remove static or required values.
|
Will not alter required values.
|
||||||
@param key The key of the item to be deleted.
|
@param key The key of the item to be nulled-out.
|
||||||
@return true if anything was actually removed.
|
@return true if anything was actually nulled-out.
|
||||||
*/
|
*/
|
||||||
bool unset(const std::string& key);
|
bool unset(const std::string& key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Remove an entry from the table.
|
||||||
|
Will not alter required values.
|
||||||
|
@param key The key of the item to be removed.
|
||||||
|
@return true if anything was actually removed.
|
||||||
|
*/
|
||||||
|
bool remove(const std::string& key);
|
||||||
|
|
||||||
/** Search the table, dumping to a stream. */
|
/** Search the table, dumping to a stream. */
|
||||||
void find(const std::string& pattern, std::ostream&) const;
|
void find(const std::string& pattern, std::ostream&) const;
|
||||||
|
|
||||||
|
@ -268,6 +303,27 @@ class ConfigurationTable {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map<HashString, std::string> HashStringMap;
|
||||||
|
|
||||||
|
class SimpleKeyValue {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
HashStringMap mMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Take a C string "A=B" and set map["A"]="B". */
|
||||||
|
void addItem(const char*);
|
||||||
|
|
||||||
|
/** Take a C string "A=B C=D E=F ..." and add all of the pairs to the map. */
|
||||||
|
void addItems(const char*s);
|
||||||
|
|
||||||
|
/** Return a reference to the string at map["key"]. */
|
||||||
|
const char* get(const char*) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,11 @@
|
||||||
|
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
ConfigurationTable gConfig("exampleconfig.db");
|
ConfigurationTable gConfig("exampleconfig.db","test",LOG_LOCAL7);
|
||||||
|
|
||||||
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
|
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
|
||||||
{
|
{
|
||||||
|
@ -61,9 +62,44 @@ int main(int argc, char *argv[])
|
||||||
cout << "defined table[" << keys[i] << "]=" << gConfig.defines(keys[i]) << endl;
|
cout << "defined table[" << keys[i] << "]=" << gConfig.defines(keys[i]) << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
gConfig.set("key5","100 200 300 400");
|
gConfig.set("key5","100 200 300 400 ");
|
||||||
std::vector<unsigned> vect = gConfig.getVector("key5");
|
std::vector<unsigned> vect = gConfig.getVector("key5");
|
||||||
cout << "vect length " << vect.size() << ": ";
|
cout << "vect length " << vect.size() << ": ";
|
||||||
for (unsigned i=0; i<vect.size(); i++) cout << " " << vect[i];
|
for (unsigned i=0; i<vect.size(); i++) cout << " " << vect[i];
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
std::vector<string> svect = gConfig.getVectorOfStrings("key5");
|
||||||
|
cout << "vect length " << svect.size() << ": ";
|
||||||
|
for (unsigned i=0; i<svect.size(); i++) cout << " " << svect[i] << ":";
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
cout << "bool " << gConfig.getBool("booltest") << endl;
|
||||||
|
gConfig.set("booltest",1);
|
||||||
|
cout << "bool " << gConfig.getBool("booltest") << endl;
|
||||||
|
gConfig.set("booltest",0);
|
||||||
|
cout << "bool " << gConfig.getBool("booltest") << endl;
|
||||||
|
|
||||||
|
gConfig.getStr("newstring","new string value");
|
||||||
|
gConfig.getNum("numnumber",42);
|
||||||
|
|
||||||
|
|
||||||
|
SimpleKeyValue pairs;
|
||||||
|
pairs.addItems(" a=1 b=34 dd=143 ");
|
||||||
|
cout<< pairs.get("a") << endl;
|
||||||
|
cout<< pairs.get("b") << endl;
|
||||||
|
cout<< pairs.get("dd") << endl;
|
||||||
|
|
||||||
|
gConfig.set("fkey","123.456");
|
||||||
|
float fval = gConfig.getFloat("fkey");
|
||||||
|
cout << "fkey " << fval << endl;
|
||||||
|
|
||||||
|
cout << "search fkey:" << endl;
|
||||||
|
gConfig.find("fkey",cout);
|
||||||
|
gConfig.unset("fkey");
|
||||||
|
cout << "search fkey:" << endl;
|
||||||
|
gConfig.find("fkey",cout);
|
||||||
|
gConfig.remove("fkey");
|
||||||
|
cout << "search fkey:" << endl;
|
||||||
|
gConfig.find("fkey",cout);
|
||||||
|
|
||||||
|
gConfig.getNum("supposedtoabort");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue