Multiple stability and usability fixes for the caldav/carddav resources

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1134465 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
v3.5.13-sru
tpearson 15 years ago
parent b0541862e3
commit 23f5d4229c

@ -95,15 +95,19 @@ ResourceCalDav::~ResourceCalDav() {
mWriteRetryTimer->stop(); // Unfortunately we cannot do anything at this point; if this timer is still running something is seriously wrong mWriteRetryTimer->stop(); // Unfortunately we cannot do anything at this point; if this timer is still running something is seriously wrong
} }
if (mLoader) {
readLockout = true;
mLoader->terminate();
mLoader->wait(TERMINATION_WAITING_TIME);
mLoadingQueueReady = true;
}
while ((mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady) { while ((mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady) {
readLockout = true; readLockout = true;
sleep(1); sleep(1);
qApp->processEvents(QEventLoop::ExcludeUserInput); qApp->processEvents(QEventLoop::ExcludeUserInput);
} }
if (mLoader) {
mLoader->terminate();
}
if (mWriter) { if (mWriter) {
mWriter->terminate(); mWriter->terminate();
} }
@ -128,7 +132,8 @@ ResourceCalDav::~ResourceCalDav() {
} }
bool ResourceCalDav::isSaving() { bool ResourceCalDav::isSaving() {
return (((mWriteRetryTimer != NULL) ? mWriteRetryTimer->isActive() : 0) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady); doSave();
return (((mWriteRetryTimer != NULL) ? 1 : 0) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady || readLockout);
} }
/*========================================================================= /*=========================================================================
@ -138,7 +143,7 @@ bool ResourceCalDav::isSaving() {
bool ResourceCalDav::doLoad() { bool ResourceCalDav::doLoad() {
bool syncCache = true; bool syncCache = true;
if ((mLoadingQueueReady == false) || (mLoadingQueue.isEmpty() == false) || (mLoader->running() == true) || (readLockout == true)) { if ((mLoadingQueueReady == false) || (mLoadingQueue.isEmpty() == false) || (mLoader->running() == true) || (isSaving() == true)) {
return true; // Silently fail; the user has obviously not responded to a dialog and we don't need to pop up more of them! return true; // Silently fail; the user has obviously not responded to a dialog and we don't need to pop up more of them!
} }
@ -189,6 +194,13 @@ bool ResourceCalDav::doSave() {
// FIXME: Calling clearChanges() here is not the ideal way since the // FIXME: Calling clearChanges() here is not the ideal way since the
// upload might fail, but there is no other place to call it... // upload might fail, but there is no other place to call it...
clearChanges(); clearChanges();
if (mWriteRetryTimer != NULL) {
if (mWriteRetryTimer->isActive() == false) {
disconnect( mWriteRetryTimer, SIGNAL(timeout()), this, SLOT(doSave()) );
delete mWriteRetryTimer;
mWriteRetryTimer = NULL;
}
}
return true; return true;
} }
else return true; // We do not need to alert the user to this transient failure; a timer has been started to retry the save else return true; // We do not need to alert the user to this transient failure; a timer has been started to retry the save
@ -277,6 +289,8 @@ void ResourceCalDav::updateProgressBar(int direction) {
// See if anything is in the queues // See if anything is in the queues
current_queued_events = mWritingQueue.count() + mLoadingQueue.count(); current_queued_events = mWritingQueue.count() + mLoadingQueue.count();
if ((direction == 0) && (mLoader->running() == true)) current_queued_events++;
if ((direction == 1) && (mWriter->running() == true)) current_queued_events++;
if (current_queued_events > original_queued_events) { if (current_queued_events > original_queued_events) {
original_queued_events = current_queued_events; original_queued_events = current_queued_events;
} }
@ -304,13 +318,13 @@ void ResourceCalDav::updateProgressBar(int direction) {
void ResourceCalDav::loadingQueuePush(const LoadingTask *task) { void ResourceCalDav::loadingQueuePush(const LoadingTask *task) {
if ((mLoadingQueue.isEmpty() == true) && (mLoader->running() == false)) { if ((mLoadingQueue.isEmpty() == true) && (mLoader->running() == false)) {
mLoadingQueue.enqueue(task); mLoadingQueue.enqueue(task);
loadingQueuePop();
updateProgressBar(0); updateProgressBar(0);
loadingQueuePop();
} }
} }
void ResourceCalDav::loadingQueuePop() { void ResourceCalDav::loadingQueuePop() {
if (!mLoadingQueueReady || mLoadingQueue.isEmpty() || (mWritingQueue.isEmpty() == false) || (mWriter->running() == true) || !mWritingQueueReady || (readLockout == true)) { if (!mLoadingQueueReady || mLoadingQueue.isEmpty() || (isSaving() == true)) {
return; return;
} }
@ -335,10 +349,10 @@ void ResourceCalDav::loadingQueuePop() {
log("starting actual download job"); log("starting actual download job");
mLoader->start(QThread::LowestPriority); mLoader->start(QThread::LowestPriority);
updateProgressBar(0);
// if all ok, removing the task from the queue // if all ok, removing the task from the queue
mLoadingQueue.dequeue(); mLoadingQueue.dequeue();
updateProgressBar(0);
delete t; delete t;
} }
@ -354,8 +368,6 @@ void ResourceCalDav::loadFinished() {
log("load finished"); log("load finished");
updateProgressBar(0);
if (!loader) { if (!loader) {
log("loader is NULL"); log("loader is NULL");
return; return;
@ -411,7 +423,10 @@ void ResourceCalDav::loadFinished() {
// Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them. // Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
// That's why no mutexes are required. // That's why no mutexes are required.
mLoader->terminate();
mLoader->wait(TERMINATION_WAITING_TIME);
mLoadingQueueReady = true; mLoadingQueueReady = true;
updateProgressBar(0);
loadingQueuePop(); loadingQueuePop();
} }
@ -515,8 +530,8 @@ void ResourceCalDav::writingQueuePush(const WritingTask *task) {
// printf("task->deleted: %s\n\r", task->deleted.ascii()); // printf("task->deleted: %s\n\r", task->deleted.ascii());
// printf("task->changed: %s\n\r", task->changed.ascii()); // printf("task->changed: %s\n\r", task->changed.ascii());
mWritingQueue.enqueue(task); mWritingQueue.enqueue(task);
writingQueuePop();
updateProgressBar(1); updateProgressBar(1);
writingQueuePop();
} }
void ResourceCalDav::writingQueuePop() { void ResourceCalDav::writingQueuePop() {
@ -563,10 +578,10 @@ void ResourceCalDav::writingQueuePop() {
log("starting actual write job"); log("starting actual write job");
mWriter->start(QThread::LowestPriority); mWriter->start(QThread::LowestPriority);
updateProgressBar(1);
// if all ok, remove the task from the queue // if all ok, remove the task from the queue
mWritingQueue.dequeue(); mWritingQueue.dequeue();
updateProgressBar(1);
delete t; delete t;
} }
@ -667,8 +682,6 @@ bool ResourceCalDav::startWriting(const QString& url) {
void ResourceCalDav::writingFinished() { void ResourceCalDav::writingFinished() {
log("writing finished"); log("writing finished");
updateProgressBar(1);
if (!mWriter) { if (!mWriter) {
log("mWriter is NULL"); log("mWriter is NULL");
return; return;
@ -707,7 +720,10 @@ void ResourceCalDav::writingFinished() {
// Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them. // Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
// That's why no mutexes are required. // That's why no mutexes are required.
mWriter->terminate();
mWriter->wait(TERMINATION_WAITING_TIME);
mWritingQueueReady = true; mWritingQueueReady = true;
updateProgressBar(1);
writingQueuePop(); writingQueuePop();
} }

@ -95,24 +95,25 @@ ResourceCardDav::~ResourceCardDav() {
mWriteRetryTimer->stop(); // Unfortunately we cannot do anything at this point; if this timer is still running something is seriously wrong mWriteRetryTimer->stop(); // Unfortunately we cannot do anything at this point; if this timer is still running something is seriously wrong
} }
if (mLoader) {
readLockout = true;
mLoader->terminate();
mLoader->wait(TERMINATION_WAITING_TIME);
mLoadingQueueReady = true;
}
while ((mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady) { while ((mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady) {
readLockout = true; readLockout = true;
sleep(1); sleep(1);
qApp->processEvents(QEventLoop::ExcludeUserInput); qApp->processEvents(QEventLoop::ExcludeUserInput);
} }
if (mLoader) {
mLoader->terminate();
}
if (mWriter) { if (mWriter) {
mWriter->terminate(); mWriter->terminate();
} }
log("waiting for jobs terminated"); log("waiting for jobs terminated");
if (mLoader) {
mLoader->wait(TERMINATION_WAITING_TIME);
}
if (mWriter) { if (mWriter) {
mWriter->wait(TERMINATION_WAITING_TIME); mWriter->wait(TERMINATION_WAITING_TIME);
} }
@ -128,7 +129,8 @@ ResourceCardDav::~ResourceCardDav() {
} }
bool ResourceCardDav::isSaving() { bool ResourceCardDav::isSaving() {
return (((mWriteRetryTimer != NULL) ? mWriteRetryTimer->isActive() : 0) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady); doSave();
return (((mWriteRetryTimer != NULL) ? 1 : 0) || (mWriter->running() == true) || (mWritingQueue.isEmpty() == false) || !mWritingQueueReady || readLockout);
} }
/*========================================================================= /*=========================================================================
@ -138,7 +140,7 @@ bool ResourceCardDav::isSaving() {
bool ResourceCardDav::load() { bool ResourceCardDav::load() {
bool syncCache = true; bool syncCache = true;
if ((mLoadingQueueReady == false) || (mLoadingQueue.isEmpty() == false) || (mLoader->running() == true) || (readLockout == true)) { if ((mLoadingQueueReady == false) || (mLoadingQueue.isEmpty() == false) || (mLoader->running() == true) || (isSaving() == true)) {
return true; // Silently fail; the user has obviously not responded to a dialog and we don't need to pop up more of them! return true; // Silently fail; the user has obviously not responded to a dialog and we don't need to pop up more of them!
} }
@ -189,6 +191,13 @@ bool ResourceCardDav::doSave() {
// FIXME: Calling clearChanges() here is not the ideal way since the // FIXME: Calling clearChanges() here is not the ideal way since the
// upload might fail, but there is no other place to call it... // upload might fail, but there is no other place to call it...
clearChanges(); clearChanges();
if (mWriteRetryTimer != NULL) {
if (mWriteRetryTimer->isActive() == false) {
disconnect( mWriteRetryTimer, SIGNAL(timeout()), this, SLOT(doSave()) );
delete mWriteRetryTimer;
mWriteRetryTimer = NULL;
}
}
return true; return true;
} }
else return true; // We do not need to alert the user to this transient failure; a timer has been started to retry the save else return true; // We do not need to alert the user to this transient failure; a timer has been started to retry the save
@ -267,6 +276,34 @@ void ResourceCardDav::setReadOnly(bool v) {
ensureReadOnlyFlagHonored(); ensureReadOnlyFlagHonored();
} }
void ResourceCardDav::updateProgressBar(int direction) {
int current_queued_events;
static int original_queued_events;
// See if anything is in the queues
current_queued_events = mWritingQueue.count() + mLoadingQueue.count();
if ((direction == 0) && (mLoader->running() == true)) current_queued_events++;
if ((direction == 1) && (mWriter->running() == true)) current_queued_events++;
if (current_queued_events > original_queued_events) {
original_queued_events = current_queued_events;
}
if (current_queued_events == 0) {
if ( mProgress != NULL) {
mProgress->setComplete();
mProgress = NULL;
original_queued_events = 0;
}
}
else {
if (mProgress == NULL) {
if (direction == 0) mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Downloading Contacts") );
if (direction == 1) mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Uploading Contacts") );
}
mProgress->setProgress( ((((float)original_queued_events-(float)current_queued_events)*100)/(float)original_queued_events) );
}
}
/*========================================================================= /*=========================================================================
| READING METHODS | READING METHODS
========================================================================*/ ========================================================================*/
@ -274,16 +311,13 @@ void ResourceCardDav::setReadOnly(bool v) {
void ResourceCardDav::loadingQueuePush(const LoadingTask *task) { void ResourceCardDav::loadingQueuePush(const LoadingTask *task) {
if ((mLoadingQueue.isEmpty() == true) && (mLoader->running() == false)) { if ((mLoadingQueue.isEmpty() == true) && (mLoader->running() == false)) {
mLoadingQueue.enqueue(task); mLoadingQueue.enqueue(task);
updateProgressBar(0);
loadingQueuePop(); loadingQueuePop();
if (mProgress == NULL) {
mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Downloading Calendar") );
mProgress->setProgress( 0 );
}
} }
} }
void ResourceCardDav::loadingQueuePop() { void ResourceCardDav::loadingQueuePop() {
if (!mLoadingQueueReady || mLoadingQueue.isEmpty() || (mWritingQueue.isEmpty() == false) || (mWriter->running() == true) || !mWritingQueueReady) { if (!mLoadingQueueReady || mLoadingQueue.isEmpty() || (isSaving() == true)) {
return; return;
} }
@ -311,6 +345,7 @@ void ResourceCardDav::loadingQueuePop() {
// if all ok, removing the task from the queue // if all ok, removing the task from the queue
mLoadingQueue.dequeue(); mLoadingQueue.dequeue();
updateProgressBar(0);
delete t; delete t;
} }
@ -326,11 +361,6 @@ void ResourceCardDav::loadFinished() {
log("load finished"); log("load finished");
if ( mProgress != NULL) {
mProgress->setComplete();
mProgress = NULL;
}
if (!loader) { if (!loader) {
log("loader is NULL"); log("loader is NULL");
return; return;
@ -387,7 +417,10 @@ void ResourceCardDav::loadFinished() {
// Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them. // Loading queue and mLoadingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
// That's why no mutexes are required. // That's why no mutexes are required.
mLoader->terminate();
mLoader->wait(TERMINATION_WAITING_TIME);
mLoadingQueueReady = true; mLoadingQueueReady = true;
updateProgressBar(0);
loadingQueuePop(); loadingQueuePop();
} }
@ -494,11 +527,8 @@ void ResourceCardDav::writingQueuePush(const WritingTask *task) {
// printf("task->deleted: %s\n\r", task->deleted.ascii()); // printf("task->deleted: %s\n\r", task->deleted.ascii());
// printf("task->changed: %s\n\r", task->changed.ascii()); // printf("task->changed: %s\n\r", task->changed.ascii());
mWritingQueue.enqueue(task); mWritingQueue.enqueue(task);
updateProgressBar(1);
writingQueuePop(); writingQueuePop();
if (mProgress == NULL) {
mProgress = KPIM::ProgressManager::createProgressItem(KPIM::ProgressManager::getUniqueID(), i18n("Saving Calendar") );
mProgress->setProgress( 0 );
}
} }
void ResourceCardDav::writingQueuePop() { void ResourceCardDav::writingQueuePop() {
@ -548,6 +578,7 @@ void ResourceCardDav::writingQueuePop() {
// if all ok, remove the task from the queue // if all ok, remove the task from the queue
mWritingQueue.dequeue(); mWritingQueue.dequeue();
updateProgressBar(1);
delete t; delete t;
} }
@ -602,11 +633,6 @@ bool ResourceCardDav::startWriting(const QString& url) {
void ResourceCardDav::writingFinished() { void ResourceCardDav::writingFinished() {
log("writing finished"); log("writing finished");
if ( mProgress != NULL) {
mProgress->setComplete();
mProgress = NULL;
}
if (!mWriter) { if (!mWriter) {
log("mWriter is NULL"); log("mWriter is NULL");
return; return;
@ -642,7 +668,10 @@ void ResourceCardDav::writingFinished() {
// Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them. // Writing queue and mWritingQueueReady flag are not shared resources, i.e. only one thread has an access to them.
// That's why no mutexes are required. // That's why no mutexes are required.
mWriter->terminate();
mWriter->wait(TERMINATION_WAITING_TIME);
mWritingQueueReady = true; mWritingQueueReady = true;
updateProgressBar(1);
writingQueuePop(); writingQueuePop();
} }

@ -117,6 +117,11 @@ protected:
*/ */
void init(); void init();
/**
* Updates the progress bar
*/
void updateProgressBar(int direction);
/** /**
* Initiates calendar loading process. * Initiates calendar loading process.
* @param url URL to load calendar data from. * @param url URL to load calendar data from.

Loading…
Cancel
Save