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(); } } }
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(); } }
StringPimpl InnerTemplate::getString() const throw(InternalProgrammerErrorException &) { LOG_BOT_METHOD("StringPimpl InnerTemplate::getString()"); logging("No operations happen within this. Empty string being returned"); return StringPimpl(); }
StringPimpl Think::getString() const throw(InternalProgrammerErrorException &) { InnerTemplateListImpl::getString(); //Think does not return anything. return StringPimpl(); }
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(); } }
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(); } }
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; } }
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(); } }
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(); } }
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(); } }
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(); } }
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(); } }
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(); } } }
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(); } }
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(); } }
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 }
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