mirror of https://github.com/procxx/kepka.git
version 0.6.6 - some network fixes and download/upload optimizations
This commit is contained in:
parent
a8fd1c54c0
commit
5dc9cdbd3c
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinuxupd$AppVersion" ]; then
|
||||
echo "tlinuxupd$AppVersion not found!";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ ! -f "./../Linux/Release/deploy/$AppVersionStr/tlinux32upd$AppVersion" ]; then
|
||||
echo "tlinux32upd$AppVersion not found!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ ! -f "./../Mac/Release/deploy/$AppVersionStr/tmacupd$AppVersion" ]; then
|
||||
echo "tmacupd$AppVersion not found!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ ! -f "./../Win32/Deploy/deploy/$AppVersionStr/tupdate$AppVersion" ]; then
|
||||
echo "tupdate$AppVersion not found!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ -d "./../Linux/Release/deploy/$AppVersionStr" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AppVersionStr=0.6.5
|
||||
AppVersion=6005
|
||||
AppVersionStr=0.6.6
|
||||
AppVersion=6006
|
||||
|
||||
if [ -d "./../Mac/Release/deploy/$AppVersionStr" ]; then
|
||||
echo "Deploy folder for version $AppVersionStr already exists!"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cd ..\Win32\Deploy
|
||||
call ..\..\..\TelegramPrivate\Sign.bat tsetup.0.6.5.exe
|
||||
call ..\..\..\TelegramPrivate\Sign.bat tsetup.0.6.6.exe
|
||||
call Prepare.exe -path Telegram.exe -path Updater.exe
|
||||
mkdir deploy\0.6.5\Telegram
|
||||
move deploy\0.6.5\Telegram.exe deploy\0.6.5\Telegram\
|
||||
mkdir deploy\0.6.6\Telegram
|
||||
move deploy\0.6.6\Telegram.exe deploy\0.6.6\Telegram\
|
||||
cd ..\..\Telegram
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#define MyAppShortName "Telegram"
|
||||
#define MyAppName "Telegram Desktop"
|
||||
#define MyAppVersion "0.6.5"
|
||||
#define MyAppVersionZero "0.6.5"
|
||||
#define MyAppFullVersion "0.6.5.0"
|
||||
#define MyAppVersion "0.6.6"
|
||||
#define MyAppVersionZero "0.6.6"
|
||||
#define MyAppFullVersion "0.6.6.0"
|
||||
#define MyAppPublisher "Telegram Messenger LLP"
|
||||
#define MyAppURL "https://tdesktop.com"
|
||||
#define MyAppExeName "Telegram.exe"
|
||||
|
|
|
@ -531,7 +531,7 @@ namespace App {
|
|||
const MTPDphotoSize &d(size.c_photoSize());
|
||||
if (d.vlocation.type() == mtpc_fileLocation) {
|
||||
const MTPDfileLocation &l(d.vlocation.c_fileLocation());
|
||||
return ImagePtr(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v);
|
||||
return ImagePtr(d.vw.v, d.vh.v, l.vdc_id.v, l.vvolume_id.v, l.vlocal_id.v, l.vsecret.v, d.vsize.v);
|
||||
}
|
||||
} break;
|
||||
case mtpc_photoCachedSize: {
|
||||
|
|
|
@ -154,6 +154,9 @@ Application::Application(int &argc, char **argv) : PsApplication(argc, argv),
|
|||
connect(&writeUserConfigTimer, SIGNAL(timeout()), this, SLOT(onWriteUserConfig()));
|
||||
writeUserConfigTimer.setSingleShot(true);
|
||||
|
||||
killDownloadSessionsTimer.setSingleShot(true);
|
||||
connect(&killDownloadSessionsTimer, SIGNAL(timeout()), this, SLOT(killDownloadSessions()));
|
||||
|
||||
if (cManyInstance()) {
|
||||
startApp();
|
||||
} else {
|
||||
|
@ -326,10 +329,46 @@ void Application::writeUserConfigIn(uint64 ms) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::killDownloadSessionsStart(int32 dc) {
|
||||
if (killDownloadSessionTimes.constFind(dc) == killDownloadSessionTimes.cend()) {
|
||||
killDownloadSessionTimes.insert(dc, getms() + MTPKillFileSessionTimeout);
|
||||
}
|
||||
if (!killDownloadSessionsTimer.isActive()) {
|
||||
killDownloadSessionsTimer.start(MTPKillFileSessionTimeout + 5);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::killDownloadSessionsStop(int32 dc) {
|
||||
killDownloadSessionTimes.remove(dc);
|
||||
if (killDownloadSessionTimes.isEmpty() && killDownloadSessionsTimer.isActive()) {
|
||||
killDownloadSessionsTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onWriteUserConfig() {
|
||||
App::writeUserConfig();
|
||||
}
|
||||
|
||||
void Application::killDownloadSessions() {
|
||||
uint64 ms = getms(), left = MTPKillFileSessionTimeout;
|
||||
for (QMap<int32, uint64>::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) {
|
||||
if (i.value() <= ms) {
|
||||
for (int j = 1; j < MTPDownloadSessionsCount; ++j) {
|
||||
MTP::killSession(MTP::dld[j] + i.key());
|
||||
}
|
||||
i = killDownloadSessionTimes.erase(i);
|
||||
} else {
|
||||
if (i.value() - ms < left) {
|
||||
left = i.value() - ms;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (!killDownloadSessionTimes.isEmpty()) {
|
||||
killDownloadSessionsTimer.start(left);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::photoUpdated(MsgId msgId, const MTPInputFile &file) {
|
||||
if (!App::self()) return;
|
||||
|
||||
|
|
|
@ -70,6 +70,9 @@ public:
|
|||
|
||||
void writeUserConfigIn(uint64 ms);
|
||||
|
||||
void killDownloadSessionsStart(int32 dc);
|
||||
void killDownloadSessionsStop(int32 dc);
|
||||
|
||||
signals:
|
||||
|
||||
void peerPhotoDone(PeerId peer);
|
||||
|
@ -100,10 +103,15 @@ public slots:
|
|||
void onEnableDebugMode();
|
||||
void onWriteUserConfig();
|
||||
|
||||
void killDownloadSessions();
|
||||
|
||||
private:
|
||||
|
||||
QMap<MsgId, PeerId> photoUpdates;
|
||||
|
||||
QMap<int32, uint64> killDownloadSessionTimes;
|
||||
QTimer killDownloadSessionsTimer;
|
||||
|
||||
void startApp();
|
||||
|
||||
typedef QPair<QLocalSocket*, QByteArray> ClientSocket;
|
||||
|
|
|
@ -17,8 +17,8 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
static const int32 AppVersion = 6005;
|
||||
static const wchar_t *AppVersionStr = L"0.6.5";
|
||||
static const int32 AppVersion = 6006;
|
||||
static const wchar_t *AppVersionStr = L"0.6.6";
|
||||
|
||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||
static const wchar_t *AppName = L"Telegram Desktop";
|
||||
|
@ -32,7 +32,7 @@ enum {
|
|||
MTPShortBufferSize = 65535, // of ints, 256 kb
|
||||
MTPPacketSizeMax = 67108864, // 64 mb
|
||||
MTPIdsBufferSize = 400, // received msgIds and wereAcked msgIds count stored
|
||||
MTPCheckResendTimeout = 5000, // how much time passed from send till we resend request or check it's state, in ms
|
||||
MTPCheckResendTimeout = 10000, // how much time passed from send till we resend request or check it's state, in ms
|
||||
MTPCheckResendWaiting = 1000, // how much time to wait for some more requests, when resending request or checking it's state, in ms
|
||||
MTPResendThreshold = 1, // how much ints should message contain for us not to resend, but to check it's state
|
||||
MTPContainerLives = 600, // container lives 10 minutes in haveSent map
|
||||
|
@ -41,6 +41,10 @@ enum {
|
|||
MTPTcpConnectionWaitTimeout = 3000, // 3 seconds waiting for tcp, until we accept http
|
||||
MTPMillerRabinIterCount = 30, // 30 Miller-Rabin iterations for dh_prime primality check
|
||||
|
||||
MTPUploadSessionsCount = 4, // max 4 upload sessions is created
|
||||
MTPDownloadSessionsCount = 4, // max 4 download sessions is created
|
||||
MTPKillFileSessionTimeout = 5000, // how much time without upload / download causes additional session kill
|
||||
|
||||
MTPEnumDCTimeout = 4000, // 4 seconds timeout for help_getConfig to work (them move to other dc)
|
||||
|
||||
MTPDebugBufferSize = 1024 * 1024, // 1 mb start size
|
||||
|
@ -209,12 +213,12 @@ enum {
|
|||
|
||||
LinkCropLimit = 360, // 360px link length max
|
||||
|
||||
DownloadPartSize = 32 * 1024, // 32kb for photo
|
||||
DownloadPartSize = 64 * 1024, // 64kb for photo
|
||||
DocumentDownloadPartSize = 128 * 1024, // 128kb for document
|
||||
MaxUploadPhotoSize = 10 * 1024 * 1024, // 10mb photos max
|
||||
MaxUploadDocumentSize = 1500 * 1024 * 1024, // 1500mb documents max
|
||||
UseBigFilesFrom = 10 * 1024 * 1024, // mtp big files methods used for files greater than 10mb
|
||||
MaxFileQueries = 32, // max 32 file parts downloaded at the same time
|
||||
MaxFileQueries = 16, // max 16 file parts downloaded at the same time
|
||||
|
||||
UploadPartSize = 32 * 1024, // 32kb for photo
|
||||
DocumentMaxPartsCount = 3000, // no more than 3000 parts
|
||||
|
@ -223,7 +227,7 @@ enum {
|
|||
DocumentUploadPartSize2 = 128 * 1024, // 128kb for small document ( <= 375mb )
|
||||
DocumentUploadPartSize3 = 256 * 1024, // 256kb for medium document ( <= 750mb )
|
||||
DocumentUploadPartSize4 = 512 * 1024, // 512kb for large document ( <= 1500mb )
|
||||
MaxUploadFileParallelSize = 512 * 1024, // max 512kb uploaded at the same time
|
||||
MaxUploadFileParallelSize = MTPUploadSessionsCount * 512 * 1024, // max 512kb uploaded at the same time in each session
|
||||
UploadRequestInterval = 500, // one part each half second, if not uploaded faster
|
||||
|
||||
MaxPhotosInMemory = 50, // try to clear some memory after 50 photos are created
|
||||
|
|
|
@ -19,8 +19,11 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||
#include "fileuploader.h"
|
||||
|
||||
FileUploader::FileUploader() : sentSize(0), uploading(0) {
|
||||
memset(sentSizes, 0, sizeof(sentSizes));
|
||||
nextTimer.setSingleShot(true);
|
||||
connect(&nextTimer, SIGNAL(timeout()), this, SLOT(sendNext()));
|
||||
killSessionsTimer.setSingleShot(true);
|
||||
connect(&killSessionsTimer, SIGNAL(timeout()), this, SLOT(killSessions()));
|
||||
}
|
||||
|
||||
void FileUploader::uploadMedia(MsgId msgId, const ReadyLocalMedia &media) {
|
||||
|
@ -60,16 +63,36 @@ void FileUploader::currentFailed() {
|
|||
|
||||
requestsSent.clear();
|
||||
docRequestsSent.clear();
|
||||
queue.remove(uploading);
|
||||
dcMap.clear();
|
||||
uploading = 0;
|
||||
sentSize = 0;
|
||||
for (int i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
sentSizes[i] = 0;
|
||||
}
|
||||
|
||||
sendNext();
|
||||
}
|
||||
|
||||
void FileUploader::sendNext() {
|
||||
if (sentSize >= MaxUploadFileParallelSize || queue.isEmpty()) return;
|
||||
void FileUploader::killSessions() {
|
||||
for (int i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::killSession(MTP::upl[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FileUploader::sendNext() {
|
||||
if (sentSize >= MaxUploadFileParallelSize) return;
|
||||
|
||||
bool killing = killSessionsTimer.isActive();
|
||||
if (queue.isEmpty()) {
|
||||
if (!killing) {
|
||||
killSessionsTimer.start(MTPKillFileSessionTimeout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (killing) {
|
||||
killSessionsTimer.stop();
|
||||
}
|
||||
Queue::iterator i = uploading ? queue.find(uploading) : queue.begin();
|
||||
if (!uploading) {
|
||||
uploading = i.key();
|
||||
|
@ -77,6 +100,12 @@ void FileUploader::sendNext() {
|
|||
i = queue.begin();
|
||||
uploading = i.key();
|
||||
}
|
||||
int todc = 0;
|
||||
for (int dc = 1; dc < MTPUploadSessionsCount; ++dc) {
|
||||
if (sentSizes[dc] < sentSizes[todc]) {
|
||||
todc = dc;
|
||||
}
|
||||
}
|
||||
if (i->media.parts.isEmpty()) {
|
||||
if (i->docSentParts >= i->docPartsCount) {
|
||||
if (requestsSent.isEmpty() && docRequestsSent.isEmpty()) {
|
||||
|
@ -125,20 +154,24 @@ void FileUploader::sendNext() {
|
|||
}
|
||||
mtpRequestId requestId;
|
||||
if (i->docSize > UseBigFilesFrom) {
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl);
|
||||
requestId = MTP::send(MTPupload_SaveBigFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_int(i->docPartsCount), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
} else {
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl);
|
||||
requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.id), MTP_int(i->docSentParts), MTP_string(toSend)), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
}
|
||||
docRequestsSent.insert(requestId, i->docSentParts);
|
||||
dcMap.insert(requestId, todc);
|
||||
sentSize += i->docPartSize;
|
||||
sentSizes[todc] += i->docPartSize;
|
||||
|
||||
i->docSentParts++;
|
||||
} else {
|
||||
LocalFileParts::iterator part = i->media.parts.begin();
|
||||
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.jpeg_id), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl);
|
||||
mtpRequestId requestId = MTP::send(MTPupload_SaveFilePart(MTP_long(i->media.jpeg_id), MTP_int(part.key()), MTP_string(part.value())), rpcDone(&FileUploader::partLoaded), rpcFail(&FileUploader::partFailed), MTP::upl[todc]);
|
||||
requestsSent.insert(requestId, part.value());
|
||||
dcMap.insert(requestId, todc);
|
||||
sentSize += part.value().size();
|
||||
sentSizes[todc] += part.value().size();
|
||||
|
||||
i->media.parts.erase(part);
|
||||
}
|
||||
|
@ -168,7 +201,13 @@ void FileUploader::clear() {
|
|||
MTP::cancel(i.key());
|
||||
}
|
||||
docRequestsSent.clear();
|
||||
dcMap.clear();
|
||||
sentSize = 0;
|
||||
for (int32 i = 0; i < MTPUploadSessionsCount; ++i) {
|
||||
MTP::killSession(MTP::upl[i]);
|
||||
sentSizes[i] = 0;
|
||||
}
|
||||
killSessionsTimer.stop();
|
||||
}
|
||||
|
||||
void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
||||
|
@ -182,12 +221,22 @@ void FileUploader::partLoaded(const MTPBool &result, mtpRequestId requestId) {
|
|||
currentFailed();
|
||||
return;
|
||||
} else {
|
||||
QMap<mtpRequestId, int32>::iterator dcIt = dcMap.find(requestId);
|
||||
if (dcIt == dcMap.cend()) { // must not happen
|
||||
currentFailed();
|
||||
return;
|
||||
}
|
||||
int32 dc = dcIt.value();
|
||||
dcMap.erase(dcIt);
|
||||
|
||||
Queue::const_iterator k = queue.constFind(uploading);
|
||||
if (i != requestsSent.cend()) {
|
||||
sentSize -= i.value().size();
|
||||
sentSizes[dc] -= i.value().size();
|
||||
requestsSent.erase(i);
|
||||
} else {
|
||||
sentSize -= k->docPartSize;
|
||||
sentSizes[dc] -= k->docPartSize;
|
||||
docRequestsSent.erase(j);
|
||||
}
|
||||
if (k->media.type == ToPreparePhoto) {
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
public slots:
|
||||
|
||||
void sendNext();
|
||||
void killSessions();
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -98,11 +99,13 @@ private:
|
|||
|
||||
QMap<mtpRequestId, QByteArray> requestsSent;
|
||||
QMap<mtpRequestId, int32> docRequestsSent;
|
||||
QMap<mtpRequestId, int32> dcMap;
|
||||
uint32 sentSize;
|
||||
uint32 sentSizes[MTPUploadSessionsCount];
|
||||
|
||||
MsgId uploading;
|
||||
Queue queue;
|
||||
Queue uploaded;
|
||||
QTimer nextTimer;
|
||||
QTimer nextTimer, killSessionsTimer;
|
||||
|
||||
};
|
||||
|
|
|
@ -336,7 +336,7 @@ int64 imageCacheSize() {
|
|||
return globalAquiredSize;
|
||||
}
|
||||
|
||||
StorageImage::StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret) : w(width), h(height), loader(new mtpFileLoader(dc, volume, local, secret)) {
|
||||
StorageImage::StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) : w(width), h(height), loader(new mtpFileLoader(dc, volume, local, secret, size)) {
|
||||
}
|
||||
|
||||
StorageImage::StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, QByteArray &bytes) : w(width), h(height), loader(0) {
|
||||
|
@ -427,11 +427,11 @@ bool StorageImage::loaded() const {
|
|||
return check();
|
||||
}
|
||||
|
||||
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret) {
|
||||
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) {
|
||||
QByteArray key(storageKey(dc, volume, local, secret));
|
||||
StorageImages::const_iterator i = storageImages.constFind(key);
|
||||
if (i == storageImages.cend()) {
|
||||
i = storageImages.insert(key, new StorageImage(width, height, dc, volume, local, secret));
|
||||
i = storageImages.insert(key, new StorageImage(width, height, dc, volume, local, secret, size));
|
||||
}
|
||||
return i.value();
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ LocalImage *getImage(const QPixmap &pixmap, QByteArray format);
|
|||
class StorageImage : public Image {
|
||||
public:
|
||||
|
||||
StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret);
|
||||
StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0);
|
||||
StorageImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, QByteArray &bytes);
|
||||
|
||||
int32 width() const;
|
||||
|
@ -155,7 +155,7 @@ private:
|
|||
mutable mtpFileLoader *loader;
|
||||
};
|
||||
|
||||
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret);
|
||||
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0);
|
||||
StorageImage *getImage(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, const QByteArray &bytes);
|
||||
Image *getImage(int32 width, int32 height, const MTPFileLocation &location);
|
||||
|
||||
|
@ -166,7 +166,7 @@ public:
|
|||
}
|
||||
ImagePtr(const QPixmap &pixmap, QByteArray format) : Parent(getImage(pixmap, format)) {
|
||||
}
|
||||
ImagePtr(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret) : Parent(getImage(width, height, dc, volume, local, secret)) {
|
||||
ImagePtr(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0) : Parent(getImage(width, height, dc, volume, local, secret, size)) {
|
||||
}
|
||||
ImagePtr(int32 width, int32 height, int32 dc, const int64 &volume, int32 local, const int64 &secret, const QByteArray &bytes) : Parent(getImage(width, height, dc, volume, local, secret, bytes)) {
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace {
|
|||
|
||||
typedef QMap<mtpRequestId, RPCResponseHandler> ParserMap;
|
||||
ParserMap parserMap;
|
||||
QMutex parserMapLock;
|
||||
|
||||
typedef QMap<mtpRequestId, mtpRequest> RequestMap;
|
||||
RequestMap requestMap;
|
||||
|
@ -268,6 +269,8 @@ namespace _mtp_internal {
|
|||
}
|
||||
|
||||
void unregisterRequest(mtpRequestId requestId) {
|
||||
requestMap.remove(requestId);
|
||||
|
||||
QMutexLocker locker(&requestByDCLock);
|
||||
RequestsByDC::iterator i = requestsByDC.find(requestId);
|
||||
if (i != requestsByDC.end()) {
|
||||
|
@ -283,9 +286,10 @@ namespace _mtp_internal {
|
|||
mtpRequestId res = reqid();
|
||||
request->requestId = res;
|
||||
if (parser.onDone || parser.onFail) {
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
parserMap.insert(res, parser);
|
||||
requestMap.insert(res, request);
|
||||
}
|
||||
requestMap.insert(res, request);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -298,14 +302,21 @@ namespace _mtp_internal {
|
|||
}
|
||||
|
||||
void clearCallbacks(mtpRequestId requestId, int32 errorCode) {
|
||||
ParserMap::iterator i = parserMap.find(requestId);
|
||||
if (i != parserMap.end()) {
|
||||
if (errorCode) {
|
||||
rpcErrorOccured(requestId, i.value(), rpcClientError("CLEAR_CALLBACK", QString("did not handle request %1, error code %2").arg(requestId).arg(errorCode)));
|
||||
RPCResponseHandler h;
|
||||
bool found = false;
|
||||
{
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
ParserMap::iterator i = parserMap.find(requestId);
|
||||
if (i != parserMap.end()) {
|
||||
h = i.value();
|
||||
found = true;
|
||||
|
||||
parserMap.erase(i);
|
||||
}
|
||||
parserMap.erase(i);
|
||||
}
|
||||
requestMap.remove(requestId);
|
||||
if (errorCode && found) {
|
||||
rpcErrorOccured(requestId, h, rpcClientError("CLEAR_CALLBACK", QString("did not handle request %1, error code %2").arg(requestId).arg(errorCode)));
|
||||
}
|
||||
_mtp_internal::unregisterRequest(requestId);
|
||||
}
|
||||
|
||||
|
@ -336,6 +347,7 @@ namespace _mtp_internal {
|
|||
if (!toClear.isEmpty()) {
|
||||
for (RPCCallbackClears::iterator i = toClear.begin(), e = toClear.end(); i != e; ++i) {
|
||||
if (cDebug()) {
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
if (parserMap.find(i->requestId) != parserMap.end()) {
|
||||
DEBUG_LOG(("RPC Info: clearing delayed callback %1, error code %2").arg(i->requestId).arg(i->errorCode));
|
||||
}
|
||||
|
@ -347,12 +359,18 @@ namespace _mtp_internal {
|
|||
}
|
||||
|
||||
void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) {
|
||||
ParserMap::iterator i = parserMap.find(requestId);
|
||||
if (i != parserMap.cend()) {
|
||||
RPCResponseHandler h(i.value());
|
||||
parserMap.erase(i);
|
||||
RPCResponseHandler h;
|
||||
{
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
ParserMap::iterator i = parserMap.find(requestId);
|
||||
if (i != parserMap.cend()) {
|
||||
h = i.value();
|
||||
parserMap.erase(i);
|
||||
|
||||
DEBUG_LOG(("RPC Info: found parser for request %1, trying to parse response..").arg(requestId));
|
||||
DEBUG_LOG(("RPC Info: found parser for request %1, trying to parse response..").arg(requestId));
|
||||
}
|
||||
}
|
||||
if (h.onDone || h.onFail) {
|
||||
try {
|
||||
if (from >= end) throw mtpErrorInsufficient();
|
||||
|
||||
|
@ -360,6 +378,7 @@ namespace _mtp_internal {
|
|||
RPCError err(MTPRpcError(from, end));
|
||||
DEBUG_LOG(("RPC Info: error received, code %1, type %2, description: %3").arg(err.code()).arg(err.type()).arg(err.description()));
|
||||
if (!rpcErrorOccured(requestId, h, err)) {
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
parserMap.insert(requestId, h);
|
||||
return;
|
||||
}
|
||||
|
@ -368,17 +387,23 @@ namespace _mtp_internal {
|
|||
}
|
||||
} catch (Exception &e) {
|
||||
if (!rpcErrorOccured(requestId, h, rpcClientError("RESPONSE_PARSE_FAILED", QString("exception text: ") + e.what()))) {
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
parserMap.insert(requestId, h);
|
||||
return;
|
||||
}
|
||||
}
|
||||
requestMap.remove(requestId);
|
||||
} else {
|
||||
DEBUG_LOG(("RPC Info: parser not found for %1").arg(requestId));
|
||||
}
|
||||
unregisterRequest(requestId);
|
||||
}
|
||||
|
||||
bool hasCallbacks(mtpRequestId requestId) {
|
||||
QMutexLocker locker(&parserMapLock);
|
||||
ParserMap::iterator i = parserMap.find(requestId);
|
||||
return (i != parserMap.cend());
|
||||
}
|
||||
|
||||
void globalCallback(const mtpPrime *from, const mtpPrime *end) {
|
||||
if (globalHandler.onDone) (*globalHandler.onDone)(0, from, end); // some updates were received
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace _mtp_internal {
|
|||
void clearCallbacksDelayed(const RPCCallbackClears &requestIds);
|
||||
void performDelayedClear();
|
||||
void execCallback(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end);
|
||||
bool hasCallbacks(mtpRequestId requestId);
|
||||
void globalCallback(const mtpPrime *from, const mtpPrime *end);
|
||||
void onStateChange(int32 dc, int32 state);
|
||||
void onSessionReset(int32 dc);
|
||||
|
@ -58,9 +59,19 @@ namespace MTP {
|
|||
mtpAuthKey &localKey();
|
||||
void createLocalKey(const QByteArray &pass, QByteArray *salt = 0);
|
||||
|
||||
static const uint32 dld = 1 * _mtp_internal::dcShift; // send(req, callbacks, MTP::dld + dc) - for download
|
||||
static const uint32 upl = 2 * _mtp_internal::dcShift; // send(req, callbacks, MTP::upl + dc) - for upload
|
||||
static const uint32 cfg = 3 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum
|
||||
static const uint32 cfg = 1 * _mtp_internal::dcShift; // send(MTPhelp_GetConfig(), MTP::cfg + dc) - for dc enum
|
||||
static const uint32 dld[MTPDownloadSessionsCount] = { // send(req, callbacks, MTP::dld[i] + dc) - for download
|
||||
0x10 * _mtp_internal::dcShift,
|
||||
0x11 * _mtp_internal::dcShift,
|
||||
0x12 * _mtp_internal::dcShift,
|
||||
0x13 * _mtp_internal::dcShift,
|
||||
};
|
||||
static const uint32 upl[MTPUploadSessionsCount] = { // send(req, callbacks, MTP::upl[i] + dc) - for upload
|
||||
0x20 * _mtp_internal::dcShift,
|
||||
0x21 * _mtp_internal::dcShift,
|
||||
0x22 * _mtp_internal::dcShift,
|
||||
0x23 * _mtp_internal::dcShift,
|
||||
};
|
||||
|
||||
void start();
|
||||
void restart();
|
||||
|
|
|
@ -679,6 +679,15 @@ void MTPautoConnection::tcpSend(mtpBuffer &buffer) {
|
|||
TCP_LOG(("TCP Info: write %1 packet %2 bytes").arg(packetNum).arg(len));
|
||||
|
||||
sock.write((const char*)&buffer[0], len);
|
||||
//int64 b = sock.bytesToWrite();
|
||||
//if (b > 100000) {
|
||||
// int a = 0;
|
||||
//}
|
||||
//sock.flush();
|
||||
//int64 b2 = sock.bytesToWrite();
|
||||
//if (b2 > 0) {
|
||||
// TCP_LOG(("TCP Info: writing many, %1 left to write").arg(b2));
|
||||
//}
|
||||
}
|
||||
|
||||
void MTPautoConnection::httpSend(mtpBuffer &buffer) {
|
||||
|
@ -1576,6 +1585,11 @@ void MTProtoConnectionPrivate::onSentSome(uint64 size) {
|
|||
DEBUG_LOG(("Checking connect for request with size %1 bytes, delay will be %2").arg(size).arg(remain));
|
||||
}
|
||||
}
|
||||
if (dc >= MTP::upl[0] && dc < MTP::upl[MTPUploadSessionsCount - 1] + _mtp_internal::dcShift) {
|
||||
remain *= MTPUploadSessionsCount;
|
||||
} else if (dc >= MTP::dld[0] && dc < MTP::dld[MTPDownloadSessionsCount - 1] + _mtp_internal::dcShift) {
|
||||
remain *= MTPDownloadSessionsCount;
|
||||
}
|
||||
connCheckTimer.start(remain);
|
||||
}
|
||||
if (!firstSentAt) firstSentAt = getms();
|
||||
|
@ -2070,15 +2084,19 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
|
|||
DEBUG_LOG(("Message Error: such message was not sent recently %1").arg(reqMsgId));
|
||||
return (badTime ? 0 : 1);
|
||||
}
|
||||
if (serverSalt) sessionData->setSalt(serverSalt); // requestsFixTimeSalt with no lookup
|
||||
unixtimeSet(serverTime, true);
|
||||
if (badTime) {
|
||||
if (serverSalt) sessionData->setSalt(serverSalt); // requestsFixTimeSalt with no lookup
|
||||
unixtimeSet(serverTime, true);
|
||||
|
||||
DEBUG_LOG(("Message Info: unixtime updated from mtpc_msgs_state_info, now %1").arg(serverTime));
|
||||
DEBUG_LOG(("Message Info: unixtime updated from mtpc_msgs_state_info, now %1").arg(serverTime));
|
||||
|
||||
badTime = false;
|
||||
badTime = false;
|
||||
}
|
||||
requestBuffer = replyTo.value();
|
||||
}
|
||||
QVector<MTPlong> toAck(1, MTP_long(reqMsgId));
|
||||
QVector<MTPlong> toAckReq(1, MTP_long(reqMsgId)), toAck;
|
||||
requestsAcked(toAck, true);
|
||||
|
||||
if (requestBuffer->size() < 9) {
|
||||
LOG(("Message Error: bad request %1 found in requestMap, size: %2").arg(reqMsgId).arg(requestBuffer->size()));
|
||||
return -1;
|
||||
|
@ -2207,7 +2225,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
requestsAcked(ids);
|
||||
requestsAcked(ids, true);
|
||||
|
||||
if (typeId == mtpc_gzip_packed) {
|
||||
DEBUG_LOG(("RPC Info: gzip container"));
|
||||
|
@ -2294,7 +2312,7 @@ int32 MTProtoConnectionPrivate::handleOneReceived(const mtpPrime *from, const mt
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
requestsAcked(ids);
|
||||
requestsAcked(ids, true);
|
||||
|
||||
retryTimeout = 1; // reset restart() timer
|
||||
} return 1;
|
||||
|
@ -2385,7 +2403,7 @@ bool MTProtoConnectionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids,
|
|||
return false;
|
||||
}
|
||||
|
||||
void MTProtoConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids) {
|
||||
void MTProtoConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) {
|
||||
uint32 idsCount = ids.size();
|
||||
|
||||
DEBUG_LOG(("Message Info: requests acked, ids %1").arg(logVectorLong(ids)));
|
||||
|
@ -2412,10 +2430,20 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids) {
|
|||
for (uint32 j = 0; j < inContCount; ++j) {
|
||||
toAckMore.push_back(MTP_long(*(inContId++)));
|
||||
}
|
||||
haveSent.erase(req);
|
||||
} else {
|
||||
wereAcked.insert(msgId, req.value()->requestId);
|
||||
mtpRequestId reqId = req.value()->requestId;
|
||||
bool moveToAcked = byResponse;
|
||||
if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler)
|
||||
moveToAcked = !_mtp_internal::hasCallbacks(reqId);
|
||||
}
|
||||
if (moveToAcked) {
|
||||
wereAcked.insert(msgId, reqId);
|
||||
haveSent.erase(req);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId));
|
||||
}
|
||||
}
|
||||
haveSent.erase(req);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: msgId %1 was not found in recent sent, while acking requests, searching in resend..").arg(msgId));
|
||||
QWriteLocker locker3(sessionData->toResendMutex());
|
||||
|
@ -2423,21 +2451,29 @@ void MTProtoConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids) {
|
|||
mtpRequestIdsMap::iterator reqIt = toResend.find(msgId);
|
||||
if (reqIt != toResend.cend()) {
|
||||
mtpRequestId reqId = reqIt.value();
|
||||
QWriteLocker locker4(sessionData->toSendMutex());
|
||||
mtpPreRequestMap &toSend(sessionData->toSendMap());
|
||||
mtpPreRequestMap::iterator req = toSend.find(reqId);
|
||||
if (req != toSend.cend()) {
|
||||
wereAcked.insert(msgId, req.value()->requestId);
|
||||
if (req.value()->requestId != reqId) {
|
||||
DEBUG_LOG(("Message Error: for msgId %1 found resent request, requestId %2, contains requestId %3").arg(msgId).arg(reqId).arg(req.value()->requestId));
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: acked msgId %1 that was prepared to resend, requestId %2").arg(msgId).arg(reqId));
|
||||
}
|
||||
toSend.erase(req);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send").arg(msgId));
|
||||
bool moveToAcked = byResponse;
|
||||
if (!moveToAcked) { // ignore ACK, if we need a response (if we have a handler)
|
||||
moveToAcked = !_mtp_internal::hasCallbacks(reqId);
|
||||
}
|
||||
if (moveToAcked) {
|
||||
QWriteLocker locker4(sessionData->toSendMutex());
|
||||
mtpPreRequestMap &toSend(sessionData->toSendMap());
|
||||
mtpPreRequestMap::iterator req = toSend.find(reqId);
|
||||
if (req != toSend.cend()) {
|
||||
wereAcked.insert(msgId, req.value()->requestId);
|
||||
if (req.value()->requestId != reqId) {
|
||||
DEBUG_LOG(("Message Error: for msgId %1 found resent request, requestId %2, contains requestId %3").arg(msgId).arg(reqId).arg(req.value()->requestId));
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: acked msgId %1 that was prepared to resend, requestId %2").arg(msgId).arg(reqId));
|
||||
}
|
||||
toSend.erase(req);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: msgId %1 was found in recent resent, requestId %2 was not found in prepared to send").arg(msgId));
|
||||
}
|
||||
toResend.erase(reqIt);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: ignoring ACK for msgId %1 because request %2 requires a response").arg(msgId).arg(reqId));
|
||||
}
|
||||
toResend.erase(reqIt);
|
||||
} else {
|
||||
DEBUG_LOG(("Message Info: msgId %1 was not found in recent resent either").arg(msgId));
|
||||
}
|
||||
|
|
|
@ -374,7 +374,7 @@ private:
|
|||
bool requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 serverTime, uint64 serverSalt);
|
||||
|
||||
// remove msgs with such ids from sessionData->haveSent, add to sessionData->wereAcked
|
||||
void requestsAcked(const QVector<MTPlong> &ids);
|
||||
void requestsAcked(const QVector<MTPlong> &ids, bool byResponse = false);
|
||||
|
||||
mtpPingId pingId, toSendPingId;
|
||||
mtpMsgId pingMsgId;
|
||||
|
|
|
@ -57,8 +57,10 @@ void mtpTextSerializeCore(MTPStringLogger &to, const mtpPrime *&from, const mtpP
|
|||
QString str = QString::fromUtf8(strUtf8);
|
||||
if (str.toUtf8() == strUtf8) {
|
||||
to.add("\"").add(str.replace('\\', "\\\\").replace('"', "\\\"").replace('\n', "\\n")).add("\" [STRING]");
|
||||
} else {
|
||||
} else if (strUtf8.size() < 64) {
|
||||
to.add(mb(strUtf8.constData(), strUtf8.size()).str()).add(" [").add(mtpWrapNumber(strUtf8.size())).add(" BYTES]");
|
||||
} else {
|
||||
to.add(mb(strUtf8.constData(), 16).str()).add(".. [").add(mtpWrapNumber(strUtf8.size())).add(" BYTES]");
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -19,8 +19,17 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
|
|||
#include "mainwidget.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "application.h"
|
||||
|
||||
namespace {
|
||||
int32 _priority = 1;
|
||||
struct DataRequested {
|
||||
DataRequested() {
|
||||
memset(v, 0, sizeof(v));
|
||||
}
|
||||
int64 v[MTPDownloadSessionsCount];
|
||||
};
|
||||
QMap<int32, DataRequested> _dataRequested;
|
||||
}
|
||||
struct mtpFileLoaderQueue {
|
||||
mtpFileLoaderQueue() : queries(0), start(0), end(0) {
|
||||
|
@ -34,10 +43,10 @@ namespace {
|
|||
LoaderQueues queues;
|
||||
}
|
||||
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), requestId(0),
|
||||
dc(dc), locationType(0), volume(volume), local(local), secret(secret),
|
||||
id(0), access(0), initialSize(0), size(0), type(MTP_storage_fileUnknown()) {
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
|
||||
dc(dc), locationType(0), volume(volume), local(local), secret(secret),
|
||||
id(0), access(0), size(size), type(MTP_storage_fileUnknown()) {
|
||||
LoaderQueues::iterator i = queues.find(dc);
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(dc, mtpFileLoaderQueue());
|
||||
|
@ -46,23 +55,23 @@ mtpFileLoader::mtpFileLoader(int32 dc, const int64 &volume, int32 local, const i
|
|||
}
|
||||
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), requestId(0),
|
||||
priority(0), inQueue(false), complete(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
|
||||
dc(dc), locationType(locType),
|
||||
id(id), access(access), file(to), duplicateInData(false), initialSize(size), type(MTP_storage_fileUnknown()) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld + dc);
|
||||
id(id), access(access), file(to), duplicateInData(false), size(size), type(MTP_storage_fileUnknown()) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(MTP::dld + dc, mtpFileLoaderQueue());
|
||||
i = queues.insert(MTP::dld[0] + dc, mtpFileLoaderQueue());
|
||||
}
|
||||
queue = &i.value();
|
||||
}
|
||||
|
||||
mtpFileLoader::mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata) : prev(0), next(0),
|
||||
priority(0), inQueue(false), complete(false), requestId(0),
|
||||
priority(0), inQueue(false), complete(false), skippedBytes(0), nextRequestOffset(0), lastComplete(false),
|
||||
dc(dc), locationType(locType),
|
||||
id(id), access(access), file(to), duplicateInData(todata), initialSize(size), type(MTP_storage_fileUnknown()) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld + dc);
|
||||
id(id), access(access), file(to), duplicateInData(todata), size(size), type(MTP_storage_fileUnknown()) {
|
||||
LoaderQueues::iterator i = queues.find(MTP::dld[0] + dc);
|
||||
if (i == queues.cend()) {
|
||||
i = queues.insert(MTP::dld + dc, mtpFileLoaderQueue());
|
||||
i = queues.insert(MTP::dld[0] + dc, mtpFileLoaderQueue());
|
||||
}
|
||||
queue = &i.value();
|
||||
}
|
||||
|
@ -89,8 +98,8 @@ float64 mtpFileLoader::currentProgress() const {
|
|||
return float64(currentOffset()) / fullSize();
|
||||
}
|
||||
|
||||
int32 mtpFileLoader::currentOffset() const {
|
||||
return file.isOpen() ? file.size() : data.size();
|
||||
int32 mtpFileLoader::currentOffset(bool includeSkipped) const {
|
||||
return (file.isOpen() ? file.size() : data.size()) - (includeSkipped ? 0 : skippedBytes);
|
||||
}
|
||||
|
||||
int32 mtpFileLoader::fullSize() const {
|
||||
|
@ -109,17 +118,18 @@ uint64 mtpFileLoader::objId() const {
|
|||
|
||||
void mtpFileLoader::loadNext() {
|
||||
if (queue->queries >= MaxFileQueries) return;
|
||||
for (mtpFileLoader *i = queue->start; i; i = i->next) {
|
||||
if (i->loadPart() && queue->queries >= MaxFileQueries) return;
|
||||
for (mtpFileLoader *i = queue->start; i;) {
|
||||
if (i->loadPart()) {
|
||||
if (queue->queries >= MaxFileQueries) return;
|
||||
} else {
|
||||
i = i->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mtpFileLoader::finishFail() {
|
||||
bool started = currentOffset() > 0;
|
||||
if (requestId) {
|
||||
requestId = 0;
|
||||
--queue->queries;
|
||||
}
|
||||
bool started = currentOffset(true) > 0;
|
||||
cancelRequests();
|
||||
type = MTP_storage_fileUnknown();
|
||||
complete = true;
|
||||
if (file.isOpen()) {
|
||||
|
@ -133,7 +143,8 @@ void mtpFileLoader::finishFail() {
|
|||
}
|
||||
|
||||
bool mtpFileLoader::loadPart() {
|
||||
if (complete || requestId) return false;
|
||||
if (complete || lastComplete || !requests.isEmpty() && !size) return false;
|
||||
if (size && nextRequestOffset >= size) return false;
|
||||
|
||||
int32 limit = DocumentDownloadPartSize;
|
||||
MTPInputFileLocation loc;
|
||||
|
@ -148,54 +159,100 @@ bool mtpFileLoader::loadPart() {
|
|||
break;
|
||||
}
|
||||
|
||||
++queue->queries;
|
||||
int32 offset = currentOffset();
|
||||
int32 offset = nextRequestOffset, dcIndex = 0;
|
||||
DataRequested &dr(_dataRequested[dc]);
|
||||
if (size) {
|
||||
for (int32 i = 1; i < MTPDownloadSessionsCount; ++i) {
|
||||
if (dr.v[i] < dr.v[dcIndex]) {
|
||||
dcIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dcIndex) {
|
||||
App::app()->killDownloadSessionsStop(dc);
|
||||
}
|
||||
|
||||
MTPupload_GetFile request(MTPupload_getFile(loc, MTP_int(offset), MTP_int(limit)));
|
||||
requestId = MTP::send(request, rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld + dc, 50);
|
||||
mtpRequestId reqId = MTP::send(request, rpcDone(&mtpFileLoader::partLoaded, offset), rpcFail(&mtpFileLoader::partFailed), MTP::dld[dcIndex] + dc, 50);
|
||||
|
||||
++queue->queries;
|
||||
dr.v[dcIndex] += limit;
|
||||
requests.insert(reqId, dcIndex);
|
||||
nextRequestOffset += limit;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result) {
|
||||
if (requestId) {
|
||||
--queue->queries;
|
||||
requestId = 0;
|
||||
}
|
||||
if (offset == currentOffset()) {
|
||||
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
|
||||
const MTPDupload_file &d(result.c_upload_file());
|
||||
const string &bytes(d.vbytes.c_string().v);
|
||||
if (bytes.size()) {
|
||||
if (file.isOpen()) {
|
||||
if (file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
|
||||
return finishFail();
|
||||
}
|
||||
} else {
|
||||
data.append(bytes.data(), bytes.size());
|
||||
void mtpFileLoader::partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req) {
|
||||
Requests::iterator i = requests.find(req);
|
||||
if (i == requests.cend()) return;
|
||||
|
||||
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
|
||||
int32 dcIndex = i.value();
|
||||
_dataRequested[dc].v[dcIndex] -= limit;
|
||||
|
||||
--queue->queries;
|
||||
requests.erase(i);
|
||||
|
||||
const MTPDupload_file &d(result.c_upload_file());
|
||||
const string &bytes(d.vbytes.c_string().v);
|
||||
if (bytes.size()) {
|
||||
if (file.isOpen()) {
|
||||
int64 fsize = file.size();
|
||||
if (offset < fsize) {
|
||||
skippedBytes -= bytes.size();
|
||||
} else if (offset > fsize) {
|
||||
skippedBytes += offset - fsize;
|
||||
}
|
||||
file.seek(offset);
|
||||
if (file.write(bytes.data(), bytes.size()) != qint64(bytes.size())) {
|
||||
return finishFail();
|
||||
}
|
||||
}
|
||||
if (bytes.size() && !(bytes.size() % 1024)) { // good next offset
|
||||
// offset += bytes.size();
|
||||
} else {
|
||||
if (duplicateInData && !file.fileName().isEmpty()) {
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return finishFail();
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
return finishFail();
|
||||
}
|
||||
data.reserve(offset + bytes.size());
|
||||
if (offset > data.size()) {
|
||||
skippedBytes += offset - data.size();
|
||||
data.resize(offset);
|
||||
}
|
||||
type = d.vtype;
|
||||
complete = true;
|
||||
if (file.isOpen()) {
|
||||
file.close();
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
if (offset == data.size()) {
|
||||
data.append(bytes.data(), bytes.size());
|
||||
} else {
|
||||
skippedBytes -= bytes.size();
|
||||
if (offset + bytes.size() > data.size()) {
|
||||
data.resize(offset + bytes.size());
|
||||
}
|
||||
memcpy(data.data() + offset, bytes.data(), bytes.size());
|
||||
}
|
||||
removeFromQueue();
|
||||
App::wnd()->update();
|
||||
App::wnd()->notifyUpdateAllPhotos();
|
||||
}
|
||||
emit progress(this);
|
||||
}
|
||||
if (!bytes.size() || (bytes.size() % 1024)) { // bad next offset
|
||||
lastComplete = true;
|
||||
}
|
||||
if (requests.isEmpty() && (lastComplete || (size && nextRequestOffset >= size))) {
|
||||
if (duplicateInData && !file.fileName().isEmpty()) {
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
return finishFail();
|
||||
}
|
||||
if (file.write(data) != qint64(data.size())) {
|
||||
return finishFail();
|
||||
}
|
||||
}
|
||||
type = d.vtype;
|
||||
complete = true;
|
||||
if (file.isOpen()) {
|
||||
file.close();
|
||||
psPostprocessFile(QFileInfo(file).absoluteFilePath());
|
||||
}
|
||||
removeFromQueue();
|
||||
App::wnd()->update();
|
||||
App::wnd()->notifyUpdateAllPhotos();
|
||||
|
||||
if (!queue->queries && dcIndex) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
}
|
||||
}
|
||||
emit progress(this);
|
||||
loadNext();
|
||||
}
|
||||
|
||||
|
@ -325,11 +382,7 @@ void mtpFileLoader::start(bool loadFirst, bool prior) {
|
|||
}
|
||||
|
||||
void mtpFileLoader::cancel() {
|
||||
bool started = currentOffset() > 0;
|
||||
if (requestId) {
|
||||
requestId = 0;
|
||||
--queue->queries;
|
||||
}
|
||||
cancelRequests();
|
||||
type = MTP_storage_fileUnknown();
|
||||
complete = true;
|
||||
if (file.isOpen()) {
|
||||
|
@ -342,6 +395,26 @@ void mtpFileLoader::cancel() {
|
|||
loadNext();
|
||||
}
|
||||
|
||||
void mtpFileLoader::cancelRequests() {
|
||||
if (requests.isEmpty()) return;
|
||||
|
||||
int32 limit = locationType ? DocumentDownloadPartSize : DownloadPartSize;
|
||||
bool wasIndex = false;
|
||||
DataRequested &dr(_dataRequested[dc]);
|
||||
for (Requests::const_iterator i = requests.cbegin(), e = requests.cend(); i != e; ++i) {
|
||||
MTP::cancel(i.key());
|
||||
int32 dcIndex = i.value();
|
||||
dr.v[dcIndex] -= limit;
|
||||
if (dcIndex) wasIndex = true;
|
||||
}
|
||||
queue->queries -= requests.size();
|
||||
requests.clear();
|
||||
|
||||
if (!queue->queries && wasIndex) {
|
||||
App::app()->killDownloadSessionsStart(dc);
|
||||
}
|
||||
}
|
||||
|
||||
bool mtpFileLoader::loading() const {
|
||||
return inQueue;
|
||||
}
|
||||
|
@ -353,6 +426,7 @@ void mtpFileLoader::started(bool loadFirst, bool prior) {
|
|||
|
||||
mtpFileLoader::~mtpFileLoader() {
|
||||
removeFromQueue();
|
||||
cancelRequests();
|
||||
}
|
||||
|
||||
namespace MTP {
|
||||
|
|
|
@ -27,7 +27,7 @@ class mtpFileLoader : public QObject, public RPCSender {
|
|||
|
||||
public:
|
||||
|
||||
mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret);
|
||||
mtpFileLoader(int32 dc, const int64 &volume, int32 local, const int64 &secret, int32 size = 0);
|
||||
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size);
|
||||
mtpFileLoader(int32 dc, const uint64 &id, const uint64 &access, mtpTypeId locType, const QString &to, int32 size, bool todata);
|
||||
bool done() const;
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
const QByteArray &bytes() const;
|
||||
QString fileName() const;
|
||||
float64 currentProgress() const;
|
||||
int32 currentOffset() const;
|
||||
int32 currentOffset(bool includeSkipped = false) const;
|
||||
int32 fullSize() const;
|
||||
|
||||
void setFileName(const QString &filename); // set filename for duplicateInData loader
|
||||
|
@ -61,14 +61,22 @@ private:
|
|||
|
||||
mtpFileLoaderQueue *queue;
|
||||
bool inQueue, complete;
|
||||
int32 requestId;
|
||||
|
||||
void cancelRequests();
|
||||
|
||||
typedef QMap<mtpRequestId, int32> Requests;
|
||||
Requests requests;
|
||||
int32 skippedBytes;
|
||||
int32 nextRequestOffset;
|
||||
bool lastComplete;
|
||||
|
||||
void started(bool loadFirst, bool prior);
|
||||
void removeFromQueue();
|
||||
|
||||
void loadNext();
|
||||
void finishFail();
|
||||
bool loadPart();
|
||||
void partLoaded(int32 offset, const MTPupload_File &result);
|
||||
void partLoaded(int32 offset, const MTPupload_File &result, mtpRequestId req);
|
||||
bool partFailed(const RPCError &error);
|
||||
|
||||
int32 dc;
|
||||
|
@ -82,7 +90,6 @@ private:
|
|||
uint64 access;
|
||||
QFile file;
|
||||
bool duplicateInData;
|
||||
int32 initialSize;
|
||||
|
||||
QByteArray data;
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ void unixtimeSet(int32 serverTime, bool force) {
|
|||
}
|
||||
unixtimeWasSet = true;
|
||||
unixtimeDelta = serverTime + 1 - myunixtime();
|
||||
DEBUG_LOG(("MTP Info: now unixtimeDelta is %1").arg(unixtimeDelta));
|
||||
}
|
||||
_initMsgIdConstants();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.6.5</string>
|
||||
<string>0.6.6</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>NOTE</key>
|
||||
|
|
Binary file not shown.
|
@ -1515,7 +1515,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.5;
|
||||
CURRENT_PROJECT_VERSION = 0.6.6;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -1533,7 +1533,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 0.6.5;
|
||||
CURRENT_PROJECT_VERSION = 0.6.6;
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
|
||||
|
@ -1559,10 +1559,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.5;
|
||||
CURRENT_PROJECT_VERSION = 0.6.6;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||
DYLIB_CURRENT_VERSION = 0.6.5;
|
||||
DYLIB_CURRENT_VERSION = 0.6.6;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
@ -1701,10 +1701,10 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 0.6.5;
|
||||
CURRENT_PROJECT_VERSION = 0.6.6;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DYLIB_COMPATIBILITY_VERSION = 0.6;
|
||||
DYLIB_CURRENT_VERSION = 0.6.5;
|
||||
DYLIB_CURRENT_VERSION = 0.6.6;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
FRAMEWORK_SEARCH_PATHS = "";
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||
|
|
Loading…
Reference in New Issue