Lots of fixes to folder refcounting all over the place. There might be even more problems elsewhere, but this fixes Intevation issue #1868.

svn path=/branches/kdepim/enterprise/kdepim/; revision=705173
wilder-work
Andreas Hartmetz 19 years ago
parent 79390b3a57
commit 8e56643c4f
  1. 2
      copyfolderjob.cpp
  2. 2
      folderstorage.cpp
  3. 10
      kmfiltermgr.cpp
  4. 16
      kmfolder.h
  5. 17
      kmfoldermaildir.cpp
  6. 18
      kmfoldermbox.cpp
  7. 46
      kmfoldersearch.cpp
  8. 24
      kmkernel.cpp
  9. 6
      kmsearchpattern.cpp
  10. 14
      kmsender.cpp
  11. 3
      undostack.cpp

@ -61,7 +61,7 @@ CopyFolderJob::~CopyFolderJob()
if ( mStorage )
{
mStorage->folder()->setMoveInProgress( false );
mStorage->close("copyfolder");
mStorage->close();
}
}

@ -1139,7 +1139,7 @@ void FolderStorage::slotProcessNextSearchBatch()
matchingSerNums.append( serNum );
}
mCurrentSearchedMsg = end;
bool complete = ( end == count() ) ? true : false;
bool complete = ( end >= count() );
emit searchResult( folder(), matchingSerNums, mSearchPattern, complete );
if ( !complete )
QTimer::singleShot( 0, this, SLOT(slotProcessNextSearchBatch()) );

@ -237,9 +237,7 @@ int KMFilterMgr::process( Q_UINT32 serNum, const KMFilter *filter )
if ( !folder || ( idx == -1 ) || ( idx >= folder->count() ) ) {
return 1;
}
bool opened = folder->isOpened();
if ( !opened )
folder->open();
KMFolderOpener openFolder(folder);
KMMsgBase *msgBase = folder->getMsgBase( idx );
bool unGet = !msgBase->isMessage();
KMMessage *msg = folder->getMsg( idx );
@ -247,15 +245,11 @@ int KMFilterMgr::process( Q_UINT32 serNum, const KMFilter *filter )
if ( !msg || !beginFiltering( msg ) ) {
if ( unGet )
folder->unGetMsg( idx );
if ( !opened )
folder->close();
return 1;
}
if ( filter->execActions( msg, stopIt ) == KMFilter::CriticalError ) {
if ( unGet )
folder->unGetMsg( idx );
if ( !opened )
folder->close();
return 2;
}
@ -270,8 +264,6 @@ int KMFilterMgr::process( Q_UINT32 serNum, const KMFilter *filter )
}
if ( unGet )
folder->unGetMsg( idx );
if ( !opened )
folder->close();
} else {
result = 1;
}

@ -656,6 +656,9 @@ private:
Usage: const KMFolderOpener opener( folder );
*/
/* This class is kept very lightweight to encourage its use. Any more comfort
would need another data element and slightly more code, so consider carefully
if you want that. */
class KMFolderOpener
{
KMFolder * f;
@ -664,7 +667,8 @@ public:
: f( folder )
{
assert( f ); //feel free to put a standard null guard here if it suits you better
f->open();
if (f->open())
f = 0;
}
//if you want the return value of open()
@ -672,15 +676,17 @@ public:
: f( folder )
{
assert( f ); //feel free to put a standard null guard here if it suits you better
*openReturnCode = f->open();
int openRc = f->open();
*openReturnCode = openRc;
if (openRc)
f = 0;
}
inline ~KMFolderOpener()
{
f->close();
if (f)
f->close();
}
inline KMFolder * folder() const { return f; }
};
#endif /*kmfolder_h*/

@ -418,12 +418,11 @@ if( fileD0.open( IO_WriteOnly ) ) {
QFile file(tmp_file);
size = msgText.length();
if (!isOpened())
KMFolderOpener openThis(folder(), &rc);
if (rc)
{
opened = true;
rc = open();
kdDebug(5006) << "KMFolderMaildir::addMsg-open: " << rc << " of folder: " << label() << endl;
if (rc) return rc;
return rc;
}
// now move the file to the correct location
@ -432,12 +431,11 @@ if( fileD0.open( IO_WriteOnly ) ) {
if (moveInternal(tmp_file, new_loc, filename, aMsg->status()).isNull())
{
file.remove();
if (opened) close();
return -1;
}
if (msgParent)
if (idx >= 0) msgParent->take(idx);
if (msgParent && idx >= 0)
msgParent->take(idx);
// just to be sure it does not end up in the index
if ( stripUid ) aMsg->setUID( 0 );
@ -493,7 +491,7 @@ if( fileD0.open( IO_WriteOnly ) ) {
mb->setIndexOffset( ftell(mIndexStream) );
mb->setIndexLength( len );
if(fwrite(buffer, len, 1, mIndexStream) != 1)
kdDebug(5006) << "Whoa! " << __FILE__ << ":" << __LINE__ << endl;
kdDebug(5006) << "Whoa! " << __FILE__ << ":" << __LINE__ << endl;
fflush(mIndexStream);
int error = ferror(mIndexStream);
@ -518,20 +516,17 @@ if( fileD0.open( IO_WriteOnly ) ) {
"(No space left on device or insufficient quota?)\n"
"Free space and sufficient quota are required to continue safely."));
if (busy) kmkernel->kbp()->busy();
if (opened) close();
*/
return error;
}
}
// some "paper work"
if (index_return)
*index_return = idx;
emitMsgAddedSignals(idx);
needsCompact = true;
if (opened) close();
/*
QFile fileD1( "testdat_xx-kmfoldermaildir-1" );
if( fileD1.open( IO_WriteOnly ) ) {

@ -926,7 +926,6 @@ DwString KMFolderMbox::getDwString(int idx)
int KMFolderMbox::addMsg( KMMessage* aMsg, int* aIndex_ret )
{
if (!canAddMsgNow(aMsg, aIndex_ret)) return 0;
bool opened = false;
QByteArray msgText;
char endStr[3];
int idx = -1, rc;
@ -934,12 +933,11 @@ int KMFolderMbox::addMsg( KMMessage* aMsg, int* aIndex_ret )
bool editing = false;
int growth = 0;
if (!mStream)
KMFolderOpener openThis(folder(), &rc);
if (rc)
{
opened = true;
rc = open();
kdDebug(5006) << "KMFolderMBox::addMsg-open: " << rc << " of folder: " << label() << endl;
if (rc) return rc;
kdDebug(5006) << "KMFolderMbox::addMsg-open: " << rc << " of folder: " << label() << endl;
return rc;
}
// take message out of the folder it is currently in, if any
@ -992,7 +990,6 @@ if( fileD1.open( IO_WriteOnly ) ) {
if (len <= 0)
{
kdDebug(5006) << "Message added to folder `" << name() << "' contains no data. Ignoring it." << endl;
if (opened) close();
return 0;
}
@ -1017,10 +1014,7 @@ if( fileD1.open( IO_WriteOnly ) ) {
fseek(mStream,0,SEEK_END); // this is needed on solaris and others
int error = ferror(mStream);
if (error)
{
if (opened) close();
return error;
}
QCString messageSeparator( aMsg->mboxMessageSeparator() );
fwrite( messageSeparator.data(), messageSeparator.length(), 1, mStream );
@ -1047,7 +1041,6 @@ if( fileD1.open( IO_WriteOnly ) ) {
"(No space left on device or insufficient quota?)\n"
"Free space and sufficient quota are required to continue safely."));
if (busy) kmkernel->kbp()->busy();
if (opened) close();
kmkernel->kbp()->idle();
*/
return error;
@ -1131,16 +1124,13 @@ if( fileD1.open( IO_WriteOnly ) ) {
"(No space left on device or insufficient quota?)\n"
"Free space and sufficient quota are required to continue safely."));
if (busy) kmkernel->kbp()->busy();
if (opened) close();
*/
return error;
}
}
// some "paper work"
if (aIndex_ret) *aIndex_ret = idx;
emitMsgAddedSignals(idx);
if (opened) close();
// All streams have been flushed without errors if we arrive here
// Return success!

@ -148,11 +148,12 @@ void KMSearch::start()
{
//close all referenced folders
QValueListIterator<QGuardedPtr<KMFolder> > fit;
for (fit = mFolders.begin(); fit != mFolders.end(); ++fit) {
for (fit = mOpenedFolders.begin(); fit != mOpenedFolders.end(); ++fit) {
if (!(*fit))
continue;
(*fit)->close("kmsearch");
(*fit)->close();
}
mOpenedFolders.clear();
mFolders.clear();
if ( running() )
@ -445,9 +446,6 @@ void KMFolderSearch::addSerNum(Q_UINT32 serNum)
assert(aFolder && (idx != -1));
if(mFolders.findIndex(aFolder) == -1) {
aFolder->open();
// Exceptional case, for when folder has invalid ids
if (mInvalid)
return;
mFolders.append(aFolder);
}
setDirty( true ); //TODO append a single entry to .ids file and sync.
@ -850,9 +848,9 @@ bool KMFolderSearch::readIndex()
}
mSerNums.push_back(serNum);
if(mFolders.findIndex(folder) == -1) {
folder->open();
if (mInvalid) //exceptional case for when folder has invalid ids
return false;
folder->open();
mFolders.append(folder);
}
KMMsgBase *mb = folder->getMsgBase(folderIdx);
@ -913,7 +911,7 @@ void KMFolderSearch::clearIndex(bool, bool)
for (fit = mFolders.begin(); fit != mFolders.end(); ++fit) {
if (!(*fit))
continue;
(*fit)->close("foldersearch");
(*fit)->close();
}
mFolders.clear();
@ -944,7 +942,7 @@ void KMFolderSearch::examineAddedMessage(KMFolder *aFolder, Q_UINT32 serNum)
KMMsgDict::instance()->getLocation(serNum, &folder, &idx);
assert(folder && (idx != -1));
assert(folder == aFolder);
folder->open();
KMFolderOpener openFolder(folder);
// if we are already checking this folder, refcount
if ( mFoldersCurrentlyBeingSearched.contains( folder ) ) {
@ -959,7 +957,6 @@ void KMFolderSearch::examineAddedMessage(KMFolder *aFolder, Q_UINT32 serNum)
mFoldersCurrentlyBeingSearched.insert( folder, 1 );
}
folder->storage()->search( search()->searchPattern(), serNum );
folder->close( "foldersearch" );
}
void KMFolderSearch::slotSearchExamineMsgDone( KMFolder* folder,
@ -970,25 +967,22 @@ void KMFolderSearch::slotSearchExamineMsgDone( KMFolder* folder,
if ( search()->searchPattern() != pattern ) return;
kdDebug(5006) << folder->label() << ": serNum " << serNum
<< " matches?" << matches << endl;
folder->open();
KMFolderOpener openFolder(folder);
if ( mFoldersCurrentlyBeingSearched.contains( folder ) ) {
unsigned int count = mFoldersCurrentlyBeingSearched[folder];
if ( count == 1 ) {
disconnect( folder->storage(),
SIGNAL( searchDone( KMFolder*, Q_UINT32,
const KMSearchPattern*, bool ) ),
this,
SLOT( slotSearchExamineMsgDone( KMFolder*, Q_UINT32,
const KMSearchPattern*, bool ) ) );
mFoldersCurrentlyBeingSearched.remove( folder );
} else {
mFoldersCurrentlyBeingSearched.replace( folder, count-1 );
}
Q_ASSERT( mFoldersCurrentlyBeingSearched.contains( folder ) );
unsigned int count = mFoldersCurrentlyBeingSearched[folder];
if ( count == 1 ) {
disconnect( folder->storage(),
SIGNAL( searchDone( KMFolder*, Q_UINT32,
const KMSearchPattern*, bool ) ),
this,
SLOT( slotSearchExamineMsgDone( KMFolder*, Q_UINT32,
const KMSearchPattern*, bool ) ) );
mFoldersCurrentlyBeingSearched.remove( folder );
} else {
Q_ASSERT( 0 ); // Can't happen (TM)
mFoldersCurrentlyBeingSearched.replace( folder, count-1 );
}
folder->close();
if ( !matches ) {
QValueVector<Q_UINT32>::const_iterator it;
@ -1109,7 +1103,7 @@ void KMFolderSearch::propagateHeaderChanged(KMFolder *aFolder, int idx)
++pos;
}
// let's try if the message matches our search
aFolder->open();
KMFolderOpener openAFolder(aFolder);
// if we are already checking this folder, refcount
if ( mFoldersCurrentlyBeingSearched.contains( aFolder ) ) {

@ -1109,7 +1109,7 @@ bool KMKernel::showMail( Q_UINT32 serialNumber, QString /* messageId */ )
KMMsgDict::instance()->getLocation(serialNumber, &folder, &idx);
if (!folder || (idx == -1))
return false;
folder->open();
KMFolderOpener openFolder(folder);
KMMsgBase *msgBase = folder->getMsgBase(idx);
if (!msgBase)
return false;
@ -1126,7 +1126,6 @@ bool KMKernel::showMail( Q_UINT32 serialNumber, QString /* messageId */ )
if (unGet)
folder->unGetMsg(idx);
folder->close();
return true;
}
@ -1140,7 +1139,7 @@ QString KMKernel::getFrom( Q_UINT32 serialNumber )
KMMsgDict::instance()->getLocation(serialNumber, &folder, &idx);
if (!folder || (idx == -1))
return QString::null;
folder->open();
KMFolderOpener openFolder(folder);
KMMsgBase *msgBase = folder->getMsgBase(idx);
if (!msgBase)
return QString::null;
@ -1149,7 +1148,6 @@ QString KMKernel::getFrom( Q_UINT32 serialNumber )
QString result = msg->from();
if (unGet)
folder->unGetMsg(idx);
folder->close();
return result;
}
@ -1171,17 +1169,16 @@ QString KMKernel::debugSernum( Q_UINT32 serialNumber )
// different folder
if (folder && (idx != -1)) {
// everything is ok
folder->open();
KMFolderOpener openFolder(folder);
msg = folder->getMsgBase( idx );
if (msg) {
res.append( QString( " subject %s,\n sender %s,\n date %s.\n" )
.arg( msg->subject() )
.arg( msg->fromStrip() )
.arg( msg->dateStr() ) );
res.append( QString( " subject %s,\n sender %s,\n date %s.\n" )
.arg( msg->subject() )
.arg( msg->fromStrip() )
.arg( msg->dateStr() ) );
} else {
res.append( QString( "Invalid serial number." ) );
res.append( QString( "Invalid serial number." ) );
}
folder->close();
} else {
res.append( QString( "Invalid serial number." ) );
}
@ -1343,8 +1340,8 @@ void KMKernel::recoverDeadLetters()
return;
KMFolder folder( 0, pathName + "autosave", KMFolderTypeMaildir, false /* no index */ );
const int rc = folder.open();
if ( rc ) {
KMFolderOpener openFolder( &folder );
if ( !folder.isOpened() ) {
perror( "cannot open autosave folder" );
return;
}
@ -1359,7 +1356,6 @@ void KMKernel::recoverDeadLetters()
win->show();
}
}
folder.close();
}
//-----------------------------------------------------------------------------

@ -760,9 +760,7 @@ bool KMSearchPattern::matches( Q_UINT32 serNum, bool ignoreBody ) const
return false;
}
bool opened = folder->isOpened();
if ( !opened )
folder->open();
KMFolderOpener openFolder(folder);
KMMsgBase *msgBase = folder->getMsgBase(idx);
if (requiresBody() && !ignoreBody) {
bool unGet = !msgBase->isMessage();
@ -773,8 +771,6 @@ bool KMSearchPattern::matches( Q_UINT32 serNum, bool ignoreBody ) const
} else {
res = matches( folder->getDwString(idx), ignoreBody );
}
if ( !opened )
folder->close();
return res;
}

@ -161,11 +161,12 @@ bool KMSender::doSend(KMMessage* aMsg, short sendNow)
if (sendNow==-1) sendNow = mSendImmediate;
const KMFolderOpener openOutbox( kmkernel->outboxFolder() );
KMFolder * const outbox = kmkernel->outboxFolder();
const KMFolderOpener openOutbox( outbox );
aMsg->setStatus(KMMsgStatusQueued);
if ( const int err = openOutbox.folder()->addMsg(aMsg) ) {
if ( const int err = outbox->addMsg(aMsg) ) {
Q_UNUSED( err );
KMessageBox::information(0,i18n("Cannot add message to outbox folder"));
return false;
@ -182,10 +183,10 @@ bool KMSender::doSend(KMMessage* aMsg, short sendNow)
* in this branch.
* Note that the unencrypted mail will be lost if the mail remains in
* the outbox across a restart anyhow, but that never worked, afaikt. */
const int idx = openOutbox.folder()->count() - 1;
const int idx = outbox->count() - 1;
KMMessage * const unencryptedMsg = aMsg->unencryptedMsg();
openOutbox.folder()->unGetMsg( idx );
KMMessage * const tempMsg = openOutbox.folder()->getMsg( idx );
outbox->unGetMsg( idx );
KMMessage * const tempMsg = outbox->getMsg( idx );
tempMsg->setUnencryptedMsg( unencryptedMsg );
if ( !sendNow || mSendInProgress )
@ -858,7 +859,7 @@ void KMSender::setStatusByLink(const KMMessage *aMsg)
int index = -1;
KMMsgDict::instance()->getLocation(msn, &folder, &index);
if (folder && index != -1) {
folder->open();
KMFolderOpener openFolder(folder);
if ( status == KMMsgStatusDeleted ) {
// Move the message to the trash folder
KMDeleteMsgCommand *cmd =
@ -867,7 +868,6 @@ void KMSender::setStatusByLink(const KMMessage *aMsg)
} else {
folder->setStatus(index, status);
}
folder->close();
} else {
kdWarning(5006) << k_funcinfo << "Cannot update linked message, it could not be found!" << endl;
}

@ -88,7 +88,7 @@ void UndoStack::undo()
UndoInfo *info = mStack.take(0);
emit undoStackChanged();
QValueList<ulong>::iterator itr;
info->destFolder->open();
KMFolderOpener openDestFolder(info->destFolder);
for( itr = info->serNums.begin(); itr != info->serNums.end(); ++itr ) {
serNum = *itr;
KMMsgDict::instance()->getLocation(serNum, &curFolder, &idx);
@ -102,7 +102,6 @@ void UndoStack::undo()
if ( info->srcFolder->count() > 1 )
info->srcFolder->unGetMsg( info->srcFolder->count() - 1 );
}
info->destFolder->close();
delete info;
}
else

Loading…
Cancel
Save