/* * Delete all database entries */ bool CDbManager::deleteAllDatabases(CLog* log) { CHECK_DB_MGR_INIT(getDatabase, false); CTimestamp starttime = _LastUpdateTime; CTimestamp endtime; endtime.setToCurrent(); TDatabaseMap::iterator it; for (it=_DatabaseMap.begin(); it!=_DatabaseMap.end(); ++it) { CDatabase* db = (*it).second; if (db == NULL) { log->displayNL("Database '%d' left with as NULL", (*it).first); } else { // flush db if (!db->buildDelta(starttime, endtime)) nlwarning("failed to build delta for database '%d' '%s'", (*it).first, db->getName().c_str()); // delete it delete db; } // unreference it (*it).second = NULL; } _DatabaseMap.clear(); return true; }
/* * Setup file name and path */ void CDBDeltaFile::setup(const std::string& name, const std::string& path, uint32 rowSize, const CTimestamp& startTimestamp, const CTimestamp& endTimestamp) { uint32 tableId; CTimestamp timestamp; nlassert(isDeltaFileName(name, tableId, timestamp)); _Name = name; _Path = NLMISC::CPath::standardizePath(path); _Header.RowSize = rowSize; _Header.FullRowSize = rowSize + getRowHeaderSize(); //_Header.Timestamp = timestamp.toTime(); _Header.StartTimestamp = uint32(startTimestamp.toTime()); _Header.EndTimestamp = uint32(endTimestamp.toTime()); }
/* * Update * Call regularly this method once a tick to apply changes to database */ void CPDSLib::update() { if (_UsePDS) { // check pds is ready to receive update if (!PDSReady()) return; if (_DbMessageQueue.empty()) return; std::list<CDbMessageQueue>::iterator it; for (it=_DbMessageQueue.begin(); it!=_DbMessageQueue.end(); ++it) { CDbMessageQueue& queue = (*it); // create a new message CMessage* msgupd = new CMessage("PD_UPDATE"); msgupd->serial(_DatabaseId); msgupd->serial(_UpdateId); _QueuedMessages.push_back(make_pair<uint32,CMessage*>(_UpdateId, msgupd)); ++_UpdateId; // serial queue msgupd->serial(queue); // send update to the pds CUnifiedNetwork::getInstance()->send("PDS", *msgupd); } // clean up for next update _DbMessageQueue.clear(); } else { uint i; // save log (updates + string manager) TTime ctime = CTime::getLocalTime(); // CTimestamp timestamp; timestamp.setToCurrent(); // setup update logs with full timestamp if (!_DbMessageQueue.empty()) { i = (uint)_UpdateLogs.size(); _UpdateLogs.resize(_DbMessageQueue.size()); for (; i<_UpdateLogs.size(); ++i) { _UpdateLogs[i].StartStamp = _PreviousTickDate; _UpdateLogs[i].EndStamp = _PreviousTickDate; } _UpdateLogs.back().EndStamp = timestamp; } _PreviousTickDate = timestamp; if (ctime - _PreviousLogSave > PDLogUpdate*1000 && !_DbMessageQueue.empty()) { // std::string logDir = getRemoteLogDirectory(); // std::string logFile = _LogStartDate.toString()+"_0000.pd_log"; // // // if don't use BS, create logdir directory tree // if (!PDUseBS && !CFile::isDirectory(logDir)) // { // if (!CFile::createDirectoryTree(logDir)) // { // nlwarning("Failed to create log root directory '%s'", logDir.c_str()); // } // // if (!CFile::setRWAccess(logDir)) // { // nlwarning("Failed, can't set RW access to directory '%s'", logDir.c_str()); // } // } // // // map update logs to msg queues // nlassert(_UpdateLogs.size() == _DbMessageQueue.size()); // for (i=0; i<_UpdateLogs.size(); ++i) // _UpdateLogs[i].setUpdates(&(_DbMessageQueue.get(i))); // // if (PDUseBS) // { // CBackupMsgSaveFile msgBS( logDir+logFile, CBackupMsgSaveFile::AppendFileCheck, PDBsi ); // msgBS.DataMsg.serialCont(_UpdateLogs); // PDBsi.append(msgBS); // } // else // { // COFile file; // if (file.open(logDir + logFile)) // { // file.serialCont(_UpdateLogs); // } // else // { // nlwarning("Failed to save log file '%s' for database %d", (logDir + logFile).c_str(), _DatabaseId); // } // } // if (PDEnableStringLog && !_StringManager.logEmpty()) // { // std::string logFile = timestamp.toString()+".string_log"; // // if (PDUseBS) // { // bool success = false; // CBackupMsgSaveFile msgBS( logDir+logFile, CBackupMsgSaveFile::SaveFileCheck, PDBsi ); // { // COXml xml; // // if (xml.init(&msgBS.DataMsg)) // { // _StringManager.storeLog(xml); // success = true; // } // else // { // nlwarning("Failed to save string log file '%s' for database %d", msgBS.FileName.c_str(), _DatabaseId); // } // } // // if (success) // { // PDBsi.sendFile(msgBS); // } // } // else // { // COFile file; // { // COXml xml; // if (file.open(logDir + logFile) && xml.init(&file)) // { // _StringManager.storeLog(xml); // } // else // { // nlwarning("Failed to save string log file '%s' for database %d", (logDir+logFile).c_str(), _DatabaseId); // } // } // } // } _PreviousLogSave = ctime; // clean up for next update _DbMessageQueue.clear(); _UpdateLogs.clear(); } if (timestamp.toTime()-_LogStartDate.toTime() > sint(PDLogFileTime.get())) { _LogStartDate = timestamp; } _DbMessageQueue.forceNextQueue(); } }
/* * Send Delta/Reference build commands */ bool CDatabase::sendBuildCommands(const CTimestamp& current) { checkUpdateRates(); while (current - _MinuteUpdateTimestamp >= MinuteUpdateRate) { CTimestamp start = _MinuteUpdateTimestamp; CTimestamp end = start + MinuteUpdateRate; CTimestamp keep = end - MinuteUpdateRate*KeepSecondsAtMinuteUpdate; string outputPath = _Reference.getMinutesUpdatePath(); string hoursUpdatePath = _Reference.getHoursUpdatePath(); string minutesUpdatePath = _Reference.getMinutesUpdatePath(); string secondsUpdatePath = _Reference.getSecondsUpdatePath(); string mintimestamp = start.toString(); string maxtimestamp = end.toString(); CDeltaBuilder::TDelta type = CDeltaBuilder::Minute; string keeptimestamp = keep.toString(); CMessage& msgdelta = CDbManager::addTask("RB_GEN_DELTA", NULL, NULL); msgdelta.serial(outputPath); msgdelta.serial(hoursUpdatePath); msgdelta.serial(minutesUpdatePath); msgdelta.serial(secondsUpdatePath); msgdelta.serial(mintimestamp); msgdelta.serial(maxtimestamp); msgdelta.serialEnum(type); msgdelta.serial(keeptimestamp); _MinuteUpdateTimestamp = end; } while (current - _HourUpdateTimestamp >= HourUpdateRate) { CTimestamp start = _HourUpdateTimestamp; CTimestamp end = start + HourUpdateRate; CTimestamp keep = end - HourUpdateRate*KeepMinutesAtHourUpdate; string outputPath = _Reference.getHoursUpdatePath(); string hoursUpdatePath = _Reference.getHoursUpdatePath(); string minutesUpdatePath = _Reference.getMinutesUpdatePath(); string secondsUpdatePath = _Reference.getSecondsUpdatePath(); string mintimestamp = start.toString(); string maxtimestamp = end.toString(); CDeltaBuilder::TDelta type = CDeltaBuilder::Hour; string keeptimestamp = keep.toString(); CMessage& msgdelta = CDbManager::addTask("RB_GEN_DELTA", NULL, NULL); msgdelta.serial(outputPath); msgdelta.serial(hoursUpdatePath); msgdelta.serial(minutesUpdatePath); msgdelta.serial(secondsUpdatePath); msgdelta.serial(mintimestamp); msgdelta.serial(maxtimestamp); msgdelta.serialEnum(type); msgdelta.serial(keeptimestamp); _HourUpdateTimestamp = end; } while (current - _DayUpdateTimestamp >= ReferenceUpdateRate) { CTimestamp start = _DayUpdateTimestamp; CTimestamp end = start + ReferenceUpdateRate; CTimestamp keep = end - ReferenceUpdateRate*KeepHoursAtReferenceUpdate; CRefIndex* next = new CRefIndex(_State.Id); *next = _Reference; next->buildNext(); string rootRefPath = _Reference.getRootPath(); string previousReferencePath = _Reference.getPath(); string nextReferencePath = next->getPath(); string logUpdatePath = _Reference.getLogPath(); string hoursUpdatePath = _Reference.getHoursUpdatePath(); string minutesUpdatePath = _Reference.getMinutesUpdatePath(); string secondsUpdatePath = _Reference.getSecondsUpdatePath(); string mintimestamp = start.toString(); string maxtimestamp = end.toString(); string keeptimestamp = keep.toString(); CMessage& msgref = CDbManager::addTask("RB_GEN_REF", this, (void*)next); msgref.serial(rootRefPath); msgref.serial(previousReferencePath); msgref.serial(nextReferencePath); msgref.serial(hoursUpdatePath); msgref.serial(minutesUpdatePath); msgref.serial(secondsUpdatePath); msgref.serial(logUpdatePath); msgref.serial(mintimestamp); msgref.serial(maxtimestamp); msgref.serial(keeptimestamp); _DayUpdateTimestamp = end; } return true; }
/* * Update manager */ bool CDbManager::update() { H_AUTO(PDS_DbManager_update); CHECK_DB_MGR_INIT(update, false); // update stamp CTableBuffer::updateCommonStamp(); TDatabaseMap::iterator it; CDatabase::checkUpdateRates(); // check evently if database need to write some delta TTime tm = CTime::getLocalTime(); if (tm >= _NextTimeDelta) { CTimestamp starttime = _LastUpdateTime; CTimestamp endtime; endtime.setToCurrent(); std::vector<uint32> ack; for (it=_DatabaseMap.begin(); it!=_DatabaseMap.end(); ++it) { CDatabase* database = (*it).second; // generate deltas if (!database->buildDelta(starttime, endtime)) nlwarning("failed to build delta for database '%d' '%s'", (*it).first, database->getName().c_str()); // obsolete? since RBS build references and tells PDS of success/failure database->checkReferenceChange(); // acknowledge last updates database->flushUpdates(ack); if (!ack.empty() && database->getMappedService().get() != 0xffff) { CMessage msgack("PD_ACK_UPD"); uint32 databaseId = (*it).first; msgack.serial(databaseId); msgack.serialCont(ack); CUnifiedNetwork::getInstance()->send(database->getMappedService(), msgack); } } _NextTimeDelta = tm - (tm%(DeltaUpdateRate*1000)) + (DeltaUpdateRate*1000); _LastUpdateTime = endtime; } CTimestamp ts; ts.setToCurrent(); // check databases require some delta packing/reference generation for (it=_DatabaseMap.begin(); it!=_DatabaseMap.end(); ++it) { CDatabase* database = (*it).second; database->sendBuildCommands(ts); } // send messages to RBS if ready while (_RBSUp && !_RBSMessages.empty()) { CUnifiedNetwork::getInstance()->send("RBS", *(_RBSMessages.front())); delete _RBSMessages.front(); _RBSMessages.pop_front(); } return true; }