mirror of
https://gitea.msk.dinamika-avia.ru/Constanta-Design/RRJServer.git
synced 2026-03-28 19:55:48 +03:00
refact1
This commit is contained in:
601
LibServer/Systems/updatecontroller.cpp
Normal file
601
LibServer/Systems/updatecontroller.cpp
Normal file
@@ -0,0 +1,601 @@
|
||||
#include "updatecontroller.h"
|
||||
|
||||
|
||||
UpdateController::UpdateController(QObject *parent) :
|
||||
QObject(parent),
|
||||
commonClientHandler(nullptr)
|
||||
{
|
||||
buildPath = QDir::currentPath() + "/" + applicationFolderName;
|
||||
sharedDataPath = QDir::currentPath() + "/" + sharedDataFolderName;
|
||||
Logger::instance().log(buildPath);
|
||||
qDebug() << hashFileName;
|
||||
}
|
||||
|
||||
void UpdateController::initialize(CommonClientHandler *commonClientHandler,DataParser *dataParser,AssetsManager *assetManager)
|
||||
{
|
||||
this->commonClientHandler = commonClientHandler;
|
||||
this->dataParser = dataParser;
|
||||
this->assetManager = assetManager;
|
||||
hashCalculator = new FastHashCalculator;
|
||||
|
||||
if (!QDir(staticDataFolderName).exists())
|
||||
{
|
||||
QDir().mkdir(staticDataFolderName);
|
||||
}
|
||||
|
||||
sizeToSend = 0;
|
||||
assetManager->initialize(this,dataParser);
|
||||
|
||||
if (!checkRequiredFolder())
|
||||
{
|
||||
emit sigErrorRequired(100);
|
||||
return;
|
||||
}
|
||||
|
||||
calculateFullHash();
|
||||
currentStreamingPath = assetManager->getLastVersion(); //TODO: сохрнаять предыдущую версию и загружать ее при включении
|
||||
setUpCurrentServerHash();
|
||||
|
||||
mutex = new QMutex;
|
||||
qDebug() << "UpdateController init thread ID " << QThread::currentThreadId();
|
||||
|
||||
emit sigInitializeFinished();
|
||||
}
|
||||
|
||||
void UpdateController::changeAssetVersion(QString versionName)
|
||||
{
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY);
|
||||
qDebug() << "UpdateController thread ID " << QThread::currentThreadId();
|
||||
currentStreamingPath = assetManager->setVersion(versionName);
|
||||
setUpCurrentServerHash();
|
||||
emit sigUpdateDocs();
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::HASH_READY);
|
||||
commonClientHandler->sendCurrentVersionToAllClient();
|
||||
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE);
|
||||
}
|
||||
|
||||
void UpdateController::createCopyVersion(QString versionName,QString newVersionName,QString author)
|
||||
{
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY);
|
||||
assetManager->createCopyVersion(versionName,newVersionName,author);
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE);
|
||||
}
|
||||
|
||||
void UpdateController::deleteAssetVersion(QString versionName)
|
||||
{
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY);
|
||||
assetManager->deleteVersion(versionName);
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE);
|
||||
}
|
||||
|
||||
void UpdateController::compareFiles(ClientHandler* handler, QByteArray array)
|
||||
{
|
||||
mutex->lock();
|
||||
serverDataList.clear();
|
||||
serverDataList = *loadHash(hashFileName);
|
||||
clientDataList.clear();
|
||||
xmlFileDataParse(array);
|
||||
checkNeedUpdate(handler);
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
|
||||
void UpdateController::showHash()
|
||||
{
|
||||
for(FileData& str : serverDataList){
|
||||
Logger::instance().log(str.hash);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateController::calculateFullHash()
|
||||
{
|
||||
Logger::instance().log("Calculate hash...");
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
qDebug() << "Start calculate... ";
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::BUSY);
|
||||
//auto *list = calculateHash(buildPath);
|
||||
|
||||
hashCalculator->calculateHashes(buildPath);
|
||||
auto* list = hashCalculator->getHashList();
|
||||
qDebug() << "Hash count: " << list->count();
|
||||
saveHash(buildHashName,list);
|
||||
calculateSharedHash();
|
||||
Logger::instance().log("Calculate hash complete");
|
||||
qDebug() << "Calculate time " << timer.elapsed();
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::FREE);
|
||||
|
||||
}
|
||||
|
||||
void UpdateController::calculateFullHashWithSetup()
|
||||
{
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::RECALCULATE_HASH);
|
||||
calculateCurrentSharedHash();
|
||||
setUpCurrentServerHash();
|
||||
commonClientHandler->slot_sendPacketToAllClients(PacketType::HASH_READY);
|
||||
}
|
||||
|
||||
void UpdateController::saveHash(QString fileName,QList<FileData> *fileList)
|
||||
{
|
||||
QFile hashFile(fileName);
|
||||
hashFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
QXmlStreamWriter xmlWriter(&hashFile);
|
||||
QListIterator<FileData> fileDataIterator(*fileList);
|
||||
|
||||
xmlWriter.setAutoFormatting(true);
|
||||
xmlWriter.writeStartDocument();
|
||||
xmlWriter.writeStartElement("FileDataList");
|
||||
|
||||
while (fileDataIterator.hasNext())
|
||||
{
|
||||
FileData data = fileDataIterator.next();
|
||||
xmlWriter.writeStartElement("FileData");
|
||||
|
||||
xmlWriter.writeAttribute("Path",data.path);
|
||||
xmlWriter.writeAttribute("Hash",data.hash);
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
xmlWriter.writeEndDocument();
|
||||
|
||||
hashFile.close();
|
||||
|
||||
}
|
||||
|
||||
QList<FileData>* UpdateController::loadHash(QString filename)
|
||||
{
|
||||
QList<FileData> *files = new QList<FileData>();
|
||||
|
||||
QFile hashFile(filename);
|
||||
QByteArray array;
|
||||
if(hashFile.open(QIODevice::ReadOnly)){
|
||||
array = hashFile.readAll();
|
||||
hashFile.close();
|
||||
}
|
||||
|
||||
QXmlStreamReader xmlReader(array);
|
||||
|
||||
while (!xmlReader.atEnd())
|
||||
{
|
||||
if(xmlReader.isStartElement())
|
||||
{
|
||||
if(xmlReader.name().toUtf8() == "FileData")
|
||||
{
|
||||
FileData data;
|
||||
|
||||
foreach(const QXmlStreamAttribute &attr,xmlReader.attributes())
|
||||
{
|
||||
QString name = attr.name().toString();
|
||||
QString value = attr.value().toString();
|
||||
|
||||
if(name == "Path")
|
||||
data.path = value;
|
||||
else if(name == "Hash")
|
||||
data.hash = value;
|
||||
}
|
||||
|
||||
files->append(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
xmlReader.readNextStartElement();
|
||||
}
|
||||
|
||||
Logger::instance().log("Hash load from file ");
|
||||
|
||||
return files;
|
||||
|
||||
}
|
||||
|
||||
void UpdateController::calculateSize()
|
||||
{
|
||||
QDirIterator iterator(buildPath);
|
||||
quint64 total = 0;
|
||||
|
||||
while(iterator.hasNext()){
|
||||
if(iterator.fileInfo().isFile()){
|
||||
total += iterator.fileInfo().size();
|
||||
}
|
||||
|
||||
iterator.next();
|
||||
}
|
||||
|
||||
Logger::instance().log("Full size: ");
|
||||
Logger::instance().log(QString::number(total));
|
||||
}
|
||||
|
||||
QString UpdateController::getCommands()
|
||||
{
|
||||
QString commandsText;
|
||||
commandsText += "check - check version ";
|
||||
commandsText += "update - update files ";
|
||||
|
||||
return commandsText;
|
||||
|
||||
}
|
||||
|
||||
void UpdateController::setUpCurrentServerHash()
|
||||
{
|
||||
QList<FileData> *fileList = new QList<FileData>;
|
||||
fileList->append(*loadHash(buildHashName));
|
||||
FileData *streamingFolder = new FileData;
|
||||
streamingFolder->hash = "FOLDER";
|
||||
streamingFolder->path = buildDataPath + streamingAssetsFolderName;
|
||||
fileList->append(*streamingFolder);
|
||||
QString streamingHashFileName = Tools::createVersionHashFilepath(assetManager->getCurrentVersionData()->getViewName());
|
||||
fileList->append(*loadHash(streamingHashFileName));
|
||||
assetManager->prepareLocalPathList(fileList);
|
||||
|
||||
saveHash(hashFileName,fileList);
|
||||
}
|
||||
|
||||
void UpdateController::setDataInfo(DataInfo *value)
|
||||
{
|
||||
dataInfo = value;
|
||||
}
|
||||
|
||||
QString UpdateController::getCurrentStreamingPath() const
|
||||
{
|
||||
return currentStreamingPath;
|
||||
}
|
||||
|
||||
QList<FileData> UpdateController::prepareRealPathList(QList<FileData> fileData)
|
||||
{
|
||||
return *assetManager->prepareRealPathList(&fileData);
|
||||
}
|
||||
|
||||
void UpdateController::setLocalFileData(QList<FileData> dataList)
|
||||
{
|
||||
serverDataList.append(dataList);
|
||||
}
|
||||
|
||||
bool UpdateController::checkNeedUpdate(ClientHandler *handler)
|
||||
{
|
||||
QList<FileData> *forSend = new QList<FileData>;
|
||||
QList<FileData> *forDelete = new QList<FileData>;
|
||||
Client *client = handler->getClient();
|
||||
|
||||
sizeToSend = 0;
|
||||
|
||||
bool needUpdate = false;
|
||||
|
||||
for (auto &item:clientDataList) //проверка на недостающие файлы по адресам
|
||||
{
|
||||
if(item.path.contains("Temp")) continue;
|
||||
if(item.path.contains("docs.xml")) continue;
|
||||
|
||||
if (!serverDataList.contains(item))
|
||||
{
|
||||
forDelete->append(item);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &item:serverDataList)
|
||||
{
|
||||
if(item.path.contains("Temp")) continue;
|
||||
if(item.path.contains("docs.xml")) continue;
|
||||
|
||||
if (!clientDataList.contains(item))
|
||||
{
|
||||
forSend->append(item);
|
||||
}
|
||||
}
|
||||
|
||||
if(forSend->length() > 0) //формирование сообщения об обновлении
|
||||
{
|
||||
QString log;
|
||||
log.append(" Client: " + client->getLogin());
|
||||
log.append(" Need updates: ");
|
||||
log.append(QString::number(forSend->length()));
|
||||
log.append(" objects");
|
||||
client->setFileSendList(*forSend);
|
||||
Logger::instance().log(log);
|
||||
needUpdate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QString log;
|
||||
log.append(" Client: " + client->getLogin());
|
||||
log.append(" no update required");
|
||||
Logger::instance().log(log);
|
||||
}
|
||||
|
||||
if(forDelete->length() > 0){
|
||||
QString log;
|
||||
log.append(" Client: " + client->getLogin());
|
||||
|
||||
log.append(" Need delete: ");
|
||||
log.append(QString::number(forDelete->length()));
|
||||
log.append(" objects");
|
||||
client->setFileDeleteList(*forDelete);
|
||||
|
||||
Logger::instance().log(log);
|
||||
needUpdate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QString log;
|
||||
log.append(" Client: " + client->getLogin());
|
||||
log.append(" no delete required");
|
||||
|
||||
Logger::instance().log(log);
|
||||
//handler->sendMessageBlock(log);
|
||||
}
|
||||
|
||||
CalculateSizeToSend(*forSend);
|
||||
handler->sendNeedUpdate(needUpdate,sizeToSend,forSend->length(),forDelete->length());
|
||||
|
||||
return needUpdate;
|
||||
}
|
||||
|
||||
QList<FileData>* UpdateController::calculateHash(QString path)
|
||||
{
|
||||
serverDataList.clear();
|
||||
|
||||
if(!QDir(path).exists()){
|
||||
QDir().mkdir(path);
|
||||
}
|
||||
|
||||
QString hashString;
|
||||
QStringList filter;
|
||||
filter << "*";
|
||||
QList<FileData> *files = new QList<FileData>;
|
||||
|
||||
QDirIterator dirIterator(path,filter, QDir::AllEntries, QDirIterator::Subdirectories);
|
||||
|
||||
while (dirIterator.hasNext())
|
||||
{
|
||||
QFileInfo fileInfo(dirIterator.next());
|
||||
FileData currentFile;
|
||||
if(fileInfo.isDir() && !fileInfo.fileName().startsWith(".") && fileInfo.fileName() != projectFolderName)
|
||||
{
|
||||
currentFile.path = Tools::createLocalPath(fileInfo.absoluteFilePath());
|
||||
currentFile.hash = "FOLDER";
|
||||
|
||||
if(!files->contains(currentFile))
|
||||
{
|
||||
files->push_back(currentFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDirIterator fileIterator(path,filter,QDir::Files | QDir::NoDotAndDotDot,QDirIterator::Subdirectories);
|
||||
|
||||
while (fileIterator.hasNext())
|
||||
{
|
||||
fileIterator.next();
|
||||
QFileInfo fileInfo = fileIterator.fileInfo();
|
||||
FileData currentFile;
|
||||
QFile file(fileInfo.absoluteFilePath());
|
||||
|
||||
quint64 fileSize = file.size(); //буффер для хэширования крупных файлов
|
||||
const quint64 bufferSize = 1024;
|
||||
|
||||
if(fileInfo.isHidden()) continue;
|
||||
|
||||
if(fileInfo.isFile() && file.open(QIODevice::ReadOnly) && !fileInfo.fileName().contains(".meta"))
|
||||
{
|
||||
char buffer[bufferSize];
|
||||
int bytesRead;
|
||||
int readSize = qMin(fileSize,bufferSize);
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
||||
|
||||
while(readSize > 0 && (bytesRead = file.read(buffer,readSize)) > 0)
|
||||
{
|
||||
fileSize -= bytesRead;
|
||||
hash.addData(buffer,bytesRead);
|
||||
readSize = qMin(fileSize,bufferSize);
|
||||
}
|
||||
|
||||
hashString = QString(hash.result().toHex());
|
||||
currentFile.path = Tools::createLocalPath(fileInfo.absoluteFilePath());
|
||||
currentFile.hash = hashString;
|
||||
files->push_back(currentFile);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
serverDataList.append(*files);
|
||||
return files;
|
||||
}
|
||||
|
||||
QString UpdateController::getPathAdditionalFile(QString name)
|
||||
{
|
||||
QString path = Tools::createSharedPath("/" + assetManager->getCurrentVersionData()->getViewName() + "/" + additionalFilesFolderName + name);
|
||||
return path;
|
||||
}
|
||||
|
||||
QString UpdateController::getPathScensFile(QString name)
|
||||
{
|
||||
QString path = Tools::createSharedPath("/" + assetManager->getCurrentVersionData()->getViewName() + "/" + rusScensFolderName + name);
|
||||
return path;
|
||||
}
|
||||
|
||||
QByteArray UpdateController::getLocalHash()
|
||||
{
|
||||
QFile hashFile(hashFileName);
|
||||
QByteArray array;
|
||||
if(hashFile.open(QIODevice::ReadOnly)){
|
||||
array = hashFile.readAll();
|
||||
hashFile.close();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
QString UpdateController::getCurrentVersionName()
|
||||
{
|
||||
return assetManager->getCurrentVersionData()->getViewName();
|
||||
}
|
||||
|
||||
void UpdateController::CalculateSizeToSend(QList<FileData> diffList)
|
||||
{
|
||||
QListIterator<FileData> serverDiffIterator(diffList);
|
||||
|
||||
while (serverDiffIterator.hasNext())
|
||||
{
|
||||
QString path;
|
||||
FileData pathForUpdate = serverDiffIterator.next();
|
||||
if(pathForUpdate.path.contains(streamingAssetsFolderName))
|
||||
{
|
||||
path = Tools::createStreamingToRealPath(pathForUpdate.path,assetManager->getCurrentVersionData());
|
||||
}
|
||||
else
|
||||
{
|
||||
path = Tools::createRootPath(pathForUpdate.path);
|
||||
}
|
||||
|
||||
QFile file(path);
|
||||
|
||||
sizeToSend += file.size();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateController::calculateSharedHash()
|
||||
{
|
||||
QDir sharedDir(sharedDataPath);
|
||||
|
||||
if(!QDir(sharedDataPath).exists())
|
||||
{
|
||||
QDir().mkdir(sharedDataPath);
|
||||
}
|
||||
|
||||
QDirIterator dirIterator(sharedDir);
|
||||
QList<FileData> *fileList = new QList<FileData>;
|
||||
QList<StreamingVersionData*> *versionList = new QList<StreamingVersionData*>;
|
||||
|
||||
while (dirIterator.hasNext())
|
||||
{
|
||||
fileList->clear();
|
||||
dirIterator.next();
|
||||
QFileInfo fileInfo = dirIterator.fileInfo();
|
||||
if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
|
||||
continue;
|
||||
|
||||
QString fileName = Tools::createVersionHashFilepath(fileInfo.fileName());
|
||||
|
||||
hashCalculator->calculateHashes(fileInfo.filePath());
|
||||
fileList = hashCalculator->getHashList();
|
||||
//fileList = calculateHash(fileInfo.absoluteFilePath());
|
||||
qDebug() << "Hash count: " << fileList->count();
|
||||
saveHash(fileName,fileList);
|
||||
|
||||
StreamingVersionData *version = new StreamingVersionData(
|
||||
fileInfo.absoluteFilePath(),fileInfo.fileName(),
|
||||
fileInfo.birthTime(),fileInfo.size());
|
||||
versionList->append(version);
|
||||
|
||||
}
|
||||
|
||||
assetManager->createFirstVersionListXML(*versionList);
|
||||
}
|
||||
|
||||
void UpdateController::calculateCurrentSharedHash()
|
||||
{
|
||||
QList<FileData> *fileList = new QList<FileData>;
|
||||
QString fileName = Tools::createVersionHashFilepath(assetManager->getCurrentVersionData()->getViewName());
|
||||
|
||||
hashCalculator->calculateHashes(currentStreamingPath);
|
||||
fileList = hashCalculator->getHashList();
|
||||
//fileList = calculateHash(currentStreamingPath);
|
||||
qDebug() << "Hash count: " << fileList->count();
|
||||
saveHash(fileName,fileList);
|
||||
}
|
||||
|
||||
void UpdateController::sendNewVersionList()
|
||||
{
|
||||
commonClientHandler->sendNewVersionListToAllClient();
|
||||
}
|
||||
|
||||
bool UpdateController::checkDuplicate(QString versionName)
|
||||
{
|
||||
return assetManager->findDuplicate(versionName);
|
||||
}
|
||||
|
||||
void UpdateController::xmlFileDataParse(QByteArray array)
|
||||
{
|
||||
QXmlStreamReader xmlReader(array);
|
||||
xmlReader.readNext();
|
||||
|
||||
//Крутимся в цикле до тех пор, пока не достигнем конца документа
|
||||
while(!xmlReader.atEnd())
|
||||
{
|
||||
//Проверяем, является ли элемент началом тега
|
||||
if(xmlReader.isStartElement())
|
||||
{
|
||||
if(xmlReader.name() == "FileData")
|
||||
{
|
||||
FileData data;
|
||||
|
||||
foreach(const QXmlStreamAttribute &attr,xmlReader.attributes())
|
||||
{
|
||||
QString name = attr.name().toString();
|
||||
QString value = attr.value().toString();
|
||||
|
||||
if(name == "Path")
|
||||
data.path = value;
|
||||
else if(name == "Hash")
|
||||
data.hash = value;
|
||||
}
|
||||
|
||||
clientDataList.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
xmlReader.readNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
StreamingVersionData* UpdateController::getCurrentVersion()
|
||||
{
|
||||
return assetManager->getCurrentVersionData();
|
||||
}
|
||||
|
||||
void UpdateController::printFileList(QList<FileData> fileData)
|
||||
{
|
||||
QListIterator<FileData> iterator(fileData);
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
auto next = iterator.next();
|
||||
Logger::instance().log(next.path);
|
||||
}
|
||||
}
|
||||
|
||||
QList<FileData> UpdateController::getClientDataList() const
|
||||
{
|
||||
return clientDataList;
|
||||
}
|
||||
|
||||
DataInfo *UpdateController::getCurrentDataInfo()
|
||||
{
|
||||
return dataInfo;
|
||||
}
|
||||
|
||||
void UpdateController::clearCurrentDataInfo()
|
||||
{
|
||||
delete dataInfo;
|
||||
}
|
||||
|
||||
bool UpdateController::checkRequiredFolder()
|
||||
{
|
||||
bool required = true;
|
||||
QDir buildDir(buildPath + "/" + projectFolderName);
|
||||
if (!buildDir.exists()) required = false;
|
||||
|
||||
QDir baseSharedDir(sharedDataPath + "/" + baseNameVersion);
|
||||
if (!baseSharedDir.exists()) required = false;
|
||||
|
||||
return required;
|
||||
}
|
||||
UpdateController::~UpdateController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user