Esempio n. 1
0
void SyncEngine::slotFinished()
{
    // emit the treewalk results.
    if( ! _journal->postSyncCleanup( _seenFiles ) ) {
        qDebug() << "Cleaning of synced ";
    }
    _journal->commit("All Finished.", false);
    emit treeWalkResult(_syncedItems);
    finalize();
}
Esempio n. 2
0
void CSyncThread::startNextTransfer()
{
    while (_iterator < _syncedItems.size()) {
        const SyncFileItem &item = _syncedItems.at(_iterator);
        ++_iterator;

        while (!_directoriesToUpdate.isEmpty() && !item._file.startsWith(_directoriesToUpdate.last()._path)) {
            // We are leaving a directory. Everything we needed to download from that directory is done.
            // Update the directory etag in the database to the new one.
            _journal->setFileRecord(_directoriesToUpdate.pop());
        }

        if (!_lastDeleted.isEmpty() &&
                item._file.startsWith(_lastDeleted) ) {
            if( item._instruction != CSYNC_INSTRUCTION_REMOVE ) {
                qDebug() << "WRN: Child of a deleted directory has different instruction than delete."
                         << item._file << _lastDeleted << item._instruction;
            } else {
                // If the item's name starts with the name of the previously deleted directory, we
                // can assume this file was already destroyed by the previous call.
                _journal->deleteFileRecord(item._file);
                continue;
            }
        }

        if (item._instruction == CSYNC_INSTRUCTION_SYNC || item._instruction == CSYNC_INSTRUCTION_NEW
                || item._instruction == CSYNC_INSTRUCTION_CONFLICT) {
            slotProgress((item._dir != SyncFileItem::Up) ? Progress::StartDownload : Progress::StartUpload,
                         item._file, 0, item._size);
        }

        _propagator->propagate(item);
        return; //propagate is async.
    }

    // We are finished !!

    while (!_directoriesToUpdate.isEmpty()) {
        // Save the etag of directories to the database.
        _journal->setFileRecord(_directoriesToUpdate.pop());
    }

    // emit the treewalk results.
    emit treeWalkResult(_syncedItems);

    csync_commit(_csync_ctx);

    qDebug() << "CSync run took " << _syncTime.elapsed() << " Milliseconds";
    slotProgress(Progress::EndSync,QString(), 0 , 0);
    emit finished();
    _propagator.reset(0);
    _syncMutex.unlock();
    thread()->quit();
}
Esempio n. 3
0
void SyncEngine::slotFinished()
{
    _anotherSyncNeeded = _anotherSyncNeeded || _propagator->_anotherSyncNeeded;

    // emit the treewalk results.
    if( ! _journal->postSyncCleanup( _seenFiles, _temporarilyUnavailablePaths ) ) {
        qDebug() << "Cleaning of synced ";
    }

    _journal->commit("All Finished.", false);
    emit treeWalkResult(_syncedItems);
    finalize(true); // FIXME: should it be true if there was errors?
}
Esempio n. 4
0
void CSyncThread::startNextTransfer()
{
    while (_iterator < _syncedItems.size()) {
        const SyncFileItem &item = _syncedItems.at(_iterator);
        ++_iterator;

        while (!_directoriesToUpdate.isEmpty() && !item._file.startsWith(_directoriesToUpdate.last()._path)) {
            _journal->setFileRecord(_directoriesToUpdate.pop());
        }

        if (!_lastDeleted.isEmpty() && item._file.startsWith(_lastDeleted)
                && item._instruction == CSYNC_INSTRUCTION_REMOVE) {
            // If the item's name starts with the name of the previously deleted directory, we
            // can assume this file was already destroyed by the previous recursive call.
            _journal->deleteFileRecord(item._file);
            continue;
        }

        if (item._instruction == CSYNC_INSTRUCTION_SYNC || item._instruction == CSYNC_INSTRUCTION_NEW
                || item._instruction == CSYNC_INSTRUCTION_CONFLICT) {
            slotProgress((item._dir != SyncFileItem::Up) ? Progress::StartDownload : Progress::StartUpload,
                         item._file, 0, item._size);
        }

        _propagator->propagate(item);
        return; //propagate is async.
    }

    while (!_directoriesToUpdate.isEmpty()) {
        _journal->setFileRecord(_directoriesToUpdate.pop());
    }

    // Everything is finished.
    _progressDataBase.save(_localPath);

    // emit the treewalk results.
    emit treeWalkResult(_syncedItems);

    csync_commit(_csync_ctx);

    qDebug() << "CSync run took " << _syncTime.elapsed() << " Milliseconds";
    slotProgress(Progress::EndSync,QString(), 0 , 0);
    emit finished();
    _propagator.reset(0);
    _syncMutex.unlock();
    thread()->quit();
}
Esempio n. 5
0
void CSyncThread::slotFinished()
{
    // emit the treewalk results.
    if( ! _journal->postSyncCleanup( _seenFiles ) ) {
        qDebug() << "Cleaning of synced ";
    }
    _journal->commit("All Finished.", false);
    emit treeWalkResult(_syncedItems);

    csync_commit(_csync_ctx);

    qDebug() << "CSync run took " << _syncTime.elapsed() << " Milliseconds";
    slotProgress(Progress::EndSync,SyncFileItem(), 0 , 0);
    emit finished();
    _propagator.reset(0);
    _syncMutex.unlock();
    _thread.quit();
}
Esempio n. 6
0
void CSyncThread::startSync()
{
    if (!_syncMutex.tryLock()) {
        qDebug() << Q_FUNC_INFO << "WARNING: Another sync seems to be running. Not starting a new one.";
        return;
    }

    qDebug() << Q_FUNC_INFO << "Sync started";

    qDebug() << "starting to sync " << qApp->thread() << QThread::currentThread();
    CSYNC *csync;
    int proxyPort = _proxy.port();

    _mutex.lock();
    _syncedItems.clear();
    _needsUpdate = false;
    _mutex.unlock();

    if( csync_create(&csync,
                     _source.toUtf8().data(),
                     _target.toUtf8().data()) < 0 ) {
        emit csyncError( tr("CSync create failed.") );
    }
    csync_set_log_verbosity(csync, 11);

    MirallConfigFile cfg;
    csync_set_config_dir( csync, cfg.configPath().toUtf8() );

    _mutex.lock();
    _csyncConfigDir = cfg.configPath();
    _mutex.unlock();

    csync_enable_conflictcopys(csync);
    QString excludeList = cfg.excludeFile();
    if( !excludeList.isEmpty() ) {
        qDebug() << "==== added CSync exclude List: " << excludeList.toUtf8();
        csync_add_exclude_list( csync, excludeList.toUtf8() );
    }

    // cleans up behind us and emits finished() to ease error handling
    CSyncRunScopeHelper helper(csync, this);

    csync_set_userdata(csync, this);

    csync_set_log_callback( csync, csyncLogCatcher );
    csync_set_auth_callback( csync, getauth );
    csync_set_progress_callback( csync, progress );

    if( csync_init(csync) < 0 ) {
        handleSyncError(csync, "csync_init");
        return;
    }

    // set module properties, mainly the proxy information.
    // do not use QLatin1String here because that has to be real const char* for C.
    csync_set_module_property(csync, "csync_context", csync);
    csync_set_module_property(csync, "proxy_type", (char*) proxyTypeToCStr(_proxy.type()) );
    csync_set_module_property(csync, "proxy_host", _proxy.hostName().toUtf8().data() );
    csync_set_module_property(csync, "proxy_port", &proxyPort );
    csync_set_module_property(csync, "proxy_user", _proxy.user().toUtf8().data()     );
    csync_set_module_property(csync, "proxy_pwd" , _proxy.password().toUtf8().data() );

    qDebug() << "#### Update start #################################################### >>";
    if( csync_update(csync) < 0 ) {
        handleSyncError(csync, "csync_update");
        return;
    }
    qDebug() << "<<#### Update end ###########################################################";

    if( csync_reconcile(csync) < 0 ) {
        handleSyncError(csync, "cysnc_reconcile");
        return;
    }

    bool walkOk = true;
    if( csync_walk_local_tree(csync, &treewalkLocal, 0) < 0 ) {
        qDebug() << "Error in local treewalk.";
        walkOk = false;
    }
    if( walkOk && csync_walk_remote_tree(csync, &treewalkRemote, 0) < 0 ) {
        qDebug() << "Error in remote treewalk.";
    }

    if (_needsUpdate)
        emit(started());

    if( csync_propagate(csync) < 0 ) {
        handleSyncError(csync, "cysnc_reconcile");
        return;
    }

    if( walkOk ) {
        if( csync_walk_local_tree(csync, &walkFinalize, 0) < 0 ||
            csync_walk_remote_tree( csync, &walkFinalize, 0 ) < 0 ) {
          qDebug() << "Error in finalize treewalk.";
        } else {
        // emit the treewalk results.
            emit treeWalkResult(_syncedItems);
        }
    }
    qDebug() << Q_FUNC_INFO << "Sync finished";
}
Esempio n. 7
0
void CSyncThread::startSync()
{
    if (!_syncMutex.tryLock()) {
        qDebug() << Q_FUNC_INFO << "WARNING: Another sync seems to be running. Not starting a new one.";
        return;
    }

    if( ! _csync_ctx ) {
        qDebug() << "XXXXXXXXXXXXXXXX FAIL: do not have csync_ctx!";
    }
    qDebug() << Q_FUNC_INFO << "Sync started";

    qDebug() << "starting to sync " << qApp->thread() << QThread::currentThread();

    _mutex.lock();
    _syncedItems.clear();
    _needsUpdate = false;
    _mutex.unlock();

    // cleans up behind us and emits finished() to ease error handling
    CSyncRunScopeHelper helper(_csync_ctx, this);

    // maybe move this somewhere else where it can influence a running sync?
    MirallConfigFile cfg;

    int downloadLimit = 0;
    if (cfg.useDownloadLimit()) {
         downloadLimit = cfg.downloadLimit() * 1000;
    }
    csync_set_module_property(_csync_ctx, "bandwidth_limit_download", &downloadLimit);

    int uploadLimit = -75; // 75%
    int useUpLimit = cfg.useUploadLimit();
    if ( useUpLimit >= 1) {
         uploadLimit = cfg.uploadLimit() * 1000;
    } else if (useUpLimit == 0) {
        uploadLimit = 0;
    }
    csync_set_module_property(_csync_ctx, "bandwidth_limit_upload", &uploadLimit);

    csync_set_progress_callback( _csync_ctx, cb_progress );

    csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
    csync_set_userdata(_csync_ctx, this);

    // TODO: This should be a part of this method, but we don't have
    // any way to get "session_key" module property from csync. Had we
    // have it, then we could keep this code and remove it from
    // AbstractCredentials implementations.
    cfg.getCredentials()->syncContextPreStart(_csync_ctx);
    // if (_lastAuthCookies.length() > 0) {
    //     // Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
    //     // when https://github.com/owncloud/core/pull/4042 is merged.
    //     QString cookiesAsString;
    //     foreach(QNetworkCookie c, _lastAuthCookies) {
    //         cookiesAsString += c.name();
    //         cookiesAsString += '=';
    //         cookiesAsString += c.value();
    //         cookiesAsString += "; ";
    //     }
    //     csync_set_module_property(_csync_ctx, "session_key", cookiesAsString.to
    // }

    // csync_set_auth_callback( _csync_ctx, getauth );



    qDebug() << "#### Update start #################################################### >>";
    if( csync_update(_csync_ctx) < 0 ) {
        handleSyncError(_csync_ctx, "csync_update");
        return;
    }
    qDebug() << "<<#### Update end ###########################################################";

    if( csync_reconcile(_csync_ctx) < 0 ) {
        handleSyncError(_csync_ctx, "csync_reconcile");
        return;
    }

    _hasFiles = false;
    bool walkOk = true;
    if( csync_walk_local_tree(_csync_ctx, &treewalkLocal, 0) < 0 ) {
        qDebug() << "Error in local treewalk.";
        walkOk = false;
    }
    if( walkOk && csync_walk_remote_tree(_csync_ctx, &treewalkRemote, 0) < 0 ) {
        qDebug() << "Error in remote treewalk.";
    }

    if (!_hasFiles && !_syncedItems.isEmpty()) {
        qDebug() << Q_FUNC_INFO << "All the files are going to be removed, asking the user";
        bool cancel = true;
        emit aboutToRemoveAllFiles(_syncedItems.first()._dir, &cancel);
        if (cancel) {
            qDebug() << Q_FUNC_INFO << "Abort sync";
            return;
        }
    }

    if (_needsUpdate)
        emit(started());

    if( csync_propagate(_csync_ctx) < 0 ) {
        handleSyncError(_csync_ctx, "cysnc_reconcile");
        return;
    }

    if( walkOk ) {
        if( csync_walk_local_tree(_csync_ctx, &walkFinalize, 0) < 0 ||
            csync_walk_remote_tree(_csync_ctx, &walkFinalize, 0 ) < 0 ) {
            qDebug() << "Error in finalize treewalk.";
        } else {
        // emit the treewalk results.
            emit treeWalkResult(_syncedItems);
        }
    }
    qDebug() << Q_FUNC_INFO << "Sync finished";
}
Esempio n. 8
0
void CSyncThread::run()
{
    CSYNC *csync;
    WalkStats *wStats = new WalkStats;
    QTime walkTime;

    wStats->sourcePath = 0;
    wStats->errorType  = 0;
    wStats->eval       = 0;
    wStats->removed    = 0;
    wStats->renamed    = 0;
    wStats->newFiles   = 0;
    wStats->ignores    = 0;
    wStats->sync       = 0;
    wStats->seenFiles  = 0;
    wStats->conflicts  = 0;
    wStats->error      = 0;
    wStats->dirPermErrors = 0;

    ProxyInfo *proxyInfo  = new ProxyInfo;

    _mutex.lock();
    proxyInfo->proxyType = qstrdup( _proxyType.toAscii().constData() );
    proxyInfo->proxyHost = qstrdup( _proxyHost.toAscii().constData() );
    proxyInfo->proxyPort = qstrdup( _proxyPort.toAscii().constData() );
    proxyInfo->proxyUser = qstrdup( _proxyUser.toAscii().constData() );
    proxyInfo->proxyPwd  = qstrdup( _proxyPwd.toAscii().constData() );

    if( csync_create(&csync,
                     _source.toUtf8().data(),
                     _target.toUtf8().data()) < 0 ) {
        emit csyncError( tr("CSync create failed.") );
    }
    // FIXME: Check if we really need this stringcopy!
    wStats->sourcePath = qstrdup( _source.toUtf8().constData() );
    _csyncConfigDir = QString::fromUtf8( csync_get_config_dir( csync ));
    _mutex.unlock();

    qDebug() << "## CSync Thread local only: " << _localCheckOnly;
    csync_set_auth_callback( csync, getauth );
    csync_enable_conflictcopys(csync);


    MirallConfigFile cfg;
    QString excludeList = cfg.excludeFile();

    if( !excludeList.isEmpty() ) {
        qDebug() << "==== added CSync exclude List: " << excludeList.toAscii();
        csync_add_exclude_list( csync, excludeList.toAscii() );
    }

    QTime t;
    t.start();

    _mutex.lock();
    if( _localCheckOnly ) {
        csync_set_local_only( csync, true );
    }
    csync_set_userdata(csync, (void*) proxyInfo);
    _mutex.unlock();

    if( csync_init(csync) < 0 ) {
        CSYNC_ERROR_CODE err = csync_get_error( csync );
        QString errStr;

        switch( err ) {
        case CSYNC_ERR_LOCK:
            errStr = tr("CSync failed to create a lock file.");
            break;
        case CSYNC_ERR_STATEDB_LOAD:
            errStr = tr("CSync failed to load the state db.");
            break;
        case CSYNC_ERR_TIMESKEW:
            errStr = tr("The system time on this client is different than the system time on the server. "
                        "Please use a time synchronization service (NTP) on the server and client machines "
                        "so that the times remain the same.");
            break;
        case CSYNC_ERR_FILESYSTEM:
            errStr = tr("CSync could not detect the filesystem type.");
            break;
        case CSYNC_ERR_TREE:
            errStr = tr("CSync got an error while processing internal trees.");
            break;
        case CSYNC_ERR_ACCESS_FAILED:
            errStr = tr("<p>The target directory %1 does not exist.</p><p>Please check the sync setup.</p>").arg(_target);
            // this is critical. The database has to be removed.
            emitStateDb(csync); // to make the name of the csync db known.
            emit wipeDb();
            break;
        case CSYNC_ERR_MODULE:
            errStr = tr("<p>The ownCloud plugin for csync could not be loaded.<br/>Please verify the installation!</p>");
            break;
        case CSYNC_ERR_LOCAL_CREATE:
        case CSYNC_ERR_LOCAL_STAT:
            errStr = tr("The local filesystem can not be written. Please check permissions.");
            break;
        case CSYNC_ERR_REMOTE_CREATE:
        case CSYNC_ERR_REMOTE_STAT:
            errStr = tr("A remote file can not be written. Please check the remote access.");
            break;
        default:
            errStr = tr("An internal error number %1 happend.").arg( (int) err );
        }
        qDebug() << " #### ERROR String emitted: " << errStr;
        emit csyncError(errStr);
        goto cleanup;
    }

    emitStateDb(csync);

    qDebug() << "#### Update start #################################################### >>";
    if( csync_update(csync) < 0 ) {
        CSYNC_ERROR_CODE err = csync_get_error( csync );
        QString errStr;

        switch( err ) {
        case CSYNC_ERR_PROXY:
            errStr = tr("CSync failed to reach the host. Either host or proxy settings are not valid.");
            break;
        default:
            errStr = tr("CSync Update failed.");
            break;
        }
        emit csyncError( errStr );
        goto cleanup;
    }
    qDebug() << "<<#### Update end ###########################################################";

    csync_set_userdata(csync, wStats);

    walkTime.start();
    if( csync_walk_local_tree(csync, &checkPermissions, 0) < 0 ) {
        qDebug() << "Error in treewalk.";
        if( wStats->errorType == WALK_ERROR_WALK ) {
            emit csyncError(tr("CSync encountered an error while examining the file system.\n"
                               "Syncing is not possible."));
        } else if( wStats->errorType == WALK_ERROR_INSTRUCTIONS ) {
            emit csyncError(tr("CSync update generated a strange instruction.\n"
                               "Please write a bug report."));
        }
        emit csyncError(tr("Local filesystem problems. Better disable Syncing and check."));
        goto cleanup;
    } else {
        // only warn, do not stop the sync process.
        if( wStats->errorType == WALK_ERROR_DIR_PERMS ) {
            emit csyncError(tr("The local filesystem has %1 write protected directories."
                               "That can hinder successful syncing.<p/>"
                               "Please make sure that all local directories are writeable.").arg(wStats->dirPermErrors));
        }
    }

    // emit the treewalk results. Do not touch the wStats after this.
    emit treeWalkResult(wStats);

    _mutex.lock();
    if( _localCheckOnly ) {
        _mutex.unlock();
        qDebug() << " ..... Local only walk finished: " << walkTime.elapsed();
        // we have to go out here as its local check only.
        goto cleanup;
    } else {
        _mutex.unlock();
        // check if we can write all over.

        if( csync_reconcile(csync) < 0 ) {
            emit csyncError(tr("CSync reconcile failed."));
            goto cleanup;
        }
        if( csync_propagate(csync) < 0 ) {
            emit csyncError(tr("CSync propagate failed."));
            goto cleanup;
        }
    }
cleanup:
    csync_destroy(csync);

    if( proxyInfo->proxyType ) free( proxyInfo->proxyType );
    if( proxyInfo->proxyHost ) free( proxyInfo->proxyHost );
    if( proxyInfo->proxyPort ) free( proxyInfo->proxyPort );
    if( proxyInfo->proxyUser ) free( proxyInfo->proxyUser );
    if( proxyInfo->proxyPwd  ) free( proxyInfo->proxyPwd  );

    free( proxyInfo );

    /*
     * Attention: do not delete the wStat memory here. it is deleted in the
     * slot catching the signel treeWalkResult because this thread can faster
     * die than the slot has read out the data.
     */
    qDebug() << "CSync run took " << t.elapsed() << " Milliseconds";
}
Esempio n. 9
0
void CSyncThread::transferCompleted(const SyncFileItem &item)
{
    qDebug() << Q_FUNC_INFO << item._file << item._status << item._errorString;

    /* Update the _syncedItems vector */

    // Search for the item in the starting from _iterator because it should be a bit before it.
    // This works because SyncFileItem::operator== only compare the file name;
    int idx = _syncedItems.lastIndexOf(item, _iterator);
    if (idx >= 0) {
        _syncedItems[idx]._instruction = item._instruction;
        _syncedItems[idx]._errorString = item._errorString;
        _syncedItems[idx]._status = item._status;
    }

    /* Remember deleted directory */

    if (item._isDirectory && item._instruction == CSYNC_INSTRUCTION_DELETED) {
        _lastDeleted = item._file;
    } else {
        _lastDeleted.clear();
    }

    /* Update the database */

    if (item._instruction == CSYNC_INSTRUCTION_DELETED) {
        _journal->deleteFileRecord(item._originalFile);
        if (!item._renameTarget.isEmpty()) {
            SyncJournalFileRecord record(item, _localPath + item._renameTarget);
            record._path = item._renameTarget;
            _journal->setFileRecord(record);
        }
    } else if(item._instruction == CSYNC_INSTRUCTION_ERROR) {
        // Don't update parents directories
        _directoriesToUpdate.clear();
    } else if (item._isDirectory) {
        // directory must not be saved to the db before we finished processing them.
        SyncJournalFileRecord record(item, _localPath + item._file);
        _directoriesToUpdate.push(record);
    } else if(item._instruction == CSYNC_INSTRUCTION_UPDATED) {
        SyncJournalFileRecord record(item, _localPath + item._file);
        _journal->setFileRecord(record);

        slotProgress((item._dir != SyncFileItem::Up) ? Progress::EndDownload : Progress::EndUpload,
                     item._file, item._size, item._size);
        _progressInfo.current_file_no++;
        _progressInfo.overall_current_bytes += item._size;

    }

    /* Start the transfer of the next file or abort if there is an error */

    if (item._status != SyncFileItem::FatalError) {
        startNextTransfer();
    } else {
        emit treeWalkResult(_syncedItems);
        emit csyncError(item._errorString);
        emit finished();
        csync_commit(_csync_ctx);
        _syncMutex.unlock();
        thread()->quit();
    }
}
Esempio n. 10
0
void CSyncThread::run()
{
    CSYNC *csync;

    WalkStats *wStats = new WalkStats;
    QTime walkTime;

    wStats->sourcePath = 0;
    wStats->errorType  = 0;
    wStats->eval       = 0;
    wStats->removed    = 0;
    wStats->renamed    = 0;
    wStats->newFiles   = 0;
    wStats->ignores    = 0;
    wStats->sync       = 0;
    wStats->seenFiles  = 0;
    wStats->conflicts  = 0;
    wStats->error      = 0;

    _mutex.lock();
    if( csync_create(&csync,
                          _source.toLocal8Bit().data(),
                          _target.toLocal8Bit().data()) < 0 ) {
        emit csyncError( tr("CSync create failed.") );
    }
    // FIXME: Check if we really need this stringcopy!
    wStats->sourcePath = qstrdup( _source.toLocal8Bit().constData() );
    _mutex.unlock();

    qDebug() << "## CSync Thread local only: " << _localCheckOnly;
    csync_set_auth_callback( csync, getauth );
    csync_enable_conflictcopys(csync);


    MirallConfigFile cfg;
    QString excludeList = cfg.excludeFile();

    if( !excludeList.isEmpty() ) {
        qDebug() << "==== added CSync exclude List: " << excludeList.toAscii();
        csync_add_exclude_list( csync, excludeList.toAscii() );
    }

    QTime t;
    t.start();

    _mutex.lock();
    if( _localCheckOnly ) {
        csync_set_local_only( csync, true );
    }
    _mutex.unlock();

    if( csync_init(csync) < 0 ) {
        CSYNC_ERROR_CODE err = csync_errno();
        QString errStr;

        switch( err ) {
        case CSYNC_ERR_LOCK:
            errStr = tr("CSync failed to create a lock file.");
            break;
        case CSYNC_ERR_STATEDB_LOAD:
            errStr = tr("CSync failed to load the state db.");
            break;
        case CSYNC_ERR_MODULE:
            errStr = tr("CSync failed to load the ownCloud module.");
            break;
        case CSYNC_ERR_TIMESKEW:
            errStr = tr("The system time between the local machine and the server differs "
                        "too much. Please use a time syncronization service (ntp) on both machines.");
            break;
        case CSYNC_ERR_FILESYSTEM:
            errStr = tr("CSync could not detect the filesystem type.");
            break;
        case CSYNC_ERR_TREE:
            errStr = tr("CSync got an error while processing internal trees.");
            break;
        default:
            errStr = tr("An internal error number %1 happend.").arg( (int) err );
        }
        qDebug() << " #### ERROR String emitted: " << errStr;
        emit csyncError(errStr);
        goto cleanup;
    }

    qDebug() << "############################################################### >>";
    if( csync_update(csync) < 0 ) {
        emit csyncError(tr("CSync Update failed."));
        goto cleanup;
    }
    qDebug() << "<<###############################################################";

    csync_set_userdata(csync, wStats);

    walkTime.start();
    if( csync_walk_local_tree(csync, &checkPermissions, 0) < 0 ) {
        qDebug() << "Error in treewalk.";
        if( wStats->errorType == WALK_ERROR_DIR_PERMS ) {
            emit csyncError(tr("The local filesystem has directories which are write protected.\n"
                               "That prevents ownCloud from successful syncing.\n"
                               "Please make sure that all directories are writeable."));
        } else if( wStats->errorType == WALK_ERROR_WALK ) {
            emit csyncError(tr("CSync encountered an error while examining the file system.\n"
                               "Syncing is not possible."));
        } else if( wStats->errorType == WALK_ERROR_INSTRUCTIONS ) {
            emit csyncError(tr("CSync update generated a strange instruction.\n"
                               "Please write a bug report."));
        }
        emit csyncError(tr("Local filesystem problems. Better disable Syncing and check."));
        goto cleanup;
    }
    qDebug() << " ..... Local walk finished: " << walkTime.elapsed();

    // emit the treewalk results. Do not touch the wStats after this.
    emit treeWalkResult(wStats);

    _mutex.lock();
    if( _localCheckOnly ) {
        _mutex.unlock();
        // we have to go out here as its local check only.
        goto cleanup;
    } else {
        _mutex.unlock();
        // check if we can write all over.

        if( csync_reconcile(csync) < 0 ) {
            emit csyncError(tr("CSync reconcile failed."));
            goto cleanup;
        }
        if( csync_propagate(csync) < 0 ) {
            emit csyncError(tr("CSync propagate failed."));
            goto cleanup;
        }
    }
cleanup:
    csync_destroy(csync);
    /*
     * Attention: do not delete the wStat memory here. it is deleted in the
     * slot catching the signel treeWalkResult because this thread can faster
     * die than the slot has read out the data.
     */
    qDebug() << "CSync run took " << t.elapsed() << " Milliseconds";
}