summaryrefslogtreecommitdiffstats
path: root/src/app/Synchronizer/synchronizertask.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/Synchronizer/synchronizertask.cpp')
-rw-r--r--src/app/Synchronizer/synchronizertask.cpp343
1 files changed, 343 insertions, 0 deletions
diff --git a/src/app/Synchronizer/synchronizertask.cpp b/src/app/Synchronizer/synchronizertask.cpp
new file mode 100644
index 0000000..9a27584
--- /dev/null
+++ b/src/app/Synchronizer/synchronizertask.cpp
@@ -0,0 +1,343 @@
+/***************************************************************************
+ synchronizertask.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "synchronizer.h"
+#include "synchronizertask.h"
+#include "synchronizerfileitem.h"
+#include "synchronizerdirlist.h"
+#include <tqtimer.h>
+#include <tqfile.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include "../VFS/vfs.h"
+
+CompareTask::CompareTask( SynchronizerFileItem *parentIn, const TQString &leftURL,
+ const TQString &rightURL, const TQString &leftDir,
+ const TQString &rightDir, bool hidden ) : SynchronizerTask (), m_parent( parentIn ),
+ m_url( leftURL ), m_dir( leftDir ), m_otherUrl( rightURL ),
+ m_otherDir( rightDir ), m_duplicate( true ),
+ m_dirList( 0 ), m_otherDirList( 0 ) {
+ ignoreHidden = hidden;
+}
+
+CompareTask::CompareTask( SynchronizerFileItem *parentIn, const TQString &urlIn,
+ const TQString &dirIn, bool isLeftIn, bool hidden ) : SynchronizerTask (),
+ m_parent( parentIn ), m_url( urlIn ), m_dir( dirIn ),
+ m_isLeft( isLeftIn ), m_duplicate( false ),
+ m_dirList( 0 ), m_otherDirList( 0 ) {
+ ignoreHidden = hidden;
+}
+
+CompareTask::~CompareTask() {
+ if( m_dirList ) {
+ delete m_dirList;
+ m_dirList = 0;
+ }
+ if( m_otherDirList ) {
+ delete m_otherDirList;
+ m_otherDirList = 0;
+ }
+}
+
+void CompareTask::start() {
+ if( m_state == ST_STATE_NEW ) {
+ m_state = ST_STATE_PENDING;
+ m_loadFinished = m_otherLoadFinished = false;
+
+ m_dirList = new SynchronizerDirList( parentWidget, ignoreHidden );
+ connect( m_dirList, TQ_SIGNAL( finished( bool ) ), this, TQ_SLOT( slotFinished( bool ) ));
+ m_dirList->load( m_url, false );
+
+ if( m_duplicate ) {
+ m_otherDirList = new SynchronizerDirList( parentWidget, ignoreHidden );
+ connect( m_otherDirList, TQ_SIGNAL( finished( bool ) ), this, TQ_SLOT( slotOtherFinished( bool ) ));
+ m_otherDirList->load( m_otherUrl, false );
+ }
+ }
+}
+
+void CompareTask::slotFinished( bool result ) {
+ if( !result ) {
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+ m_loadFinished = true;
+
+ if( m_otherLoadFinished || !m_duplicate )
+ m_state = ST_STATE_READY;
+}
+
+
+void CompareTask::slotOtherFinished( bool result ) {
+ if( !result ) {
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+ m_otherLoadFinished = true;
+
+ if( m_loadFinished )
+ m_state = ST_STATE_READY;
+}
+
+CompareContentTask::CompareContentTask( Synchronizer *syn, SynchronizerFileItem *itemIn, const KURL &leftURLIn,
+ const KURL &rightURLIn, TDEIO::filesize_t sizeIn ) : SynchronizerTask(),
+ leftURL( leftURLIn ), rightURL( rightURLIn ),
+ size( sizeIn ), errorPrinted(false), leftReadJob( 0 ),
+ rightReadJob( 0 ), compareArray(), item( itemIn ), timer( 0 ),
+ leftFile( 0 ), rightFile( 0 ), received( 0 ), sync( syn ) {
+}
+
+CompareContentTask::~CompareContentTask() {
+ abortContentComparing();
+
+ if( timer )
+ delete timer;
+ if( leftFile )
+ delete leftFile;
+ if( rightFile )
+ delete rightFile;
+}
+
+void CompareContentTask::start() {
+ m_state = ST_STATE_PENDING;
+
+ if( leftURL.isLocalFile() && rightURL.isLocalFile() ) {
+ leftFile = new TQFile( leftURL.path() );
+ if( !leftFile->open( IO_ReadOnly ) ) {
+ KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( leftURL.path() ));
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+
+ rightFile = new TQFile( rightURL.path() );
+ if( !rightFile->open( IO_ReadOnly ) ) {
+ KMessageBox::error(parentWidget, i18n("Error at opening %1!").arg( rightURL.path() ));
+ m_state = ST_STATE_ERROR;
+ return;
+ }
+
+ timer = new TQTimer( this );
+ connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+
+ localFileCompareCycle();
+ } else {
+ leftReadJob = TDEIO::get( leftURL, false, false );
+ rightReadJob = TDEIO::get( rightURL, false, false );
+
+ connect(leftReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(rightReadJob, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(slotDataReceived(TDEIO::Job *, const TQByteArray &)));
+ connect(leftReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotFinished(TDEIO::Job *)));
+ connect(rightReadJob, TQ_SIGNAL(result(TDEIO::Job*)),
+ this, TQ_SLOT(slotFinished(TDEIO::Job *)));
+
+ rightReadJob->suspend();
+
+ timer = new TQTimer( this );
+ connect( timer, TQ_SIGNAL(timeout()), this, TQ_SLOT(sendStatusMessage()) );
+ timer->start( 1000, true );
+ }
+}
+
+void CompareContentTask::localFileCompareCycle() {
+
+ bool different = false;
+
+ char leftBuffer[ 1440 ];
+ char rightBuffer[ 1440 ];
+
+ TQTime timer;
+ timer.start();
+
+ int cnt = 0;
+
+ while ( !leftFile->atEnd() && !rightFile->atEnd() )
+ {
+ int leftBytes = leftFile->readBlock( leftBuffer, sizeof( leftBuffer ) );
+ int rightBytes = rightFile->readBlock( rightBuffer, sizeof( rightBuffer ) );
+
+ if( leftBytes != rightBytes ) {
+ different = true;
+ break;
+ }
+
+ if( leftBytes <= 0 )
+ break;
+
+ received += leftBytes;
+
+ if( memcmp( leftBuffer, rightBuffer, leftBytes ) ) {
+ different = true;
+ break;
+ }
+
+ if( (++cnt % 16) == 0 && timer.elapsed() >= 250 )
+ break;
+ }
+
+ if( different ) {
+ sync->compareContentResult( item, false );
+ m_state = ST_STATE_READY;
+ return;
+ }
+
+ if( leftFile->atEnd() && rightFile->atEnd() ) {
+ sync->compareContentResult( item, true );
+ m_state = ST_STATE_READY;
+ return;
+ }
+
+ TQTimer::singleShot( 0, this, TQ_SLOT( localFileCompareCycle() ) );
+}
+
+
+void CompareContentTask::slotDataReceived(TDEIO::Job *job, const TQByteArray &data)
+{
+ int bufferLen = compareArray.size();
+ int dataLen = data.size();
+
+ if( job == leftReadJob )
+ received += dataLen;
+
+ do
+ {
+ if( bufferLen == 0 )
+ {
+ compareArray.duplicate( data.data(), dataLen );
+ break;
+ }
+
+ int minSize = ( dataLen < bufferLen ) ? dataLen : bufferLen;
+
+ for( int i = 0; i != minSize; i++ )
+ if( data[i] != compareArray[i] )
+ {
+ abortContentComparing();
+ return;
+ }
+
+ if( minSize == bufferLen )
+ {
+ compareArray.duplicate( data.data() + bufferLen, dataLen - bufferLen );
+ if( dataLen == bufferLen )
+ return;
+ break;
+ }
+ else
+ {
+ compareArray.duplicate( compareArray.data() + dataLen, bufferLen - dataLen );
+ return;
+ }
+
+ }while ( false );
+
+ TDEIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob;
+
+ if( otherJob == 0 )
+ {
+ if( compareArray.size() )
+ abortContentComparing();
+ }
+ else
+ {
+ if( !((TDEIO::TransferJob *)job)->isSuspended() )
+ {
+ ((TDEIO::TransferJob *)job)->suspend();
+ otherJob->resume();
+ }
+ }
+}
+
+void CompareContentTask::slotFinished(TDEIO::Job *job)
+{
+ TDEIO::TransferJob *otherJob = ( job == leftReadJob ) ? rightReadJob : leftReadJob;
+
+ if( job == leftReadJob )
+ leftReadJob = 0;
+ else
+ rightReadJob = 0;
+
+ if( otherJob )
+ otherJob->resume();
+
+ if( job->error() )
+ {
+ timer->stop();
+ abortContentComparing();
+ }
+
+ if( job->error() && job->error() != TDEIO::ERR_USER_CANCELED && !errorPrinted )
+ {
+ errorPrinted = true;
+ KMessageBox::error(parentWidget, i18n("IO error at comparing file %1 with %2!")
+ .arg( vfs::pathOrURL( leftURL ) )
+ .arg( vfs::pathOrURL( rightURL ) ) );
+ }
+
+ if( leftReadJob == 0 && rightReadJob == 0 )
+ {
+ if( !compareArray.size() )
+ sync->compareContentResult( item, true );
+ else
+ sync->compareContentResult( item, false );
+
+ m_state = ST_STATE_READY;
+ }
+}
+
+void CompareContentTask::abortContentComparing()
+{
+ if( timer )
+ timer->stop();
+
+ if( leftReadJob )
+ leftReadJob->kill( false );
+ if( rightReadJob )
+ rightReadJob->kill( false );
+
+ if( item->task() >= TT_UNKNOWN )
+ sync->compareContentResult( item, false );
+
+ m_state = ST_STATE_READY;
+}
+
+void CompareContentTask::sendStatusMessage()
+{
+ double perc = (size == 0) ? 1. : (double)received / (double)size;
+ int percent = (int)(perc * 10000. + 0.5);
+ TQString statstr = TQString( "%1.%2%3" ).arg( percent / 100 ).arg( ( percent / 10 )%10 ).arg( percent % 10 ) + "%";
+ setStatusMessage( i18n( "Comparing file %1 (%2)..." ).arg( leftURL.fileName() ).arg( statstr ) );
+ timer->start( 500, true );
+}
+
+#include "synchronizertask.moc"