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(); } csync_set_module_property(_csync_ctx, "bandwidth_limit_download", &downloadLimit); int uploadLimit = -75; // 75% int useUpLimit = cfg.useUploadLimit(); if ( useUpLimit >= 1) { uploadLimit = cfg.uploadLimit(); } 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); 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 += "; "; }
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"; }
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); }
void SyncEngine::startSync() { Q_ASSERT(!_syncRunning); _syncRunning = true; if( ! _csync_ctx ) { qDebug() << "XXXXXXXXXXXXXXXX FAIL: do not have csync_ctx!"; } _syncedItems.clear(); _needsUpdate = false; csync_resume(_csync_ctx); 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(); bool isUpdateFrom_1_5 = _journal->isUpdateFrom_1_5(); _journal->close(); if( fileRecordCount == -1 ) { qDebug() << "No way to create a sync journal!"; emit csyncError(tr("Unable to initialize a sync journal.")); finalize(); 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"; } if (fileRecordCount > 1 && isUpdateFrom_1_5) { qDebug() << "detected update from 1.5"; // Disable the read from DB to be sure to re-read all the fileid and etags. csync_set_read_from_db(_csync_ctx, false); } } 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 ); don't set the loglevel here, it shall be done by folder.cpp or owncloudcmd.cpp int timeout = OwncloudPropagator::httpTimeout(); csync_set_module_property(_csync_ctx, "timeout", &timeout); _stopWatch.start(); qDebug() << "#### Update start #################################################### >>"; UpdateJob *job = new UpdateJob(_csync_ctx); job->moveToThread(&_thread); connect(job, SIGNAL(finished(int)), this, SLOT(slotUpdateFinished(int))); QMetaObject::invokeMethod(job, "start", Qt::QueuedConnection); }
void SyncEngine::startSync() { Q_ASSERT(!_syncRunning); _syncRunning = true; Q_ASSERT(_csync_ctx); _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"; } fileRecordCount = _journal->getFileRecordCount(); // this creates the DB if it does not exist yet bool isUpdateFrom_1_5 = _journal->isUpdateFrom_1_5(); if( fileRecordCount == -1 ) { qDebug() << "No way to create a sync journal!"; emit csyncError(tr("Unable to initialize a sync journal.")); finalize(); return; // database creation error! } if (fileRecordCount >= 1 && isUpdateFrom_1_5) { qDebug() << "detected update from 1.5" << fileRecordCount << isUpdateFrom_1_5; // Disable the read from DB to be sure to re-read all the fileid and etags. csync_set_read_from_db(_csync_ctx, false); } else { csync_set_read_from_db(_csync_ctx, true); } bool usingSelectiveSync = (!_selectiveSyncBlackList.isEmpty()); qDebug() << (usingSelectiveSync ? "====Using Selective Sync" : "====NOT Using Selective Sync"); if (fileRecordCount >= 0 && fileRecordCount < 50 && !usingSelectiveSync) { qDebug() << "===== Activating recursive PROPFIND (currently" << fileRecordCount << "file records)"; bool no_recursive_propfind = false; csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind); } else { bool no_recursive_propfind = true; csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind); } 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_level( 11 ); don't set the loglevel here, it shall be done by folder.cpp or owncloudcmd.cpp int timeout = OwncloudPropagator::httpTimeout(); csync_set_module_property(_csync_ctx, "timeout", &timeout); _stopWatch.start(); qDebug() << "#### Discovery start #################################################### >>"; DiscoveryJob *job = new DiscoveryJob(_csync_ctx); job->_selectiveSyncBlackList = _selectiveSyncBlackList; job->moveToThread(&_thread); connect(job, SIGNAL(finished(int)), this, SLOT(slotDiscoveryJobFinished(int))); connect(job, SIGNAL(folderDiscovered(bool,QString)), this, SIGNAL(folderDiscovered(bool,QString))); QMetaObject::invokeMethod(job, "start", Qt::QueuedConnection); }
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 directory."); finalize(); return; } _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(); 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"); if (fileRecordCount >= 0 && fileRecordCount < 50 && !usingSelectiveSync) { qDebug() << "===== Activating recursive PROPFIND (currently" << fileRecordCount << "file records)"; bool no_recursive_propfind = false; csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind); } else { bool no_recursive_propfind = true; csync_set_module_property(_csync_ctx, "no_recursive_propfind", &no_recursive_propfind); } csync_set_userdata(_csync_ctx, this); _account->credentials()->syncContextPreStart(_csync_ctx); // csync_set_auth_callback( _csync_ctx, getauth ); //csync_set_log_level( 11 ); don't set the loglevel here, it shall be done by folder.cpp or owncloudcmd.cpp int timeout = OwncloudPropagator::httpTimeout(); csync_set_module_property(_csync_ctx, "timeout", &timeout); _stopWatch.start(); qDebug() << "#### Discovery start #################################################### >>"; _discoveryMainThread = new DiscoveryMainThread(account()); _discoveryMainThread->setParent(this); connect(this, SIGNAL(finished()), _discoveryMainThread, SLOT(deleteLater())); 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->_newSharedFolderSizeLimit = _newSharedFolderSizeLimit; 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(newSharedFolder(QString)), this, SIGNAL(newSharedFolder(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); }
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; csync_resume(_csync_ctx); 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 ); don't set the loglevel here, it shall be done by folder.cpp or owncloudcmd.cpp _syncTime.start(); // Only used for the updater progress as we use the new propagator right now which does its own thing csync_set_progress_callback(_csync_ctx, csyncthread_updater_progress_callback); qDebug() << "#### Update start #################################################### >>"; UpdateJob *job = new UpdateJob(_csync_ctx); job->moveToThread(&_thread); connect(job, SIGNAL(finished(int)), this, SLOT(slotUpdateFinished(int))); QMetaObject::invokeMethod(job, "start", Qt::QueuedConnection); }
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); }
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"; }
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"; }
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"; }