Beispiel #1
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();
}
Beispiel #2
0
void QFileTrans::slotPresenceReceived(const QXmppPresence &presence)
{
    bool check;
    Q_UNUSED(check);

    // if we don't have a recipient, or if the presence is not from the recipient,
    // do nothing
    if (m_recipient.isEmpty() ||
        QXmppUtils::jidToBareJid(presence.from()) != m_recipient ||
        presence.type() != QXmppPresence::Available)
        return;

    // send the file and connect to the job's signals
    QXmppTransferJob *job = transferManager->sendFile(presence.from(), ":/example_3_transferHandling.cpp", "example source code");

    check = connect(job, SIGNAL(error(QXmppTransferJob::Error)),
                    this, SLOT(slotError(QXmppTransferJob::Error)));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(finished()),
                    this, SLOT(slotFinished()));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(progress(qint64,qint64)),
                    this, SLOT(slotProgress(qint64,qint64)));
    Q_ASSERT(check);
}
Beispiel #3
0
bool CSyncThread::checkBlacklisting( SyncFileItem *item )
{
    bool re = false;

    if( !_journal ) {
        qWarning() << "Journal is undefined!";
        return false;
    }

    SyncJournalBlacklistRecord entry = _journal->blacklistEntry(item->_file);
    item->_blacklistedInDb = false;

    // if there is a valid entry in the blacklist table and the retry count is
    // already null or smaller than 0, the file is blacklisted.
    if( entry.isValid() ) {
        item->_blacklistedInDb = true;

        if( entry._retryCount <= 0 ) {
            re = true;
        }

        // if the retryCount is 0, but the etag for downloads or the mtime for uploads
        // has changed, it is tried again
        // note that if the retryCount is -1 we never try again.
        if( entry._retryCount == 0 ) {
            if( item->_dir == SyncFileItem::Up ) { // check the modtime
                if(item->_modtime == 0 || entry._lastTryModtime == 0) {
                    re = false;
                } else {
                    if( item->_modtime != entry._lastTryModtime ) {
                        re = false;
                        qDebug() << item->_file << " is blacklisted, but has changed mtime!";
                    }
                }
            } else {
                // download, check the etag.
                if( item->_etag.isEmpty() || entry._lastTryEtag.isEmpty() ) {
                    qDebug() << item->_file << "one ETag is empty, no blacklisting";
                    return false;
                } else {
                    if( item->_etag != entry._lastTryEtag ) {
                        re = false;
                        qDebug() << item->_file << " is blacklisted, but has changed etag!";
                    }
                }
            }
        }

        if( re ) {
            qDebug() << "Item is on blacklist: " << entry._file << "retries:" << entry._retryCount;
            item->_instruction = CSYNC_INSTRUCTION_IGNORE;
            // FIXME: put the error string into an .arg(..) later
            item->_errorString = tr("The item is not synced because of previous errors:")
                    + QLatin1String(" ")+ entry._errorString;
            slotProgress( Progress::SoftError, *item );
        }
    }

    return re;
}
Beispiel #4
0
void xmppClient::slotPresenceReceived(const QXmppPresence &presence)
{
    const QLatin1String recipient("*****@*****.**");

    // if we are the recipient, or if the presence is not from the recipient,
    // do nothing
    if (jidToBareJid(configuration().jid()) == recipient ||
        jidToBareJid(presence.from()) != recipient ||
        presence.type() != QXmppPresence::Available)
        return;

    // send the file and connect to the job's signals
    QXmppTransferJob *job = transferManager->sendFile(presence.from(), "xmppClient.cpp");

    bool check = connect( job, SIGNAL(error(QXmppTransferJob::Error)),
             this, SLOT(slotError(QXmppTransferJob::Error)) );
    Q_ASSERT(check);

    check = connect( job, SIGNAL(finished()),
             this, SLOT(slotFinished()) );
    Q_ASSERT(check);

    check = connect( job, SIGNAL(progress(qint64,qint64)),
             this, SLOT(slotProgress(qint64,qint64)) );
    Q_ASSERT(check);
}
Beispiel #5
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();
}
Beispiel #6
0
BundlingWidget::BundlingWidget( Connections* cons, QWidget* parent ) :
        m_progress( 0 )
{

    m_cons = cons;
    connect( cons, SIGNAL( progress() ), this, SLOT( slotProgress() ), Qt::QueuedConnection );
    connect( cons, SIGNAL( finished() ), this, SLOT( slotFinished() ) );

    m_layout = new QVBoxLayout();

    QHBoxLayout* hLayout = new QHBoxLayout();
    m_startButton = new QPushButton( tr( "Bundle" ) );
    connect( m_startButton, SIGNAL( clicked() ), this, SLOT( start() ) );

    SliderWithEdit* cthr = new SliderWithEdit( QString( "compatibility threshold" ) );
    cthr->setMin( 0.01f );
    cthr->setMax( 1.0f );
    cthr->setValue( 0.8f );
    m_layout->addWidget( cthr );
    connect( cthr, SIGNAL( valueChanged( float, int) ), m_cons, SLOT( setCthr( float, int) ) );

    SliderWithEdit* bell = new SliderWithEdit( QString( "mean shift kernel radius" ) );
    bell->setMin( 0.01f );
    bell->setMax( 100.0f );
    bell->setValue( 5.0f );
    m_layout->addWidget( bell );
    connect( bell, SIGNAL( valueChanged( float, int) ), m_cons, SLOT( setBell( float, int) ) );

    SliderWithEditInt* smooth = new SliderWithEditInt( QString( "smoothing steps" ) );
    smooth->setMin( 1 );
    smooth->setMax( 10 );
    smooth->setValue( 3 );
    m_layout->addWidget( smooth );
    connect( smooth, SIGNAL( valueChanged( int, int) ), m_cons, SLOT( setSmooth( int, int) ) );

    int iterations = 10;//TODO: calculate number of iterations

    m_progressBar = new QProgressBar( this );
    m_progressBar->setValue( 0 );
    m_progressBar->setMaximum( iterations );
    m_progressBar->hide();

    m_layout->addWidget( m_progressBar );

    hLayout->addStretch();
    hLayout->addWidget( m_startButton );

    m_layout->addLayout( hLayout );

    m_layout->addStretch();
    setLayout( m_layout );
}
Beispiel #7
0
void IbbTransferTarget::slotFileReceived(QXmppTransferJob *job)
{
    qDebug() << "Got transfer request from:" << job->jid();

    bool check = connect(job, SIGNAL(error(QXmppTransferJob::Error)), this, SLOT(slotError(QXmppTransferJob::Error)));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(finished()), this, SLOT(slotFinished()));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(progress(qint64,qint64)), this, SLOT(slotProgress(qint64,qint64)));
    Q_ASSERT(check);

    m_buffer->open(QIODevice::WriteOnly);
    job->accept(m_buffer);
}
Beispiel #8
0
void xmppClient::slotFileReceived(QXmppTransferJob *job)
{
    qDebug() << "Got transfer request from:" << job->jid();

    bool check = connect(job, SIGNAL(error(QXmppTransferJob::Error)), this, SLOT(slotError(QXmppTransferJob::Error)));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(finished()), this, SLOT(slotFinished()));
    Q_ASSERT(check);

    check = connect(job, SIGNAL(progress(qint64,qint64)), this, SLOT(slotProgress(qint64,qint64)));
    Q_ASSERT(check);

    // allocate a buffer to receive the file
    QBuffer *buffer = new QBuffer(this);
    buffer->open(QIODevice::WriteOnly);
    job->accept(buffer);
}
Beispiel #9
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();
}
Beispiel #10
0
void SD::start()
{
    QAtomicInt currentId( 0 );
    int numThreads = GLFunctions::idealThreadCount;

    // create threads
    for ( int i = 0; i < numThreads; ++i )
    {
        SDThread* t = new SDThread( m_dataset, i );
        m_threads.push_back( t );
        connect( t, SIGNAL( progress() ), this, SLOT( slotProgress() ), Qt::QueuedConnection );
        connect( t, SIGNAL( finished() ), this, SLOT( slotThreadFinished() ), Qt::QueuedConnection );
    }

    // run threads
    for ( int i = 0; i < numThreads; ++i )
    {
        ++m_threadsRunning;
        m_threads[i]->start();
    }
}
Beispiel #11
0
/*
 * read from the stderr of the child
 * process
 */
void FileTransfer::slotRead() {
    QByteArray ar(4096);
    int len = read(m_comm[0], ar.data(), 4096 );
    for (int i = 0; i < len; i++ ) {
        // printf("%c", ar[i] );
    }
    ar.resize( len );
    QString str( ar );
    QStringList lis = QStringList::split(' ', str );
    /*
     * Transfer finished.. either complete or incomplete
     */
    if ( lis[0].simplifyWhiteSpace() == "Transfer" ) {
        return;
    }
    /*
     * do progress reading
     */
    slotProgress( lis );


}
Beispiel #12
0
bool SongDownloader::downloadFromQueue() {
    QUrl downloadUrl = m_downloadQueue.dequeue();
    //Extract the filename from the URL path
    QString filename = downloadUrl.path();
    QFileInfo fileInfo(filename);
    filename = fileInfo.fileName();

    m_pDownloadedFile = new QFile(filename + TEMP_EXTENSION);
    if (!m_pDownloadedFile->open(QIODevice::WriteOnly)) {
        //TODO: Error
        qDebug() << "Failed to open" << m_pDownloadedFile->fileName();
        return false;
    }

    qDebug() << "SongDownloader: setting up download stuff";
    m_pRequest = new QNetworkRequest(downloadUrl);

    //Set up user agent for great justice
    QString mixxxUA = QString("%1 %2").arg(QApplication::applicationName(),
                                           Version::version());
    // HTTP request headers must be latin1.
    QByteArray mixxxUABA = mixxxUA.toLatin1();
    m_pRequest->setRawHeader("User-Agent", mixxxUABA);
    m_pReply = m_pNetwork->get(*m_pRequest);

    connect(m_pReply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
    connect(m_pReply, SIGNAL(error(QNetworkReply::NetworkError)),
         this, SLOT(slotError(QNetworkReply::NetworkError)));
    connect(m_pReply, SIGNAL(downloadProgress(qint64, qint64)),
            this, SLOT(slotProgress(qint64, qint64)));
    connect(m_pReply, SIGNAL(downloadProgress(qint64, qint64)),
            this, SIGNAL(downloadProgress(qint64, qint64)));
    connect(m_pReply, SIGNAL(finished()),
            this, SLOT(slotDownloadFinished()));

    return true;
}
Beispiel #13
0
void CSyncThread::slotUpdateFinished(int updateResult)
{
    if (updateResult < 0 ) {
        handleSyncError(_csync_ctx, "csync_update");
        return;
    }
    qDebug() << "<<#### Update end #################################################### " << _syncTime.elapsed();

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

    slotProgress(Progress::StartSync, SyncFileItem(), 0, 0);

    _progressInfo = Progress::Info();

    _hasFiles = false;
    bool walkOk = true;
    _seenFiles.clear();

    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.";
    }

    // Adjust the paths for the renames.
    for (SyncFileItemVector::iterator it = _syncedItems.begin();
            it != _syncedItems.end(); ++it) {
        it->_file = adjustRenamedPath(it->_file);
    }

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

    if (_needsUpdate)
        emit(started());

    ne_session_s *session = 0;
    // that call to set property actually is a get which will return the session
    // FIXME add a csync_get_module_property to csync

    csync_set_module_property(_csync_ctx, "get_dav_session", &session);
    Q_ASSERT(session);

    _propagator.reset(new OwncloudPropagator (session, _localPath, _remoteUrl, _remotePath,
                                              _journal, &_thread));
    connect(_propagator.data(), SIGNAL(completed(SyncFileItem)),
            this, SLOT(transferCompleted(SyncFileItem)), Qt::QueuedConnection);
    connect(_propagator.data(), SIGNAL(progress(Progress::Kind,SyncFileItem,quint64,quint64)),
            this, SLOT(slotProgress(Progress::Kind,SyncFileItem,quint64,quint64)));
    connect(_propagator.data(), SIGNAL(progressChanged(qint64)), this, SLOT(slotProgressChanged(qint64)));
    connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()));

    setNetworkLimits();

    _propagator->start(_syncedItems);
}
Beispiel #14
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();
    }
}
Beispiel #15
0
void SyncEngine::slotUpdateFinished(int updateResult)
{
    if (updateResult < 0 ) {
        handleSyncError(_csync_ctx, "csync_update");
        return;
    }
    qDebug() << "<<#### Update end #################################################### " << _stopWatch.addLapTime(QLatin1String("Update Finished"));

    if( csync_reconcile(_csync_ctx) < 0 ) {
        handleSyncError(_csync_ctx, "csync_reconcile");
        return;
    }
    _stopWatch.addLapTime(QLatin1String("Reconcile Finished"));

    _progressInfo = Progress::Info();

    _hasFiles = false;
    bool walkOk = true;
    _seenFiles.clear();

    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.";
    }

    // Adjust the paths for the renames.
    for (SyncFileItemVector::iterator it = _syncedItems.begin();
            it != _syncedItems.end(); ++it) {
        it->_file = adjustRenamedPath(it->_file);
    }

    // Sanity check
    if (!_journal->isConnected()) {
        qDebug() << "Bailing out, DB failure";
        emit csyncError(tr("Cannot open the sync journal"));
        finalize();
        return;
    }

    // To announce the beginning of the sync
    emit aboutToPropagate(_syncedItems);
    emit transmissionProgress(_progressInfo);

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

    if (_needsUpdate)
        emit(started());

    ne_session_s *session = 0;
    // that call to set property actually is a get which will return the session
    csync_set_module_property(_csync_ctx, "get_dav_session", &session);
    Q_ASSERT(session);

    _propagator.reset(new OwncloudPropagator (session, _localPath, _remoteUrl, _remotePath,
                                              _journal, &_thread));
    connect(_propagator.data(), SIGNAL(completed(SyncFileItem)),
            this, SLOT(slotJobCompleted(SyncFileItem)));
    connect(_propagator.data(), SIGNAL(progress(SyncFileItem,quint64)),
            this, SLOT(slotProgress(SyncFileItem,quint64)));
    connect(_propagator.data(), SIGNAL(adjustTotalTransmissionSize(qint64)), this, SLOT(slotAdjustTotalTransmissionSize(qint64)));
    connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection);

    // apply the network limits to the propagator
    setNetworkLimits(_uploadLimit, _downloadLimit);

    _propagator->start(_syncedItems);
}
Beispiel #16
0
void SyncEngine::slotDiscoveryJobFinished(int discoveryResult)
{
    // To clean the progress info
    emit folderDiscovered(false, QString());

    if (discoveryResult < 0 ) {
        handleSyncError(_csync_ctx, "csync_update");
        return;
    }
    qDebug() << "<<#### Discovery end #################################################### " << _stopWatch.addLapTime(QLatin1String("Discovery Finished"));

    // Sanity check
    if (!_journal->isConnected()) {
        qDebug() << "Bailing out, DB failure";
        emit csyncError(tr("Cannot open the sync journal"));
        finalize();
        return;
    } else {
        // Commits a possibly existing (should not though) transaction and starts a new one for the propagate phase
        _journal->commitIfNeededAndStartNewTransaction("Post discovery");
    }

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

    _stopWatch.addLapTime(QLatin1String("Reconcile Finished"));

    _progressInfo = Progress::Info();

    _hasNoneFiles = false;
    _hasRemoveFile = false;
    bool walkOk = true;
    _seenFiles.clear();

    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.";
    }

    // The map was used for merging trees, convert it to a list:
    _syncedItems = _syncItemMap.values().toVector();

    // Adjust the paths for the renames.
    for (SyncFileItemVector::iterator it = _syncedItems.begin();
            it != _syncedItems.end(); ++it) {
        it->_file = adjustRenamedPath(it->_file);
    }

    // Sort items per destination
    std::sort(_syncedItems.begin(), _syncedItems.end());

    // make sure everything is allowed
    checkForPermission();

    // To announce the beginning of the sync
    emit aboutToPropagate(_syncedItems);
    _progressInfo._completedFileCount = ULLONG_MAX; // indicate the start with max
    emit transmissionProgress(_progressInfo);
    _progressInfo._completedFileCount = 0;

    if (!_hasNoneFiles && _hasRemoveFile) {
        qDebug() << Q_FUNC_INFO << "All the files are going to be changed, asking the user";
        bool cancel = false;
        emit aboutToRemoveAllFiles(_syncedItems.first()._direction, &cancel);
        if (cancel) {
            qDebug() << Q_FUNC_INFO << "Abort sync";
            finalize();
            return;
        }
    }

    if (_needsUpdate)
        emit(started());

    ne_session_s *session = 0;
    // that call to set property actually is a get which will return the session
    csync_set_module_property(_csync_ctx, "get_dav_session", &session);
    Q_ASSERT(session);

    // post update phase script: allow to tweak stuff by a custom script in debug mode.
    if( !qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT").isEmpty() ) {
#ifndef NDEBUG
        QString script = qgetenv("OWNCLOUD_POST_UPDATE_SCRIPT");

        qDebug() << "OOO => Post Update Script: " << script;
        QProcess::execute(script.toUtf8());
#else
    qDebug() << "**** Attention: POST_UPDATE_SCRIPT installed, but not executed because compiled with NDEBUG";
#endif
    }

    // do a database commit
    _journal->commit("post treewalk");

    _propagator.reset(new OwncloudPropagator (session, _localPath, _remoteUrl, _remotePath,
                                              _journal, &_thread));
    connect(_propagator.data(), SIGNAL(completed(SyncFileItem)),
            this, SLOT(slotJobCompleted(SyncFileItem)));
    connect(_propagator.data(), SIGNAL(progress(SyncFileItem,quint64)),
            this, SLOT(slotProgress(SyncFileItem,quint64)));
    connect(_propagator.data(), SIGNAL(adjustTotalTransmissionSize(qint64)), this, SLOT(slotAdjustTotalTransmissionSize(qint64)));
    connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()), Qt::QueuedConnection);

    // apply the network limits to the propagator
    setNetworkLimits(_uploadLimit, _downloadLimit);

    deleteStaleDownloadInfos();
    deleteStaleUploadInfos();
    deleteStaleBlacklistEntries();
    _journal->commit("post stale entry removal");

    _propagator->start(_syncedItems);
}
Beispiel #17
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();
    _syncedItems.clear();
    _needsUpdate = false;

    _abortRequestedMutex.lock();
    if (!_abortRequested.fetchAndAddRelease(0)) {
        csync_resume(_csync_ctx);
    }
    _abortRequestedMutex.unlock();


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

    if (!_journal->exists()) {
        qDebug() << "=====sync looks new (no DB exists), activating recursive PROPFIND if csync supports it";
        bool no_recursive_propfind = false;
        csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind);
    } else {
        // retrieve the file count from the db and close it afterwards because
        // csync_update also opens the database.
        int fileRecordCount = 0;
        fileRecordCount = _journal->getFileRecordCount();
        _journal->close();

        if( fileRecordCount == -1 ) {
            qDebug() << "No way to create a sync journal!";
            emit csyncError(tr("Unable to initialize a sync journal."));

            csync_commit(_csync_ctx);
            emit finished();
            _syncMutex.unlock();
            thread()->quit();

            return;
            // database creation error!
        } else if ( fileRecordCount < 50 ) {
            qDebug() << "=====sync DB has only" << fileRecordCount << "items, enable recursive PROPFIND if csync supports it";
            bool no_recursive_propfind = false;
            csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind);
        } else {
            qDebug() << "=====sync with existing DB";
        }
    }

    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.
    if (Account *account = AccountManager::instance()->account()) {
        account->credentials()->syncContextPreStart(_csync_ctx);
    } else {
        qDebug() << Q_FUNC_INFO << "No default Account object, huh?";
    }
    // 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 );
    csync_set_log_callback( csyncLogCatcher );
    csync_set_log_level( 11 );

    _syncTime.start();

    QElapsedTimer updateTime;
    updateTime.start();
    qDebug() << "#### Update start #################################################### >>";

    if( csync_update(_csync_ctx) < 0 ) {
        handleSyncError(_csync_ctx, "csync_update");
        return;
    }
    qDebug() << "<<#### Update end #################################################### " << updateTime.elapsed();

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

    slotProgress(Progress::StartSync, SyncFileItem(), 0, 0);

    _progressInfo = Progress::Info();

    _hasFiles = false;
    bool walkOk = true;
    _seenFiles.clear();

    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.";
    }

    // Adjust the paths for the renames.
    for (SyncFileItemVector::iterator it = _syncedItems.begin();
            it != _syncedItems.end(); ++it) {
        it->_file = adjustRenamedPath(it->_file);
    }

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

    if (_needsUpdate)
        emit(started());

    ne_session_s *session = 0;
    // that call to set property actually is a get which will return the session
    // FIXME add a csync_get_module_property to csync

    csync_set_module_property(_csync_ctx, "get_dav_session", &session);
    Q_ASSERT(session);

    _propagator.reset(new OwncloudPropagator (session, _localPath, _remotePath,
                                              _journal, &_abortRequested));
    connect(_propagator.data(), SIGNAL(completed(SyncFileItem)),
            this, SLOT(transferCompleted(SyncFileItem)), Qt::QueuedConnection);
    connect(_propagator.data(), SIGNAL(progress(Progress::Kind,SyncFileItem,quint64,quint64)),
            this, SLOT(slotProgress(Progress::Kind,SyncFileItem,quint64,quint64)));
    connect(_propagator.data(), SIGNAL(progressChanged(qint64)), this, SLOT(slotProgressChanged(qint64)));
    connect(_propagator.data(), SIGNAL(finished()), this, SLOT(slotFinished()));

    int downloadLimit = 0;
    if (cfg.useDownloadLimit()) {
        downloadLimit = cfg.downloadLimit() * 1000;
    }
    _propagator->_downloadLimit = downloadLimit;

    int uploadLimit = -75; // 75%
    int useUpLimit = cfg.useUploadLimit();
    if ( useUpLimit >= 1) {
        uploadLimit = cfg.uploadLimit() * 1000;
    } else if (useUpLimit == 0) {
        uploadLimit = 0;
    }
    _propagator->_uploadLimit = uploadLimit;

    _propagator->start(_syncedItems);
}
Beispiel #18
0
int CSyncThread::treewalkFile( TREE_WALK_FILE *file, bool remote )
{
    if( ! file ) return -1;
    SyncFileItem item;
    item._file = QString::fromUtf8( file->path );
    item._originalFile = item._file;
    item._instruction = file->instruction;
    item._dir = SyncFileItem::None;
    item._fileId = QString::fromUtf8(file->file_id);

    // record the seen files to be able to clean the journal later
    _seenFiles[item._file] = QString();

    switch(file->error_status) {
    case CSYNC_STATUS_OK:
        break;
    case CSYNC_STATUS_INDIVIDUAL_IS_SYMLINK:
        item._errorString = tr("Symbolic links are not supported in syncing.");
        break;
    case CSYNC_STATUS_INDIVIDUAL_IGNORE_LIST:
        item._errorString = tr("File is listed on the ignore list.");
        break;
    case CSYNC_STATUS_INDIVIDUAL_IS_INVALID_CHARS:
        item._errorString = tr("File contains invalid characters that can not be synced cross platform.");
        break;
    default:
        Q_ASSERT("Non handled error-status");
        /* No error string */
    }

    item._isDirectory = file->type == CSYNC_FTW_TYPE_DIR;
    item._modtime = file->modtime;
    item._etag = file->etag;
    item._size = file->size;
    item._should_update_etag = file->should_update_etag;
    switch( file->type ) {
    case CSYNC_FTW_TYPE_DIR:
        item._type = SyncFileItem::Directory;
        break;
    case CSYNC_FTW_TYPE_FILE:
        item._type = SyncFileItem::File;
        break;
    case CSYNC_FTW_TYPE_SLINK:
        item._type = SyncFileItem::SoftLink;
        break;
    default:
        item._type = SyncFileItem::UnknownType;
    }

    SyncFileItem::Direction dir;

    int re = 0;

    switch(file->instruction) {
    case CSYNC_INSTRUCTION_NONE:
        break;
    case CSYNC_INSTRUCTION_NEW:
    case CSYNC_INSTRUCTION_SYNC:
    case CSYNC_INSTRUCTION_CONFLICT:
    case CSYNC_INSTRUCTION_RENAME:
    case CSYNC_INSTRUCTION_REMOVE:
        _progressInfo.overall_file_count++;
        _progressInfo.overall_transmission_size += file->size;
        //fall trough
    default:
        _needsUpdate = true;
    }
    switch(file->instruction) {
    case CSYNC_INSTRUCTION_UPDATED:
        // We need to update the database.
        _journal->setFileRecord(SyncJournalFileRecord(item, _localPath + item._file));
        item._instruction = CSYNC_INSTRUCTION_NONE;
        // fall trough
    case CSYNC_INSTRUCTION_NONE:
        if (item._isDirectory && remote) {
            // Because we want still to update etags of directories
            dir = SyncFileItem::None;
        } else {
            // No need to do anything.
            _hasFiles = true;

            return re;
        }
        break;
    case CSYNC_INSTRUCTION_RENAME:
        dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
        item._renameTarget = QString::fromUtf8( file->rename_path );
        if (item._isDirectory)
            _renamedFolders.insert(item._file, item._renameTarget);
        break;
    case CSYNC_INSTRUCTION_REMOVE:
        dir = !remote ? SyncFileItem::Down : SyncFileItem::Up;
                break;
    case CSYNC_INSTRUCTION_CONFLICT:
    case CSYNC_INSTRUCTION_IGNORE:
    case CSYNC_INSTRUCTION_ERROR:
        //
        slotProgress(Progress::SoftError, item, 0, 0);
        dir = SyncFileItem::None;
        break;
    case CSYNC_INSTRUCTION_EVAL:
    case CSYNC_INSTRUCTION_NEW:
    case CSYNC_INSTRUCTION_SYNC:
    case CSYNC_INSTRUCTION_STAT_ERROR:
    case CSYNC_INSTRUCTION_DELETED:
    default:
        dir = remote ? SyncFileItem::Down : SyncFileItem::Up;
        break;
    }

    item._dir = dir;
    // check for blacklisting of this item.
    // if the item is on blacklist, the instruction was set to IGNORE
    checkBlacklisting( &item );

    if (file->instruction != CSYNC_INSTRUCTION_IGNORE
        && file->instruction != CSYNC_INSTRUCTION_REMOVE) {
      _hasFiles = true;
    }
    _syncedItems.append(item);

    return re;
}
QssEditor::QssEditor(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QssEditor),
    m_changed(false)
{
    ui->setupUi(this);

    // some default values
    QHash<QString, QVariant> defaultValues;

    defaultValues.insert(SETTING_PREVIEW_DELAY, 750);

    Settings::instance()->addDefaultValues(defaultValues);

    resetWindowTitle();

    // icons
    ui->toolOpen->setIcon(QIcon::fromTheme("document-open", QIcon(":/images/open.png")));
    ui->toolSave->setIcon(QIcon::fromTheme("document-save", QIcon(":/images/save.png")));
    ui->toolSaveAs->setIcon(QIcon::fromTheme("document-save-as", QIcon(":/images/saveas.png")));
    ui->toolClose->setIcon(QIcon::fromTheme("window-close", QIcon(":/images/close.png")));
    ui->toolUndo->setIcon(QIcon::fromTheme("edit-undo", QIcon(":/images/undo.png")));
    ui->toolRedo->setIcon(QIcon::fromTheme("edit-redo", QIcon(":/images/redo.png")));
    ui->toolOptions->setIcon(QIcon::fromTheme("preferences-system", QIcon(":/images/options.png")));

    // application shortcuts
    new QShortcut(QKeySequence::Quit, this, SLOT(slotQuit()));
    new QShortcut(QKeySequence::Find, this, SLOT(slotFind()));
    new QShortcut(QKeySequence::FindNext, this, SLOT(slotFindNext()));
    new QShortcut(QKeySequence::HelpContents, this, SLOT(slotAbout()));

    // shortcuts
    ui->toolOpen->setShortcut(QKeySequence::Open);
    ui->toolSave->setShortcut(QKeySequence::Save);
    ui->toolSaveAs->setShortcut(QKeySequence::SaveAs);
    ui->toolClose->setShortcut(QKeySequence::Close);

    // built-in Qt icon
    ui->toolAboutQt->setIcon(QIcon(
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    ":/qt-project.org/qmessagebox/images/qtlogo-64.png"
#else
    ":/trolltech/qmessagebox/images/qtlogo-64.png"
#endif
                                 ));

    // menu for toolbutton
    QMenu *toolButtonMenu = new QMenu(this);
    toolButtonMenu->addAction("Item1");
    toolButtonMenu->addSeparator();
    toolButtonMenu->addAction("Item2");
    ui->toolButton->setMenu(toolButtonMenu);

    m_timerDelayedApply = new QTimer(this);
    m_timerDelayedApply->setSingleShot(true);
    connect(m_timerDelayedApply, SIGNAL(timeout()), this, SLOT(slotApplyCss()));
    resetPreviewDelay();

    QTimer *timerProgress = new QTimer(this);
    timerProgress->setInterval(500);
    connect(timerProgress, SIGNAL(timeout()), this, SLOT(slotProgress()));
    timerProgress->start();

    ui->splitter->setCollapsible(0, false);
    ui->splitter->setStretchFactor(0, 1);

    // splitter size
    QList<int> list = QList<int>() << width()/2 << width()/2;
    ui->splitter->setSizes(list);

    // some MDI windows
    QMdiSubWindow *mdi = ui->mdiArea->addSubWindow(new QLabel("MDI", ui->mdiArea));
    mdi->resize(160, 80);

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    ui->tree->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
#else
    ui->tree->header()->setResizeMode(QHeaderView::ResizeToContents);
    ui->table->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
#endif

    ui->tree->topLevelItem(0)->setExpanded(true);

    ui->text->setCaretLineVisible(true);
    ui->text->setCaretLineBackgroundColor(QColor("gainsboro"));

    ui->text->setAutoIndent(true);
    ui->text->setIndentationGuides(false);
    ui->text->setIndentationsUseTabs(true);
    ui->text->setIndentationWidth(4);

    ui->text->setMarginsBackgroundColor(QColor("gainsboro"));
    ui->text->setMarginLineNumbers(1, true);
    ui->text->setMarginWidth(1, 50);

    ui->text->setAutoCompletionSource(QsciScintilla::AcsAll);
    ui->text->setAutoCompletionReplaceWord(true);
    ui->text->setAutoCompletionCaseSensitivity(false);
    ui->text->setAutoCompletionUseSingle(QsciScintilla::AcusAlways);
    ui->text->setAutoCompletionThreshold(0);

    ui->text->setBraceMatching(QsciScintilla::SloppyBraceMatch);
    ui->text->setMatchedBraceBackgroundColor(Qt::yellow);
    ui->text->setUnmatchedBraceForegroundColor(Qt::blue);

    // QSS lexer
    QsciLexerQSS *lexQss = new QsciLexerQSS(this);
    ui->text->setLexer(lexQss);

    ui->text->setFocus();
    ui->text->installEventFilter(this);

    restoreLastFiles();

    QTimer::singleShot(0, this, SLOT(slotDelayedOpen()));
}