#include "datamanager.h" DataManager::DataManager(const bool &dryMode) :dryMode(dryMode) { db = std::make_shared("192.168.1.4", "deloitte", "postgres", "34rjkciea12", dryMode); //db = std::make_shared("localhost", "deloitte", "postgres", "34rjkciea12"); if (db->isOpen()){ Logger::setDBMan(db); nextLastSync = db->getNow(); lastSync = db->getLastSync(); } connect(db.get(), &DatabaseManager::error, this, &DataManager::error, Qt::QueuedConnection); } // load all tokens from colnod to comparing with working set from DB void DataManager::fillFullTokensColnod(const QString& response) { QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); if (!items.empty()) { for (QJsonValueRef item : items){ auto token = std::make_shared(); token->fromJSON(item.toObject()); allTokensFromColnodById.insert(token->idToStringWithoutBraces(), token); allTokensFromColnodByName.insert(token->getName(), token); } } else{ qCritical() << "Colnod is Empty"; } } // load working set with updated tokens from Colnod void DataManager::fillTokensToUpdateColnod(const QString& response) { QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); if (!items.empty()) { for (QJsonValueRef item : items) { auto token = std::make_shared(); token->fromJSON(item.toObject()); token->setDeleted(false); tokensToUpdateFromColnodToDB.insert(token->idToStringWithoutBraces(), token); } qInfo() << "Colnod:" << tokensToUpdateFromColnodToDB.size() << "tokens to update"; } else { qInfo() << "Colnod: 0 tokens to update"; } } // load working set with updated subjects from Colnod void DataManager::fillSubjectsToUpdateColnod(const QString& response) { QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); if (!items.empty()) { for (QJsonValueRef item : items) { auto subject = std::make_shared(); subject->fromJSON(item.toObject()); subject->setDeleted(false); subjectsToUpdateFromColnodToDB.insert(subject->idToStringWithoutBraces(), subject); } qInfo() << "Colnod:" << subjectsToUpdateFromColnodToDB.size() << "subjects to update"; } else { qInfo() << "Colnod:" << "0 subjects to update"; } } // load working sets with updated/deleted tokens from DB void DataManager::fillTokensToChangeDB() { if (db->isOpen()){ QSqlQuery query = db->getUpdatedTokens(); while (query.next()) { auto token = std::make_shared(); token->fromSQLRecord(query); if (token->getDeleted()){ // sort to delete / to update tokensFromDBToDeleteFromColnod.append(token->idToStringWithoutBraces()); } else{ tokensToUpdateFromDBToColnod.insert(token->idToStringWithoutBraces(), token); } } qDebug() << "DB:" << tokensToUpdateFromDBToColnod.size() << "tokens to update"; qDebug() << "DB:" << tokensFromDBToDeleteFromColnod.size() << "tokens to delete"; } else emit error(); } void DataManager::fillSubjectsToUpdateDB() { // Not needed yet } // load working set with subjest to delete from Colnod void DataManager::fillSubjectsToDeleteColnod(const QString& json) { QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); if (!items.empty()) { for (QJsonValueRef item : items) { subjectsFromColnodToDeleteFromDB.append(item.toString()); } qInfo() << "Colnod:" << subjectsFromColnodToDeleteFromDB.size() << "subjects to delete"; } else { qInfo() << "Colnod: 0 subjects to delete"; } } // load working set with tokens to delete from DB void DataManager::fillTokensToDeleteColnod(const QString& json) { QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); if (!items.empty()) { for (QJsonValueRef item : items) { tokensFromColnodToDeleteFromDB.append(item.toString()); } qInfo() << "Colnod:" << tokensFromColnodToDeleteFromDB.size() << "tokens to delete"; } else { qInfo() << "Colnod: 0 tokens to delete"; } } void DataManager::fillSubjectsToDeleteDB() { // Not needed yet } // update subjects from colnod to DB void DataManager::pushSubjectsToDB() { if (subjectsToUpdateFromColnodToDB.isEmpty()) { qInfo() << "DB: 0 subjects added"; qInfo() << "DB: 0 subjects updated"; return; } int updated = 0; int added = 0; for (const auto& subject : subjectsToUpdateFromColnodToDB) { if (db->saveSubject(subject, "colnod_subject") > 0){ added++; if (dryMode) qInfo() << "Adding subject:" << subject->idToStringWithoutBraces() << "to DB"; else Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"added", "DB")); } else{ updated++; if (dryMode) qInfo() << "Updating subject:" << subject->idToStringWithoutBraces() << "to DB"; else Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"updated", "DB")); } db->saveSubjectAttributes(subject, "colnod_subject_attribute"); } qInfo() << "DB:" << added << "subjects added"; qInfo() << "DB:" << updated << "subjects updated"; } // update tokens from colnod to DB void DataManager::pushTokensToDB() { if (tokensToUpdateFromColnodToDB.isEmpty()){ qInfo() << "DB: 0 tokens added"; qInfo() << "DB: 0 tokens updated"; return; } filterTokensColnod(); int updated = 0; int added = 0; for (const auto& token : tokensToUpdateFromColnodToDB) { QString text; // 1 = adding token // -1 = updating token if (db->saveToken(token, "colnod_token") == 1){ added++; text = "Added"; } else { updated++; text = "Updating"; } if (dryMode) qInfo() << text << "token:" << token->idToStringWithoutBraces() << "to DB"; else Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), text, "DB")); } qInfo() << "DB:" << added << "tokens added/edited"; qInfo() << "DB:" << updated << "tokens updated"; } void DataManager::deleteSubjectsFromDB() { if (subjectsFromColnodToDeleteFromDB.isEmpty()) { qInfo() << "DB: 0 subjects deleted"; return; } for (const auto& subjectId : subjectsFromColnodToDeleteFromDB) { db->setDeleted(subjectId, "colnod_subject", nextLastSync); if (dryMode) qInfo() << "Deleting subject:" << subjectId << "from DB"; else Logger::logToDb(Logger::makeSubjectMsg(subjectId, "deleted", "DB")); } qInfo() << "DB:" << subjectsFromColnodToDeleteFromDB.size() << " subject deleted"; } // "delete" (set deleted true) tokens in DB depends on Colnod void DataManager::setDeletedToTokensFromDB() { if (tokensFromColnodToDeleteFromDB.isEmpty()) { qDebug() << "DB: 0 tokens deleted"; return; } int alreadyDeleted = 0; for (const auto& tokenId : tokensFromColnodToDeleteFromDB) { if (!db->checkDeletedToken(tokenId)){ db->setDeleted(tokenId, "colnod_token", nextLastSync); if (dryMode) qInfo() << "Deleting token:" << tokenId << "from DB"; else Logger::logToDb(Logger::makeTokenMsg(tokenId, "deleted", "DB")); } else alreadyDeleted++; } qDebug() << "DB:" << tokensFromColnodToDeleteFromDB.size() - alreadyDeleted << "tokens deleted"; } // recreate working tables void DataManager::emptyDatabase() { db->dropTables(); db->createTables(); } quint64 DataManager::getLastModifiedOfToken(const QString &id) { auto record = db->getToken(id); auto token = std::make_shared(); token->fromSQLRecord(record); return token->getLastModified(); } //clear all structures void DataManager::clear() { subjectsToUpdateFromColnodToDB.clear(); subjectsFromColnodToDeleteFromDB.clear(); tokensToUpdateFromColnodToDB.clear(); tokensFromColnodToDeleteFromDB.clear(); //subjectsDB.clear(); // not need yet // subjectsToDeleteDB.clear(); // not need yet tokensToUpdateFromDBToColnod.clear(); tokensFromDBToDeleteFromColnod.clear(); allTokensFromColnodById.clear(); } // on the very end of sync update last sync time to begin time of this sync void DataManager::updateLastSync() { if (db->isOpen()) db->updateLastSync(nextLastSync); } // these to filter functions solve colision tokens -> remove when change on this token is earlier then change on the same token on the other side (Colnod/DB) void DataManager::filterTokensDB() { QList idsToDelete; for (const auto& token : tokensToUpdateFromDBToColnod) { QString id = token->idToStringWithoutBraces(); Q_ASSERT(token != allTokensFromColnodById.value(id)); // if working sets are loading correctly equels should never happend if (allTokensFromColnodById.contains(id) && *token < *allTokensFromColnodById.value(id)) idsToDelete.append(id); if (allTokensFromColnodById.contains(id) && token->getLastModified() == allTokensFromColnodById.value(id)->getLastUpdate()){ idsToDelete.append(id); qWarning() << "Same token has been edited in colnod and db in same time. Change from Colnod has been used"; } if (allTokensFromColnodByName.contains(token->getName())){ qWarning() << "Token:" << token->idToStringWithoutBraces() << "won't be added to Colnod, because token with the same name already exists, please change it manually"; if (!dryMode){ QString message = QString("Error: Token: %1 won't be added to Colnod, because token with the same name already exists, please change it manually").arg(token->idToStringWithoutBraces()); Logger::logToDb(Logger::makeErrorMsg("Db", message)); } } } for (const auto &id : idsToDelete) tokensToUpdateFromDBToColnod.remove(id); } void DataManager::filterTokensColnod() { QList idsToDelete; for (const auto &token : tokensToUpdateFromColnodToDB) { QString id = token->idToStringWithoutBraces(); auto record = db->getToken(id); if (!record.isValid()) continue; auto tokenDB = std::make_shared(); tokenDB->fromSQLRecord(record); if (*tokenDB == *token || *tokenDB > *token){ idsToDelete.append(id); } } for (const auto &id : idsToDelete) tokensToUpdateFromColnodToDB.remove(id); } // sync last update from colnod to DB void DataManager::setLastUpdate() { if (!tokensToUpdateFromColnodToDB.isEmpty()) for (const auto &token : tokensToUpdateFromColnodToDB) db->setLastUpdate(token->idToStringWithoutBraces(), token->getLastUpdate()); } void DataManager::setLastUpdate(const QString &id) { db->setLastUpdate(id, nextLastSync); }