yacreader/YACReaderLibrary/yacreader_local_server.cpp
Luis Ángel San Martín 5aa02a19bb clang-format
2021-10-18 21:56:52 +02:00

246 lines
7.4 KiB
C++

#include "yacreader_local_server.h"
#include <QLocalServer>
#include <QLocalSocket>
#include <QPointer>
#include "yacreader_global.h"
#include "db_helper.h"
#include "comic_db.h"
#include "QsLog.h"
using namespace YACReader;
QMutex YACReaderClientConnectionWorker::dbMutex;
// int YACReaderClientConnectionWorker::count = 0;
YACReaderLocalServer::YACReaderLocalServer(QObject *parent)
: QObject(parent)
{
localServer = new QLocalServer(this);
QLocalServer::removeServer(YACREADERLIBRARY_GUID);
if (!localServer->listen(YACREADERLIBRARY_GUID)) {
QLOG_ERROR() << "Unable to create local server";
}
connect(localServer, &QLocalServer::newConnection, this, &YACReaderLocalServer::sendResponse);
}
bool YACReaderLocalServer::isListening()
{
return localServer->isListening();
}
/*void YACReaderLocalServer::run()
{
while(1)
exec();
}*/
void YACReaderLocalServer::sendResponse()
{
QLocalSocket *clientConnection = localServer->nextPendingConnection();
// connect(clientConnection, SIGNAL(disconnected()),clientConnection, SLOT(deleteLater()));
clientConnection->setParent(0);
auto worker = new YACReaderClientConnectionWorker(clientConnection);
if (worker != 0) {
clientConnection->moveToThread(worker);
connect(worker, &YACReaderClientConnectionWorker::comicUpdated, this, &YACReaderLocalServer::comicUpdated);
connect(worker, &QThread::finished, worker, &QObject::deleteLater);
worker->start();
}
QLOG_TRACE() << "connection incoming";
// clientConnection->waitForBytesWritten();*/
// clientConnection->disconnectFromServer();
}
bool YACReaderLocalServer::isRunning()
{
QLocalSocket socket;
socket.connectToServer(YACREADERLIBRARY_GUID);
if (socket.waitForConnected(500))
return true; // Server is running (another instance of YACReaderLibrary has been launched)
return false;
}
void YACReaderLocalServer::close()
{
localServer->close();
}
YACReaderClientConnectionWorker::YACReaderClientConnectionWorker(QLocalSocket *cc)
: QThread(), clientConnection(cc)
{
}
YACReaderClientConnectionWorker::~YACReaderClientConnectionWorker()
{
}
/*#include <QFile>
#include <QTextStream>
#include <QDateTime>*/
void YACReaderClientConnectionWorker::run()
{
/*{
QFile f(QString("c:/temp/thread%1.txt").arg(count));
f.open(QIODevice::Append);
QTextStream out(&f);
out << QString("Thread%1 starts").arg(count) << endl;
f.close();
}
uint t1 = QDateTime::currentMSecsSinceEpoch();*/
quint64 libraryId;
ComicDB comic;
OpenComicSource source = { OpenComicSource::ReadingList, 0 };
qulonglong nextComicId;
int tries = 0;
int dataAvailable = 0;
QByteArray packageSize;
clientConnection->waitForReadyRead(1000);
while (((long unsigned int)packageSize.size() < sizeof(quint32)) && (tries < 20)) {
packageSize.append(clientConnection->read(sizeof(quint32) - packageSize.size()));
clientConnection->waitForReadyRead(100);
if (dataAvailable == packageSize.size()) {
tries++;
}
dataAvailable = packageSize.size();
}
if (tries == 20) {
QLOG_ERROR() << "Local connection: unable to read the message size" << clientConnection->errorString();
return;
}
QDataStream sizeStream(packageSize);
sizeStream.setVersion(QDataStream::Qt_4_8);
quint32 totalSize = 0;
sizeStream >> totalSize;
tries = 0;
QByteArray data;
int dataRead = 0;
while ((quint32)data.size() < totalSize && tries < 200) {
data.append(clientConnection->readAll());
if ((quint32)data.length() < totalSize)
clientConnection->waitForReadyRead(100);
if (dataRead == data.length()) // no bytes were read
tries++;
dataRead = data.length();
}
if (tries == 200) {
QLOG_ERROR() << QString("Local connection: unable to read message (%1,%2)").arg(data.size()).arg(totalSize);
return;
}
QDataStream dataStream(data);
quint8 msgType;
dataStream >> msgType;
switch (msgType) {
case YACReader::RequestComicInfo: {
dataStream >> libraryId;
dataStream >> source;
dataStream >> comic;
QList<ComicDB> siblings;
if (source.source == OpenComicSource::ReadingList) {
getComicInfoFromReadingList(libraryId, source.sourceId, comic, siblings);
} else {
getComicInfo(libraryId, comic, siblings);
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_8);
out << (quint32)0;
out << comic;
out << siblings;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));
int written = 0;
tries = 0;
while (written != block.size() && tries < 200) {
int ret = clientConnection->write(block);
clientConnection->waitForBytesWritten(10);
if (ret != -1) {
written += ret;
clientConnection->flush();
} else
tries++;
}
if (tries == 200 && written != block.size()) {
QLOG_ERROR() << QString("Local connection (comic info requested): unable to send response (%1,%2)").arg(written).arg(block.size());
}
break;
}
case YACReader::SendComicInfo: {
bool nextComicInfoAvailable;
dataStream >> libraryId;
dataStream >> comic;
if (dataStream.atEnd()) {
nextComicInfoAvailable = false;
} else {
nextComicInfoAvailable = true;
dataStream >> nextComicId;
}
if (nextComicInfoAvailable) {
updateComic(libraryId, comic, nextComicId);
} else {
updateComic(libraryId, comic);
}
break;
}
}
clientConnection->waitForDisconnected();
clientConnection->deleteLater();
/*count++;
uint t2 = QDateTime::currentMSecsSinceEpoch();
{
QFile f(QString("c:/temp/thread%1.txt").arg(count));
f.open(QIODevice::Append);
QTextStream out(&f);
out << QString("Thread%1 ends : time - %2").arg(count).arg(t2-t1) << endl;
f.close();
}*/
}
void YACReaderClientConnectionWorker::getComicInfo(quint64 libraryId, ComicDB &comic, QList<ComicDB> &siblings)
{
QMutexLocker locker(&dbMutex);
comic = DBHelper::getComicInfo(libraryId, comic.id);
siblings = DBHelper::getSiblings(libraryId, comic.parentId);
}
void YACReaderClientConnectionWorker::getComicInfoFromReadingList(quint64 libraryId, unsigned long long readingListId, ComicDB &comic, QList<ComicDB> &siblings)
{
QMutexLocker locker(&dbMutex);
comic = DBHelper::getComicInfo(libraryId, comic.id);
siblings = DBHelper::getReadingListFullContent(libraryId, readingListId, true);
}
void YACReaderClientConnectionWorker::updateComic(quint64 libraryId, ComicDB &comic)
{
QMutexLocker locker(&dbMutex);
DBHelper::update(libraryId, comic.info);
emit comicUpdated(libraryId, comic);
}
void YACReaderClientConnectionWorker::updateComic(quint64 libraryId, ComicDB &comic, qulonglong nextComicId)
{
QMutexLocker locker(&dbMutex);
DBHelper::update(libraryId, comic.info);
ComicInfo nextcomicinfo;
nextcomicinfo.id = nextComicId;
DBHelper::setComicAsReading(libraryId, nextcomicinfo);
emit comicUpdated(libraryId, comic);
}