///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2026 Equinor ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimBatchQueue.h" #include "RiaPreferencesBatch.h" #include "RiaPreferencesOpm.h" #include "RiaWslTools.h" #include "ProcessControl/RimProcess.h" #include "RimBatchQueueLocal.h" #include "RimBatchQueueLsf.h" #include "RimBatchQueueSlurm.h" #include #include CAF_PDM_ABSTRACT_SOURCE_INIT( RimBatchQueue, "BatchQueue" ); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimBatchQueue::RimBatchQueue( RiaDefines::BatchSchedulerType schedulerType ) : m_schedulerType( schedulerType ) { } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RimBatchQueue* RimBatchQueue::createBatchQueue() { switch ( RiaPreferencesBatch::current()->batchScheduler() ) { case RiaDefines::BatchSchedulerType::LSF: return new RimBatchQueueLsf(); case RiaDefines::BatchSchedulerType::SLURM: return new RimBatchQueueSlurm(); default: case RiaDefines::BatchSchedulerType::LOCAL_COMPUTER: break; } return new RimBatchQueueLocal(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::pair, QString> RimBatchQueue::runCommand( QStringList command, std::shared_ptr monitor ) { QStringList cmdList; if ( RiaPreferencesOpm::current()->useWsl() ) { cmdList.append( RiaWslTools::wslCommand() ); cmdList.append( RiaPreferencesOpm::current()->wslArguments() ); } cmdList.append( command ); auto proc = std::make_unique( true, monitor ); QString cmd = cmdList.takeFirst(); proc->setCommand( cmd ); if ( !cmdList.isEmpty() ) proc->addParameters( cmdList ); if ( proc->start() ) { return { std::move( proc ), QString() }; } return { nullptr, QString( "Failed to run command." ) }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::pair RimBatchQueue::buildLaunchScript( QString workDir ) { // write launch script to the working directory QString filename = workDir + "/launch_job.sh"; QFile file( filename ); if ( !file.open( QIODevice::WriteOnly ) ) { return { false, QString( "Failed to create launch script file %1." ).arg( filename ) }; } // build launch script QTextStream out( &file ); out << "#!/bin/sh\n"; auto additionalOptions = RiaPreferencesBatch::current()->batchSchedulerOptions(); if ( !additionalOptions.isEmpty() ) { out << launchScriptDirective() << " " << additionalOptions << "\n\n"; } if ( m_process != nullptr ) { QString cmdLine = m_process->command(); for ( auto& p : m_process->parameters() ) { cmdLine += " " + p; } out << cmdLine << "\n"; } out << "\n"; file.setPermissions( file.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeUser ); file.close(); return { true, filename }; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- QString RimBatchQueue::generateJobName() { if ( m_process == nullptr ) return "ResInsight_Job"; QString candidate = m_process->description(); candidate.replace( " ", "" ); candidate = candidate.left( 10 ); candidate = "RI_" + candidate; return candidate; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimBatchQueue::readStdOutErrIntoProcessLog() { if ( !m_stdOutFileName.isEmpty() ) { QFile file( m_stdOutFileName ); if ( file.open( QIODevice::ReadOnly ) ) { QTextStream in( &file ); while ( !in.atEnd() ) { m_process->appendStdOut( in.readLine() ); } file.close(); } } if ( !m_stdErrFileName.isEmpty() ) { QFile file( m_stdErrFileName ); if ( file.open( QIODevice::ReadOnly ) ) { QTextStream in( &file ); while ( !in.atEnd() ) { m_process->appendStdErr( in.readLine() ); } file.close(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RiaDefines::BatchSchedulerType RimBatchQueue::schedulerType() const { return m_schedulerType; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimBatchQueue::cleanUpOldLogFiles() { if ( !m_stdOutFileName.isEmpty() && QFile::exists( m_stdOutFileName ) ) { QFile::remove( m_stdOutFileName ); } if ( !m_stdErrFileName.isEmpty() && QFile::exists( m_stdErrFileName ) ) { QFile::remove( m_stdErrFileName ); } }