feat: fast hash checker

This commit is contained in:
semenov
2025-09-23 09:23:04 +03:00
parent c9c62d22c0
commit 60c3d6244e
13 changed files with 17266 additions and 17077 deletions

View File

@@ -1,6 +1,7 @@
#include "UpdateController.h" #include "UpdateController.h"
#include <QElapsedTimer>
#include <QThread> #include <QThread>
UpdateController::UpdateController(QObject *parent) : UpdateController::UpdateController(QObject *parent) :
@@ -15,23 +16,33 @@ void UpdateController::initialize(VersionContainer *versionContainer,DataParserO
this->versionContainer = versionContainer; this->versionContainer = versionContainer;
this->sendSystem = sendSystem; this->sendSystem = sendSystem;
this->dataParserOut = dataParserOut; this->dataParserOut = dataParserOut;
hashCalculator = new FastHashCalculator;
} }
void UpdateController::calculateCommonHash() void UpdateController::calculateCommonHash()
{ {
appDataList.clear(); appDataList.clear();
appDataList = calculateHash(applicationFolderPath,"StreamingAssets"); QElapsedTimer timer;
timer.start();
qDebug() << "Start calculate... ";
//appDataList = calculateHash(applicationFolderPath,"StreamingAssets");
hashCalculator->calculateHashes(applicationFolderPath,"StreamingAssets");
appDataList = *hashCalculator->getHashList();
calculateStreamingHash(); calculateStreamingHash();
appDataList.append(streamingDataList); appDataList.append(streamingDataList);
qDebug() << "Hash count: " << appDataList.count() ;
dataParserOut->createFileDataList(appDataList,fullStaticDataFolderName + hashFilename); dataParserOut->createFileDataList(appDataList,fullStaticDataFolderName + hashFilename);
qDebug() << "UpdateController threadID " << QThread::currentThreadId(); qDebug() << "UpdateController threadID " << QThread::currentThreadId();
qDebug() <<"Calculate time " << timer.elapsed();
} }
void UpdateController::calculateStreamingHash() void UpdateController::calculateStreamingHash()
{ {
streamingDataList.clear(); streamingDataList.clear();
streamingDataList = calculateHash(QDir::currentPath() + streamingAssetsPath,""); //streamingDataList = calculateHash(QDir::currentPath() + streamingAssetsPath,"");
std::sort(streamingDataList.begin(),streamingDataList.end()); hashCalculator->calculateHashes(QDir::currentPath() + streamingAssetsPath,"");
streamingDataList = *hashCalculator->getHashList();
//std::sort(streamingDataList.begin(),streamingDataList.end());
dataParserOut->createFileDataList(streamingDataList,streamingHashFilename); dataParserOut->createFileDataList(streamingDataList,streamingHashFilename);
} }
@@ -84,7 +95,7 @@ QList<FileData> UpdateController::calculateHash(const QString& path,const QStrin
emit sigSendHashInfo(fullSize,Tools::convertFileSize(currentSize,false)); emit sigSendHashInfo(fullSize,Tools::convertFileSize(currentSize,false));
quint64 fileSize = file.size(); //буффер для хэширования крупных файлов quint64 fileSize = file.size(); //буффер для хэширования крупных файлов
const quint64 bufferSize = 10240; const quint64 bufferSize = 1024;
if(fileInfo.isHidden()) continue; if(fileInfo.isHidden()) continue;
if(ignoreName != "" && fileInfo.path().contains(ignoreName)) continue; if(ignoreName != "" && fileInfo.path().contains(ignoreName)) continue;

View File

@@ -3,6 +3,7 @@
#include "Core/sendsystem.h" #include "Core/sendsystem.h"
#include "Core/versioncontainer.h" #include "Core/versioncontainer.h"
#include "fasthashcalculator.h"
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include <QXmlStreamAttribute> #include <QXmlStreamAttribute>
@@ -40,6 +41,7 @@ signals:
private: private:
SendSystem *sendSystem; SendSystem *sendSystem;
DataParserOutput * dataParserOut; DataParserOutput * dataParserOut;
FastHashCalculator* hashCalculator;
QString applicationFolderPath; QString applicationFolderPath;
VersionContainer *versionContainer; VersionContainer *versionContainer;
QList<FileData> appDataList; QList<FileData> appDataList;

View File

@@ -0,0 +1,98 @@
#include "fasthashcalculator.h"
#include <QtConcurrent>
FastHashCalculator::FastHashCalculator(QObject *parent) : QObject(parent)
{
hashList = new QList<FileData>();
}
void FastHashCalculator::calculateHashes(const QString& path, const QString& ignoreName)
{
hashList->clear();
if(!QDir(path).exists()){
QDir().mkdir(path);
}
QString hashString;
QStringList filter;
filter << "*";
QList<FileData> *folders = new QList<FileData>;
//QString fullSize = Tools::convertFileSize(getDirectorySize(path),false);
QDirIterator dirIterator(path,filter, QDir::AllEntries, QDirIterator::Subdirectories);
while (dirIterator.hasNext())
{
QFileInfo fileInfo(dirIterator.next());
FileData currentFolder;
if(fileInfo.isDir() && !fileInfo.fileName().startsWith(".") && fileInfo.fileName() != "RRJLoader")
{
currentFolder.path = Tools::createLocalPath(fileInfo.absoluteFilePath());
currentFolder.hash = "FOLDER";
if(!folders->contains(currentFolder))
{
folders->push_back(currentFolder);
}
}
}
QDirIterator fileIterator(path,filter,QDir::Files | QDir::NoDotAndDotDot,QDirIterator::Subdirectories);
QList<QString> files;
files.clear();
while(fileIterator.hasNext())
{
fileIterator.next();
QFileInfo fileInfo = fileIterator.fileInfo();
QString path = fileInfo.absoluteFilePath();
if (fileInfo.isHidden()) continue;
if (!fileInfo.isFile()) continue;
if (fileInfo.fileName().contains(".meta")) continue;
if (ignoreName != "" && fileInfo.path().contains(ignoreName)) continue;
files.append(path);
}
QtConcurrent::map(files, [this](const QString &filePath)
{
QByteArray hash = calculateFileHashOptimized(filePath);
QMutexLocker locker(&_mutex);
FileData currentFile;
QString hashName;
currentFile.path = Tools::createLocalPath(filePath);
currentFile.hash = hash.toHex();
hashList->append(currentFile);
}).waitForFinished();
hashList->append(*folders);
emit finished();
}
QByteArray FastHashCalculator::calculateFileHashOptimized(const QString &filePath)
{
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) return QByteArray();
QCryptographicHash hash(QCryptographicHash::Md5);
const qint64 bufferSize = 2 * 1024; // 2MB
QByteArray buffer;
buffer.resize(bufferSize);
while (!file.atEnd()) {
qint64 bytesRead = file.read(buffer.data(), bufferSize);
hash.addData(buffer.constData(), bytesRead);
}
return hash.result();
}
QList<FileData> *FastHashCalculator::getHashList() const
{
return hashList;
}

34
Core/fasthashcalculator.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef FASTHASHCALCULATOR_H
#define FASTHASHCALCULATOR_H
#include <QHash>
#include <QMutex>
#include <QObject>
#include <QFile>
#include <QDirIterator>
#include <Data/FileData.h>
#include "tools.h"
class FastHashCalculator : public QObject
{
Q_OBJECT
public:
explicit FastHashCalculator(QObject *parent = nullptr);
void calculateHashes(const QString& path, const QString& ignoreName);
QList<FileData> *getHashList() const;
signals:
void finished();
private:
QByteArray calculateFileHashOptimized(const QString &filePath);
void calculateSingleHash(const QString &filePath);
QList<FileData>* hashList;
QMutex _mutex;
quint64 currentSize;
};
#endif // FASTHASHCALCULATOR_H

View File

@@ -47,7 +47,6 @@ void TCPClient::setConnect(ServerSettings *serverSettings)
} }
} }
void TCPClient::setDisconnect() void TCPClient::setDisconnect()
{ {
socket->disconnect(); socket->disconnect();

View File

@@ -23,7 +23,7 @@ public:
void initialize(RecognizeSystem *recognize,SendSystem *sendSystem); void initialize(RecognizeSystem *recognize,SendSystem *sendSystem);
void setConnect(ServerSettings *serverSettings); void setConnect(ServerSettings *serverSettings);
~TCPClient(){}; ~TCPClient(){};
void setDisconnect();
bool getIsConnected() const; bool getIsConnected() const;
signals: signals:
@@ -43,8 +43,6 @@ private:
QTcpSocket *socket; QTcpSocket *socket;
RecognizeSystem *recognizeSystem; RecognizeSystem *recognizeSystem;
bool isConnected; bool isConnected;
void setDisconnect();
}; };
#endif // TCPCLIENT_H #endif // TCPCLIENT_H

View File

@@ -1,7 +1,7 @@
QT += core gui QT += core gui
QT += network QT += network
QT += xml QT += xml
QT += testlib QT += concurrent
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11 CONFIG += c++11
@@ -18,6 +18,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \ SOURCES += \
Core/dataparseroutput.cpp \ Core/dataparseroutput.cpp \
Core/fasthashcalculator.cpp \
Core/notifycontroller.cpp \ Core/notifycontroller.cpp \
Core/postprocessorsystem.cpp \ Core/postprocessorsystem.cpp \
Core/sendsystem.cpp \ Core/sendsystem.cpp \
@@ -45,6 +46,7 @@ SOURCES += \
HEADERS += \ HEADERS += \
Core/dataparseroutput.h \ Core/dataparseroutput.h \
Core/fasthashcalculator.h \
Core/notifycontroller.h \ Core/notifycontroller.h \
Core/postprocessorsystem.h \ Core/postprocessorsystem.h \
Core/versioncontainer.h \ Core/versioncontainer.h \

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<AuthData Login="O1" Password="1111" InstructorName="" ClientName="Коровин А.В." AccessType="trainee"/> <AuthData Login="O5" Password="5555" InstructorName="" ClientName="Синицин И.И." AccessType="trainee"/>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<ServerSettingsContainer> <ServerSettingsContainer>
<ServerSettings Port="6000" LocalPortMath="18004" AutoStart="0" Language="RUS" DestPortMath="18003" UseMathModel="1" Address="192.168.100.134"/> <ServerSettings Address="192.168.100.83" Port="6000" UseMathModel="1" AutoStart="0" DestPortMath="18003" Language="RUS" LocalPortMath="18004"/>
<VersionData Created="Вт авг 19 11:09:28 2025" isChangable="0" Version="base"/> <VersionData Version="base" Created="Ср авг 20 17:12:35 2025" isChangable="0"/>
</ServerSettingsContainer> </ServerSettingsContainer>

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ClientNotify Code="DISABLE"/> <ClientAutorization Login="O5" Password="5555"/>

View File

@@ -351,14 +351,13 @@ void CoreManager::saveServerSettingsWithConnect()
if(client->getIsConnected()) if(client->getIsConnected())
{ {
client->setDisconnect();
entryWidget->showLoginWidget(true); entryWidget->showLoginWidget(true);
widgetManager->getMainWindow()->showOfflineButton(true); widgetManager->getMainWindow()->showOfflineButton(true);
widgetManager->activateLoadingAnimation(false); widgetManager->activateLoadingAnimation(false);
} }
else
{ emit sigSetConnect(settings);
emit sigSetConnect(settings);
}
} }
void CoreManager::checkAppAvailable() void CoreManager::checkAppAvailable()