28 #include "compactionjob.h"
30 #include "broadcaststatus.h"
31 using KPIM::BroadcastStatus;
32 #include "kmfoldermbox.h"
33 #include "kmfoldermaildir.h"
36 #include <tdelocale.h>
39 #include <tqfileinfo.h>
42 #include <sys/types.h>
46 using namespace KMail;
49 #define COMPACTIONJOB_NRMESSAGES 100
51 #define COMPACTIONJOB_TIMERINTERVAL 100
54 :
ScheduledJob( folder, immediate ), mTimer( this,
"mTimer" ), mTmpFile( 0 ),
55 mCurrentIndex( 0 ), mFolderOpen( false ), mSilent( false )
59 MboxCompactionJob::~MboxCompactionJob()
63 void MboxCompactionJob::kill()
65 Q_ASSERT( mCancellable );
67 if ( mFolderOpen && mSrcFolder && mSrcFolder->storage() )
68 mSrcFolder->storage()->close(
"mboxcompact");
73 if ( !mTempName.isEmpty() )
74 TQFile::remove( mTempName );
78 TQString MboxCompactionJob::realLocation()
const
80 TQString location = mSrcFolder->location();
81 TQFileInfo inf( location );
82 if (inf.isSymLink()) {
83 KURL u; u.setPath( location );
86 return KURL( u, inf.readLink() ).path();
91 int MboxCompactionJob::executeNow(
bool silent )
95 KMFolderMbox* mbox =
static_cast<KMFolderMbox *
>( storage );
97 kdDebug(5006) << storage->
location() <<
" compaction skipped." << endl;
99 TQString str = i18n(
"For safety reasons, compaction has been disabled for %1" ).arg( mbox->label() );
100 BroadcastStatus::instance()->setStatusMsg( str );
104 kdDebug(5006) <<
"Compacting " << mSrcFolder->idString() << endl;
106 if (KMFolderIndex::IndexOk != mbox->indexStatus()) {
107 kdDebug(5006) <<
"Critical error: " << storage->
location() <<
108 " has been modified by an external application while KMail was running." << endl;
112 const TQFileInfo pathInfo( realLocation() );
115 mTempName = pathInfo.dirPath() +
"/." + pathInfo.fileName() +
".compacted";
117 mode_t old_umask = umask(077);
118 mTmpFile = fopen(TQFile::encodeName(mTempName),
"w");
121 kdWarning(5006) <<
"Couldn't start compacting " << mSrcFolder->label()
122 <<
" : " << strerror( errno )
123 <<
" while creating " << mTempName << endl;
126 mOpeningFolder =
true;
127 storage->
open(
"mboxcompact");
128 mOpeningFolder =
false;
133 kdDebug(5006) <<
"MboxCompactionJob: starting to compact folder " << mSrcFolder->location() <<
" into " << mTempName << endl;
134 connect( &mTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotDoWork() ) );
136 mTimer.start( COMPACTIONJOB_TIMERINTERVAL );
141 void MboxCompactionJob::slotDoWork()
144 KMFolderMbox* mbox =
static_cast<KMFolderMbox *
>( mSrcFolder->storage() );
146 int nbMessages = mImmediate ? -1 : COMPACTIONJOB_NRMESSAGES;
147 int rc = mbox->compact( mCurrentIndex, nbMessages,
148 mTmpFile, mOffset , bDone );
150 mCurrentIndex += COMPACTIONJOB_NRMESSAGES;
155 void MboxCompactionJob::done(
int rc )
158 mCancellable =
false;
159 KMFolderMbox* mbox =
static_cast<KMFolderMbox *
>( mSrcFolder->storage() );
161 rc = fflush(mTmpFile);
163 rc = fsync(fileno(mTmpFile));
164 rc |= fclose(mTmpFile);
167 bool autoCreate = mbox->autoCreateIndex();
168 TQString box( realLocation() );
169 ::rename(TQFile::encodeName(mTempName), TQFile::encodeName(box));
172 mbox->setAutoCreateIndex(
false );
173 mbox->close(
"mboxcompact",
true);
174 mbox->setAutoCreateIndex( autoCreate );
175 mbox->setNeedsCompacting(
false );
176 str = i18n(
"Folder \"%1\" successfully compacted" ).arg( mSrcFolder->label() );
177 kdDebug(5006) << str << endl;
179 mbox->close(
"mboxcompact");
180 str = i18n(
"Error occurred while compacting \"%1\". Compaction aborted." ).arg( mSrcFolder->label() );
181 kdDebug(5006) <<
"Error occurred while compacting " << mbox->location() << endl;
182 kdDebug(5006) <<
"Compaction aborted." << endl;
183 TQFile::remove( mTempName );
188 BroadcastStatus::instance()->setStatusMsg( str );
197 :
ScheduledJob( folder, immediate ), mTimer( this,
"mTimer" ),
198 mCurrentIndex( 0 ), mFolderOpen( false ), mSilent( false )
202 MaildirCompactionJob::~MaildirCompactionJob()
206 void MaildirCompactionJob::kill()
208 Q_ASSERT( mCancellable );
210 if ( mFolderOpen && mSrcFolder && mSrcFolder->storage() )
211 mSrcFolder->storage()->close(
"maildircompact");
216 int MaildirCompactionJob::executeNow(
bool silent )
219 KMFolderMaildir* storage =
static_cast<KMFolderMaildir *
>( mSrcFolder->storage() );
220 kdDebug(5006) <<
"Compacting " << mSrcFolder->idString() << endl;
222 mOpeningFolder =
true;
223 storage->open(
"maildircompact");
224 mOpeningFolder =
false;
226 TQString subdirNew(storage->location() +
"/new/");
228 mEntryList = d.entryList();
231 kdDebug(5006) <<
"MaildirCompactionJob: starting to compact in folder " << mSrcFolder->location() << endl;
232 connect( &mTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotDoWork() ) );
234 mTimer.start( COMPACTIONJOB_TIMERINTERVAL );
239 void MaildirCompactionJob::slotDoWork()
242 KMFolderMaildir* storage =
static_cast<KMFolderMaildir *
>( mSrcFolder->storage() );
244 int nbMessages = mImmediate ? -1 : COMPACTIONJOB_NRMESSAGES;
245 int rc = storage->compact( mCurrentIndex, nbMessages, mEntryList, bDone );
247 mCurrentIndex += COMPACTIONJOB_NRMESSAGES;
252 void MaildirCompactionJob::done(
int rc )
254 KMFolderMaildir* storage =
static_cast<KMFolderMaildir *
>( mSrcFolder->storage() );
256 mCancellable =
false;
259 str = i18n(
"Folder \"%1\" successfully compacted" ).arg( mSrcFolder->label() );
261 str = i18n(
"Error occurred while compacting \"%1\". Compaction aborted." ).arg( mSrcFolder->label() );
264 storage->setNeedsCompacting(
false );
265 storage->close(
"maildircompact");
266 if ( storage->isOpened() )
267 storage->updateIndex();
269 BroadcastStatus::instance()->setStatusMsg( str );
281 switch(
folder()->storage()->folderType() ) {
282 case KMFolderTypeMbox:
284 case KMFolderTypeCachedImap:
285 case KMFolderTypeMaildir:
292 #include "compactionjob.moc"
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
virtual int open(const char *owner)=0
Open folder for access.
bool compactable() const
false if index file is out of sync with mbox file
TQString location() const
Returns full path to folder file.
A job that runs in the background and compacts maildir folders.
MaildirCompactionJob(KMFolder *folder, bool immediate)
folder should be a folder with a KMFolderMaildir storage.
A job that runs in the background and compacts mbox folders.
MboxCompactionJob(KMFolder *folder, bool immediate)
folder should be a folder with a KMFolderMbox storage.
virtual ScheduledJob * run()
Run this task, i.e.
Base class for scheduled jobs.
KMFolder * folder() const
The folder which this task is about, 0 if it was deleted meanwhile.