Add cancellation of well path collection loading.

This commit is contained in:
Kristian Bendiksen 2024-08-14 16:54:41 +02:00
parent 8d92908253
commit bf2a852b4d
12 changed files with 143 additions and 19 deletions

View File

@ -762,6 +762,9 @@ void RiaOsduConnector::requestParquetData( const QString& url, const QString& da
RiaLogging::info( "Requesting download of parquet from: " + url ); RiaLogging::info( "Requesting download of parquet from: " + url );
auto reply = makeDownloadRequest( url, dataPartitionId, token, RiaCloudDefines::contentTypeParquet() ); auto reply = makeDownloadRequest( url, dataPartitionId, token, RiaCloudDefines::contentTypeParquet() );
m_repliesMutex.lock();
m_replies[id] = reply;
m_repliesMutex.unlock();
connect( reply, connect( reply,
&QNetworkReply::finished, &QNetworkReply::finished,
@ -792,3 +795,19 @@ void RiaOsduConnector::parquetDownloadComplete( const QByteArray& contents, cons
m_parquetData[id] = contents; m_parquetData[id] = contents;
m_parquetErrors[id] = errorMessage; m_parquetErrors[id] = errorMessage;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RiaOsduConnector::cancelRequestForId( const QString& id )
{
QMutexLocker lock( &m_repliesMutex );
auto it = m_replies.find( id );
if ( it != m_replies.end() )
{
if ( !it->second.isNull() )
{
it->second->abort();
}
}
}

View File

@ -113,6 +113,8 @@ public:
QString wellIdForWellboreId( const QString& wellboreId ) const; QString wellIdForWellboreId( const QString& wellboreId ) const;
void cancelRequestForId( const QString& id );
void clearCachedData(); void clearCachedData();
QString dataPartition() const; QString dataPartition() const;
@ -173,6 +175,7 @@ private:
const QString m_dataPartitionId; const QString m_dataPartitionId;
mutable QMutex m_mutex; mutable QMutex m_mutex;
mutable QMutex m_repliesMutex;
std::vector<OsduField> m_fields; std::vector<OsduField> m_fields;
std::vector<OsduWell> m_wells; std::vector<OsduWell> m_wells;
std::map<QString, std::vector<OsduWellbore>> m_wellbores; std::map<QString, std::vector<OsduWellbore>> m_wellbores;
@ -180,4 +183,5 @@ private:
std::map<QString, std::vector<OsduWellLog>> m_wellLogs; std::map<QString, std::vector<OsduWellLog>> m_wellLogs;
std::map<QString, QByteArray> m_parquetData; std::map<QString, QByteArray> m_parquetData;
std::map<QString, QString> m_parquetErrors; std::map<QString, QString> m_parquetErrors;
std::map<QString, QPointer<QNetworkReply>> m_replies;
}; };

View File

@ -79,6 +79,20 @@ bool RimOsduWellPathDataLoader::isRunnable() const
return false; return false;
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RimOsduWellPathDataLoader::cancel()
{
RiaApplication* app = RiaApplication::instance();
RiaOsduConnector* osduConnector = app->makeOsduConnector();
for ( auto& [trajectoryId, taskId] : m_taskIds )
{
osduConnector->cancelRequestForId( trajectoryId );
}
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

View File

@ -38,6 +38,7 @@ public:
RimOsduWellPathDataLoader(); RimOsduWellPathDataLoader();
void loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) override; void loadData( caf::PdmObject& pdmObject, const QString& dataType, int taskId, caf::ProgressInfo& progressInfo ) override;
bool isRunnable() const override; bool isRunnable() const override;
void cancel() override;
private slots: private slots:
void parquetDownloadComplete( const QByteArray& contents, const QString& url, const QString& id ); void parquetDownloadComplete( const QByteArray& contents, const QString& url, const QString& id );

View File

@ -151,10 +151,6 @@ void RimWellPathCollection::fieldChangedByUi( const caf::PdmFieldHandle* changed
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void RimWellPathCollection::loadDataAndUpdate() void RimWellPathCollection::loadDataAndUpdate()
{ {
caf::ProgressInfo progress( 3, "Reading well paths from file" );
readWellPathFormationFiles();
auto hasOsduData = []( const std::vector<RimWellPath*>& wellPaths ) -> bool auto hasOsduData = []( const std::vector<RimWellPath*>& wellPaths ) -> bool
{ {
for ( RimWellPath* wellPath : wellPaths ) for ( RimWellPath* wellPath : wellPaths )
@ -168,6 +164,22 @@ void RimWellPathCollection::loadDataAndUpdate()
return false; return false;
}; };
auto countWellLogs = []( const std::vector<RimWellPath*>& wellPaths ) -> bool
{
size_t count = 0;
for ( RimWellPath* wellPath : wellPaths )
{
count += wellPath->wellLogs().size();
}
return count;
};
caf::ProgressInfo progress( allWellPaths().size() + countWellLogs( allWellPaths() ) + 2, "Reading well paths from file", false, true );
readWellPathFormationFiles();
progress.incrementProgress();
if ( hasOsduData( allWellPaths() ) ) if ( hasOsduData( allWellPaths() ) )
{ {
auto osduConnector = RiaApplication::instance()->makeOsduConnector(); auto osduConnector = RiaApplication::instance()->makeOsduConnector();
@ -185,7 +197,11 @@ void RimWellPathCollection::loadDataAndUpdate()
dataLoadController->loadData( *wellPath, wellPathGeometryKeyword, progress ); dataLoadController->loadData( *wellPath, wellPathGeometryKeyword, progress );
} }
dataLoadController->blockUntilDone( wellPathGeometryKeyword ); dataLoadController->blockUntilDone( wellPathGeometryKeyword );
progress.incrementProgress();
if ( progress.isCancelled() )
{
return;
}
progress.setProgressDescription( QString( "Reading well logs." ) ); progress.setProgressDescription( QString( "Reading well logs." ) );
for ( RimWellPath* wellPath : allWellPaths() ) for ( RimWellPath* wellPath : allWellPaths() )
@ -196,7 +212,6 @@ void RimWellPathCollection::loadDataAndUpdate()
} }
} }
dataLoadController->blockUntilDone( wellLogKeyword ); dataLoadController->blockUntilDone( wellLogKeyword );
progress.incrementProgress();
progress.setProgressDescription( QString( "Reading additional data." ) ); progress.setProgressDescription( QString( "Reading additional data." ) );
for ( RimWellPath* wellPath : allWellPaths() ) for ( RimWellPath* wellPath : allWellPaths() )
@ -692,15 +707,15 @@ void RimWellPathCollection::readWellPathFormationFiles()
{ {
caf::ProgressInfo progress( m_wellPaths.size(), "Reading well picks from file" ); caf::ProgressInfo progress( m_wellPaths.size(), "Reading well picks from file" );
for ( size_t wpIdx = 0; wpIdx < m_wellPaths.size(); wpIdx++ ) for ( const auto& wellPath : m_wellPaths )
{ {
QString errorMessage; QString errorMessage;
if ( !m_wellPaths[wpIdx]->readWellPathFormationsFile( &errorMessage, m_wellPathFormationsImporter.get() ) ) if ( !wellPath->readWellPathFormationsFile( &errorMessage, m_wellPathFormationsImporter.get() ) )
{ {
RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), "File open error", errorMessage ); RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), "File open error", errorMessage );
} }
progress.setProgressDescription( QString( "Reading formation file %1" ).arg( wpIdx ) ); progress.setProgressDescription( QString( "Reading formation file for %1" ).arg( wellPath->name() ) );
progress.incrementProgress(); progress.incrementProgress();
} }
} }

View File

@ -31,7 +31,9 @@ set(PROJECT_FILES
add_library(${PROJECT_NAME} ${PROJECT_FILES}) add_library(${PROJECT_NAME} ${PROJECT_FILES})
target_link_libraries(${PROJECT_NAME} cafProjectDataModel ${QT_LIBRARIES}) target_link_libraries(
${PROJECT_NAME} cafProjectDataModel cafUserInterface ${QT_LIBRARIES}
)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -39,6 +39,7 @@
#include "cafDataLoadTask.h" #include "cafDataLoadTask.h"
#include "cafDataLoader.h" #include "cafDataLoader.h"
#include "cafPdmObject.h" #include "cafPdmObject.h"
#include "cafProgressInfo.h"
#include <QApplication> #include <QApplication>
#include <QRunnable> #include <QRunnable>
@ -87,6 +88,7 @@ void DataLoadController::loadData( caf::PdmObject& object, const QString& dataTy
{ {
QMutexLocker locker( &m_mutex ); QMutexLocker locker( &m_mutex );
m_pendingTasksByType[dataType]++; m_pendingTasksByType[dataType]++;
m_progressInfos[dataType] = &progressInfo;
locker.unlock(); locker.unlock();
if ( it->second->isRunnable() ) if ( it->second->isRunnable() )
@ -117,6 +119,16 @@ void DataLoadController::blockUntilDone( const QString& dataType )
{ {
QMutexLocker locker( &m_mutex ); QMutexLocker locker( &m_mutex );
numPending = m_pendingTasksByType[dataType]; numPending = m_pendingTasksByType[dataType];
if ( m_progressInfos[dataType]->isCancelled() )
{
for ( auto& [key, loader] : m_dataLoaders )
{
if ( key.second == dataType )
{
loader->cancel();
}
}
}
} }
QApplication::processEvents(); QApplication::processEvents();
@ -131,4 +143,5 @@ void DataLoadController::onTaskFinished( const caf::SignalEmitter* emitter, QStr
{ {
QMutexLocker locker( &m_mutex ); QMutexLocker locker( &m_mutex );
m_pendingTasksByType[dataType]--; m_pendingTasksByType[dataType]--;
m_progressInfos[dataType]->incrementProgress();
} }

View File

@ -77,6 +77,7 @@ private:
std::map<std::pair<QString, QString>, std::unique_ptr<caf::DataLoader>> m_dataLoaders; std::map<std::pair<QString, QString>, std::unique_ptr<caf::DataLoader>> m_dataLoaders;
std::map<QString, int> m_pendingTasksByType; std::map<QString, int> m_pendingTasksByType;
std::map<QString, ProgressInfo*> m_progressInfos;
int m_taskId; int m_taskId;
QMutex m_mutex; QMutex m_mutex;

View File

@ -45,3 +45,10 @@ DataLoader::DataLoader()
: taskDone( this ) : taskDone( this )
{ {
} }
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void DataLoader::cancel()
{
}

View File

@ -59,6 +59,8 @@ public:
virtual bool isRunnable() const = 0; virtual bool isRunnable() const = 0;
virtual void cancel();
caf::Signal<QString, int> taskDone; caf::Signal<QString, int> taskDone;
}; };

View File

@ -47,6 +47,7 @@
#include <QApplication> #include <QApplication>
#include <QCoreApplication> #include <QCoreApplication>
#include <QObject>
#include <QPointer> #include <QPointer>
#include <QProgressDialog> #include <QProgressDialog>
#include <QThread> #include <QThread>
@ -71,6 +72,7 @@ ProgressTask::ProgressTask( ProgressInfo& parentTask )
: m_parentTask( parentTask ) : m_parentTask( parentTask )
{ {
} }
ProgressTask::~ProgressTask() ProgressTask::~ProgressTask()
{ {
m_parentTask.incrementProgress(); m_parentTask.incrementProgress();
@ -125,9 +127,11 @@ ProgressTask::~ProgressTask()
/// If you do not need a title for a particular level, simply pass "" and it will be ignored. /// If you do not need a title for a particular level, simply pass "" and it will be ignored.
/// \sa setProgressDescription /// \sa setProgressDescription
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
ProgressInfo::ProgressInfo( size_t maxProgressValue, const QString& title, bool delayShowingProgress ) ProgressInfo::ProgressInfo( size_t maxProgressValue, const QString& title, bool delayShowingProgress, bool allowCancel )
{ {
ProgressInfoStatic::start( maxProgressValue, title, delayShowingProgress ); m_isCancelled.store( false );
ProgressInfoStatic::start( *this, maxProgressValue, title, delayShowingProgress, allowCancel );
if ( dynamic_cast<QApplication*>( QCoreApplication::instance() ) ) if ( dynamic_cast<QApplication*>( QCoreApplication::instance() ) )
{ {
@ -195,6 +199,16 @@ void ProgressInfo::setNextProgressIncrement( size_t nextStepSize )
ProgressInfoStatic::setNextProgressIncrement( nextStepSize ); ProgressInfoStatic::setNextProgressIncrement( nextStepSize );
} }
void ProgressInfo::cancel()
{
m_isCancelled.store( true );
}
bool ProgressInfo::isCancelled() const
{
return m_isCancelled;
}
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -462,13 +476,18 @@ ProgressInfoBlocker::~ProgressInfoBlocker()
/// ///
//================================================================================================== //==================================================================================================
bool ProgressInfoStatic::s_disabled = false; bool ProgressInfoStatic::s_disabled = false;
bool ProgressInfoStatic::s_running = false; bool ProgressInfoStatic::s_running = false;
bool ProgressInfoStatic::s_isButtonConnected = false;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// ///
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
void ProgressInfoStatic::start( size_t maxProgressValue, const QString& title, bool delayShowingProgress ) void ProgressInfoStatic::start( ProgressInfo& progressInfo,
size_t maxProgressValue,
const QString& title,
bool delayShowingProgress,
bool allowCancel )
{ {
if ( !isUpdatePossible() ) return; if ( !isUpdatePossible() ) return;
@ -485,7 +504,20 @@ void ProgressInfoStatic::start( size_t maxProgressValue, const QString& title, b
{ {
dialog->setMinimum( 0 ); dialog->setMinimum( 0 );
dialog->setWindowTitle( title ); dialog->setWindowTitle( title );
dialog->setCancelButton( nullptr ); if ( allowCancel )
{
dialog->setCancelButtonText( "Cancel" );
if ( !s_isButtonConnected )
{
QObject::connect( dialog, &QProgressDialog::canceled, [&progressInfo]() { progressInfo.cancel(); } );
s_isButtonConnected = true;
}
}
else
{
dialog->setCancelButton( nullptr );
}
if ( delayShowingProgress ) if ( delayShowingProgress )
{ {
dialog->setMinimumDuration( 2000 ); dialog->setMinimumDuration( 2000 );
@ -548,7 +580,7 @@ void ProgressInfoStatic::setProgress( size_t progressValue )
if ( progressValue > maxProgressStack_v.back() ) if ( progressValue > maxProgressStack_v.back() )
{ {
reportError( "setProgress() is called with a progressValue > max, progressValue == " + reportError( "setProgress() is called with a progressValue > max, progressValue == " +
std::to_string( progressValue ) ); std::to_string( progressValue ) + " max == " + std::to_string( maxProgressStack_v.back() ) );
progressValue = maxProgressStack_v.back(); progressValue = maxProgressStack_v.back();
} }
@ -662,6 +694,8 @@ void ProgressInfoStatic::finished()
{ {
if ( dialog ) if ( dialog )
{ {
QObject::disconnect( dialog, &QProgressDialog::canceled, nullptr, nullptr );
dialog->reset(); dialog->reset();
dialog->close(); dialog->close();
s_running = false; s_running = false;

View File

@ -38,6 +38,8 @@
#include <cstddef> #include <cstddef>
#include <atomic>
class QString; class QString;
namespace caf namespace caf
@ -57,15 +59,20 @@ private:
class ProgressInfo class ProgressInfo
{ {
public: public:
ProgressInfo( size_t maxProgressValue, const QString& title, bool delayShowingProgress = true ); ProgressInfo( size_t maxProgressValue, const QString& title, bool delayShowingProgress = true, bool allowCancel = false );
~ProgressInfo(); ~ProgressInfo();
void setProgressDescription( const QString& description ); void setProgressDescription( const QString& description );
void setProgress( size_t progressValue ); void setProgress( size_t progressValue );
void incrementProgress(); void incrementProgress();
void setNextProgressIncrement( size_t nextStepSize ); void setNextProgressIncrement( size_t nextStepSize );
void cancel();
bool isCancelled() const;
ProgressTask task( const QString& description, int stepSize = 1 ); ProgressTask task( const QString& description, int stepSize = 1 );
private:
std::atomic<bool> m_isCancelled;
}; };
class ProgressInfoBlocker class ProgressInfoBlocker
@ -78,7 +85,11 @@ public:
class ProgressInfoStatic class ProgressInfoStatic
{ {
public: public:
static void start( size_t maxProgressValue, const QString& title, bool delayShowingProgress ); static void start( ProgressInfo& progressInfo,
size_t maxProgressValue,
const QString& title,
bool delayShowingProgress,
bool allowCance );
static void setProgressDescription( const QString& description ); static void setProgressDescription( const QString& description );
static void setProgress( size_t progressValue ); static void setProgress( size_t progressValue );
@ -95,6 +106,7 @@ private:
friend class ProgressInfoBlocker; friend class ProgressInfoBlocker;
static bool s_running; static bool s_running;
static bool s_disabled; static bool s_disabled;
static bool s_isButtonConnected;
}; };
} // namespace caf } // namespace caf