mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-04 05:43:14 +00:00 
			
		
		
		
	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:
		@@ -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");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -353,7 +353,7 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
	} // try
 | 
						} // try
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	catch (ConfigurationTableKeyNotFound e) {
 | 
						catch (ConfigurationTableKeyNotFound e) {
 | 
				
			||||||
		LOG(ALERT) << "required configuration key " << e.key() << " not defined, aborting";
 | 
							LOG(EMERG) << "required configuration parameter " << e.key() << " not defined, aborting";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);
 | 
						if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user