Ejemplo n.º 1
0
bool DiscoveryJob::checkSelectiveSyncNewFolder(const QString &path, RemotePermissions remotePerm)
{
    if (_syncOptions._confirmExternalStorage && !_syncOptions._newFilesAreVirtual
        && remotePerm.hasPermission(RemotePermissions::IsMounted)) {
        // external storage.

        /* Note: DiscoverySingleDirectoryJob::directoryListingIteratedSlot make sure that only the
         * root of a mounted storage has 'M', all sub entries have 'm' */

        // Only allow it if the white list contains exactly this path (not parents)
        // We want to ask confirmation for external storage even if the parents where selected
        if (_selectiveSyncWhiteList.contains(path + QLatin1Char('/'))) {
            return false;
        }

        emit newBigFolder(path, true);
        return true;
    }

    // If this path or the parent is in the white list, then we do not block this file
    if (findPathInList(_selectiveSyncWhiteList, path)) {
        return false;
    }

    auto limit = _syncOptions._newBigFolderSizeLimit;
    if (limit < 0 || _syncOptions._newFilesAreVirtual) {
        // no limit, everything is allowed;
        return false;
    }

    // Go in the main thread to do a PROPFIND to know the size of this folder
    qint64 result = -1;

    {
        QMutexLocker locker(&_vioMutex);
        emit doGetSizeSignal(path, &result);
        _vioWaitCondition.wait(&_vioMutex);
    }

    if (result >= limit) {
        // we tell the UI there is a new folder
        emit newBigFolder(path, false);
        return true;
    } else {
        // it is not too big, put it in the white list (so we will not do more query for the children)
        // and and do not block.
        auto p = path;
        if (!p.endsWith(QLatin1Char('/'))) {
            p += QLatin1Char('/');
        }
        _selectiveSyncWhiteList.insert(std::upper_bound(_selectiveSyncWhiteList.begin(),
                                           _selectiveSyncWhiteList.end(), p),
            p);

        return false;
    }
}
Ejemplo n.º 2
0
void SyncEngine::startSync()
{
    if (_journal->exists()) {
        QVector< SyncJournalDb::PollInfo > pollInfos = _journal->getPollInfos();
        if (!pollInfos.isEmpty()) {
            qDebug() << "Finish Poll jobs before starting a sync";
            CleanupPollsJob *job = new CleanupPollsJob(pollInfos, _account,
                                                       _journal, _localPath, this);
            connect(job, SIGNAL(finished()), this, SLOT(startSync()));
            connect(job, SIGNAL(aborted(QString)), this, SLOT(slotCleanPollsJobAborted(QString)));
            job->start();
            return;
        }
    }

    Q_ASSERT(!_syncRunning);
    _syncRunning = true;

    Q_ASSERT(_csync_ctx);

    if (!QDir(_localPath).exists()) {
        // No _tr, it should only occur in non-mirall
        emit csyncError("Unable to find local sync folder.");
        finalize(false);
        return;
    }

    // Check free size on disk first.
    const qint64 minFree = criticalFreeSpaceLimit();
    const qint64 freeBytes = Utility::freeDiskSpace(_localPath);
    if (freeBytes >= 0) {
        qDebug() << "There are" << freeBytes << "bytes available at" << _localPath
                 << "and at least" << minFree << "are required";
        if (freeBytes < minFree) {
            emit csyncError(tr("Only %1 are available, need at least %2 to start").arg(
                                Utility::octetsToString(freeBytes),
                                Utility::octetsToString(minFree)));
            finalize(false);
            return;
        }
    } else {
        qDebug() << "Could not determine free space available at" << _localPath;
    }

    _syncedItems.clear();
    _syncItemMap.clear();
    _needsUpdate = false;

    csync_resume(_csync_ctx);

    int fileRecordCount = -1;
    if (!_journal->exists()) {
        qDebug() << "=====sync looks new (no DB exists)";
    } else {
        qDebug() << "=====sync with existing DB";
    }

    qDebug() <<  "=====Using Qt" << qVersion();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    qDebug() <<  "=====Using SSL library version"
             <<  QSslSocket::sslLibraryVersionString().toUtf8().data();
#endif

    fileRecordCount = _journal->getFileRecordCount(); // this creates the DB if it does not exist yet

    if( fileRecordCount == -1 ) {
        qDebug() << "No way to create a sync journal!";
        emit csyncError(tr("Unable to initialize a sync journal."));
        finalize(false);
        return;
        // database creation error!
    }

    _csync_ctx->read_remote_from_db = true;

    // This tells csync to never read from the DB if it is empty
    // thereby speeding up the initial discovery significantly.
    _csync_ctx->db_is_empty = (fileRecordCount == 0);

    auto selectiveSyncBlackList = _journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList);
    bool usingSelectiveSync = (!selectiveSyncBlackList.isEmpty());
    qDebug() << (usingSelectiveSync ? "====Using Selective Sync" : "====NOT Using Selective Sync");

    csync_set_userdata(_csync_ctx, this);

    _stopWatch.start();

    qDebug() << "#### Discovery start #################################################### >>";

    _discoveryMainThread = new DiscoveryMainThread(account());
    _discoveryMainThread->setParent(this);
    connect(this, SIGNAL(finished(bool)), _discoveryMainThread, SLOT(deleteLater()));
    qDebug() << "=====Server" << account()->serverVersion()
             <<  QString("rootEtagChangesNotOnlySubFolderEtags=%1").arg(account()->rootEtagChangesNotOnlySubFolderEtags());
    if (account()->rootEtagChangesNotOnlySubFolderEtags()) {
        connect(_discoveryMainThread, SIGNAL(etag(QString)), this, SLOT(slotRootEtagReceived(QString)));
    } else {
        connect(_discoveryMainThread, SIGNAL(etagConcatenation(QString)), this, SLOT(slotRootEtagReceived(QString)));
    }

    DiscoveryJob *discoveryJob = new DiscoveryJob(_csync_ctx);
    discoveryJob->_selectiveSyncBlackList = selectiveSyncBlackList;
    discoveryJob->_selectiveSyncWhiteList =
        _journal->getSelectiveSyncList(SyncJournalDb::SelectiveSyncWhiteList);
    discoveryJob->_newBigFolderSizeLimit = _newBigFolderSizeLimit;
    discoveryJob->moveToThread(&_thread);
    connect(discoveryJob, SIGNAL(finished(int)), this, SLOT(slotDiscoveryJobFinished(int)));
    connect(discoveryJob, SIGNAL(folderDiscovered(bool,QString)),
            this, SIGNAL(folderDiscovered(bool,QString)));

    connect(discoveryJob, SIGNAL(newBigFolder(QString)),
            this, SIGNAL(newBigFolder(QString)));


    // This is used for the DiscoveryJob to be able to request the main thread/
    // to read in directory contents.
    qDebug() << Q_FUNC_INFO << _remotePath << _remoteUrl;
    _discoveryMainThread->setupHooks( discoveryJob, _remotePath);

    // Starts the update in a seperate thread
    QMetaObject::invokeMethod(discoveryJob, "start", Qt::QueuedConnection);
}
Ejemplo n.º 3
0
void Folder::startSync(const QStringList &pathList)
{
    Q_ASSERT(_accountState);

    Q_UNUSED(pathList)
    if (!_csync_ctx) {
        // no _csync_ctx yet,  initialize it.
        init();

        if (!_csync_ctx) {
            qDebug() << Q_FUNC_INFO << "init failed.";
            // the error should already be set
            QMetaObject::invokeMethod(this, "slotSyncFinished", Qt::QueuedConnection);
            return;
        }
    } else if (proxyDirty()) {
        setProxyDirty(false);
    }
    csync_set_log_level( Logger::instance()->isNoop() ? 0 : 11 );

    if (isBusy()) {
        qCritical() << "* ERROR csync is still running and new sync requested.";
        return;
    }
    _errors.clear();
    _csyncError = false;
    _csyncUnavail = false;

    _timeSinceLastSyncStart.restart();
    _syncResult.clearErrors();
    _syncResult.setStatus( SyncResult::SyncPrepare );
    _syncResult.setSyncFileItemVector(SyncFileItemVector());
    emit syncStateChange();

    qDebug() << "*** Start syncing " << alias() << " - client version"
             << qPrintable(Theme::instance()->version());

    if (! setIgnoredFiles())
    {
        slotSyncError(tr("Could not read system exclude file"));
        QMetaObject::invokeMethod(this, "slotSyncFinished", Qt::QueuedConnection);
        return;
    }

    // pass the setting if hidden files are to be ignored, will be read in csync_update
    _csync_ctx->ignore_hidden_files = _definition.ignoreHiddenFiles;

    _engine.reset(new SyncEngine( _accountState->account(), _csync_ctx, path(), remoteUrl().path(), remotePath(), &_journal));

    qRegisterMetaType<SyncFileItemVector>("SyncFileItemVector");
    qRegisterMetaType<SyncFileItem::Direction>("SyncFileItem::Direction");

    connect(_engine.data(), SIGNAL(rootEtag(QString)), this, SLOT(etagRetreivedFromSyncEngine(QString)));
    connect( _engine.data(), SIGNAL(treeWalkResult(const SyncFileItemVector&)),
              this, SLOT(slotThreadTreeWalkResult(const SyncFileItemVector&)), Qt::QueuedConnection);
    connect( _engine.data(), SIGNAL(aboutToPropagate(SyncFileItemVector&)),
              this, SLOT(slotAboutToPropagate(SyncFileItemVector&)));

    connect(_engine.data(), SIGNAL(started()),  SLOT(slotSyncStarted()), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(finished(bool)), SLOT(slotSyncFinished(bool)), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(csyncError(QString)), SLOT(slotSyncError(QString)), Qt::QueuedConnection);
    connect(_engine.data(), SIGNAL(csyncUnavailable()), SLOT(slotCsyncUnavailable()), Qt::QueuedConnection);

    //direct connection so the message box is blocking the sync.
    connect(_engine.data(), SIGNAL(aboutToRemoveAllFiles(SyncFileItem::Direction,bool*)),
                    SLOT(slotAboutToRemoveAllFiles(SyncFileItem::Direction,bool*)));
    connect(_engine.data(), SIGNAL(folderDiscovered(bool,QString)), this, SLOT(slotFolderDiscovered(bool,QString)));
    connect(_engine.data(), SIGNAL(transmissionProgress(ProgressInfo)), this, SLOT(slotTransmissionProgress(ProgressInfo)));
    connect(_engine.data(), SIGNAL(itemCompleted(const SyncFileItem &, const PropagatorJob &)),
            this, SLOT(slotItemCompleted(const SyncFileItem &, const PropagatorJob &)));
    connect(_engine.data(), SIGNAL(syncItemDiscovered(const SyncFileItem &)), this, SLOT(slotSyncItemDiscovered(const SyncFileItem &)));
    connect(_engine.data(), SIGNAL(newBigFolder(QString)), this, SLOT(slotNewBigFolderDiscovered(QString)));

    setDirtyNetworkLimits();

    ConfigFile cfgFile;
    auto newFolderLimit = cfgFile.newBigFolderSizeLimit();
    quint64 limit = newFolderLimit.first ? newFolderLimit.second * 1000 * 1000 : -1; // convert from MB to B
    _engine->setNewBigFolderSizeLimit(limit);

    QMetaObject::invokeMethod(_engine.data(), "startSync", Qt::QueuedConnection);

    // disable events until syncing is done
    // _watcher->setEventsEnabled(false);
    emit syncStarted();
}