Пример #1
0
void DatabaseManager::printEntireDB()
{
	Dbc *cursor = NULL;
	try 
	{
		Dbt dbKey;
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			cout << "key :" << keyString.c_str() << endl << "data:" << dataString.c_str() << endl << endl;
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
		std::cerr << "Error in deleteRecordRange: "
				   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
	}
}
Пример #2
0
StringPimpl Gender::getString() const
throw(InternalProgrammerErrorException &)
{
    LOG_BOT_METHOD("StringPimpl Gender::getString() const");

    try
    {
        if(m_pimpl->m_atomic)
        {
            logging("This is an atomic element shortcut");
            Star star(m_pimpl->m_builder);
            StringPimpl returnString = star.getString();
            return m_pimpl->m_builder.genderSubstitute(returnString);
        }
        else
        {
            return m_pimpl->m_builder.genderSubstitute(InnerTemplateListImpl::getString());
        }
    }
    catch(Exception &e)
    {
        logging(String("Fatal exception occured:") + e.what());
        return StringPimpl();
    }
}
Пример #3
0
StringPimpl InnerTemplate::getString() const 
	throw(InternalProgrammerErrorException &)
{
	LOG_BOT_METHOD("StringPimpl InnerTemplate::getString()");
	logging("No operations happen within this.  Empty string being returned");
	return StringPimpl();
}
Пример #4
0
StringPimpl Think::getString() const
	throw(InternalProgrammerErrorException &)
{
	InnerTemplateListImpl::getString();

	//Think does not return anything.
	return StringPimpl();
}
Пример #5
0
StringPimpl DatabaseManager::getRecord(const StringPimpl &key, bool caseSensitive)
{
	Dbt dbKey, dbData;
	StringPimpl caseInsensitive;
	if(!caseSensitive)
	{
		caseInsensitive = key;
		caseInsensitive.transformToUpperCase();
		dbKey.set_data((void *)caseInsensitive.c_str());
		dbKey.set_size((caseInsensitive.size() + 1) * sizeof(char));
	}
	else
	{
		dbKey.set_data((void *)key.c_str());
		dbKey.set_size((key.size() + 1) * sizeof(char));
	}

	Dbc *cursor = NULL;

	try
	{
		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET);
		cursor->close();
		if(ret != DB_NOTFOUND)
		{
			return StringPimpl((char *) dbData.get_data());
		}
		else
		{
			return StringPimpl();
		}
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in getDatabaseRecord transaction: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return StringPimpl();
    }
}
Пример #6
0
StringPimpl TopicStar::getString() const
	throw(InternalProgrammerErrorException &)
{
	try
	{
		return m_pimpl->m_builder.getTopicStar(m_pimpl->m_index);
	}
	catch(IllegalArgumentException &e)
	{
		logging(String("Size Exceeded: ") + e.what());
		m_pimpl->m_builder.getCallBacks().topicStarTagSizeExceeded();
		return StringPimpl();
	}
	catch(Exception &e)
	{
		logging(String("Another exception occured, returning empty string:") + e.what());
		return StringPimpl();
	}
}
Пример #7
0
bool DatabaseManager::recordRangeExists(const StringPimpl &key)
{
	//Go through the range of the existence keys and 
	//add them to the list
	Dbc *cursor = NULL;
	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			if(!keyString.startsWith(key) || keyString == key) {
				//We are at the end of the range
				break;
			}
			else 
			{
				cursor->close();
				return true;
			}
		}
		cursor->close();
		return false;
	}
	catch (DbException &e) 
	{
		std::cerr << "Error in deleteRecordRange: "
				   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return false;
	}
}
Пример #8
0
StringPimpl TemplateSideThat::getString() const
	throw(InternalProgrammerErrorException &)
{
	try
	{
		return FrameworkFactory::getInstance()->getGraphBuilderFramework()->getPreviousBotResponsePunctuation(m_pimpl->m_previousBotResponse, m_pimpl->m_sentence);
	}
	catch(IllegalArgumentException &)
	{
		FrameworkFactory *factory = FrameworkFactory::getInstance();
		IdentificationManager *ident = IdentificationManager::getInstance();
		GraphBuilderFramework *builder = factory->getGraphBuilderFramework();
		builder->getCallBacks().thatTagSizeExceeded(ident->getUserId(), ident->getBotId(), ident->getEndUserId());
		return StringPimpl();
	}
	catch(Exception &)
	{
		//Fatal exception occured
		return StringPimpl();		
	}
}
Пример #9
0
StringPimpl ThatStar::getString() const
throw(InternalProgrammerErrorException &)
{
    LOG_BOT_METHOD("StringPimpl ThatStar::getString() const");

    try
    {
        return m_pimpl->m_builder.getThatStar(m_pimpl->m_index);
    }
    catch(IllegalArgumentException &e)
    {
        logging(String("Size Exceeded: ") + e.what());
        m_pimpl->m_builder.getCallBacks().thatStarTagSizeExceeded();
        return StringPimpl();
    }
    catch(Exception &e)
    {
        logging(String("Fatal exception occured:") + e.what());
        return StringPimpl();
    }
}
Пример #10
0
StringPimpl TopicStar::getString() const
	throw(InternalProgrammerErrorException &)
{
	try
	{
		return FrameworkFactory::getInstance()->getGraphBuilderFramework()->getTopicStar(m_pimpl->m_index);
	}
	catch(IllegalArgumentException &)
	{
		//Size Exceeded
		FrameworkFactory *factory = FrameworkFactory::getInstance();
		IdentificationManager *ident = IdentificationManager::getInstance();
		GraphBuilderFramework *builder = factory->getGraphBuilderFramework();
		builder->getCallBacks().topicStarTagSizeExceeded(ident->getUserId(), ident->getBotId(), ident->getEndUserId());
		return StringPimpl();
	}
	catch(Exception &)
	{
		//Another exception occured, returning empty string
		return StringPimpl();
	}
}
Пример #11
0
StringPimpl Size::getString() const
	throw(InternalProgrammerErrorException &)
{
	try
	{
		return lexical_cast<String>(m_pimpl->m_builder.getSize()).c_str();
	}
	catch(bad_lexical_cast &)
	{
		logging("Error, Bad lexical cast");
		throw InternalProgrammerErrorExceptionImpl("[StringPimpl Size::getString() const], bad lexical cast");
		return StringPimpl();
	}
}
Пример #12
0
StringPimpl Random::getString() const
	throw(InternalProgrammerErrorException &)
{
	//this avoids division by zero
	if(m_pimpl->m_sentence.size() == 0)
	{
		return StringPimpl();
	}
	else
	{
		int randomNumber = (rand() % m_pimpl->m_sentence.size());	
		return m_pimpl->m_sentence.at(randomNumber)->getString().transformByTrimmingWhiteSpace();
	}
}
Пример #13
0
void DatabaseManager::deleteRecordRange(const StringPimpl &key)
{
	Dbc *cursor = NULL;

	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			if(!keyString.startsWith(key)) {
				//We are at the end of the range
				break;
			} 
			cursor->del(0);
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in deleteRecordRange: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
    }
}
Пример #14
0
StringPimpl Person2::getString() const
	throw(InternalProgrammerErrorException &)
{
	try
	{
		if(m_pimpl->m_atomic)
		{
			//This is an atomic element shortcut
			Star star;
			StringPimpl returnString = star.getString();
			return FrameworkFactory::getInstance()->getGraphBuilderFramework()->person2Substitute(returnString);
		}
		else
		{
			return FrameworkFactory::getInstance()->getGraphBuilderFramework()->person2Substitute(InnerTemplateListImpl::getString());
		}
	}
	catch(Exception &)
	{
		//Fatal exception occured"
		return StringPimpl();
	}
}
Пример #15
0
StringPimpl Condition::getString() const
	throw(InternalProgrammerErrorException &)
{
	LOG_BOT_METHOD("StringPimpl Condition::getString() const");
	if(this->isBlockCondition())
	{
		logging("This is a block condition");
		if(m_pimpl->m_builder.predicateMatch(m_pimpl->m_predicateName.c_str(), m_pimpl->m_aimlPattern.c_str()))
		{
			logging("Matched the aimlpattern to the predicate's pattern");
			logging("Returning the string");
			return getStringFromSentence(m_pimpl->m_sentence);
		}
		else
		{
			logging("Did not match the aimlpattern, returning empty string");
			return StringPimpl();
		}
	}
	else 
	{
		logging("This is either a single or multi-predicate condition");		
		
		typedef ListSharedPtrInnerTemplate::const_iterator CI;

		for(CI it = m_pimpl->m_sentence.begin(); it != m_pimpl->m_sentence.end(); ++it) 
		{
			if((*it)->instanceOf("Li"))
			{
				shared_ptr<Li> li = std::static_pointer_cast<Li>(*it);
				StringPimpl liPredicateName = li->getPredicateName();
				StringPimpl liAimlPattern = li->getAimlPattern();

				if(li->isDefaultListItem())
				{
					logging("Encountered default list item.  Returning its string");
					String s = li->getString().c_str();
					trim(s);
					return s.c_str();
				}
				else if(this->isSinglePredicateCondition())
				{
					logging("This is a single Predicate condition");
					if(m_pimpl->m_builder.predicateMatch(m_pimpl->m_predicateName.c_str(), liAimlPattern.c_str()))
					{
						String s = (*it)->getString().c_str();
						trim(s);
						return s.c_str();
					}
				}
				else if(isMutliPredicateCondition())
				{
					logging("This is a multi-predicate condition");
					if(m_pimpl->m_builder.predicateMatch(liPredicateName.c_str(), liAimlPattern.c_str()))
					{
						String s = (*it)->getString().c_str();
						trim(s);
						return s.c_str();
					}
				}
				else
				{
					logging("Inernal programmer Error, the condition block code is corrupted.");
					throw InternalProgrammerErrorExceptionImpl("[StringPimpl Condition::getString()] Condition block code is corrupted.");
					return StringPimpl();
				}
			}
			else if((*it)->instanceOf("PlainWord"))
			{
				//Check for plain word.  If it is a plain word skip to the next
				continue;	
			}
			else
			{
				//Not a plain word, something else.  Throw a bad cast.
				logging("Internal programmer error.  Bad cast, was expecting a Li");
				throw InternalProgrammerErrorExceptionImpl("[StringPimpl Condition::getString() const].  Bad cast, was expecting a Li");
				return StringPimpl();
			}
		}
			
		logging("Nothing matched. Returning empty string");
		return StringPimpl();

	}
}
Пример #16
0
StringPimpl System::getString() const
	throw(InternalProgrammerErrorException &)
{
	LOG_BOT_METHOD("StringPimpl System::getString() const");
	
	//@todo when the time comes to break api this needs to 
	//call GraphBuilder.callCommand(command) instead of having
	//this code duplicated.

#ifdef _WIN32

	STARTUPINFO si;
	SECURITY_ATTRIBUTES sa;
	SECURITY_DESCRIPTOR sd;
	PROCESS_INFORMATION pi;
	HANDLE read_pipe, write_pipe;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	int fd, create;
	OSVERSIONINFO osv;
	osv.dwOSVersionInfoSize = sizeof(osv);
	
	GetVersionEx(&osv);

	if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
	{
		InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
		SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
		sa.lpSecurityDescriptor = &sd;
	}
	else
	{
		/* Pipe will use ACLs from default descriptor */
		sa.lpSecurityDescriptor = NULL;
	}

	/* Create a new pipe with system's default buffer size */
	if (!CreatePipe(&read_pipe, &write_pipe, &sa, 0))
	{
		//error 
		return StringPimpl();
	}
	

	GetStartupInfo(&si);

	/* Sets the standard output handle for the process to the
	   handle specified in hStdOutput */
	si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;

	si.hStdOutput = write_pipe;
	si.hStdError  = (HANDLE) _get_osfhandle (2);
	si.wShowWindow = SW_HIDE;
	string cmd("cmd.exe /c \"");
	cmd += InnerTemplateListImpl::getString().c_str();
	cmd += "\"";
	char *command = strdup(cmd.c_str());
	create = CreateProcess(
		NULL,				// The full path of app to launch
		command, // Command line parameters
		NULL,					// Default process security attributes
		NULL,					// Default thread security attributes
		TRUE,					// Inherit handles from the parent
		0,						// Normal priority
		NULL,					// Use the same environment as the parent
		NULL,					// Use app's directory as current
		&si,					// Startup Information
		&pi);					// Process information stored upon return

	if (!create)
	{
		//error
		return StringPimpl();
	}

	/* Associates a file descriptor with the stdout pipe */
	fd = _open_osfhandle((intptr_t)read_pipe, _O_BINARY);

	/* Close the handle that we're not going to use */
	CloseHandle(write_pipe);

	if (!fd)
	{
		//error
		return StringPimpl();
	}
	
	FILE *file = 0;

	/* Open the pipe stream using its file descriptor */
	file = fdopen(fd, "r");

	if(!file)
	{
		//error
		return StringPimpl();
	}

	if (command)
		free(command);

	int pid = (int)pi.hProcess;
	char c = 0;
	string returnString;
	while (c != EOF)
	{
		c = (char)getc(file);
		
		if(isascii(c))
		{
			returnString += c;
		}
	}

	/* Close the pipe once it's not needed anymore */
	fclose(file);
	return returnString.c_str();

#else

	FILE *file;
	file = popen(InnerTemplateListImpl::getString().c_str(), "r");
	char c = 0;
	string returnString;
	while (c != EOF)
	{
		c = (char)getc(file);

		if(isascii(c))
		{
			returnString += c;
		}
	}

	fclose(file);
	return returnString.c_str();
#endif

}
Пример #17
0
namespace impl 
{

class DatabaseManagerImpl
{
	public:
		DatabaseManagerImpl()
			: m_alreadyInitialized(false),
			  m_databaseEnvironment(0),
			  m_database(0),
			  m_cursorFlags(0)
		{
			m_envFlags =
				DB_CREATE      |  // Create the environment if it does not exist
				DB_INIT_LOCK   |  // Initialize the locking subsystem
				DB_INIT_LOG    |  // Initialize the logging subsystem
				DB_INIT_TXN    |  // Initialize the transactional subsystem. This
								  // also turns on logging.
				DB_INIT_MPOOL  |  // Initialize the memory pool (in-memory cache)
				DB_THREAD;        // Cause the environment to be free-threaded
		}
		bool m_alreadyInitialized;
		mutex m_this;
		static DatabaseManager *m_instance;
		DbEnv *m_databaseEnvironment;
		static mutex *m_databaseEnvironmentMutex;
		Db *m_database;
		static StringPimpl m_dbEnvironmentDirectory;
		thread_specific_ptr<bool> m_transactionInProgress;
		u_int32_t m_cursorFlags;
		u_int32_t m_envFlags;
		
		thread_specific_ptr<DbTxn *> m_transaction;
		
		void setEnvironmentDirectoryDefault()
		{
			//Initialize the db environment variable
	#       ifdef _WIN32
				char *initPath = getenv("ALLUSERSPROFILE");
	#       else
				char *initPath = getenv("HOME");
	#       endif
			
			if(initPath != NULL)
			{
				m_dbEnvironmentDirectory = initPath;
                # ifdef _WIN32
				m_dbEnvironmentDirectory += "\\Application Data\\.RebeccaAIMLDB";
                # else
				m_dbEnvironmentDirectory += "/.RebeccaAIMLDB";                
                # endif
			}
			else
			{
				//Can't find either varialble so just 
				//using the current directory of the process
				m_dbEnvironmentDirectory = "./.RebeccaAIMLDB";
			}
		}

		void checkTSSInit()
		{
			if(m_transactionInProgress.get() == 0)
			{
				m_transactionInProgress.reset(new bool);
				(*m_transactionInProgress) = false;
			}

			if(m_transaction.get() == 0)
			{
				m_transaction.reset(new DbTxn *);
				(*m_transaction) = NULL;
			}
		}
};

//static initializations
DatabaseManager *DatabaseManagerImpl::m_instance = 0;
StringPimpl DatabaseManagerImpl::m_dbEnvironmentDirectory = StringPimpl();
mutex *DatabaseManagerImpl::m_databaseEnvironmentMutex = new mutex();
const StringPimpl DatabaseManager::m_reserved = "_@reserved_@";

DatabaseManager::DatabaseManager()
	: m_pimpl(new DatabaseManagerImpl)
{
	mutex::scoped_lock synchronized(m_pimpl->m_this);
	if(m_pimpl->m_alreadyInitialized)
	{
		return;
	}
	m_pimpl->m_alreadyInitialized = true;
	if(m_pimpl->m_dbEnvironmentDirectory.empty())
	{
		m_pimpl->setEnvironmentDirectoryDefault();
	}

	//Create directory for the environment
	//If it already exists then we're good.
	m_pimpl->m_dbEnvironmentDirectory.transformIntoAbsoluteFilePath();
	//Get the file format in the native string for db
	path nativeFileFormat(m_pimpl->m_dbEnvironmentDirectory.c_str(), native);

	//Get the complete path to the file
	path completePath = complete(nativeFileFormat);
	create_directories(completePath);

	//Open the Database environment
    m_pimpl->m_databaseEnvironment = new DbEnv(0);
	m_pimpl->m_databaseEnvironment->open(m_pimpl->m_dbEnvironmentDirectory.c_str(), m_pimpl->m_envFlags, 0);
	m_pimpl->m_database = new Db(m_pimpl->m_databaseEnvironment, 0);
	m_pimpl->m_databaseEnvironment->set_message_stream(&cout);
	m_pimpl->m_database->set_message_stream(&cout);
	//Open the actual RebeccaAIML DB
//	u_int32_t dbflags = DB_CREATE | DB_AUTO_COMMIT | DB_READ_UNCOMMITTED;
	u_int32_t dbflags = DB_CREATE;
    m_pimpl->m_database->open(NULL,             // Txn pointer 
                              "RebeccaAIMLDB",  // File name 
                              NULL,             // Logical db name 
                              DB_BTREE,         // Database type (using btree) 
                              dbflags,          // Open flags 
                              0);               // File mode. Using defaults 
}

DatabaseManager *DatabaseManager::reset()
{
	if(DatabaseManagerImpl::m_instance != 0)
	{
		delete DatabaseManagerImpl::m_instance;
	}
	DatabaseManagerImpl::m_instance = new DatabaseManager();
	return DatabaseManagerImpl::m_instance;
}

void DatabaseManager::setEnvironmentDirectory(const StringPimpl &directory)
{
	//Synchronize entire method
	mutex::scoped_lock synchronized(*DatabaseManagerImpl::m_databaseEnvironmentMutex);
	DatabaseManagerImpl::m_dbEnvironmentDirectory = directory;
}

DatabaseManager *DatabaseManager::getInstance()
{
	return DatabaseManagerImpl::m_instance;
}


void DatabaseManager::beginTransaction()
{ 
	m_pimpl->checkTSSInit();
	if(!(*m_pimpl->m_transactionInProgress))
	{
		m_pimpl->m_databaseEnvironment->txn_begin(NULL, &(*m_pimpl->m_transaction), DB_READ_UNCOMMITTED);
		(*m_pimpl->m_transactionInProgress) = true;
	}
}

void DatabaseManager::endTransaction()
{ 
	m_pimpl->checkTSSInit();
	if((*m_pimpl->m_transactionInProgress))
	{
		(*m_pimpl->m_transaction)->commit(0);
		//m_pimpl->m_transaction.reset(new DbTxn *);
		(*m_pimpl->m_transaction) = NULL;
		*m_pimpl->m_transactionInProgress = false;
	}
}

bool DatabaseManager::recordExists(const StringPimpl &key)
{
	Dbt dbKey, dbData;
	dbKey.set_data((void *)key.c_str());
	dbKey.set_size((key.size() + 1) * sizeof(char));
	Dbc *cursor = NULL;

	try
	{
		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET);
		cursor->close();
		if(ret != DB_NOTFOUND)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in databse recordExists"
			<< e.what() << e.get_errno() <<  std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return false;
    }
}

void DatabaseManager::sync()
{
	m_pimpl->m_database->sync(0);
}

bool DatabaseManager::getRecord(const StringPimpl &key, 
                                StringPimpl &data,
								bool caseSensitive)
{
	Dbt dbKey, dbData;
	StringPimpl caseInsensitive;
	if(!caseSensitive)
	{
		caseInsensitive = key;
		caseInsensitive.transformToUpperCase();
		dbKey.set_data((void *)caseInsensitive.c_str());
		dbKey.set_size((caseInsensitive.size() + 1) * sizeof(char));
	}
	else
	{
		dbKey.set_data((void *)key.c_str());
		dbKey.set_size((key.size() + 1) * sizeof(char));
	}

	Dbc *cursor = NULL;

	try
	{
		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET);
		cursor->close();
		if(ret != DB_NOTFOUND)
		{
			data = StringPimpl((char *) dbData.get_data());
			return true;
		}
		else
		{
			return false;
		}
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in getDatabaseRecord transaction: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return false;
    }
}

StringPimpl DatabaseManager::getRecord(const StringPimpl &key, bool caseSensitive)
{
	Dbt dbKey, dbData;
	StringPimpl caseInsensitive;
	if(!caseSensitive)
	{
		caseInsensitive = key;
		caseInsensitive.transformToUpperCase();
		dbKey.set_data((void *)caseInsensitive.c_str());
		dbKey.set_size((caseInsensitive.size() + 1) * sizeof(char));
	}
	else
	{
		dbKey.set_data((void *)key.c_str());
		dbKey.set_size((key.size() + 1) * sizeof(char));
	}

	Dbc *cursor = NULL;

	try
	{
		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET);
		cursor->close();
		if(ret != DB_NOTFOUND)
		{
			return StringPimpl((char *) dbData.get_data());
		}
		else
		{
			return StringPimpl();
		}
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in getDatabaseRecord transaction: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return StringPimpl();
    }
}

void DatabaseManager::addRecordWithCount(const StringPimpl &key, 
										 const StringPimpl &value)
{
	if(!recordCountExists(key, value))
	{
		int size = getRecordTotalCount(key);
		addRecord(m_reserved + key + "_@size_@", StringPimpl::getString(size + 1));

		//This enables us to do a fast lookup without having to loop through
		//the entire list just to check for the existence of the key
		addRecord(m_reserved + key + "_@existence_@" + value, value);
	}
}

int DatabaseManager::getRecordTotalCount(const StringPimpl &key)
{
	StringPimpl sizeAsString = getRecord(m_reserved + key + "_@size_@", true);
	if(sizeAsString.empty())
	{
		return 0;
	}
	else
	{
		return sizeAsString.getInteger();
	}
}

void DatabaseManager::deleteRecordWithCount(const StringPimpl &key,
											const StringPimpl &value)
{
	vector<StringPimpl> files;

	//decrement the size by one
	if(recordCountExists(key, value))
	{
		int size = getRecordTotalCount(key);
		addRecord(m_reserved + key + "_@size_@", StringPimpl::getString(size - 1));
		deleteRecord(m_reserved + key + "_@existence_@" + value);
	}
}

bool DatabaseManager::recordCountExists(const StringPimpl &key)
{
	return recordExists(m_reserved + key + "_@size_@");
}

bool DatabaseManager::recordExists(const StringPimpl &key, const StringPimpl &value)
{
	StringPimpl record = getRecord(key, true);
	return record == value;
}

bool DatabaseManager::recordCountExists(const StringPimpl &key, const StringPimpl &value)
{
	return recordExists(m_reserved + key + "_@existence_@" + value, value);
}

StringPimpl *DatabaseManager::getRecordRange(const StringPimpl &key, unsigned int &size)
{
	vector<StringPimpl> records = getRecordRangeAsVector(key);
	size = records.size();
	if(records.size() > 0)
	{
		StringPimpl *arrayList = new StringPimpl[records.size()];
		for(unsigned int i = 0; i < records.size(); ++i)
		{
			arrayList[i] = records.at(i);
		}
		return arrayList;
	}
	else
	{
		return 0;
	}
}

StringPimpl *DatabaseManager::getRecordCountList(const StringPimpl &key, unsigned int &size)
{
	return getRecordRange(m_reserved + key + "_@existence_@", size);
}

vector<StringPimpl> DatabaseManager::getRecordCountListAsVector(const StringPimpl &key)
{
	return getRecordRangeAsVector(m_reserved + key + "_@existence_@");
}


bool DatabaseManager::recordRangeExists(const StringPimpl &key)
{
	//Go through the range of the existence keys and 
	//add them to the list
	Dbc *cursor = NULL;
	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			if(!keyString.startsWith(key) || keyString == key) {
				//We are at the end of the range
				break;
			}
			else 
			{
				cursor->close();
				return true;
			}
		}
		cursor->close();
		return false;
	}
	catch (DbException &e) 
	{
		std::cerr << "Error in deleteRecordRange: "
				   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
		return false;
	}
}

vector<StringPimpl> DatabaseManager::getRecordRangeAsVector(const StringPimpl &key)
{
	vector<StringPimpl> list;

	//Go through the range of the existence keys and 
	//add them to the list
	Dbc *cursor = NULL;
	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			if(!keyString.startsWith(key) || keyString == key) {
				//We are at the end of the range
				break;
			} 
			list.push_back(dataString);
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
		std::cerr << "Error in deleteRecordRange: "
				   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
	}

	return list;
}

void DatabaseManager::printEntireDB()
{
	Dbc *cursor = NULL;
	try 
	{
		Dbt dbKey;
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			cout << "key :" << keyString.c_str() << endl << "data:" << dataString.c_str() << endl << endl;
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
		std::cerr << "Error in deleteRecordRange: "
				   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
	}
}

void DatabaseManager::deleteRecordCount(const StringPimpl &key)
{
	deleteRecordRange(m_reserved + key);
}

void DatabaseManager::addRecord(const StringPimpl &key,
								const StringPimpl &value)
{
	//Set up the key
	Dbt dbKey;
	dbKey.set_data((void *)key.c_str());
	dbKey.set_size((key.size() + 1) * sizeof(char));

	//Set up the data to insert
	Dbt dbData;
	dbData.set_data((void *)value.c_str());
	dbData.set_size((value.size() + 1) * sizeof(char));
	
	try 
	{
		m_pimpl->checkTSSInit();
		int ret = m_pimpl->m_database->put(&(**m_pimpl->m_transaction), &dbKey, &dbData, 0);
	}
	catch (DbException &e) 
	{
            std::cerr << "Error in addRecord: "
                       << e.what() << e.get_errno() << std::endl;
    }
}

void DatabaseManager::deleteRecord(const StringPimpl &key)
{
	Dbc *cursor = NULL;
	
	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET);
		if(ret != DB_NOTFOUND)
		{
			cursor->del(0);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in addRecord: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
    }

}


void DatabaseManager::deleteRecordRange(const StringPimpl &key)
{
	Dbc *cursor = NULL;

	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData;

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_SET_RANGE);
		
		while(ret != DB_NOTFOUND)
		{
			StringPimpl dataString = StringPimpl((char *) dbData.get_data());
			StringPimpl keyString = StringPimpl((char *) dbKey.get_data());
			if(!keyString.startsWith(key)) {
				//We are at the end of the range
				break;
			} 
			cursor->del(0);
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
        std::cerr << "Error in deleteRecordRange: "
                   << e.what() << e.get_errno() << std::endl;
		if(cursor != NULL)
		{
			cursor->close();
		}
    }
}

void DatabaseManager::deleteRecordRange(const StringPimpl &key,
										const StringPimpl &range)
{
	Dbc *cursor = NULL;

	try 
	{
		Dbt dbKey((void *)key.c_str(), key.size() + 1);
		Dbt dbData((void *) range.c_str(), range.size() + 1);

		m_pimpl->checkTSSInit();
		m_pimpl->m_database->cursor(&(**m_pimpl->m_transaction), &cursor, m_pimpl->m_cursorFlags);
		int ret = cursor->get(&dbKey, &dbData, DB_GET_BOTH_RANGE);
		
		while(ret != DB_NOTFOUND)
		{
			cursor->del(0);
			ret = cursor->get(&dbKey, &dbData, DB_NEXT);
		}
		cursor->close();
	}
	catch (DbException &e) 
	{
            std::cerr << "Error in addRecord: "
                       << e.what() << e.get_errno() << std::endl;
			if(cursor != NULL)
			{
				cursor->close();
			}
    }
}

DatabaseManager::~DatabaseManager()
{
	//Close the database
	if(m_pimpl->m_database != 0)
	{
        try 
		{
			m_pimpl->m_database->close(0);
        } 
		catch (DbException &e) 
		{
            std::cerr << "Error in closing the database: "
                       << e.what() << e.get_errno() << std::endl;
        }
	}

	//Close the DB environment
	if(m_pimpl->m_databaseEnvironment != 0) 
	{
        try 
		{
			m_pimpl->m_databaseEnvironment->close(0);
        } 
		catch (DbException &e) 
		{
            std::cerr << "Error in closing the database environment: "
                       << e.what() << e.get_errno() << std::endl;
        }
	}

	//Delete the databse
	if(m_pimpl->m_database != 0)
	{
		///@todo why can't we delete this without crashing?
		//delete m_pimpl->m_database;
	}

	//Delete the environment
	if(m_pimpl->m_databaseEnvironment != 0)
	{
		///@todo why can't we delete this without crashing?
		//delete m_pimpl->m_databaseEnvironment;
	}

	//delete the pimpl
	delete m_pimpl;
}

} //end of namespace impl