diff --git a/scheduler/SchedulerTest.cpp b/scheduler/SchedulerTest.cpp index d0f0833f28ca60ff4e0506d9df6471711d6f969a..53dd60d587307401068215fe455aa7bc51c0c530 100644 --- a/scheduler/SchedulerTest.cpp +++ b/scheduler/SchedulerTest.cpp @@ -2069,14 +2069,14 @@ TEST_P(SchedulerTest, expandRepackRequest) { rrp.startThreads(); for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_EQ(rrp.allThreadsDone(),true); @@ -2352,18 +2352,18 @@ TEST_P(SchedulerTest, expandRepackRequestRetrieveFailed) { auto it = executedJobs.begin(); it++; while(it != executedJobs.end()){ - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); it++; } std::unique_ptr<cta::RetrieveJob> failedJobUniqPtr = std::move(*(executedJobs.begin())); - rrp.reportFailedJob(std::move(failedJobUniqPtr),cta::exception::Exception("FailedJob expandRepackRequestFailedRetrieve")); + rrp.reportFailedJob(std::move(failedJobUniqPtr),cta::exception::Exception("FailedJob expandRepackRequestFailedRetrieve"), lc); rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_EQ(rrp.allThreadsDone(),true); @@ -2390,14 +2390,14 @@ TEST_P(SchedulerTest, expandRepackRequestRetrieveFailed) { rrp.startThreads(); - rrp.reportFailedJob(std::move(retrieveJob),cta::exception::Exception("FailedJob for unit test expandRepackRequestFailedRetrieve")); + rrp.reportFailedJob(std::move(retrieveJob),cta::exception::Exception("FailedJob for unit test expandRepackRequestFailedRetrieve"), lc); rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_EQ(rrp.allThreadsDone(),true); } @@ -2596,15 +2596,15 @@ TEST_P(SchedulerTest, expandRepackRequestArchiveSuccess) { //Report all jobs as succeeded for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_TRUE(rrp.allThreadsDone()); @@ -2847,15 +2847,15 @@ TEST_P(SchedulerTest, expandRepackRequestArchiveFailed) { //Report all jobs as succeeded for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_TRUE(rrp.allThreadsDone()); @@ -3915,15 +3915,15 @@ TEST_P(SchedulerTest, expandRepackRequestAddCopiesOnly) { //Report all jobs as succeeded for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_TRUE(rrp.allThreadsDone()); @@ -4351,15 +4351,15 @@ TEST_P(SchedulerTest, expandRepackRequestMoveAndAddCopies){ //Report all jobs as succeeded for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); ASSERT_TRUE(rrp.allThreadsDone()); @@ -4634,15 +4634,15 @@ TEST_P(SchedulerTest, cancelRepackRequest) { //Report all jobs as succeeded for(auto it = executedJobs.begin(); it != executedJobs.end(); ++it) { - rrp.reportCompletedJob(std::move(*it)); + rrp.reportCompletedJob(std::move(*it), lc); } rrp.setDiskDone(); rrp.setTapeDone(); - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); rrp.waitThread(); } { diff --git a/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp b/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp index 5832e2f3b3dcc81e52a6b5955ffbe4b71cd0f1ca..a2fdb81120ccc30bc5f459df7ed31274aa1546b6 100644 --- a/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp +++ b/tapeserver/castor/tape/tapeserver/SCSI/Constants.cpp @@ -1186,7 +1186,7 @@ const castor::tape::SCSI::senseConstants::error_info castor::tape::SCSI::senseCo {0x7471, "Logical unit access not authorized"}, {0x7479, "Security conflict in translated device"}, - {0, NULL} + {0, nullptr} }; const castor::tape::SCSI::senseConstants::error_range_info castor::tape::SCSI::senseConstants::ascRangesStrings[] = @@ -1197,7 +1197,7 @@ const castor::tape::SCSI::senseConstants::error_range_info castor::tape::SCSI::s {0x42, 0x00, 0xff, "Power-on or self-test failure (%02x)"}, {0x4D, 0x00, 0xff, "Tagged overlapped commands (task tag %02x)"}, {0x70, 0x00, 0xff, "Decompression exception short algorithm id of %02x"}, - {0, 0, 0, NULL} + {0, 0, 0, nullptr} }; /* description of the sense key values */ diff --git a/tapeserver/castor/tape/tapeserver/daemon/CleanerSession.cpp b/tapeserver/castor/tape/tapeserver/daemon/CleanerSession.cpp index 874acdc7092b83a313d940b484ad60cc7f5c784f..8f6e498d560e5e39e3dc6b03db7208601d067f62 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/CleanerSession.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/CleanerSession.cpp @@ -263,7 +263,7 @@ std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(drive::createDrive(driveInfo, m_sysWrapper)); - if(NULL == drive.get()) { + if(nullptr == drive.get()) { cta::exception::Exception ex; ex.getMessage() << "Failed to instantiate drive object"; throw ex; diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp index 12fbef8b1d655c86baf46f4d28892c34305f1ff5..92ac4e903fe3d83cbc087c4221c8f8c402e4d002 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.cpp @@ -27,13 +27,13 @@ #include "castor/tape/tapeserver/daemon/RecallTaskInjector.hpp" #include "castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp" #include "castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp" -#include "castor/tape/tapeserver/daemon/TapeServerReporter.hpp" #include "castor/tape/tapeserver/daemon/VolumeInfo.hpp" #include "castor/tape/tapeserver/drive/DriveInterface.hpp" #include "castor/tape/tapeserver/SCSI/Device.hpp" #include "common/exception/Exception.hpp" #include "scheduler/RetrieveMount.hpp" #include "castor/tape/tapeserver/RAO/RAOParams.hpp" +#include "TapeServerReporter.hpp" #include <google/protobuf/stubs/common.h> #include <memory> @@ -42,26 +42,22 @@ //------------------------------------------------------------------------------ //Constructor //------------------------------------------------------------------------------ -castor::tape::tapeserver::daemon::DataTransferSession::DataTransferSession( - const std::string & hostname, - cta::log::Logger & log, - System::virtualWrapper & sysWrapper, - const cta::tape::daemon::TpconfigLine & driveConfig, - cta::mediachanger::MediaChangerFacade & mc, - cta::tape::daemon::TapedProxy & initialProcess, - cta::server::ProcessCap & capUtils, - const DataTransferConfig & castorConf, - cta::Scheduler & scheduler): - m_log(log), - m_sysWrapper(sysWrapper), - m_driveConfig(driveConfig), - m_castorConf(castorConf), - m_driveInfo({driveConfig.unitName, cta::utils::getShortHostname(), driveConfig.logicalLibrary}), - m_mc(mc), - m_intialProcess(initialProcess), - m_capUtils(capUtils), - m_scheduler(scheduler) - { +castor::tape::tapeserver::daemon::DataTransferSession::DataTransferSession(const std::string& hostname, cta::log::Logger& log, + System::virtualWrapper& sysWrapper, + const cta::tape::daemon::TpconfigLine& driveConfig, + cta::mediachanger::MediaChangerFacade& mc, + cta::tape::daemon::TapedProxy& initialProcess, + cta::server::ProcessCap& capUtils, const DataTransferConfig& castorConf, + cta::Scheduler& scheduler) : + m_log(log), + m_sysWrapper(sysWrapper), + m_driveConfig(driveConfig), + m_castorConf(castorConf), + m_driveInfo({driveConfig.unitName, cta::utils::getShortHostname(), driveConfig.logicalLibrary}), + m_mediaChanger(mc), + m_initialProcess(initialProcess), + m_capUtils(capUtils), + m_scheduler(scheduler) { } //------------------------------------------------------------------------------ @@ -72,16 +68,16 @@ castor::tape::tapeserver::daemon::DataTransferSession::DataTransferSession( * for by tape thread to access /dev/nst */ void castor::tape::tapeserver::daemon::DataTransferSession::setProcessCapabilities( - const std::string &capabilities){ + const std::string& capabilities) { cta::log::LogContext lc(m_log); try { m_capUtils.setProcText(capabilities); cta::log::LogContext::ScopedParam sp(lc, - cta::log::Param("capabilities", m_capUtils.getProcText())); + cta::log::Param("capabilities", m_capUtils.getProcText())); lc.log(cta::log::INFO, "Set process capabilities for using tape"); - } catch(const cta::exception::Exception &ne) { + } catch (const cta::exception::Exception& ne) { lc.log(cta::log::ERR, - "Failed to set process capabilities for using the tape "); + "Failed to set process capabilities for using the tape "); } } @@ -97,7 +93,7 @@ void castor::tape::tapeserver::daemon::DataTransferSession::setProcessCapabiliti * Then branch to the right execution */ castor::tape::tapeserver::daemon::Session::EndOfSessionAction - castor::tape::tapeserver::daemon::DataTransferSession::execute() { +castor::tape::tapeserver::daemon::DataTransferSession::execute() { // 1) Prepare the logging environment cta::log::LogContext lc(m_log); // Create a sticky thread name, which will be overridden by the other threads @@ -106,24 +102,28 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction setProcessCapabilities("cap_sys_rawio+ep"); + TapeServerReporter tapeServerReporter(m_initialProcess, m_driveConfig, m_hostname, m_volInfo, lc); + // 2a) Determine if we want to mount at all (for now) - // This variable will allow us to see if we switched from down to up and start a + // This variable will allow us to see if we switched from down to up and start an // empty drive probe session if so. bool downUpTransition = false; -schedule: + schedule: while (true) { try { auto desiredState = m_scheduler.getDesiredDriveState(m_driveConfig.unitName, lc); if (!desiredState.up) { - downUpTransition = true; + downUpTransition = true; // We wait a bit before polling the scheduler again. // TODO: parametrize the duration? - m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, lc); - sleep (5); - } else { + m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, + lc); + sleep(5); + } + else { break; } - } catch (cta::Scheduler::NoSuchDrive & e) { + } catch (cta::Scheduler::NoSuchDrive& e) { // The object store does not even know about this drive. We will report our state // (default status is down). m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, lc); @@ -133,7 +133,8 @@ schedule: // down to up. In such a case, we will run an empty if (downUpTransition) { downUpTransition = false; - m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Probing, lc); + m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Probing, + lc); castor::tape::tapeserver::daemon::EmptyDriveProbe emptyDriveProbe(m_log, m_driveConfig, m_sysWrapper); lc.log(cta::log::INFO, "Transition from down to up detected. Will check if a tape is in the drive."); if (!emptyDriveProbe.driveIsEmpty()) { @@ -144,14 +145,15 @@ schedule: driveState.forceDown = false; std::string errorMsg = "A tape was detected in the drive. Putting the drive down."; cta::optional<std::string> probeErrorMsg = emptyDriveProbe.getProbeErrorMsg(); - if(probeErrorMsg) + if (probeErrorMsg) errorMsg = probeErrorMsg.value(); int logLevel = cta::log::ERR; - driveState.setReasonFromLogMsg(logLevel,errorMsg); + driveState.setReasonFromLogMsg(logLevel, errorMsg); m_scheduler.setDesiredDriveState(securityIdentity, m_driveConfig.unitName, driveState, lc); lc.log(logLevel, errorMsg); goto schedule; - } else { + } + else { lc.log(cta::log::INFO, "No tape detected in the drive. Proceeding with scheduling."); } } @@ -159,10 +161,12 @@ schedule: std::unique_ptr<cta::TapeMount> tapeMount; // As getting next mount could be long, we report the drive as up immediately. m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Up, lc); + tapeServerReporter.reportState(cta::tape::session::SessionState::Scheduling, cta::tape::session::SessionType::Undetermined); + try { if (m_scheduler.getNextMountDryRun(m_driveConfig.logicalLibrary, m_driveConfig.unitName, lc)) - tapeMount.reset(m_scheduler.getNextMount(m_driveConfig.logicalLibrary, m_driveConfig.unitName, lc).release()); - } catch (cta::exception::Exception & e) { + tapeMount = m_scheduler.getNextMount(m_driveConfig.logicalLibrary, m_driveConfig.unitName, lc); + } catch (cta::exception::Exception& e) { cta::log::ScopedParamContainer localParams(lc); std::string exceptionMsg = e.getMessageValue(); int logLevel = cta::log::ERR; @@ -174,22 +178,22 @@ schedule: cta::common::dataStructures::DesiredDriveState driveState; driveState.up = false; driveState.forceDown = false; - driveState.setReasonFromLogMsg(cta::log::ERR,exceptionMsg); + driveState.setReasonFromLogMsg(cta::log::ERR, exceptionMsg); m_scheduler.setDesiredDriveState(cliId, m_driveConfig.unitName, driveState, lc); return MARK_DRIVE_AS_DOWN; } // No mount to be done found, that was fast... - if (!tapeMount.get()) { + if (!tapeMount) { lc.log(cta::log::DEBUG, "No new mount found. (sleeping 10 seconds)"); m_scheduler.reportDriveStatus(m_driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Up, lc); - sleep (10); + sleep(10); goto schedule; // return MARK_DRIVE_AS_UP; } - m_volInfo.vid=tapeMount->getVid(); - m_volInfo.mountType=tapeMount->getMountType(); - m_volInfo.nbFiles=tapeMount->getNbFiles(); - m_volInfo.mountId=tapeMount->getMountTransactionId(); + m_volInfo.vid = tapeMount->getVid(); + m_volInfo.mountType = tapeMount->getMountType(); + m_volInfo.nbFiles = tapeMount->getNbFiles(); + m_volInfo.mountId = tapeMount->getMountTransactionId(); // 2c) ... and log. // Make the DGN and TPVID parameter permanent. cta::log::ScopedParamContainer params(lc); @@ -198,73 +202,79 @@ schedule: { cta::log::ScopedParamContainer localParams(lc); localParams.add("tapebridgeTransId", tapeMount->getMountTransactionId()) - .add("mountType", mountTypeToString(m_volInfo.mountType)); + .add("mountType", toCamelCaseString(m_volInfo.mountType)); lc.log(cta::log::INFO, "Got volume from client"); } // Depending on the type of session, branch into the right execution - switch(m_volInfo.mountType) { - case cta::common::dataStructures::MountType::Retrieve: - return executeRead(lc, dynamic_cast<cta::RetrieveMount *>(tapeMount.get())); - case cta::common::dataStructures::MountType::ArchiveForUser: - case cta::common::dataStructures::MountType::ArchiveForRepack: - return executeWrite(lc, dynamic_cast<cta::ArchiveMount *>(tapeMount.get())); - - - case cta::common::dataStructures::MountType::Label: - return executeLabel(lc, dynamic_cast<cta::LabelMount *>(tapeMount.get())); - default: - return MARK_DRIVE_AS_UP; + switch (m_volInfo.mountType) { + case cta::common::dataStructures::MountType::Retrieve: + return executeRead(lc, dynamic_cast<cta::RetrieveMount *>(tapeMount.get()), tapeServerReporter); + case cta::common::dataStructures::MountType::ArchiveForUser: + case cta::common::dataStructures::MountType::ArchiveForRepack: + return executeWrite(lc, dynamic_cast<cta::ArchiveMount *>(tapeMount.get()), tapeServerReporter); + case cta::common::dataStructures::MountType::Label: + return executeLabel(lc, dynamic_cast<cta::LabelMount *>(tapeMount.get())); + default: + return MARK_DRIVE_AS_UP; } } + //------------------------------------------------------------------------------ //DataTransferSession::executeRead //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::Session::EndOfSessionAction - castor::tape::tapeserver::daemon::DataTransferSession::executeRead(cta::log::LogContext & lc, cta::RetrieveMount *retrieveMount) { - // We are ready to start the session. We need to create the whole machinery - // in order to get the task injector ready to check if we actually have a +castor::tape::tapeserver::daemon::DataTransferSession::executeRead(cta::log::LogContext& logContext, + cta::RetrieveMount *retrieveMount, + TapeServerReporter& reporter) { + // We are ready to start the session. We need to create the whole machinery + // in order to get the task injector ready to check if we actually have a // file to recall. // findDrive does not throw exceptions (it catches them to log errors) - // A NULL pointer is returned on failure + // A nullptr is returned on failure retrieveMount->setFetchEosFreeSpaceScript(m_castorConf.fetchEosFreeSpaceScript); - std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(findDrive(m_driveConfig,lc,retrieveMount)); - if(!drive.get()) return MARK_DRIVE_AS_DOWN; + std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(findDrive(m_driveConfig, logContext, retrieveMount)); + + if (!drive) { + reporter.bailout(); + return MARK_DRIVE_AS_DOWN; + } // We can now start instantiating all the components of the data path { // Allocate all the elements of the memory management (in proper order // to refer them to each other) - RecallReportPacker rrp(retrieveMount, lc); - rrp.disableBulk(); //no bulk needed anymore - RecallWatchDog rwd(15,60*10,m_intialProcess,*retrieveMount,m_driveConfig.unitName,lc); - - RecallMemoryManager mm(m_castorConf.nbBufs, m_castorConf.bufsz,lc); - TapeServerReporter tsr(m_intialProcess, m_driveConfig, - m_hostname, m_volInfo, lc); - //we retrieved the detail from the client in execute, so at this point + RecallReportPacker reportPacker(retrieveMount, logContext); + reportPacker.disableBulk(); //no bulk needed anymore + RecallWatchDog watchDog(15, 60 * 10, m_initialProcess, *retrieveMount, m_driveConfig.unitName, logContext); + + RecallMemoryManager memoryManager(m_castorConf.nbBufs, m_castorConf.bufsz, logContext); + + //we retrieved the detail from the client in execute, so at this point //we can already report ! - tsr.reportState(cta::tape::session::SessionState::Mounting, - cta::tape::session::SessionType::Retrieve); - - TapeReadSingleThread trst(*drive, m_mc, tsr, m_volInfo, - m_castorConf.bulkRequestRecallMaxFiles,m_capUtils,rwd,lc,rrp, - m_castorConf.useLbp, m_castorConf.useRAO, m_castorConf.useEncryption, m_castorConf.externalEncryptionKeyScript,*retrieveMount, m_castorConf.tapeLoadTimeout); - DiskWriteThreadPool dwtp(m_castorConf.nbDiskThreads, - rrp, - rwd, - lc, - m_castorConf.xrootPrivateKey, - m_castorConf.xrootTimeout); - RecallTaskInjector rti(mm, trst, dwtp, *retrieveMount, - m_castorConf.bulkRequestRecallMaxFiles, - m_castorConf.bulkRequestRecallMaxBytes,lc); + reporter.reportState(cta::tape::session::SessionState::Mounting, + cta::tape::session::SessionType::Retrieve); + + TapeReadSingleThread readSingleThread(*drive, m_mediaChanger, reporter, m_volInfo, + m_castorConf.bulkRequestRecallMaxFiles, m_capUtils, watchDog, logContext, reportPacker, + m_castorConf.useLbp, m_castorConf.useRAO, m_castorConf.useEncryption, + m_castorConf.externalEncryptionKeyScript, *retrieveMount, m_castorConf.tapeLoadTimeout); + + DiskWriteThreadPool threadPool(m_castorConf.nbDiskThreads, + reportPacker, + watchDog, + logContext, + m_castorConf.xrootPrivateKey, + m_castorConf.xrootTimeout); + RecallTaskInjector taskInjector(memoryManager, readSingleThread, threadPool, *retrieveMount, + m_castorConf.bulkRequestRecallMaxFiles, + m_castorConf.bulkRequestRecallMaxBytes, logContext); // Workaround for bug CASTOR-4829: tapegateway: should request positioning by blockid for recalls instead of fseq // In order to implement the fix, the task injector needs to know the type // of the client - trst.setTaskInjector(&rti); - rrp.setWatchdog(rwd); + readSingleThread.setTaskInjector(&taskInjector); + reportPacker.setWatchdog(watchDog); - rti.setDriveInterface(trst.getDriveReference()); + taskInjector.setDriveInterface(readSingleThread.getDriveReference()); // We are now ready to put everything in motion. First step is to check // we get any concrete job to be done from the client (via the task injector) @@ -272,52 +282,54 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction // The RecallTaskInjector and the TapeReadSingleThread share the promise if (m_castorConf.useRAO) { - castor::tape::tapeserver::rao::RAOParams raoDataConfig(m_castorConf.useRAO,m_castorConf.raoLtoAlgorithm, m_castorConf.raoLtoAlgorithmOptions,m_volInfo.vid); - rti.initRAO(raoDataConfig, &m_scheduler.getCatalogue()); + castor::tape::tapeserver::rao::RAOParams raoDataConfig(m_castorConf.useRAO, m_castorConf.raoLtoAlgorithm, m_castorConf.raoLtoAlgorithmOptions, + m_volInfo.vid); + taskInjector.initRAO(raoDataConfig, &m_scheduler.getCatalogue()); } bool noFilesToRecall = false; bool fetchResult = false; bool reservationResult = false; - fetchResult = rti.synchronousFetch(noFilesToRecall); + fetchResult = taskInjector.synchronousFetch(noFilesToRecall); if (fetchResult) { - reservationResult = rti.reserveSpaceForNextJobBatch(); + reservationResult = taskInjector.reserveSpaceForNextJobBatch(); } //only mount the tape if we can confirm that we will do some work, otherwise do an empty mount if (fetchResult && reservationResult) { // We got something to recall. Time to start the machinery - trst.setWaitForInstructionsTime(timer.secs()); - rwd.startThread(); - trst.startThreads(); - dwtp.startThreads(); - rrp.startThreads(); - rti.startThreads(); - tsr.startThreads(); - // This thread is now going to be idle until the system unwinds at the end + readSingleThread.setWaitForInstructionsTime(timer.secs()); + watchDog.startThread(); + readSingleThread.startThreads(); + threadPool.startThreads(); + reportPacker.startThreads(); + taskInjector.startThreads(); + reporter.startThreads(); + // This thread is now going to be idle until the system unwinds at the end // of the session // All client notifications are done by the report packer, including the // end of session - rti.waitThreads(); - dwtp.waitThreads(); - rrp.setDiskDone(); - trst.waitThreads(); - rrp.setTapeDone(); - rrp.waitThread(); - tsr.waitThreads(); - rwd.stopAndWaitThread(); - return trst.getHardwareStatus(); - } else { - // If the first pop from the queue fails, just log this was an empty mount and that's it. - // The memory management will be deallocated automatically. + taskInjector.waitThreads(); + threadPool.waitThreads(); + reportPacker.setDiskDone(); + readSingleThread.waitThreads(); + reportPacker.setTapeDone(); + reportPacker.waitThread(); + reporter.waitThreads(); + watchDog.stopAndWaitThread(); + return readSingleThread.getHardwareStatus(); + } + else { + // If the first pop from the queue fails, just log this was an empty mount and that's it. The memory management + // will be deallocated automatically. int priority = cta::log::ERR; std::string status = "success"; - if(!fetchResult || !reservationResult){ - //If this is an empty mount because no files have been popped from the queue - //or because disk reservation failed, it is just a warning + if (!fetchResult || !reservationResult) { + // If this is an empty mount because no files have been popped from the queue + // or because disk reservation failed, it is just a warning priority = cta::log::WARNING; status = "failure"; } - lc.log(priority, "Aborting recall mount startup: empty mount"); + logContext.log(priority, "Aborting recall mount startup: empty mount"); std::string mountId = retrieveMount->getMountTransactionId(); std::string mountType = cta::common::dataStructures::toString(retrieveMount->getMountType()); @@ -325,155 +337,156 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction cta::log::Param errorMessageParam("errorMessage", "Aborted: empty recall mount"); cta::log::Param mountIdParam("mountId", mountId); cta::log::Param mountTypeParam("mountType", mountType); - cta::log::Param statusParam("status",status); + cta::log::Param statusParam("status", status); - cta::log::LogContext::ScopedParam sp1(lc, errorMessageParam); + cta::log::LogContext::ScopedParam sp1(logContext, errorMessageParam); try { retrieveMount->abort("Aborted: empty recall mount"); - rwd.updateStats(TapeSessionStats()); - rwd.reportStats(); - std::list<cta::log::Param> paramList { errorMessageParam, mountIdParam, mountTypeParam, statusParam }; - m_intialProcess.addLogParams(m_driveConfig.unitName,paramList); - cta::log::LogContext::ScopedParam sp08(lc, cta::log::Param("MountTransactionId", mountId)); - cta::log::LogContext::ScopedParam sp11(lc, cta::log::Param("errorMessage", "Aborted: empty recall mount")); - lc.log(priority, "Notified client of end session with error"); - } catch(cta::exception::Exception & ex) { - cta::log::LogContext::ScopedParam sp1(lc, cta::log::Param("notificationError", ex.getMessageValue())); - lc.log(cta::log::ERR, "Failed to notified client of end session with error"); + watchDog.updateStats(TapeSessionStats()); + watchDog.reportStats(); + std::list<cta::log::Param> paramList{errorMessageParam, mountIdParam, mountTypeParam, statusParam}; + m_initialProcess.addLogParams(m_driveConfig.unitName, paramList); + cta::log::LogContext::ScopedParam sp08(logContext, cta::log::Param("MountTransactionId", mountId)); + cta::log::LogContext::ScopedParam sp11(logContext, cta::log::Param("errorMessage", "Aborted: empty recall mount")); + logContext.log(priority, "Notified client of end session with error"); + } catch (cta::exception::Exception& ex) { + cta::log::LogContext::ScopedParam sp12(logContext, cta::log::Param("notificationError", ex.getMessageValue())); + logContext.log(cta::log::ERR, "Failed to notified client of end session with error"); } // Empty mount, hardware is OK return MARK_DRIVE_AS_UP; } } } + //------------------------------------------------------------------------------ //DataTransferSession::executeWrite //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::Session::EndOfSessionAction - castor::tape::tapeserver::daemon::DataTransferSession::executeWrite( - cta::log::LogContext & lc, cta::ArchiveMount *archiveMount) { - // We are ready to start the session. We need to create the whole machinery - // in order to get the task injector ready to check if we actually have a +castor::tape::tapeserver::daemon::DataTransferSession::executeWrite(cta::log::LogContext& logContext, + cta::ArchiveMount *archiveMount, + TapeServerReporter& reporter) { + // We are ready to start the session. We need to create the whole machinery + // in order to get the task injector ready to check if we actually have a // file to migrate. // 1) Get hold of the drive error logs are done inside the findDrive function - std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(findDrive(m_driveConfig,lc,archiveMount)); - if (!drive.get()) return MARK_DRIVE_AS_DOWN; + std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(findDrive(m_driveConfig, logContext, archiveMount)); + if (!drive) return MARK_DRIVE_AS_DOWN; // Once we got hold of the drive, we can run the session { //dereferencing configLine is safe, because if configLine were not valid, - //then findDrive would have return NULL and we would have not end up there - TapeServerReporter tsr(m_intialProcess, m_driveConfig, m_hostname,m_volInfo,lc); - - MigrationMemoryManager mm(m_castorConf.nbBufs, - m_castorConf.bufsz,lc); - MigrationReportPacker mrp(archiveMount, lc); - MigrationWatchDog mwd(15,60*10,m_intialProcess,*archiveMount,m_driveConfig.unitName,lc); - TapeWriteSingleThread twst(*drive, - m_mc, - tsr, - mwd, - m_volInfo, - lc, - mrp, - m_capUtils, - m_castorConf.maxFilesBeforeFlush, - m_castorConf.maxBytesBeforeFlush, - m_castorConf.useLbp, - m_castorConf.useEncryption, - m_castorConf.externalEncryptionKeyScript, - *archiveMount, - m_castorConf.tapeLoadTimeout); - - DiskReadThreadPool drtp(m_castorConf.nbDiskThreads, - m_castorConf.bulkRequestMigrationMaxFiles, - m_castorConf.bulkRequestMigrationMaxBytes, - mwd, - lc, - m_castorConf.xrootPrivateKey, - m_castorConf.xrootTimeout); - MigrationTaskInjector mti(mm, drtp, twst, *archiveMount, - m_castorConf.bulkRequestMigrationMaxFiles, - m_castorConf.bulkRequestMigrationMaxBytes,lc); - drtp.setTaskInjector(&mti); - twst.setTaskInjector(&mti); - mrp.setWatchdog(mwd); + //then findDrive would have return nullptr and we would have not end up there + MigrationMemoryManager memoryManager(m_castorConf.nbBufs, + m_castorConf.bufsz, logContext); + MigrationReportPacker reportPacker(archiveMount, logContext); + MigrationWatchDog watchDog(15, 60 * 10, m_initialProcess, *archiveMount, m_driveConfig.unitName, logContext); + TapeWriteSingleThread writeSingleThread(*drive, + m_mediaChanger, + reporter, + watchDog, + m_volInfo, + logContext, + reportPacker, + m_capUtils, + m_castorConf.maxFilesBeforeFlush, + m_castorConf.maxBytesBeforeFlush, + m_castorConf.useLbp, + m_castorConf.useEncryption, + m_castorConf.externalEncryptionKeyScript, + *archiveMount, + m_castorConf.tapeLoadTimeout); + + + DiskReadThreadPool threadPool(m_castorConf.nbDiskThreads, + m_castorConf.bulkRequestMigrationMaxFiles, + m_castorConf.bulkRequestMigrationMaxBytes, + watchDog, + logContext, + m_castorConf.xrootPrivateKey, + m_castorConf.xrootTimeout); + MigrationTaskInjector taskInjector(memoryManager, threadPool, writeSingleThread, *archiveMount, + m_castorConf.bulkRequestMigrationMaxFiles, + m_castorConf.bulkRequestMigrationMaxBytes, logContext); + threadPool.setTaskInjector(&taskInjector); + writeSingleThread.setTaskInjector(&taskInjector); + reportPacker.setWatchdog(watchDog); cta::utils::Timer timer; bool noFilesToMigrate = false; - if (mti.synchronousInjection(noFilesToMigrate)) { - const uint64_t firstFseqFromClient = mti.firstFseqToWrite(); + if (taskInjector.synchronousInjection(noFilesToMigrate)) { + const uint64_t firstFseqFromClient = taskInjector.firstFseqToWrite(); //the last fseq written on the tape is the first file's fseq minus one - twst.setlastFseq(firstFseqFromClient-1); + writeSingleThread.setlastFseq(firstFseqFromClient - 1); - //we retrieved the detail from the client in execute, so at this point + //we retrieved the detail from the client in execute, so at this point //we can report we will mount the tape. // TODO: create a "StartingSession" state as the mounting will happen in // the to-be-created tape thread. try { - tsr.reportState(cta::tape::session::SessionState::Mounting, - cta::tape::session::SessionType::Archive); - } catch (cta::exception::Exception & e) { - cta::log::LogContext::ScopedParam sp1(lc, cta::log::Param("errorMessage", e.getMessage().str())); - lc.log(cta::log::INFO, "Aborting the session after problem with mount details. Notifying the client."); - mrp.synchronousReportEndWithErrors(e.getMessageValue(), 666, lc); + reporter.reportState(cta::tape::session::SessionState::Mounting, + cta::tape::session::SessionType::Archive); + } catch (cta::exception::Exception& e) { + cta::log::LogContext::ScopedParam sp1(logContext, cta::log::Param("errorMessage", e.getMessage().str())); + logContext.log(cta::log::INFO, "Aborting the session after problem with mount details. Notifying the client."); + reportPacker.synchronousReportEndWithErrors(e.getMessageValue(), 666, logContext); return MARK_DRIVE_AS_UP; } catch (...) { - lc.log(cta::log::INFO, "Aborting the session after problem with mount details (unknown exception). Notifying the client."); - mrp.synchronousReportEndWithErrors("Unknown exception while checking session parameters with VMGR", 666, lc); + logContext.log(cta::log::INFO, "Aborting the session after problem with mount details (unknown exception). Notifying the client."); + reportPacker.synchronousReportEndWithErrors("Unknown exception while checking session parameters with VMGR", 666, logContext); return MARK_DRIVE_AS_UP; } // We have something to do: start the session by starting all the // threads. - mm.startThreads(); - drtp.startThreads(); - mwd.startThread(); - twst.setWaitForInstructionsTime(timer.secs()); - twst.startThreads(); - mrp.startThreads(); - mti.startThreads(); - tsr.startThreads(); - + memoryManager.startThreads(); + threadPool.startThreads(); + watchDog.startThread(); + writeSingleThread.setWaitForInstructionsTime(timer.secs()); + writeSingleThread.startThreads(); + reportPacker.startThreads(); + taskInjector.startThreads(); + reporter.startThreads(); // Synchronise with end of threads - mti.waitThreads(); - mrp.waitThread(); - twst.waitThreads(); - drtp.waitThreads(); - mm.waitThreads(); - tsr.waitThreads(); - mwd.stopAndWaitThread(); - - return twst.getHardwareStatus(); - } else { + taskInjector.waitThreads(); + reportPacker.waitThread(); + writeSingleThread.waitThreads(); + threadPool.waitThreads(); + memoryManager.waitThreads(); + reporter.waitThreads(); + watchDog.stopAndWaitThread(); + + return writeSingleThread.getHardwareStatus(); + } + else { // Just log this was an empty mount and that's it. The memory management // will be deallocated automatically. int priority = cta::log::ERR; std::string status = "failure"; - if(noFilesToMigrate){ + if (noFilesToMigrate) { priority = cta::log::WARNING; status = "success"; } - lc.log(priority, "Aborting migration mount startup: empty mount"); + logContext.log(priority, "Aborting migration mount startup: empty mount"); std::string mountId = archiveMount->getMountTransactionId(); std::string mountType = cta::common::dataStructures::toString(archiveMount->getMountType()); cta::log::Param errorMessageParam("errorMessage", "Aborted: empty migration mount"); cta::log::Param mountIdParam("mountId", mountId); - cta::log::Param mountTypeParam("mountType",mountType); + cta::log::Param mountTypeParam("mountType", mountType); cta::log::Param statusParam("status", status); - cta::log::LogContext::ScopedParam sp1(lc, errorMessageParam); + cta::log::LogContext::ScopedParam sp1(logContext, errorMessageParam); try { archiveMount->complete(); - mwd.updateStats(TapeSessionStats()); - mwd.reportStats(); - std::list<cta::log::Param> paramList { errorMessageParam, mountIdParam, mountTypeParam, statusParam }; - m_intialProcess.addLogParams(m_driveConfig.unitName,paramList); - cta::log::LogContext::ScopedParam sp1(lc, cta::log::Param("MountTransactionId", mountId)); - lc.log(priority, "Notified client of end session with error"); - } catch(cta::exception::Exception & ex) { - cta::log::LogContext::ScopedParam sp1(lc, cta::log::Param("notificationError", ex.getMessageValue())); - lc.log(cta::log::ERR, "Failed to notified client of end session with error"); + watchDog.updateStats(TapeSessionStats()); + watchDog.reportStats(); + std::list<cta::log::Param> paramList{errorMessageParam, mountIdParam, mountTypeParam, statusParam}; + m_initialProcess.addLogParams(m_driveConfig.unitName, paramList); + cta::log::LogContext::ScopedParam sp11(logContext, cta::log::Param("MountTransactionId", mountId)); + logContext.log(priority, "Notified client of end session with error"); + } catch (cta::exception::Exception& ex) { + cta::log::LogContext::ScopedParam sp12(logContext, cta::log::Param("notificationError", ex.getMessageValue())); + logContext.log(cta::log::ERR, "Failed to notified client of end session with error"); } // Empty mount, hardware safe return MARK_DRIVE_AS_UP; @@ -485,7 +498,7 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction //DataTransferSession::executeLabel //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::Session::EndOfSessionAction - castor::tape::tapeserver::daemon::DataTransferSession::executeLabel(cta::log::LogContext& lc, cta::LabelMount* labelMount) { +castor::tape::tapeserver::daemon::DataTransferSession::executeLabel(cta::log::LogContext& logContext, cta::LabelMount *labelMount) { throw cta::exception::Exception("In DataTransferSession::executeLabel(): not implemented"); // TODO } @@ -504,116 +517,101 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction */ /** * Try to find the drive that is described by m_request.driveUnit - * @param lc For logging purpose - * @return the drive if found, NULL otherwise + * @param logContext For logging purpose + * @return the drive if found, nullptr otherwise */ castor::tape::tapeserver::drive::DriveInterface * -castor::tape::tapeserver::daemon::DataTransferSession::findDrive(const cta::tape::daemon::TpconfigLine - &driveConfig, cta::log::LogContext& lc, cta::TapeMount *mount) { +castor::tape::tapeserver::daemon::DataTransferSession::findDrive(const cta::tape::daemon::TpconfigLine& driveConfig, cta::log::LogContext& logContext, + cta::TapeMount *mount) { // Find the drive in the system's SCSI devices castor::tape::SCSI::DeviceVector dv(m_sysWrapper); castor::tape::SCSI::DeviceInfo driveInfo; try { driveInfo = dv.findBySymlink(driveConfig.devFilename); - } catch (castor::tape::SCSI::DeviceVector::NotFound & e) { + } catch (castor::tape::SCSI::DeviceVector::NotFound& e) { // We could not find this drive in the system's SCSI devices - cta::log::LogContext::ScopedParam sp09(lc, cta::log::Param("devFilename", driveConfig.devFilename)); - lc.log(cta::log::ERR, "Drive not found on this path"); + cta::log::LogContext::ScopedParam sp09(logContext, cta::log::Param("devFilename", driveConfig.devFilename)); + logContext.log(cta::log::ERR, "Drive not found on this path"); std::stringstream errMsg; const std::string headerErrMsg = "Drive not found on this path"; - errMsg << headerErrMsg << lc; + errMsg << headerErrMsg << logContext; mount->abort(headerErrMsg + e.getMessageValue()); - cta::log::LogContext::ScopedParam sp10(lc, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); - cta::log::LogContext::ScopedParam sp13(lc, cta::log::Param("errorMessage", errMsg.str())); - lc.log(cta::log::ERR, "Notified client of end session with error"); - return NULL; - } catch (cta::exception::Exception & e) { + cta::log::LogContext::ScopedParam sp10(logContext, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); + cta::log::LogContext::ScopedParam sp13(logContext, cta::log::Param("errorMessage", errMsg.str())); + logContext.log(cta::log::ERR, "Notified client of end session with error"); + return nullptr; + } catch (cta::exception::Exception& e) { // We could not find this drive in the system's SCSI devices - cta::log::LogContext::ScopedParam sp09(lc, cta::log::Param("devFilename", driveConfig.devFilename)); - cta::log::LogContext::ScopedParam sp10(lc, cta::log::Param("errorMessage", e.getMessageValue())); - lc.log(cta::log::ERR, "Error looking to path to tape drive"); + cta::log::LogContext::ScopedParam sp09(logContext, cta::log::Param("devFilename", driveConfig.devFilename)); + cta::log::LogContext::ScopedParam sp10(logContext, cta::log::Param("errorMessage", e.getMessageValue())); + logContext.log(cta::log::ERR, "Error looking to path to tape drive"); std::stringstream errMsg; const std::string headerErrMsg = "Error looking to path to tape drive: "; - errMsg << headerErrMsg << lc; + errMsg << headerErrMsg << logContext; mount->abort(headerErrMsg + e.getMessageValue()); - cta::log::LogContext::ScopedParam sp11(lc, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); - cta::log::LogContext::ScopedParam sp14(lc, cta::log::Param("errorMessage", errMsg.str())); - lc.log(cta::log::ERR, "Notified client of end session with error"); - return NULL; + cta::log::LogContext::ScopedParam sp11(logContext, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); + cta::log::LogContext::ScopedParam sp14(logContext, cta::log::Param("errorMessage", errMsg.str())); + logContext.log(cta::log::ERR, "Notified client of end session with error"); + return nullptr; } catch (...) { // We could not find this drive in the system's SCSI devices - cta::log::LogContext::ScopedParam sp09(lc, cta::log::Param("devFilename", driveConfig.devFilename)); - lc.log(cta::log::ERR, "Unexpected exception while looking for drive"); + cta::log::LogContext::ScopedParam sp09(logContext, cta::log::Param("devFilename", driveConfig.devFilename)); + logContext.log(cta::log::ERR, "Unexpected exception while looking for drive"); std::stringstream errMsg; const std::string headerErrMsg = "Unexpected exception while looking for drive"; - errMsg << headerErrMsg << lc; + errMsg << headerErrMsg << logContext; mount->abort(headerErrMsg); - cta::log::LogContext::ScopedParam sp10(lc, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); - cta::log::LogContext::ScopedParam sp13(lc, cta::log::Param("errorMessage", errMsg.str())); - lc.log(cta::log::ERR, "Notified client of end session with error"); - return NULL; + cta::log::LogContext::ScopedParam sp10(logContext, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); + cta::log::LogContext::ScopedParam sp13(logContext, cta::log::Param("errorMessage", errMsg.str())); + logContext.log(cta::log::ERR, "Notified client of end session with error"); + return nullptr; } try { std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive; drive.reset(castor::tape::tapeserver::drive::createDrive(driveInfo, m_sysWrapper)); - if (drive.get()) drive->config = driveConfig; + if (drive) drive->config = driveConfig; return drive.release(); - } catch (cta::exception::Exception & e) { + } catch (cta::exception::Exception& e) { // We could not find this drive in the system's SCSI devices - cta::log::LogContext::ScopedParam sp09(lc, cta::log::Param("devFilename", driveConfig.devFilename)); - cta::log::LogContext::ScopedParam sp10(lc, cta::log::Param("errorMessage", e.getMessageValue())); - lc.log(cta::log::ERR, "Error opening tape drive"); + cta::log::LogContext::ScopedParam sp09(logContext, cta::log::Param("devFilename", driveConfig.devFilename)); + cta::log::LogContext::ScopedParam sp10(logContext, cta::log::Param("errorMessage", e.getMessageValue())); + logContext.log(cta::log::ERR, "Error opening tape drive"); std::stringstream errMsg; const std::string headerErrMsg = "Error opening tape drive"; - errMsg << headerErrMsg << lc; + errMsg << headerErrMsg << logContext; mount->abort(headerErrMsg); - cta::log::LogContext::ScopedParam sp11(lc, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); - cta::log::LogContext::ScopedParam sp14(lc, cta::log::Param("errorMessage", errMsg.str())); - lc.log(cta::log::ERR, "Notified client of end session with error"); - return NULL; + cta::log::LogContext::ScopedParam sp11(logContext, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); + cta::log::LogContext::ScopedParam sp14(logContext, cta::log::Param("errorMessage", errMsg.str())); + logContext.log(cta::log::ERR, "Notified client of end session with error"); + return nullptr; } catch (...) { // We could not find this drive in the system's SCSI devices - cta::log::LogContext::ScopedParam sp09(lc, cta::log::Param("devFilename", driveConfig.devFilename)); - lc.log(cta::log::ERR, "Unexpected exception while opening drive"); + cta::log::LogContext::ScopedParam sp09(logContext, cta::log::Param("devFilename", driveConfig.devFilename)); + logContext.log(cta::log::ERR, "Unexpected exception while opening drive"); std::stringstream errMsg; const std::string headerErrMsg = "Unexpected exception while opening drive"; - errMsg << headerErrMsg << lc; + errMsg << headerErrMsg << logContext; mount->abort(headerErrMsg); - cta::log::LogContext::ScopedParam sp10(lc, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); - cta::log::LogContext::ScopedParam sp13(lc, cta::log::Param("errorMessage", errMsg.str())); - lc.log(cta::log::ERR, "Notified client of end session with error"); - return NULL; + cta::log::LogContext::ScopedParam sp10(logContext, cta::log::Param("tapebridgeTransId", mount->getMountTransactionId())); + cta::log::LogContext::ScopedParam sp13(logContext, cta::log::Param("errorMessage", errMsg.str())); + logContext.log(cta::log::ERR, "Notified client of end session with error"); + return nullptr; } } //------------------------------------------------------------------------------ // destructor //------------------------------------------------------------------------------ -castor::tape::tapeserver::daemon::DataTransferSession::~DataTransferSession() - throw () { +castor::tape::tapeserver::daemon::DataTransferSession::~DataTransferSession() noexcept { try { google::protobuf::ShutdownProtobufLibrary(); - } catch(...) { + } catch (...) { m_log(cta::log::ERR, "google::protobuf::ShutdownProtobufLibrary() threw an" - " unexpected exception"); - } -} - -//----------------------------------------------------------------------------- -// volumeModeToString -//----------------------------------------------------------------------------- -const char *castor::tape::tapeserver::daemon::DataTransferSession:: - mountTypeToString(const cta::common::dataStructures::MountType mountType) const throw() { - switch(mountType) { - case cta::common::dataStructures::MountType::Retrieve: return "Retrieve"; - case cta::common::dataStructures::MountType::ArchiveForUser : return "ArchiveForUser"; - case cta::common::dataStructures::MountType::ArchiveForRepack : return "ArchiveForRepack"; - case cta::common::dataStructures::MountType::Label: return "Label"; - default : return "UNKNOWN"; + " unexpected exception"); } } diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.hpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.hpp index 93343872e4d8cd412ef0ce94584491a1506c9e72..b3ca46c284c5a7a7d57a6d1e0497ac38d92df583 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSession.hpp @@ -37,116 +37,112 @@ namespace castor { namespace tape { namespace tapeserver { namespace daemon { + +/** + * The main class handling a tape session. This is the main container started + * by the master process. It will drive a separate process. Only the sub + * process interface is not included here to allow testability. + */ +class DataTransferSession : public Session { +public: + /** + * Constructor. + * + * @param log Object representing the API of the CASTOR logging system. + */ + DataTransferSession(const std::string& hostname, cta::log::Logger& log, + System::virtualWrapper& sysWrapper, + const cta::tape::daemon::TpconfigLine& driveConfig, + cta::mediachanger::MediaChangerFacade& mc, + cta::tape::daemon::TapedProxy& initialProcess, + cta::server::ProcessCap& capUtils, const DataTransferConfig& castorConf, + cta::Scheduler& scheduler); + + /** + * Execute the session and return the type of action to be performed + * immediately after the session has completed. + * + * The session is responsible for mounting a tape into the tape drive, + * working with that tape, unloading the tape from the drive and then + * dismounting the tape from the drive and storing it back in its home slot + * within the tape library. + * + * If this method throws an exception and the session is not a cleaner + * session then it assumed that the post session action is + * EndOfSessionAction::CLEAN_DRIVE. + * + * If this method throws an exception and the session is a cleaner + * session then it assumed that the post session action is + * EndOfSessionAction::MARK_DRIVE_AS_DOWN. + * + * @return Returns the type of action to be performed after the session has + * completed. + */ + EndOfSessionAction execute() override; + + /** + * Sets the capabilities of the process and logs the result. + * + * @param capabilities The string representation of the capabilities. + */ + void setProcessCapabilities(const std::string& capabilities); + + /** Temporary method used for debugging while building the session class */ + std::string getVid() const { return m_volInfo.vid; } + /** - * The main class handling a tape session. This is the main container started - * by the master process. It will drive a separate process. Only the sub - * process interface is not included here to allow testability. + * Destructor. */ - class DataTransferSession: public Session { - public: - /** - * Constructor. - * - * @param log Object representing the API of the CASTOR logging system. - */ - DataTransferSession( - const std::string & hostname, - cta::log::Logger & log, - System::virtualWrapper & sysWrapper, - const cta::tape::daemon::TpconfigLine & driveConfig, - cta::mediachanger::MediaChangerFacade & mc, - cta::tape::daemon::TapedProxy & initialProcess, - cta::server::ProcessCap &capUtils, - const DataTransferConfig & castorConf, - cta::Scheduler &scheduler); + ~DataTransferSession() noexcept override; - /** - * Execute the session and return the type of action to be performed - * immediately after the session has completed. - * - * The session is responsible for mounting a tape into the tape drive, - * working with that tape, unloading the tape from the drive and then - * dismounting the tape from the drive and storing it back in its home slot - * within the tape library. - * - * If this method throws an exception and the session is not a cleaner - * session then it assumed that the post session action is - * EndOfSessionAction::CLEAN_DRIVE. - * - * If this method throws an exception and the session is a cleaner - * session then it assumed that the post session action is - * EndOfSessionAction::MARK_DRIVE_AS_DOWN. - * - * @return Returns the type of action to be performed after the session has - * completed. - */ - EndOfSessionAction execute(); +private: - /** - * Sets the capabilities of the process and logs the result. - * - * @param capabilities The string representation of the capabilities. - */ - void setProcessCapabilities(const std::string &capabilities); + /** + * Object representing the API of the CASTOR logging system. + */ + cta::log::Logger& m_log; + VolumeInfo m_volInfo; + System::virtualWrapper& m_sysWrapper; + /** + * The configuration of the tape drive to be used by this session. + */ + const cta::tape::daemon::TpconfigLine m_driveConfig; + const DataTransferConfig& m_castorConf; + /** + * The drive information bundle allowing drive register update. + * Filled up at construction time. + */ + const cta::common::dataStructures::DriveInfo m_driveInfo; + + /** utility to find the drive on the system. This function logs + * all errors and hence does not throw exceptions. It returns nullptr + * in case of failure. */ + castor::tape::tapeserver::drive::DriveInterface *findDrive( + const cta::tape::daemon::TpconfigLine& driveConfig, cta::log::LogContext& logContext, cta::TapeMount *mount); + + /** sub-part of execute for the read sessions */ + EndOfSessionAction executeRead(cta::log::LogContext& logContext, cta::RetrieveMount *retrieveMount, TapeServerReporter& reporter); - /** Temporary method used for debugging while building the session class */ - std::string getVid() { return m_volInfo.vid; } - - /** - * Destructor. - */ - ~DataTransferSession() throw(); + /** sub-part of execute for a write session */ + EndOfSessionAction executeWrite(cta::log::LogContext& logContext, cta::ArchiveMount *archiveMount, TapeServerReporter& reporter); - private: - - /** - * Object representing the API of the CASTOR logging system. - */ - cta::log::Logger & m_log; - VolumeInfo m_volInfo; - System::virtualWrapper & m_sysWrapper; - /** - * The configuration of the tape drive to be used by this session. - */ - const cta::tape::daemon::TpconfigLine m_driveConfig; - const DataTransferConfig & m_castorConf; - /** - * The drive information bundle allowing drive register update. - * Filled up at construction time. - */ - const cta::common::dataStructures::DriveInfo m_driveInfo; - /** utility to find the drive on the system. This function logs - * all errors and hence does not throw exceptions. It returns NULL - * in case of failure. */ - castor::tape::tapeserver::drive::DriveInterface * findDrive( - const cta::tape::daemon::TpconfigLine &driveConfig, cta::log::LogContext & lc, cta::TapeMount *mount); - - /** sub-part of execute for the read sessions */ - EndOfSessionAction executeRead(cta::log::LogContext & lc, cta::RetrieveMount *retrieveMount); - /** sub-part of execute for a write session */ - EndOfSessionAction executeWrite(cta::log::LogContext & lc, cta::ArchiveMount *archiveMount); - /** sub-part of execute for a label session */ - EndOfSessionAction executeLabel(cta::log::LogContext & lc, cta::LabelMount *labelMount); - /** Reference to the MediaChangerFacade, allowing the mounting of the tape - * by the library. It will be used exclusively by the tape thread. */ - cta::mediachanger::MediaChangerFacade & m_mc; - /** Reference to the tape server's parent process to report detailed status */ - cta::tape::daemon::TapedProxy & m_intialProcess; - /** Object providing utilities for working UNIX capabilities. */ - cta::server::ProcessCap &m_capUtils; - /** hostname, used to report status of the drive */ - const std::string m_hostname; - /** - * The scheduler, i.e. the local interface to the Objectstore DB - */ - cta::Scheduler &m_scheduler; + /** sub-part of execute for a label session */ + EndOfSessionAction executeLabel(cta::log::LogContext& logContext, cta::LabelMount *labelMount); - /** - * Returns the string representation of the specified mount type - */ - const char *mountTypeToString(const cta::common::dataStructures::MountType mountType) const - throw(); - }; + /** Reference to the MediaChangerFacade, allowing the mounting of the tape + * by the library. It will be used exclusively by the tape thread. */ + cta::mediachanger::MediaChangerFacade& m_mediaChanger; + /** Reference to the tape server's parent process to report detailed status */ + cta::tape::daemon::TapedProxy& m_initialProcess; + /** Object providing utilities for working UNIX capabilities. */ + cta::server::ProcessCap& m_capUtils; + /** hostname, used to report status of the drive */ + const std::string m_hostname; + /** + * The scheduler, i.e. the local interface to the Objectstore DB + */ + cta::Scheduler& m_scheduler; +}; } } } diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp index c367e39416645c69dcfe56593eed1a7003a64f62..3ed451e5f70b58b04a765795dcc9d3b87285f30d 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp @@ -55,7 +55,9 @@ #ifdef STDOUT_LOGGING #include "common/log/StdoutLogger.hpp" #else + #include "common/log/DummyLogger.hpp" + #endif #include <dirent.h> @@ -83,12 +85,12 @@ namespace { * This structure is used to parameterize scheduler tests. */ struct DataTransferSessionTestParam { - cta::SchedulerDatabaseFactory &dbFactory; + cta::SchedulerDatabaseFactory& dbFactory; - DataTransferSessionTestParam( - cta::SchedulerDatabaseFactory &dbFactory): + explicit DataTransferSessionTestParam( + cta::SchedulerDatabaseFactory& dbFactory) : dbFactory(dbFactory) { - } + } }; // struct DataTransferSessionTest } @@ -97,24 +99,24 @@ struct DataTransferSessionTestParam { * The data transfer test is a parameterized test. It takes a pair of name server * and scheduler database factories as a parameter. */ -class DataTransferSessionTest: public ::testing::TestWithParam<DataTransferSessionTestParam> { +class DataTransferSessionTest : public ::testing::TestWithParam<DataTransferSessionTestParam> { public: - DataTransferSessionTest(): - m_dummyLog("dummy", "dummy"){ + DataTransferSessionTest() : + m_dummyLog("dummy", "dummy") { } - class FailedToGetCatalogue: public std::exception { + class FailedToGetCatalogue : public std::exception { public: - const char *what() const throw() { + const char *what() const noexcept { return "Failed to get catalogue"; } }; - class FailedToGetScheduler: public std::exception { + class FailedToGetScheduler : public std::exception { public: - const char *what() const throw() { + const char *what() const noexcept { return "Failed to get scheduler"; } }; @@ -128,10 +130,10 @@ public: }; #endif - virtual void SetUp() { + void SetUp() override { using namespace cta; - const DataTransferSessionTestParam ¶m = GetParam(); + const DataTransferSessionTestParam& param = GetParam(); const uint64_t nbConns = 1; const uint64_t nbArchiveFileListingConns = 1; #ifdef USE_ORACLE_CATALOGUE @@ -154,21 +156,21 @@ public: m_catalogue = cta::make_unique<catalogue::InMemoryCatalogue>(m_dummyLog, nbConns, nbArchiveFileListingConns); #endif m_db = param.dbFactory.create(m_catalogue); - m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2*1000*1000); + m_scheduler = cta::make_unique<Scheduler>(*m_catalogue, *m_db, 5, 2 * 1000 * 1000); strncpy(m_tmpDir, "/tmp/DataTransferSessionTestXXXXXX", sizeof(m_tmpDir)); - if(!mkdtemp(m_tmpDir)) { + if (!mkdtemp(m_tmpDir)) { const std::string errMsg = cta::utils::errnoToString(errno); std::ostringstream msg; msg << "Failed to create directory with template" - " /tmp/DataTransferSessionTestXXXXXX: " << errMsg; - bzero(m_tmpDir, sizeof(m_tmpDir)); + " /tmp/DataTransferSessionTestXXXXXX: " << errMsg; + memset(m_tmpDir, 0, sizeof(m_tmpDir)); throw cta::exception::Exception(msg.str()); } struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); - if(stat(m_tmpDir, &statBuf)) { + memset(&statBuf, 0, sizeof(statBuf)); + if (stat(m_tmpDir, &statBuf)) { const std::string errMsg = cta::utils::errnoToString(errno); std::ostringstream msg; msg << "Failed to stat directory " << m_tmpDir << ": " << errMsg; @@ -180,18 +182,18 @@ public: system(cmd.str().c_str()); } - virtual void TearDown() { + void TearDown() override { m_scheduler.reset(); m_catalogue.reset(); m_db.reset(); // If Setup() created a temporary directory - if(m_tmpDir) { + if (m_tmpDir) { // Open the directory std::unique_ptr<DIR, std::function<int(DIR*)>> dir(opendir(m_tmpDir), closedir); - if(NULL == dir.get()) { + if (nullptr == dir) { const std::string errMsg = cta::utils::errnoToString(errno); std::ostringstream msg; msg << "Failed to open directory " << m_tmpDir << ": " << errMsg; @@ -199,12 +201,12 @@ public: } // Delete each of the files within the directory - struct dirent *entry = NULL; - while((entry = readdir(dir.get()))) { + struct dirent *entry = nullptr; + while ((entry = readdir(dir.get()))) { const std::string entryName(entry->d_name); - if(entryName != "." && entryName != "..") { + if (entryName != "." && entryName != "..") { const std::string entryPath = std::string(m_tmpDir) + "/" + entryName; - if(unlink(entryPath.c_str())) { + if (unlink(entryPath.c_str())) { const std::string errMsg = cta::utils::errnoToString(errno); std::ostringstream msg; msg << "Failed to unlink " << entryPath; @@ -214,7 +216,7 @@ public: } // Delete the now empty directory - if(rmdir(m_tmpDir)) { + if (rmdir(m_tmpDir)) { const std::string errMsg = cta::utils::errnoToString(errno); std::ostringstream msg; msg << "Failed to delete directory " << m_tmpDir << ": " << errMsg; @@ -223,23 +225,23 @@ public: } } - cta::catalogue::Catalogue &getCatalogue() { + cta::catalogue::Catalogue& getCatalogue() { cta::catalogue::Catalogue *const ptr = m_catalogue.get(); - if(NULL == ptr) { + if (nullptr == ptr) { throw FailedToGetCatalogue(); } return *ptr; } - cta::Scheduler &getScheduler() { + cta::Scheduler& getScheduler() { cta::Scheduler *const ptr = m_scheduler.get(); - if(NULL == ptr) { + if (nullptr == ptr) { throw FailedToGetScheduler(); } return *ptr; } - cta::catalogue::CreateTapeAttributes getDefaultTape(){ + cta::catalogue::CreateTapeAttributes getDefaultTape() { cta::catalogue::CreateTapeAttributes tape; tape.vid = s_vid; tape.mediaType = s_mediaType; @@ -284,7 +286,7 @@ public: return vo; } - cta::common::dataStructures::TapeDrive getDefaultTapeDrive(const std::string &driveName) { + cta::common::dataStructures::TapeDrive getDefaultTapeDrive(const std::string& driveName) { cta::common::dataStructures::TapeDrive tapeDrive; tapeDrive.driveName = driveName; tapeDrive.host = "admin_host"; @@ -301,7 +303,7 @@ public: void setupDefaultCatalogue() { using namespace cta; - auto & catalogue=getCatalogue(); + auto& catalogue = getCatalogue(); auto mountPolicy = getDefaultMountPolicy(); @@ -344,7 +346,7 @@ public: ASSERT_EQ(rule.creationLog, rule.lastModificationLog); cta::common::dataStructures::VirtualOrganization vo = getDefaultVirtualOrganization(); - catalogue.createVirtualOrganization(s_adminOnAdminHost,vo); + catalogue.createVirtualOrganization(s_adminOnAdminHost, vo); common::dataStructures::StorageClass storageClass; storageClass.name = s_storageClassName; @@ -359,11 +361,11 @@ public: const cta::optional<std::string> tapePoolSupply("value for the supply pool mechanism"); ASSERT_NO_THROW(catalogue.createTapePool(s_adminOnAdminHost, s_tapePoolName, vo.name, nbPartialTapes, tapePoolEncryption, - tapePoolSupply, tapePoolComment)); + tapePoolSupply, tapePoolComment)); const uint32_t copyNb = 1; const std::string archiveRouteComment = "Archive-route comment"; catalogue.createArchiveRoute(s_adminOnAdminHost, s_storageClassName, copyNb, s_tapePoolName, - archiveRouteComment); + archiveRouteComment); cta::catalogue::MediaType mediaType; mediaType.name = s_mediaType; @@ -373,7 +375,7 @@ public: mediaType.maxLPos = 171097; mediaType.nbWraps = 112; mediaType.comment = "comment"; - catalogue.createMediaType(s_adminOnAdminHost,mediaType); + catalogue.createMediaType(s_adminOnAdminHost, mediaType); const std::string driveName = "T10D6116"; const auto tapeDrive = getDefaultTapeDrive(driveName); @@ -385,18 +387,18 @@ public: * @param log the string containing the CTA logs * @return the map that gives for each RAO call, the associated ordered Fseqs according to the RAO algorithm result */ - std::map<size_t, std::vector<std::string>> getRAOFseqs(const std::string & log){ - std::map<size_t,std::vector<std::string>> ret; + std::map<size_t, std::vector<std::string>> getRAOFseqs(const std::string& log) { + std::map<size_t, std::vector<std::string>> ret; std::string logCopy = log; std::string recallRAOOrderMsg = "Recall order of FSEQs using RAO: "; size_t recallRAOOrderMsgSize = recallRAOOrderMsg.size(); size_t posRAOMsg = logCopy.find(recallRAOOrderMsg); size_t i = 0; - while(posRAOMsg != std::string::npos){ + while (posRAOMsg != std::string::npos) { size_t posFirstFseq = posRAOMsg + recallRAOOrderMsgSize; - size_t posLastFseq = logCopy.find("\"",posFirstFseq); - std::string stringFseq = logCopy.substr(posFirstFseq,posLastFseq - posFirstFseq); - cta::utils::splitString(stringFseq,' ',ret[i]); + size_t posLastFseq = logCopy.find('\"', posFirstFseq); + std::string stringFseq = logCopy.substr(posFirstFseq, posLastFseq - posFirstFseq); + cta::utils::splitString(stringFseq, ' ', ret[i]); logCopy = logCopy.substr(posLastFseq); posRAOMsg = logCopy.find(recallRAOOrderMsg); i++; @@ -407,27 +409,27 @@ public: private: // Prevent copying - DataTransferSessionTest(const DataTransferSessionTest &) = delete; + DataTransferSessionTest(const DataTransferSessionTest&) = delete; // Prevent assignment - DataTransferSessionTest & operator= (const DataTransferSessionTest &) = delete; + DataTransferSessionTest& operator=(const DataTransferSessionTest&) = delete; std::unique_ptr<cta::SchedulerDatabase> m_db; std::unique_ptr<cta::catalogue::Catalogue> m_catalogue; std::unique_ptr<cta::Scheduler> m_scheduler; protected: - #ifdef STDOUT_LOGGING +#ifdef STDOUT_LOGGING cta::log::StdoutLogger m_dummyLog; - #else +#else cta::log::DummyLogger m_dummyLog; - #endif +#endif // Default parameters for storage classes, etc... const std::string s_userName = "user_name"; const std::string s_diskInstance = "disk_instance"; const std::string s_storageClassName = "TestStorageClass"; - const cta::common::dataStructures::SecurityIdentity s_adminOnAdminHost = { "admin1", "host1" }; + const cta::common::dataStructures::SecurityIdentity s_adminOnAdminHost = {"admin1", "host1"}; const std::string s_tapePoolName = "TestTapePool"; const std::string s_libraryName = "TestLogicalLibrary"; const std::string s_vid = "TstVid"; // We really need size <= 6 characters due to tape label format. @@ -447,7 +449,7 @@ protected: TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy", "tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -466,8 +468,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -477,10 +479,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -497,20 +499,20 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); - for (int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a path to a remote destination file std::ostringstream remoteFilePath; remoteFilePath << "file://" << m_tmpDir << "/test" << fseq; @@ -518,7 +520,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -535,12 +537,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -551,9 +553,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -568,9 +570,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -580,9 +582,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -592,8 +594,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; castor::tape::tapeserver::daemon::DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); - + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -601,9 +602,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { ASSERT_EQ(s_vid, sess.getVid()); // 10) Check the remote files exist and have the correct size - for(auto & path: remoteFilePaths) { + for (const auto& path: remoteFilePaths) { struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); const int statRc = stat(path.substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing ASSERT_EQ(0, statRc); ASSERT_EQ(1000, statBuf.st_size); //same size of data @@ -612,10 +613,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) { // 10) Check logs std::string logToCheck = logger.getLog(); logToCheck += ""; - ASSERT_NE(std::string::npos,logToCheck.find("MSG=\"Tape session started\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " - "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" " - "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" vendor=\"TestVendor\" " - "capacityInBytes=\"12345678\"")); + ASSERT_NE(std::string::npos, logToCheck.find("MSG=\"Tape session started for read\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " + "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" " + "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" vendor=\"TestVendor\" " + "capacityInBytes=\"12345678\"")); ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" " "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" " "mountTotalUncorrectedReadErrors=\"1\" mountTotalNonMediumErrorCounts=\"2\"")); @@ -808,7 +809,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongChecksumRecall) { // 10) Check logs std::string logToCheck = logger.getLog(); logToCheck += ""; - ASSERT_NE(std::string::npos,logToCheck.find("MSG=\"Tape session started\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " + ASSERT_NE(std::string::npos,logToCheck.find("MSG=\"Tape session started for read\" thread=\"TapeRead\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" " "logicalLibrary=\"TestLogicalLibrary\" mountType=\"Retrieve\" vendor=\"TestVendor\" " "capacityInBytes=\"12345678\"")); @@ -828,7 +829,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { // to recall the first file and cancel the second. // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -847,8 +848,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -858,10 +859,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -878,19 +879,19 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; castor::tape::SCSI::Structures::zeroStruct(&data); - int fseq=1; + int fseq = 1; { // Create a path to a remote destination file std::ostringstream remoteFilePath; @@ -913,16 +914,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { { // Create a fictious file record on the tape to allow adding one to fseq=2 afterwards. auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); - tapeFileWritten.archiveFileId=666; + tapeFileWritten.archiveFileId = 666; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::checksum::ChecksumBlob::HexToByteArray("0xDEADBEEF")); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.blockId=0; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.blockId = 0; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = std::to_string(fseq); tapeFileWritten.diskFileOwnerUid = DISK_FILE_SOME_USER; @@ -935,16 +936,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { { // Create an archive file entry in the archive catalogue auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); - tapeFileWritten.archiveFileId=1000 + fseq; + tapeFileWritten.archiveFileId = 1000 + fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq + 1; - tapeFileWritten.blockId=wf.getBlockId() + 10000; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq + 1; + tapeFileWritten.blockId = wf.getBlockId() + 10000; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = std::to_string(fseq + 1); @@ -956,9 +957,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { } // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=1000 + fseq; + rReq.archiveFileID = 1000 + fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -971,9 +972,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -983,9 +984,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -995,7 +996,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -1022,7 +1023,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) { TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1041,8 +1042,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1052,10 +1053,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1070,27 +1071,27 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { int MAX_RECALLS = 50; int MAX_BULK_RECALLS = 31; - std::map<size_t,std::vector<std::string>> expectedRAOFseqOrder; + std::map<size_t, std::vector<std::string>> expectedRAOFseqOrder; //RAO for the fake drive is a std::reverse // 6) Prepare files for reading by writing them to the mock system { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); int fseq; - for (fseq=1; fseq <= MAX_RECALLS ; fseq ++) { + for (fseq = 1; fseq <= MAX_RECALLS; fseq++) { expectedRAOFseqOrder[fseq / MAX_BULK_RECALLS].push_back(std::to_string(fseq)); // Create a path to a remote destination file std::ostringstream remoteFilePath; @@ -1099,7 +1100,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -1116,12 +1117,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -1132,9 +1133,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -1146,16 +1147,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { } //As RAO with the fakedrive is a std::reverse of the vector of the files given in parameter, //we reverse all expected fseqs vectors - std::reverse(expectedRAOFseqOrder[0].begin(),expectedRAOFseqOrder[0].end()); - std::reverse(expectedRAOFseqOrder[1].begin(),expectedRAOFseqOrder[1].end()); + std::reverse(expectedRAOFseqOrder[0].begin(), expectedRAOFseqOrder[0].end()); + std::reverse(expectedRAOFseqOrder[1].begin(), expectedRAOFseqOrder[1].end()); scheduler.waitSchedulerDbSubthreadsComplete(); // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.rawLibrarySlot; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.rawLibrarySlot; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -1165,9 +1166,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = MAX_BULK_RECALLS - 1; castorConf.nbDiskThreads = 1; castorConf.useRAO = true; @@ -1178,7 +1179,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; castor::tape::tapeserver::daemon::DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -1187,9 +1188,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { ASSERT_EQ(s_vid, sess.getVid()); // 10) Check the remote files exist and have the correct size - for(auto & path: remoteFilePaths) { + for (const auto& path: remoteFilePaths) { struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); const int statRc = stat(path.substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing ASSERT_EQ(0, statRc); ASSERT_EQ(1000, statBuf.st_size); //same size of data @@ -1207,12 +1208,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecall) { "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" " "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); - ASSERT_EQ(expectedRAOFseqOrder,getRAOFseqs(logToCheck)); + ASSERT_EQ(expectedRAOFseqOrder, getRAOFseqs(logToCheck)); } TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1231,8 +1232,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeNonRAODrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1242,10 +1243,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1260,28 +1261,28 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { int MAX_RECALLS = 50; int MAX_BULK_RECALLS = 31; - std::map<size_t,std::vector<std::string>> expectedRAOOrder; + std::map<size_t, std::vector<std::string>> expectedRAOOrder; // 6) Prepare files for reading by writing them to the mock system { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); int fseq; //For the RAO orders we will have two rao calls : first with 30 files, //the second with 20 files - for (fseq=1; fseq <= MAX_RECALLS ; fseq ++) { + for (fseq = 1; fseq <= MAX_RECALLS; fseq++) { expectedRAOOrder[fseq / MAX_BULK_RECALLS].push_back(std::to_string(fseq)); // Create a path to a remote destination file std::ostringstream remoteFilePath; @@ -1290,7 +1291,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -1307,12 +1308,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -1323,9 +1324,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -1339,9 +1340,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.rawLibrarySlot; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.rawLibrarySlot; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -1351,9 +1352,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = MAX_BULK_RECALLS - 1; castorConf.nbDiskThreads = 1; castorConf.useRAO = true; @@ -1365,7 +1366,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; castor::tape::tapeserver::daemon::DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -1374,9 +1375,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { ASSERT_EQ(s_vid, sess.getVid()); // 10) Check the remote files exist and have the correct size - for(auto & path: remoteFilePaths) { + for (const auto& path: remoteFilePaths) { struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); const int statRc = stat(path.substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing ASSERT_EQ(0, statRc); ASSERT_EQ(1000, statBuf.st_size); //same size of data @@ -1394,12 +1395,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallLinearAlgorithm) { "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" " "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); - ASSERT_EQ(expectedRAOOrder,getRAOFseqs(logToCheck)); + ASSERT_EQ(expectedRAOOrder, getRAOFseqs(logToCheck)); } TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistShouldApplyLinear) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1418,8 +1419,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeNonRAODrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1429,10 +1430,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1447,28 +1448,28 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS int MAX_RECALLS = 50; int MAX_BULK_RECALLS = 31; - std::map<size_t,std::vector<std::string>> expectedRAOOrder; + std::map<size_t, std::vector<std::string>> expectedRAOOrder; // 6) Prepare files for reading by writing them to the mock system { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); int fseq; //For the RAO orders we will have two rao calls : first with 30 files, //the second with 20 files - for (fseq=1; fseq <= MAX_RECALLS ; fseq ++) { + for (fseq = 1; fseq <= MAX_RECALLS; fseq++) { expectedRAOOrder[fseq / MAX_BULK_RECALLS].push_back(std::to_string(fseq)); // Create a path to a remote destination file std::ostringstream remoteFilePath; @@ -1477,7 +1478,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -1494,12 +1495,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -1510,9 +1511,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -1526,9 +1527,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.rawLibrarySlot; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.rawLibrarySlot; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -1538,9 +1539,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = MAX_BULK_RECALLS - 1; castorConf.nbDiskThreads = 1; castorConf.useRAO = true; @@ -1553,7 +1554,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; castor::tape::tapeserver::daemon::DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -1562,9 +1563,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS ASSERT_EQ(s_vid, sess.getVid()); // 10) Check the remote files exist and have the correct size - for(auto & path: remoteFilePaths) { + for (const auto& path: remoteFilePaths) { struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); const int statRc = stat(path.substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing ASSERT_EQ(0, statRc); ASSERT_EQ(1000, statBuf.st_size); //same size of data @@ -1582,14 +1583,15 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallRAOAlgoDoesNotExistS "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" " "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); - ASSERT_NE(std::string::npos, logToCheck.find("In RAOAlgorithmFactoryFactory::createAlgorithmFactory(), unable to determine the RAO algorithm to use")); + ASSERT_NE(std::string::npos, + logToCheck.find("In RAOAlgorithmFactoryFactory::createAlgorithmFactory(), unable to determine the RAO algorithm to use")); - ASSERT_EQ(expectedRAOOrder,getRAOFseqs(logToCheck)); + ASSERT_EQ(expectedRAOOrder, getRAOFseqs(logToCheck)); } TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1608,8 +1610,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeNonRAODrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1619,10 +1621,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1637,28 +1639,28 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { int MAX_RECALLS = 30; int MAX_BULK_RECALLS = 20; - std::map<size_t,std::vector<std::string>> expectedRAOOrder; + std::map<size_t, std::vector<std::string>> expectedRAOOrder; // 6) Prepare files for reading by writing them to the mock system { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); int fseq; //For the RAO orders we will have two rao calls : first with 30 files, //the second with 20 files - for (fseq=1; fseq <= MAX_RECALLS ; fseq ++) { + for (fseq = 1; fseq <= MAX_RECALLS; fseq++) { expectedRAOOrder[fseq / MAX_BULK_RECALLS].push_back(std::to_string(fseq)); // Create a path to a remote destination file std::ostringstream remoteFilePath; @@ -1667,7 +1669,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -1684,12 +1686,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -1700,9 +1702,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -1716,9 +1718,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { // 6) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.rawLibrarySlot; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.rawLibrarySlot; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -1728,9 +1730,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { // 7) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = MAX_BULK_RECALLS - 1; castorConf.nbDiskThreads = 1; castorConf.useRAO = true; @@ -1743,7 +1745,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; castor::tape::tapeserver::daemon::DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); // 8) Run the data transfer session sess.execute(); @@ -1752,9 +1754,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { ASSERT_EQ(s_vid, sess.getVid()); // 10) Check the remote files exist and have the correct size - for(auto & path: remoteFilePaths) { + for (const auto& path: remoteFilePaths) { struct stat statBuf; - bzero(&statBuf, sizeof(statBuf)); + memset(&statBuf, 0, sizeof(statBuf)); const int statRc = stat(path.substr(7).c_str(), &statBuf); //remove the "file://" for stat-ing ASSERT_EQ(0, statRc); ASSERT_EQ(1000, statBuf.st_size); //same size of data @@ -1775,13 +1777,13 @@ TEST_P(DataTransferSessionTest, DataTransferSessionRAORecallSLTFRAOAlgorithm) { ASSERT_NE(std::string::npos, logToCheck.find("In RAOManager::queryRAO(), successfully performed RAO.")); ASSERT_NE(std::string::npos, logToCheck.find("executedRAOAlgorithm=\"sltf\"")); - ASSERT_EQ(expectedRAOOrder,getRAOFseqs(logToCheck)); + ASSERT_EQ(expectedRAOOrder, getRAOFseqs(logToCheck)); } TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1800,8 +1802,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive; // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1811,10 +1813,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1831,20 +1833,20 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); - for (int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a path to a remote destination file std::ostringstream remoteFilePath; remoteFilePath << "file://" << m_tmpDir << "/test" << fseq; @@ -1852,7 +1854,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -1869,12 +1871,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -1885,9 +1887,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -1900,9 +1902,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { // 7) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/noSuchDrive", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -1921,7 +1923,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { castor::messages::TapeserverProxyDummy initialProcess; cta::server::ProcessCapDummy capUtils; DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); ASSERT_NO_THROW(sess.execute()); std::string temp = logger.getLog(); ASSERT_NE(std::string::npos, logger.getLog().find("Could not stat path: /dev/noSuchDrive")); @@ -1930,7 +1932,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) { TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -1946,12 +1948,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { //delete is unnecessary //pointer with ownership will be passed to the application, //which will do the delete - const bool failOnMount=true; + const bool failOnMount = true; mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive(failOnMount); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester; @@ -1961,10 +1963,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -1981,20 +1983,20 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { { // Label the tape castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"], - s_vid, false); + s_vid, false); mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // And write to it castor::tape::tapeserver::daemon::VolumeInfo volInfo; - volInfo.vid=s_vid; + volInfo.vid = s_vid; castor::tape::tapeFile::WriteSession ws(*mockSys.fake.m_pathToDrive["/dev/nst0"], - volInfo , 0, true, false); + volInfo, 0, true, false); // Write a few files on the virtual tape and modify the archive name space // so that it is in sync uint8_t data[1000]; - size_t archiveFileSize=sizeof(data); + size_t archiveFileSize = sizeof(data); castor::tape::SCSI::Structures::zeroStruct(&data); - for (int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a path to a remote destination file std::ostringstream remoteFilePath; remoteFilePath << "file://" << m_tmpDir << "/test" << fseq; @@ -2002,7 +2004,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { // Create an archive file entry in the archive namespace auto tapeFileWrittenUP = cta::make_unique<cta::catalogue::TapeFileWritten>(); - auto &tapeFileWritten=*tapeFileWrittenUP; + auto& tapeFileWritten = *tapeFileWrittenUP; std::set<cta::catalogue::TapeItemWrittenPointer> tapeFileWrittenSet; tapeFileWrittenSet.insert(tapeFileWrittenUP.release()); @@ -2019,12 +2021,12 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { wf.close(); // Create file entry in the archive namespace - tapeFileWritten.archiveFileId=fseq; + tapeFileWritten.archiveFileId = fseq; tapeFileWritten.checksumBlob.insert(cta::checksum::ADLER32, cta::utils::getAdler32(data, archiveFileSize)); - tapeFileWritten.vid=volInfo.vid; - tapeFileWritten.size=archiveFileSize; - tapeFileWritten.fSeq=fseq; - tapeFileWritten.copyNb=1; + tapeFileWritten.vid = volInfo.vid; + tapeFileWritten.size = archiveFileSize; + tapeFileWritten.fSeq = fseq; + tapeFileWritten.copyNb = 1; tapeFileWritten.diskInstance = s_diskInstance; tapeFileWritten.diskFileId = fseq; @@ -2035,9 +2037,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { catalogue.filesWrittenToTape(tapeFileWrittenSet); // Schedule the retrieval of the file - std::string diskInstance="disk_instance"; + std::string diskInstance = "disk_instance"; cta::common::dataStructures::RetrieveRequest rReq; - rReq.archiveFileID=fseq; + rReq.archiveFileID = fseq; rReq.requester.name = s_userName; rReq.requester.group = "someGroup"; rReq.dstURL = remoteFilePaths.back(); @@ -2050,9 +2052,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { // 7) Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -2062,9 +2064,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { // 8) Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; castorConf.nbDiskThreads = 3; castorConf.tapeLoadTimeout = 300; @@ -2074,7 +2076,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { cta::server::ProcessCap capUtils; castor::messages::TapeserverProxyDummy initialProcess; DataTransferSession sess("tapeHost", logger, mockSys, - driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); + driveConfig, mc, initialProcess, capUtils, castorConf, scheduler); ASSERT_NO_THROW(sess.execute()); std::string temp = logger.getLog(); ASSERT_NE(std::string::npos, logger.getLog().find("Failed to mount the tape")); @@ -2095,7 +2097,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) { TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -2110,8 +2112,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { mockSys.fake.setupForVirtualDriveSLC6(); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester("user", "group"); @@ -2121,10 +2123,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -2159,7 +2161,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // Create the files and schedule the archivals - for(int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a source file. sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); sourceFiles.back()->randomFill(1000); @@ -2167,8 +2169,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { // Schedule the archival of the file cta::common::dataStructures::ArchiveRequest ar; ar.checksumBlob.insert(cta::checksum::ADLER32, sourceFiles.back()->adler32()); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); + ar.storageClass = s_storageClassName; + ar.srcURL = std::string("file://") + sourceFiles.back()->path(); ar.requester.name = requester.username; ar.requester.group = "group"; ar.fileSize = 1000; @@ -2178,16 +2180,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { ar.diskFileInfo.gid = DISK_FILE_GID; const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); + scheduler.queueArchiveWithGivenId(archiveFileId, s_diskInstance, ar, logContext); } } scheduler.waitSchedulerDbSubthreadsComplete(); // Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -2197,11 +2199,11 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { // Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestMigrationMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -2216,7 +2218,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { logToCheck += ""; ASSERT_EQ(s_vid, sess.getVid()); auto afiiter = archiveFileIds.begin(); - for(auto & sf: sourceFiles) { + for (const auto& sf: sourceFiles) { auto afi = *(afiiter++); auto afs = catalogue.getArchiveFileById(afi); ASSERT_EQ(1, afs.tapeFiles.size()); @@ -2228,14 +2230,14 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) { // Check logs for drive statistics ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" " - "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " - "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\"")); + "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " + "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\"")); ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" lifetimeMediumEfficiencyPrct=\"100\" " - "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" " - "mountReadTransients=\"10\" " - "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" " - "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); + "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" " + "mountReadTransients=\"10\" " + "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" " + "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\"")); } TEST_P(DataTransferSessionTest, DataTransferSessionWrongFileSizeMigration) { @@ -2792,7 +2794,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongFilesizeInMiddleOfBatchM TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -2807,8 +2809,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { mockSys.fake.setupForVirtualDriveSLC6(); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester("user", "group"); @@ -2818,10 +2820,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -2856,7 +2858,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // Create the files and schedule the archivals - for(int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a source file. sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); sourceFiles.back()->randomFill(1000); @@ -2864,8 +2866,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { // Schedule the archival of the file cta::common::dataStructures::ArchiveRequest ar; ar.checksumBlob.insert(cta::checksum::ADLER32, sourceFiles.back()->adler32()); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); + ar.storageClass = s_storageClassName; + ar.srcURL = std::string("file://") + sourceFiles.back()->path(); ar.requester.name = requester.username; ar.requester.group = "group"; ar.fileSize = 1000; @@ -2876,7 +2878,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { ar.diskFileInfo.gid = DISK_FILE_GID; const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); + scheduler.queueArchiveWithGivenId(archiveFileId, s_diskInstance, ar, logContext); // Delete the even files: the migration will work for half of them. if (!(fseq % 2)) sourceFiles.pop_back(); } @@ -2885,9 +2887,9 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { // Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -2897,11 +2899,11 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { // Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestMigrationMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.maxBytesBeforeFlush = 9999999; @@ -2918,22 +2920,22 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { temp += ""; ASSERT_EQ(s_vid, sess.getVid()); // We should now have 5 successfully read files. - size_t count=0; - std::string::size_type pos=0; - std::string successLog="MSG=\"File successfully read from disk\""; + size_t count = 0; + std::string::size_type pos = 0; + std::string successLog = "MSG=\"File successfully read from disk\""; while ((pos = logger.getLog().find(successLog, pos)) != std::string::npos) { - pos+=successLog.size(); + pos += successLog.size(); count++; } //std::cout << logger.getLog() << std::endl; ASSERT_EQ(5, count); cta::catalogue::TapeSearchCriteria tapeCriteria; - tapeCriteria.vid=s_vid; + tapeCriteria.vid = s_vid; auto tapeInfo = catalogue.getTapes(tapeCriteria); ASSERT_EQ(1, tapeInfo.size()); // We should have max fseq at least 10. It could be higher is a retry manages to sneak in. ASSERT_LE(10, tapeInfo.begin()->lastFSeq); - ASSERT_EQ(5*1000, tapeInfo.begin()->dataOnTapeInBytes); + ASSERT_EQ(5 * 1000, tapeInfo.begin()->dataOnTapeInBytes); // Check logs for drive statistics std::string logToCheck = logger.getLog(); @@ -2956,7 +2958,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) { // TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -2971,8 +2973,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { mockSys.fake.setupForVirtualDriveSLC6(); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester("user", "group"); @@ -2982,10 +2984,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -3021,7 +3023,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // Create the files and schedule the archivals - for(int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a source file. sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); sourceFiles.back()->randomFill(1000); @@ -3029,8 +3031,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { // Schedule the archival of the file cta::common::dataStructures::ArchiveRequest ar; ar.checksumBlob.insert(cta::checksum::ADLER32, sourceFiles.back()->adler32()); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); + ar.storageClass = s_storageClassName; + ar.srcURL = std::string("file://") + sourceFiles.back()->path(); ar.requester.name = requester.username; ar.requester.group = "group"; ar.fileSize = 1000; @@ -3040,16 +3042,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { ar.diskFileInfo.gid = DISK_FILE_GID; const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); + scheduler.queueArchiveWithGivenId(archiveFileId, s_diskInstance, ar, logContext); } } scheduler.waitSchedulerDbSubthreadsComplete(); // Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -3059,11 +3061,11 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { // Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestMigrationMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -3093,7 +3095,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { checksumBlob.insert(cta::checksum::ADLER32, (*sourceFiles_front)->adler32()); ASSERT_EQ(afs.checksumBlob, checksumBlob); ASSERT_EQ(1000, afs.fileSize); - } else { + } + else { ASSERT_FALSE(afsItor.hasMore()); } // The tape should now be marked as full @@ -3107,9 +3110,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { // Check logs for drive statistics std::string logToCheck = logger.getLog(); logToCheck += ""; - ASSERT_NE(std::string::npos,logToCheck.find("MSG=\"Tape session started\" thread=\"TapeWrite\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " - "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" logicalLibrary=\"TestLogicalLibrary\" " - "mountType=\"ArchiveForUser\" vendor=\"TestVendor\" capacityInBytes=\"12345678\"")); + ASSERT_NE(std::string::npos, + logToCheck.find("MSG=\"Tape session started for write\" thread=\"TapeWrite\" tapeDrive=\"T10D6116\" tapeVid=\"TstVid\" " + "mountId=\"1\" vo=\"vo\" mediaType=\"LTO7M\" tapePool=\"TestTapePool\" logicalLibrary=\"TestLogicalLibrary\" " + "mountType=\"ArchiveForUser\" vendor=\"TestVendor\" capacityInBytes=\"12345678\"")); ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" serialNumber=\"123456\" " "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\"")); @@ -3123,7 +3127,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) { TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -3137,8 +3141,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { mockSys.fake.setupForVirtualDriveSLC6(); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester("user", "group"); @@ -3148,10 +3152,10 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -3175,7 +3179,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { //which will do the delete const uint64_t tapeSize = 5000; mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive(tapeSize, - castor::tape::tapeserver::drive::FakeDrive::OnFlush); + castor::tape::tapeserver::drive::FakeDrive::OnFlush); // We can prepare files for writing on the drive. // Tempfiles are in this scope so they are kept alive @@ -3188,7 +3192,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind(); // Create the files and schedule the archivals - for(int fseq=1; fseq <= 10 ; fseq ++) { + for (int fseq = 1; fseq <= 10; fseq++) { // Create a source file. sourceFiles.emplace_back(cta::make_unique<unitTests::TempFile>()); sourceFiles.back()->randomFill(1000); @@ -3196,8 +3200,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { // Schedule the archival of the file cta::common::dataStructures::ArchiveRequest ar; ar.checksumBlob.insert(cta::checksum::ADLER32, sourceFiles.back()->adler32()); - ar.storageClass=s_storageClassName; - ar.srcURL=std::string("file://") + sourceFiles.back()->path(); + ar.storageClass = s_storageClassName; + ar.srcURL = std::string("file://") + sourceFiles.back()->path(); ar.requester.name = requester.username; ar.requester.group = "group"; ar.fileSize = 1000; @@ -3207,16 +3211,16 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { ar.diskFileInfo.gid = DISK_FILE_GID; const auto archiveFileId = scheduler.checkAndGetNextArchiveFileId(s_diskInstance, ar.storageClass, ar.requester, logContext); archiveFileIds.push_back(archiveFileId); - scheduler.queueArchiveWithGivenId(archiveFileId,s_diskInstance,ar,logContext); + scheduler.queueArchiveWithGivenId(archiveFileId, s_diskInstance, ar, logContext); } } scheduler.waitSchedulerDbSubthreadsComplete(); // Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -3226,11 +3230,11 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { // Create the data transfer session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestMigrationMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -3260,7 +3264,8 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { checksumBlob.insert(cta::checksum::ADLER32, (*sourceFiles_front)->adler32()); ASSERT_EQ(afs.checksumBlob, checksumBlob); ASSERT_EQ(1000, afs.fileSize); - } else { + } + else { ASSERT_FALSE(afsItor.hasMore()); } // The tape should now be marked as full @@ -3286,7 +3291,7 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) { TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { // 0) Prepare the logger for everyone - cta::log::StringLogger logger("dummy","tapeServerUnitTest",cta::log::DEBUG); + cta::log::StringLogger logger("dummy", "tapeServerUnitTest", cta::log::DEBUG); cta::log::LogContext logContext(logger); setupDefaultCatalogue(); @@ -3300,8 +3305,8 @@ TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { mockSys.fake.setupForVirtualDriveSLC6(); // 4) Create the scheduler - auto & catalogue = getCatalogue(); - auto & scheduler = getScheduler(); + auto& catalogue = getCatalogue(); + auto& scheduler = getScheduler(); // Always use the same requester const cta::common::dataStructures::SecurityIdentity requester("user", "group"); @@ -3311,10 +3316,10 @@ TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { std::list<std::string> remoteFilePaths; // 5) Create the environment for the migration to happen (library + tape) - const std::string libraryComment = "Library comment"; + const std::string libraryComment = "Library comment"; const bool libraryIsDisabled = false; catalogue.createLogicalLibrary(s_adminOnAdminHost, s_libraryName, - libraryIsDisabled, libraryComment); + libraryIsDisabled, libraryComment); { auto libraries = catalogue.getLogicalLibraries(); ASSERT_EQ(1, libraries.size()); @@ -3338,14 +3343,14 @@ TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { //which will do the delete const uint64_t tapeSize = 5000; mockSys.fake.m_pathToDrive["/dev/nst0"] = new castor::tape::tapeserver::drive::FakeDrive(tapeSize, - castor::tape::tapeserver::drive::FakeDrive::OnFlush); + castor::tape::tapeserver::drive::FakeDrive::OnFlush); // Report the drive's existence and put it up in the drive register. cta::tape::daemon::TpconfigLine driveConfig("T10D6116", "TestLogicalLibrary", "/dev/tape_T10D6116", "dummy"); cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=driveConfig.unitName; - driveInfo.logicalLibrary=driveConfig.logicalLibrary; - driveInfo.host="host"; + driveInfo.driveName = driveConfig.unitName; + driveInfo.logicalLibrary = driveConfig.logicalLibrary; + driveInfo.host = "host"; // We need to create the drive in the registry before being able to put it up. scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, logContext); cta::common::dataStructures::DesiredDriveState driveState; @@ -3355,11 +3360,11 @@ TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { // Create cleaner session DataTransferConfig castorConf; - castorConf.bufsz = 1024*1024; // 1 MB memory buffers + castorConf.bufsz = 1024 * 1024; // 1 MB memory buffers castorConf.nbBufs = 10; - castorConf.bulkRequestRecallMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestRecallMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestRecallMaxFiles = 1000; - castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100)*1000*1000*1000; + castorConf.bulkRequestMigrationMaxBytes = UINT64_C(100) * 1000 * 1000 * 1000; castorConf.bulkRequestMigrationMaxFiles = 1000; castorConf.nbDiskThreads = 1; castorConf.tapeLoadTimeout = 300; @@ -3383,9 +3388,9 @@ TEST_P(DataTransferSessionTest, CleanerSessionFailsShouldPutTheDriveDown) { ); auto endOfSessionAction = cleanerSession.execute(); //the tape has not been labeled so the cleanerSession should have failed and put the drive down. - cta::common::dataStructures::DesiredDriveState newDriveState = scheduler.getDesiredDriveState(driveConfig.unitName,logContext); + cta::common::dataStructures::DesiredDriveState newDriveState = scheduler.getDesiredDriveState(driveConfig.unitName, logContext); ASSERT_FALSE(newDriveState.up); - ASSERT_EQ(castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN,endOfSessionAction); + ASSERT_EQ(castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN, endOfSessionAction); } #undef TEST_MOCK_DB @@ -3400,7 +3405,7 @@ INSTANTIATE_TEST_CASE_P(MockSchedulerTest, SchedulerTest, static cta::OStoreDBFactory<cta::objectstore::BackendVFS> OStoreDBFactoryVFS; INSTANTIATE_TEST_CASE_P(OStoreDBPlusMockSchedulerTestVFS, DataTransferSessionTest, - ::testing::Values(DataTransferSessionTestParam(OStoreDBFactoryVFS))); + ::testing::Values(DataTransferSessionTestParam(OStoreDBFactoryVFS))); #endif #ifdef TEST_RADOS diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.cpp index 8d940f0827c00f681a8b1925daeec7aa5d5757bf..6e61e06de56f27e6730361ba4acdd1b511cf4619 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.cpp @@ -49,7 +49,7 @@ void DiskReadTask::execute(cta::log::LogContext& lc, cta::disk::DiskFileFactory cta::utils::Timer totalTime(localTime); size_t blockId=0; size_t migratingFileSize=m_archiveJob->archiveFile.fileSize; - MemBlock* mb=NULL; + MemBlock* mb = nullptr; // This out-of-try-catch variables allows us to record the stage of the // process we're in, and to count the error if it occurs. // We will not record errors for an empty string. This will allow us to @@ -122,7 +122,7 @@ void DiskReadTask::execute(cta::log::LogContext& lc, cta::disk::DiskFileFactory // We are done with the block, push it to the write task m_nextTask.pushDataBlock(mb); - mb=NULL; + mb = nullptr; } //end of while(migratingFileSize>0) m_stats.filesCount++; @@ -157,7 +157,7 @@ void DiskReadTask::execute(cta::log::LogContext& lc, cta::disk::DiskFileFactory } mb->markAsFailed(e.getMessageValue(), 666); // TODO - Drop error code m_nextTask.pushDataBlock(mb); - mb=NULL; + mb = nullptr; cta::log::ScopedParamContainer spc(lc); spc.add("blockID",blockId) @@ -186,7 +186,7 @@ void DiskReadTask::circulateAllBlocks(size_t fromBlockId, MemBlock * mb){ mb->m_fileid = m_archiveJob->archiveFile.archiveFileID; mb->markAsCancelled(); m_nextTask.pushDataBlock(mb); - mb=NULL; + mb = nullptr; } //end of while } diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.hpp b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.hpp index c600047f7b080b57ea11f738561f923ba96843c5..54f1495c8f1513e1800cdf4b0ed6dfc46cfbc013 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTask.hpp @@ -78,7 +78,7 @@ private: /** * Circulate the remaining free blocks after an error * @param fromBlockId the number of already processed - * @param mb pointer to a possible already popped free block (NULL otherwise) + * @param mb pointer to a possible already popped free block (nullptr otherwise) */ void circulateAllBlocks(size_t fromBlockId, MemBlock * mb); /** diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTaskTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTaskTest.cpp index 61f0247e4bb4446de39f8762dafb421fa87f6ea6..314976aa291d15a2de559bf1bd5a5ddd3ed219f0 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskReadTaskTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskReadTaskTest.cpp @@ -36,7 +36,7 @@ namespace unitTests{ class TestingArchiveJob: public cta::ArchiveJob { public: TestingArchiveJob(): cta::ArchiveJob(nullptr, - *((cta::catalogue::Catalogue *)NULL), cta::common::dataStructures::ArchiveFile(), + *((cta::catalogue::Catalogue *)nullptr), cta::common::dataStructures::ArchiveFile(), "", cta::common::dataStructures::TapeFile()) { } }; diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskReadThreadPool.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskReadThreadPool.cpp index 3c9d46b576c3c82be007b59dcc5e0094f3e05951..aaedfebc82ee0f1407daa7cd17356729482ef666 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskReadThreadPool.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskReadThreadPool.cpp @@ -91,7 +91,7 @@ void DiskReadThreadPool::push(DiskReadTask *t) { void DiskReadThreadPool::finish() { /* Insert one endOfSession per thread */ for (size_t i=0; i<m_threads.size(); i++) { - m_tasks.push(NULL); + m_tasks.push(nullptr); } } @@ -158,7 +158,7 @@ void DiskReadThreadPool::DiskReadWorkerThread::run() { while(1) { task.reset( m_parent.popAndRequestMore(m_lc)); m_threadStat.waitInstructionsTime += localTime.secs(cta::utils::Timer::resetCounter); - if (NULL!=task.get()) { + if (nullptr != task.get()) { task->execute(m_lc, m_diskFileFactory,m_parent.m_watchdog, m_threadID); m_threadStat += task->getTaskStats(); } diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTask.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTask.cpp index da1f90baa8525aa770cee44e467d57992aa6dd38..915825338bfa6ad325b24ed2cb414b3fc191b2ba 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTask.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTask.cpp @@ -63,7 +63,7 @@ bool DiskWriteTask::execute(RecallReportPacker& reporter,cta::log::LogContext& int blockId = 0; unsigned long checksum = Payload::zeroAdler32(); - while(1) { + while(true) { if(MemBlock* const mb = m_fifo.pop()) { m_stats.waitDataTime+=localTime.secs(cta::utils::Timer::resetCounter); AutoReleaseBlock<RecallMemoryManager> releaser(mb,m_memManager); @@ -108,7 +108,7 @@ bool DiskWriteTask::execute(RecallReportPacker& reporter,cta::log::LogContext& currentErrorToCount = ""; blockId++; - //end if block non NULL + //end if block non nullptr } else if(isVerifyOnly) { // No file to close, we are done break; @@ -134,7 +134,7 @@ bool DiskWriteTask::execute(RecallReportPacker& reporter,cta::log::LogContext& cs << std::hex << std::nouppercase << std::setfill('0') << std::setw(8) << (uint32_t)checksum; m_retrieveJob->transferredChecksumValue = cs.str(); } - reporter.reportCompletedJob(std::move(m_retrieveJob)); + reporter.reportCompletedJob(std::move(m_retrieveJob), lc); m_stats.waitReportingTime+=localTime.secs(cta::utils::Timer::resetCounter); m_stats.transferTime = transferTime.secs(); m_stats.totalTime = totalTime.secs(); @@ -166,7 +166,7 @@ bool DiskWriteTask::execute(RecallReportPacker& reporter,cta::log::LogContext& params.add("errorMessage", e.getMessageValue()); logWithStat(cta::log::ERR, isVerifyOnly ? "File verification failed" : "File writing to disk failed", lc); lc.logBacktrace(cta::log::ERR, e.backtrace()); - reporter.reportFailedJob(std::move(m_retrieveJob), e); + reporter.reportFailedJob(std::move(m_retrieveJob), e, lc); watchdog.deleteParameter("stillOpenFileForThread"+ std::to_string((long long)threadID)); diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp index 07bc73623a45f54a861d0f84453fb61f875f0a98..220e8ade9ce2013822c202002028984e36625026 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteTaskTest.cpp @@ -67,20 +67,20 @@ namespace unitTests{ using namespace castor::tape::tapeserver::client; using namespace cta::disk; struct MockRecallReportPacker : public RecallReportPacker { - void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob) override { + void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); completeJobs++; } - void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex) override { + void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); failedJobs++; } void disableBulk() override {} - void reportEndOfSession() override { + void reportEndOfSession(cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); endSessions++; } - void reportEndOfSessionWithErrors(const std::string msg, int error_code) override { + void reportEndOfSessionWithErrors(const std::string& msg, int error_code, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); endSessionsWithError++; } @@ -97,7 +97,7 @@ namespace unitTests{ int endSessions; int endSessionsWithError; }; - + TEST(castor_tape_tapeserver_daemon, DiskWriteTaskFailedBlock){ using ::testing::_; @@ -132,7 +132,7 @@ namespace unitTests{ MemBlock* mb=mm.getFreeBlock(); t.pushDataBlock(mb); - t.pushDataBlock(NULL); + t.pushDataBlock(nullptr); castor::messages::TapeserverProxyDummy tspd; cta::TapeMountDummy tmd; RecallWatchDog rwd(1,1,tspd,tmd,"", lc); diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.cpp index b1cac5b8ce3db3c6fab305020d5b1ac122e1a91c..d46b895f599bdc62bde2a1e08b6e3677868aef64 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.cpp @@ -21,6 +21,7 @@ #include <memory> #include <sstream> +#include <utility> namespace castor { namespace tape { @@ -31,18 +32,17 @@ namespace daemon { // constructor //------------------------------------------------------------------------------ DiskWriteThreadPool::DiskWriteThreadPool(int nbThread, - RecallReportPacker& report, - RecallWatchDog& recallWatchDog, - cta::log::LogContext lc, - const std::string & xrootPrivateKeyPath, - uint16_t xrootTimeout): - m_xrootPrivateKeyPath(xrootPrivateKeyPath), + RecallReportPacker& report, + RecallWatchDog& recallWatchDog, + const cta::log::LogContext& lc, + std::string xrootPrivateKeyPath, + uint16_t xrootTimeout) : + m_xrootPrivateKeyPath(std::move(xrootPrivateKeyPath)), m_xrootTimeout(xrootTimeout), - m_reporter(report),m_watchdog(recallWatchDog),m_lc(lc) -{ + m_reporter(report), m_watchdog(recallWatchDog), m_lc(lc) { m_lc.pushOrReplace(cta::log::Param("threadCount", nbThread)); - for(int i=0; i<nbThread; i++) { - DiskWriteWorkerThread * thr = new DiskWriteWorkerThread(*this); + for (int i = 0; i < nbThread; i++) { + auto *thr = new DiskWriteWorkerThread(*this); m_threads.push_back(thr); } m_lc.log(cta::log::DEBUG, "Created threads in DiskWriteThreadPool::DiskWriteThreadPool"); @@ -55,7 +55,7 @@ DiskWriteThreadPool::~DiskWriteThreadPool() { // A barrier preventing destruction of the object if a poster has still not // returned yet from the push or finish function. cta::threading::MutexLocker ml(m_pusherProtection); - while (m_threads.size()) { + while (!m_threads.empty()) { delete m_threads.back(); m_threads.pop_back(); } @@ -66,9 +66,8 @@ DiskWriteThreadPool::~DiskWriteThreadPool() { // DiskWriteThreadPool::startThreads //------------------------------------------------------------------------------ void DiskWriteThreadPool::startThreads() { - for (std::vector<DiskWriteWorkerThread *>::iterator i=m_threads.begin(); - i != m_threads.end(); ++i) { - (*i)->start(); + for (const auto & m_thread : m_threads) { + m_thread->start(); } m_lc.log(cta::log::INFO, "Starting threads in DiskWriteThreadPool::DiskWriteThreadPool"); } @@ -77,9 +76,8 @@ void DiskWriteThreadPool::startThreads() { // DiskWriteThreadPool::waitThreads //------------------------------------------------------------------------------ void DiskWriteThreadPool::waitThreads() { - for (std::vector<DiskWriteWorkerThread *>::iterator i=m_threads.begin(); - i != m_threads.end(); ++i) { - (*i)->wait(); + for (const auto & m_thread : m_threads) { + m_thread->wait(); } m_lc.log(cta::log::INFO, "All DiskWriteThreadPool threads are now complete"); } @@ -87,10 +85,10 @@ void DiskWriteThreadPool::waitThreads() { //------------------------------------------------------------------------------ // DiskWriteThreadPool::push //------------------------------------------------------------------------------ -void DiskWriteThreadPool::push(DiskWriteTask *t) { +void DiskWriteThreadPool::push(DiskWriteTask *t) { { - if(NULL==t){ - throw cta::exception::Exception("NULL task should not been directly pushed into DiskWriteThreadPool"); + if (nullptr == t) { + throw cta::exception::Exception("nullptr task should not been directly pushed into DiskWriteThreadPool"); } } cta::threading::MutexLocker ml(m_pusherProtection); @@ -102,41 +100,45 @@ void DiskWriteThreadPool::push(DiskWriteTask *t) { //------------------------------------------------------------------------------ void DiskWriteThreadPool::finish() { cta::threading::MutexLocker ml(m_pusherProtection); - for (size_t i=0; i<m_threads.size(); i++) { - m_tasks.push(NULL); + for (size_t i = 0; i < m_threads.size(); i++) { + m_tasks.push(nullptr); } } + //------------------------------------------------------------------------------ //addThreadStats //------------------------------------------------------------------------------ -void DiskWriteThreadPool::addThreadStats(const DiskStats& other){ +void DiskWriteThreadPool::addThreadStats(const DiskStats& other) { cta::threading::MutexLocker lock(m_statAddingProtection); - m_pooldStat+=other; + m_pooldStat += other; } + //------------------------------------------------------------------------------ //logWithStat //------------------------------------------------------------------------------ -void DiskWriteThreadPool::logWithStat(int level, const std::string& message){ +void DiskWriteThreadPool::logWithStat(int level, const std::string& message) { m_pooldStat.totalTime = m_totalTime.secs(); cta::log::ScopedParamContainer params(m_lc); params.add("poolReadWriteTime", m_pooldStat.readWriteTime) - .add("poolChecksumingTime",m_pooldStat.checksumingTime) - .add("poolWaitDataTime",m_pooldStat.waitDataTime) - .add("poolWaitReportingTime",m_pooldStat.waitReportingTime) - .add("poolCheckingErrorTime",m_pooldStat.checkingErrorTime) - .add("poolOpeningTime",m_pooldStat.openingTime) + .add("poolChecksumingTime", m_pooldStat.checksumingTime) + .add("poolWaitDataTime", m_pooldStat.waitDataTime) + .add("poolWaitReportingTime", m_pooldStat.waitReportingTime) + .add("poolCheckingErrorTime", m_pooldStat.checkingErrorTime) + .add("poolOpeningTime", m_pooldStat.openingTime) .add("poolClosingTime", m_pooldStat.closingTime) - .add("poolRealTime",m_pooldStat.totalTime) - .add("poolFileCount",m_pooldStat.filesCount) + .add("poolRealTime", m_pooldStat.totalTime) + .add("poolFileCount", m_pooldStat.filesCount) .add("poolDataVolume", m_pooldStat.dataVolume) .add("poolGlobalPayloadTransferSpeedMBps", - m_pooldStat.totalTime?1.0*m_pooldStat.dataVolume/1000/1000/m_pooldStat.totalTime:0) + m_pooldStat.totalTime ? 1.0 * m_pooldStat.dataVolume / 1000 / 1000 / m_pooldStat.totalTime : 0) .add("poolAverageDiskPerformanceMBps", - m_pooldStat.transferTime?1.0*m_pooldStat.dataVolume/1000/1000/m_pooldStat.transferTime:0.0) + m_pooldStat.transferTime ? 1.0 * m_pooldStat.dataVolume / 1000 / 1000 / m_pooldStat.transferTime : 0.0) .add("poolOpenRWCloseToTransferTimeRatio", - m_pooldStat.transferTime?(m_pooldStat.openingTime+m_pooldStat.readWriteTime+m_pooldStat.closingTime)/m_pooldStat.transferTime:0.0); - m_lc.log(level,message); + m_pooldStat.transferTime ? (m_pooldStat.openingTime + m_pooldStat.readWriteTime + m_pooldStat.closingTime) / m_pooldStat.transferTime + : 0.0); + m_lc.log(level, message); } + //------------------------------------------------------------------------------ // DiskWriteWorkerThread::run //------------------------------------------------------------------------------ @@ -145,43 +147,43 @@ void DiskWriteThreadPool::DiskWriteWorkerThread::run() { logParams.add("thread", "DiskWrite") .add("threadID", m_threadID); m_lc.log(cta::log::INFO, "Starting DiskWriteWorkerThread"); - - std::unique_ptr<DiskWriteTask> task; + + std::unique_ptr<DiskWriteTask> task; cta::utils::Timer localTime; cta::utils::Timer totalTime(localTime); - - while(1) { + + while (true) { task.reset(m_parentThreadPool.m_tasks.pop()); - m_threadStat.waitInstructionsTime+=localTime.secs(cta::utils::Timer::resetCounter); - if (NULL!=task.get()) { - if(false==task->execute(m_parentThreadPool.m_reporter,m_lc, - m_diskFileFactory, m_parentThreadPool.m_watchdog, m_threadID)) { + m_threadStat.waitInstructionsTime += localTime.secs(cta::utils::Timer::resetCounter); + if (nullptr != task) { + if (false == task->execute(m_parentThreadPool.m_reporter, m_lc, + m_diskFileFactory, m_parentThreadPool.m_watchdog, m_threadID)) { ++m_parentThreadPool.m_failedWriteCount; - cta::log::ScopedParamContainer logParams(m_lc); - logParams.add("errorCount", m_parentThreadPool.m_failedWriteCount); + cta::log::ScopedParamContainer params(m_lc); + params.add("errorCount", m_parentThreadPool.m_failedWriteCount); m_lc.log(cta::log::ERR, "Task failed: counting another error for this session"); } - m_threadStat+=task->getTaskStats(); - } //end of task!=NULL + m_threadStat += task->getTaskStats(); + } //end of task!=nullptr else { - m_lc.log(cta::log::DEBUG,"DiskWriteWorkerThread exiting: no more work"); + m_lc.log(cta::log::DEBUG, "DiskWriteWorkerThread exiting: no more work"); break; } - } //enf of while(1) + } //enf of while(true) m_threadStat.totalTime = totalTime.secs(); logWithStat(cta::log::INFO, "Finishing DiskWriteWorkerThread"); m_parentThreadPool.addThreadStats(m_threadStat); - if(0 == --m_parentThreadPool.m_nbActiveThread){ + if (0 == --m_parentThreadPool.m_nbActiveThread) { - //Im the last Thread alive, report end of session - if(m_parentThreadPool.m_failedWriteCount==0){ - m_parentThreadPool.m_reporter.reportEndOfSession(); + // In the last Thread alive, report end of session + if (m_parentThreadPool.m_failedWriteCount == 0) { + m_parentThreadPool.m_reporter.reportEndOfSession(m_lc); m_parentThreadPool.logWithStat(cta::log::INFO, "As last exiting DiskWriteWorkerThread, reported a successful end of session"); } - else{ - m_parentThreadPool.m_reporter.reportEndOfSessionWithErrors("End of recall session with error(s)",666); - cta::log::ScopedParamContainer logParams(m_lc); - logParams.add("errorCount", m_parentThreadPool.m_failedWriteCount); + else { + m_parentThreadPool.m_reporter.reportEndOfSessionWithErrors("End of recall session with error(s)", 666, m_lc); + cta::log::ScopedParamContainer params(m_lc); + params.add("errorCount", m_parentThreadPool.m_failedWriteCount); m_parentThreadPool.logWithStat(cta::log::INFO, "As last exiting DiskWriteWorkerThread, reported an end of session with errors"); } const double deliveryTime = m_parentThreadPool.m_totalTime.secs(); @@ -195,24 +197,28 @@ void DiskWriteThreadPool::DiskWriteWorkerThread::run() { void DiskWriteThreadPool::DiskWriteWorkerThread:: logWithStat(int level, const std::string& msg) { cta::log::ScopedParamContainer params(m_lc); - params.add("threadReadWriteTime", m_threadStat.readWriteTime) - .add("threadChecksumingTime",m_threadStat.checksumingTime) - .add("threadWaitDataTime",m_threadStat.waitDataTime) - .add("threadWaitReportingTime",m_threadStat.waitReportingTime) - .add("threadCheckingErrorTime",m_threadStat.checkingErrorTime) - .add("threadOpeningTime",m_threadStat.openingTime) - .add("threadClosingTime", m_threadStat.closingTime) - .add("threadTransferTime",m_threadStat.transferTime) - .add("threadTotalTime",m_threadStat.totalTime) - .add("threadDataVolume",m_threadStat.dataVolume) - .add("threadFileCount",m_threadStat.filesCount) - .add("threadGlobalPayloadTransferSpeedMBps", - m_threadStat.totalTime?1.0*m_threadStat.dataVolume/1000/1000/m_threadStat.totalTime:0) - .add("threadAverageDiskPerformanceMBps", - m_threadStat.transferTime?1.0*m_threadStat.dataVolume/1000/1000/m_threadStat.transferTime:0.0) - .add("threadOpenRWCloseToTransferTimeRatio", - m_threadStat.transferTime?(m_threadStat.openingTime+m_threadStat.readWriteTime+m_threadStat.closingTime)/m_threadStat.transferTime:0.0); - m_lc.log(level,msg); + params.add("threadReadWriteTime", m_threadStat.readWriteTime) + .add("threadChecksumingTime", m_threadStat.checksumingTime) + .add("threadWaitDataTime", m_threadStat.waitDataTime) + .add("threadWaitReportingTime", m_threadStat.waitReportingTime) + .add("threadCheckingErrorTime", m_threadStat.checkingErrorTime) + .add("threadOpeningTime", m_threadStat.openingTime) + .add("threadClosingTime", m_threadStat.closingTime) + .add("threadTransferTime", m_threadStat.transferTime) + .add("threadTotalTime", m_threadStat.totalTime) + .add("threadDataVolume", m_threadStat.dataVolume) + .add("threadFileCount", m_threadStat.filesCount) + .add("threadGlobalPayloadTransferSpeedMBps", + m_threadStat.totalTime ? 1.0 * m_threadStat.dataVolume / 1000 / 1000 / m_threadStat.totalTime : 0) + .add("threadAverageDiskPerformanceMBps", + m_threadStat.transferTime ? 1.0 * m_threadStat.dataVolume / 1000 / 1000 / m_threadStat.transferTime : 0.0) + .add("threadOpenRWCloseToTransferTimeRatio", + m_threadStat.transferTime ? (m_threadStat.openingTime + m_threadStat.readWriteTime + m_threadStat.closingTime) / + m_threadStat.transferTime : 0.0); + m_lc.log(level, msg); +} +} +} +} } -}}}} diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.hpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.hpp index a6de06c543689082ac130e020b5f080af86ceac9..1bc38fedc892f9f2fd18d32c9edaa3ac8113baea 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPool.hpp @@ -29,7 +29,9 @@ #include "disk/RadosStriperPool.hpp" #include "common/Timer.hpp" #include <vector> + #define __STDC_FORMAT_MACROS + #include <inttypes.h> namespace castor { @@ -53,35 +55,37 @@ public: * be no side effect on the caller's logs. * @param xrootPrivateKeyPath the path to the xroot private key file. */ - DiskWriteThreadPool(int nbThread, - RecallReportPacker& reportPacker, - RecallWatchDog& recallWatchDog, - cta::log::LogContext lc, - const std::string & xrootPrivateKeyPath, - uint16_t xrootTimeout); + DiskWriteThreadPool(int nbThread, + RecallReportPacker& reportPacker, + RecallWatchDog& recallWatchDog, + const cta::log::LogContext& lc, + std::string xrootPrivateKeyPath, + uint16_t xrootTimeout); + /** * Destructor: we suppose the threads are no running (waitThreads() should - * be called befor destruction unless the threads were not started. + * be called before destruction unless the threads were not started. */ virtual ~DiskWriteThreadPool(); - + /** * Starts the thread created at construction time. */ - + void startThreads(); + /** * Waits for completion of all the pool's threads. */ void waitThreads(); - + /** * Pushes a pointer to a task. The thread pool owns the task and will * de-allocate it. * @param t pointer to the task */ void push(DiskWriteTask *t); - + /** * Signals to the thread pool that there will be no more tasks pushed to it, * and that the threads can therefore complete. @@ -93,43 +97,45 @@ private: cta::threading::AtomicCounter<int> m_nbActiveThread; /** Thread safe counter for failed tasks */ cta::threading::AtomicCounter<int> m_failedWriteCount; - + /** * Private class implementing the worker threads. */ - class DiskWriteWorkerThread: private cta::threading::Thread { + class DiskWriteWorkerThread : private cta::threading::Thread { public: - DiskWriteWorkerThread(DiskWriteThreadPool & manager): - m_threadID(manager.m_nbActiveThread++),m_parentThreadPool(manager), - m_lc(m_parentThreadPool.m_lc), - m_diskFileFactory(manager.m_xrootPrivateKeyPath, - manager.m_xrootTimeout, manager.m_striperPool) - { + explicit DiskWriteWorkerThread(DiskWriteThreadPool& manager) : + m_threadID(manager.m_nbActiveThread++), m_parentThreadPool(manager), + m_lc(m_parentThreadPool.m_lc), + m_diskFileFactory(manager.m_xrootPrivateKeyPath, + manager.m_xrootTimeout, manager.m_striperPool) { // This thread Id will remain for the rest of the thread's lifetime (and - // also context's lifetime) so ne need for a scope. + // also context's lifetime) so no need for a scope. m_lc.pushOrReplace(cta::log::Param("threadID", m_threadID)); - m_lc.log(cta::log::INFO,"DiskWrite Thread created"); + m_lc.log(cta::log::INFO, "DiskWrite Thread created"); } - + void start() { cta::threading::Thread::start(); } + void wait() { cta::threading::Thread::wait(); } + private: void logWithStat(int level, const std::string& message); + /* - * For measuring how long are the the different steps + * For measuring how long are the different steps */ DiskStats m_threadStat; - + /** * To identify the thread */ const int m_threadID; - + /** * The owning thread pool */ - DiskWriteThreadPool & m_parentThreadPool; - + DiskWriteThreadPool& m_parentThreadPool; + /** * For logging the event */ @@ -143,14 +149,15 @@ private: virtual void run(); }; + /** * When a thread finishm it call this function to Add its stats to one one of the * Threadpool * @param threadStats */ void addThreadStats(const DiskStats& threadStats); - - + + /** * When the last thread finish, we log all m_pooldStat members + message * at the given level @@ -158,26 +165,26 @@ private: * @param message */ void logWithStat(int level, const std::string& message); - + /** The actual container for the thread objects */ std::vector<DiskWriteWorkerThread *> m_threads; /** Mutex protecting the pushers of new tasks from having the object deleted * under their feet. */ cta::threading::Mutex m_pusherProtection; - + /** To protect addThreadStats from concurrent calls */ cta::threading::Mutex m_statAddingProtection; protected: /** The (thread safe) queue of tasks */ - cta::threading::BlockingQueue<DiskWriteTask*> m_tasks; - + cta::threading::BlockingQueue<DiskWriteTask *> m_tasks; + /** * Parameter: path to xroot private key */ std::string m_xrootPrivateKeyPath; - + /** * Parameter: xroot timeout */ @@ -198,17 +205,20 @@ private: * Measure the thread pool's lifetime */ cta::utils::Timer m_totalTime; - + /** Reference to the report packer where tasks report the result of their * individual files and the end of session (for the last thread) */ RecallReportPacker& m_reporter; - + /** Reference to the session watchdog, allowing reporting of errors to it. */ RecallWatchDog& m_watchdog; - + /** logging context that will be copied by each thread for individual context */ cta::log::LogContext m_lc; }; -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp index 0eeb827460c8c2bad19c319fccf32caac04ce84c..71508fb7d123ea0750b677e824cc46af7f462f40 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/DiskWriteThreadPoolTest.cpp @@ -127,7 +127,7 @@ namespace unitTests{ mb->m_fileid=i+1; mb->m_fileBlock=0; t->pushDataBlock(mb); - t->pushDataBlock(NULL); + t->pushDataBlock(nullptr); dwtp.push(t); } diff --git a/tapeserver/castor/tape/tapeserver/daemon/EmptyDriveProbe.cpp b/tapeserver/castor/tape/tapeserver/daemon/EmptyDriveProbe.cpp index 467a92dc01ce16332ae338c1eb42662af7c8b1ec..629206bb09363eb0c3a7ef312bc0f8c357c41feb 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/EmptyDriveProbe.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/EmptyDriveProbe.cpp @@ -93,7 +93,7 @@ std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(drive::createDrive(driveInfo, m_sysWrapper)); - if(NULL == drive.get()) { + if(nullptr == drive.get()) { cta::exception::Exception ex; ex.getMessage() << "Failed to instantiate drive object"; throw ex; diff --git a/tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.cpp b/tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.cpp index e526233778ef530b40810a1cf3c60c613be2dc0b..f8e19e47f51c2c7c9352aa1a659a67064bf2ba1e 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.cpp @@ -30,9 +30,9 @@ namespace daemon { //------------------------------------------------------------------------------ // Constructor //------------------------------------------------------------------------------ -EncryptionControl::EncryptionControl(bool useEncryption, const std::string& scriptPath): -m_useEncryption(useEncryption), -m_path(scriptPath) { +EncryptionControl::EncryptionControl(bool useEncryption, const std::string& scriptPath) : + m_useEncryption(useEncryption), + m_path(scriptPath) { if (m_path.size() && m_path[0] != '/') { cta::exception::Exception ex("In EncryptionControl::EncryptionControl: the script path is not absolute: "); ex.getMessage() << m_path; @@ -42,18 +42,19 @@ m_path(scriptPath) { //------------------------------------------------------------------------------ // enable //------------------------------------------------------------------------------ -auto EncryptionControl::enable(castor::tape::tapeserver::drive::DriveInterface &m_drive, - const std::string& vid, SetTag st) -> EncryptionStatus { +auto EncryptionControl::enable(castor::tape::tapeserver::drive::DriveInterface& m_drive, + const std::string& vid, SetTag st) -> EncryptionStatus { + EncryptionStatus encStatus; if (m_path.empty()) { if (m_useEncryption) { //if encryption is enabled, an external script is required cta::exception::Exception ex; ex.getMessage() << "In EncryptionControl::enableEncryption: " - "failed to enable encryption: path provided is empty but tapeserver is configured to use encryption"; + "failed to enable encryption: path provided is empty but tapeserver is configured to use encryption"; throw ex; } - encStatus = { false, "", "", ""}; + encStatus = {false, "", "", ""}; return encStatus; } @@ -74,10 +75,11 @@ auto EncryptionControl::enable(castor::tape::tapeserver::drive::DriveInterface & "failed to enable encryption: "; if (sp.wasKilled()) { ex.getMessage() << "script was killed with signal: " << sp.killSignal(); - } else { + } + else { ex.getMessage() << "script returned: " << sp.exitValue(); } - ex.getMessage() << " called=" << "\'" << argsToString(args, " ") << "\'" + ex.getMessage() << " called=" << "\'" << argsToString(args, " ") << "\'" << " stdout=" << sp.stdout() << " stderr=" << sp.stderr(); throw ex; @@ -85,7 +87,8 @@ auto EncryptionControl::enable(castor::tape::tapeserver::drive::DriveInterface & encStatus = parse_json_script_output(sp.stdout()); if (encStatus.on) { m_drive.setEncryptionKey(encStatus.key); - } else { + } + else { /* * If tapeserver fails completely and leaves drive in dirty state, we should always clear * encryption key from the drive if data are to be written unencrypted. @@ -98,19 +101,19 @@ auto EncryptionControl::enable(castor::tape::tapeserver::drive::DriveInterface & //------------------------------------------------------------------------------ // disable //------------------------------------------------------------------------------ -bool EncryptionControl::disable(castor::tape::tapeserver::drive::DriveInterface &m_drive) { +bool EncryptionControl::disable(castor::tape::tapeserver::drive::DriveInterface& m_drive) { return m_drive.clearEncryptionKey(); } namespace { struct JsonObjectDeleter { - void operator() (json_object *jo) { json_object_put(jo); } + void operator()(json_object *jo) { json_object_put(jo); } }; } namespace { struct JsonTokenerDeleter { - void operator() (json_tokener *jt) { json_tokener_free(jt); } + void operator()(json_tokener *jt) { json_tokener_free(jt); } }; } @@ -143,7 +146,7 @@ EncryptionControl::EncryptionStatus EncryptionControl::parse_json_script_output( stdout_map.find("key_id") == stdout_map.end() || stdout_map.find("encryption_key") == stdout_map.end() || stdout_map.find("message") == stdout_map.end() - ) { + ) { cta::exception::Exception ex("In EncryptionControl::parse_json_script_output: invalid json interface."); throw ex; } @@ -156,24 +159,27 @@ EncryptionControl::EncryptionStatus EncryptionControl::parse_json_script_output( } std::map<std::string, std::string> EncryptionControl::flatten_json_object_to_map(const std::string& prefix, - json_object *jobj) { + json_object *jobj) { std::map<std::string, std::string> ret; json_object_object_foreach(jobj, key, val) { if (json_object_get_type(val) == json_type_object) { std::map<std::string, std::string> sec_map = flatten_json_object_to_map(key, val); ret.insert(sec_map.begin(), sec_map.end()); - } else { - if (json_object_get_type(val) == json_type_string) // parse only string values at the deepest level - ret[prefix+key] = json_object_get_string(val); + } + else { + if (json_object_get_type(val) == json_type_string) { // parse only string values at the deepest level + ret[prefix + key] = json_object_get_string(val); + } } } return ret; } std::string EncryptionControl::argsToString(std::list<std::string> args, const std::string& delimiter) { - if (args.empty()) + if (args.empty()) { return ""; + } std::ostringstream toBeReturned; std::copy(args.begin(), --args.end(), std::ostream_iterator<std::string>(toBeReturned, delimiter.c_str())); diff --git a/tapeserver/castor/tape/tapeserver/daemon/LabelSession.cpp b/tapeserver/castor/tape/tapeserver/daemon/LabelSession.cpp index d3e9d546cac30cd54a8baabbe1f1a32a2d54ef03..73189292561e00f59aa99f23534d4b940b8ce948 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/LabelSession.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/LabelSession.cpp @@ -191,7 +191,7 @@ std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> std::unique_ptr<drive::DriveInterface> drive(drive::createDrive(driveInfo, m_sysWrapper)); - if(NULL == drive.get()) { + if(nullptr == drive.get()) { cta::exception::Exception ex; ex.getMessage() << "Failed to instantiate drive object"; throw ex; diff --git a/tapeserver/castor/tape/tapeserver/daemon/MemBlock.hpp b/tapeserver/castor/tape/tapeserver/daemon/MemBlock.hpp index ec314a0327b4a3e0e532d40596e3ea4665b5b322..cb9d3cd05207e7376f5918b0657b63c69a27ce05 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/MemBlock.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/MemBlock.hpp @@ -180,7 +180,7 @@ public: m_payload.reset(); //delete the previous m_context (if allocated) - //and set the new one to NULL + //and set the new one to nullptr m_context.reset(); } /** Unique memory block id */ diff --git a/tapeserver/castor/tape/tapeserver/daemon/MigrationMemoryManager.cpp b/tapeserver/castor/tape/tapeserver/daemon/MigrationMemoryManager.cpp index 5411c4b8dcb917ec3d7be506c26c1733bfe08565..79c7c1958ad5d4d0f0303c14feb5d4884761e8e4 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/MigrationMemoryManager.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/MigrationMemoryManager.cpp @@ -103,7 +103,7 @@ size_t MigrationMemoryManager::blockCapacity() { //------------------------------------------------------------------------------ void MigrationMemoryManager::finish() { - addClient(NULL); + addClient(nullptr); } //------------------------------------------------------------------------------ @@ -125,7 +125,7 @@ void MigrationMemoryManager::releaseBlock(MemBlock* mb) void MigrationMemoryManager::run() { while (true) { DataPipeline* c = m_clientQueue.pop(); - // If the c is a NULL pointer, that means end of clients + // If the c is a nullptr pointer, that means end of clients if (!c) return; // Spin on the the client. We rely on the fact that he will want // at least one block (which is the case currently) diff --git a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.cpp b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.cpp index 64614948997d6816de8bd2c75628556236c7e9eb..f418fbb11ec68d4646e3e8f23f38d12149ca43cb 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.cpp @@ -119,8 +119,8 @@ void MigrationReportPacker::reportTapeFull(cta::log::LogContext& lc) { //------------------------------------------------------------------------------ //reportEndOfSession -//------------------------------------------------------------------------------ -void MigrationReportPacker::reportEndOfSession(cta::log::LogContext & lc) { +//------------------------------------------------------------------------------ +void MigrationReportPacker::reportEndOfSession(cta::log::LogContext& lc) { cta::log::ScopedParamContainer params(lc); params.add("type", "ReportEndofSession"); lc.log(cta::log::DEBUG, "In MigrationReportPacker::reportEndOfSession(), pushing a report."); @@ -131,8 +131,8 @@ void MigrationReportPacker::reportEndOfSession(cta::log::LogContext & lc) { //------------------------------------------------------------------------------ //reportEndOfSessionWithErrors -//------------------------------------------------------------------------------ -void MigrationReportPacker::reportEndOfSessionWithErrors(std::string msg,int errorCode, cta::log::LogContext & lc){ +//------------------------------------------------------------------------------ +void MigrationReportPacker::reportEndOfSessionWithErrors(std::string msg, int errorCode, cta::log::LogContext& lc) { cta::log::ScopedParamContainer params(lc); params.add("type", "ReportEndofSessionWithErrors"); lc.log(cta::log::DEBUG, "In MigrationReportPacker::reportEndOfSessionWithErrors(), pushing a report."); @@ -155,8 +155,8 @@ void MigrationReportPacker::reportTestGoingToEnd(cta::log::LogContext& lc) { //------------------------------------------------------------------------------ //synchronousReportEndWithErrors -//------------------------------------------------------------------------------ -void MigrationReportPacker::synchronousReportEndWithErrors(const std::string msg, int errorCode, cta::log::LogContext & lc){ +//------------------------------------------------------------------------------ +void MigrationReportPacker::synchronousReportEndWithErrors(const std::string& msg, int errorCode, cta::log::LogContext& lc) { cta::log::ScopedParamContainer params(lc); params.add("type", "ReportEndofSessionWithErrors"); lc.log(cta::log::DEBUG, "In MigrationReportPacker::synchronousReportEndWithErrors(), reporting asynchronously session complete."); @@ -169,13 +169,12 @@ void MigrationReportPacker::synchronousReportEndWithErrors(const std::string msg lc.log(cta::log::INFO, "Reported end of session with error to client after sending file errors"); } else { - const std::string& msg = "Reported end of session with error to client"; // As a measure of safety we censor any session error which is not ENOSPC into // Meaningless 666 (used to be SEINTERNAL in CASTOR). ENOSPC is the only one interpreted by the tape gateway. if (ENOSPC != errorCode) { errorCode = 666; } - lc.log(cta::log::INFO, msg); + lc.log(cta::log::INFO, "Reported end of session with error to client"); } if (m_watchdog) { m_watchdog->addParameter(cta::log::Param("status", @@ -418,9 +417,9 @@ void MigrationReportPacker::ReportError::execute(MigrationReportPacker& reportPa cta::log::ScopedParamContainer params(reportPacker.m_lc); params.add("ExceptionMSG", ex.getMessageValue()) .add("fileId", m_failedArchiveJob->archiveFile.archiveFileID); - reportPacker.m_lc.log(cta::log::WARNING,"In MigrationReportPacker::ReportError::execute(): call to m_failedArchiveJob->failed(), job does not exist in the objectstore."); - } - catch (cta::exception::Exception & ex) { + reportPacker.m_lc.log(cta::log::WARNING, + "In MigrationReportPacker::ReportError::execute(): call to m_failedArchiveJob->failed(), job does not exist in the objectstore."); + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer params(reportPacker.m_lc); params.add("ExceptionMSG", ex.getMessageValue()) .add("fileId", m_failedArchiveJob->archiveFile.archiveFileID); @@ -467,7 +466,7 @@ void MigrationReportPacker::WorkerThread::run() { //either from the catch a few lines above or directly from rep->execute cta::log::ScopedParamContainer params(lc); params.add("exceptionMSG", e.getMessageValue()); - lc.log(cta::log::ERR, "In MigrationPacker::run(): Received a CTA exception while reporting archive mount results."); + lc.log(cta::log::ERR, "In MigrationReportPacker::WorkerThread::run(): Received a CTA exception while reporting archive mount results."); if (m_parent.m_watchdog) { m_parent.m_watchdog->addToErrorCount("Error_reporting"); m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); @@ -485,7 +484,7 @@ void MigrationReportPacker::WorkerThread::run() { else { params.add("exceptionType", typeid(e).name()); } - lc.log(cta::log::ERR, "In MigrationPacker::run(): Received a standard exception while reporting archive mount results."); + lc.log(cta::log::ERR, "In MigrationReportPacker::WorkerThread::run(): Received a standard exception while reporting archive mount results."); if (m_parent.m_watchdog) { m_parent.m_watchdog->addToErrorCount("Error_reporting"); m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); @@ -493,7 +492,7 @@ void MigrationReportPacker::WorkerThread::run() { } catch (...) { //we get there because to tried to close the connection and it failed //either from the catch a few lines above or directly from rep->execute - lc.log(cta::log::ERR, "In MigrationPacker::run(): Received an unknown exception while reporting archive mount results."); + lc.log(cta::log::ERR, "In MigrationReportPacker::WorkerThread::run(): Received an unknown exception while reporting archive mount results."); if (m_parent.m_watchdog) { m_parent.m_watchdog->addToErrorCount("Error_reporting"); m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); diff --git a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.hpp b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.hpp index 41cb8a17488998989c19dc3281bcc23dfde9ef65..b3e50d69f7bfc7da04797a840fa71ae53ed0b6a6 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPacker.hpp @@ -26,34 +26,31 @@ #include "scheduler/ArchiveJob.hpp" #include <list> #include <memory> +#include <utility> namespace castor { namespace tape { namespace tapeserver { namespace daemon { - + class MigrationReportPacker : public ReportPackerInterface<detail::Migration> { public: /** * @param tg The client who is asking for a migration of his files * and to whom we have to report to the status of the operations. */ - MigrationReportPacker(cta::ArchiveMount *archiveMount, cta::log::LogContext& lc); - + MigrationReportPacker(cta::ArchiveMount *archiveMount, cta::log::LogContext& lc); + ~MigrationReportPacker(); - + /** * Create into the MigrationReportPacker a report for the successful migration * of migratedFile * @param migratedFile the file successfully migrated - * @param checksum the checksum we computed of the file we have just migrated - * @param blockId The tape logical object ID of the first block of the header - * of the file. This is 0 (instead of 1) for the first file on the tape (aka - * fseq = 1). * @param lc log context provided by the calling thread. */ - virtual void reportCompletedJob(std::unique_ptr<cta::ArchiveJob> successfulArchiveJob, cta::log::LogContext & lc); - + virtual void reportCompletedJob(std::unique_ptr<cta::ArchiveJob> successfulArchiveJob, cta::log::LogContext& lc); + /** * Create into the MigrationReportPacker a report for a skipped file. We left a placeholder on tape, so * writing can carry on, but this fSeq holds no data. In the mean time, the job has to count a failure. @@ -61,57 +58,59 @@ public: * @param ex the reason for the failure * @param lc log context provided by the calling thread. */ - virtual void reportSkippedJob(std::unique_ptr<cta::ArchiveJob> skippedArchiveJob, const std::string& failure, cta::log::LogContext & lc); + virtual void reportSkippedJob(std::unique_ptr<cta::ArchiveJob> skippedArchiveJob, const std::string& failure, cta::log::LogContext& lc); + /** - * Create into the MigrationReportPacker a report for the failled migration + * Create into the MigrationReportPacker a report for the failed migration * of migratedFile - * @param migratedFile the file which failled + * @param migratedFile the file which failed * @param ex the reason for the failure * @param lc log context provided by the calling thread. */ - virtual void reportFailedJob(std::unique_ptr<cta::ArchiveJob> failedArchiveJob, const cta::exception::Exception& ex, cta::log::LogContext & lc); - - /** - * Create into the MigrationReportPacker a report for the signaling a flusing on tape - * @param compressStats - * @param lc log context provided by the calling thread. - * - */ - virtual void reportFlush(drive::compressionStats compressStats, cta::log::LogContext & lc); - + virtual void reportFailedJob(std::unique_ptr<cta::ArchiveJob> failedArchiveJob, const cta::exception::Exception& ex, cta::log::LogContext& lc); + + /** + * Create into the MigrationReportPacker a report for the signaling a flushing on tape + * @param compressStats + * @param lc log context provided by the calling thread. + * + */ + virtual void reportFlush(drive::compressionStats compressStats, cta::log::LogContext& lc); + /** * Create into the MigrationReportPacker a report of reaching the end of the tape. * @param lc log context provided by the calling thread. */ - virtual void reportTapeFull(cta::log::LogContext & lc); - + virtual void reportTapeFull(cta::log::LogContext& lc); + /** * Report the drive state and set it in the central drive register. This * function is to be used by the tape thread when running. * @param state the new drive state. + * @param reason the comment to a change. * @param lc log context provided by the calling thread. */ - virtual void reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string> & reason, cta::log::LogContext & lc); - + virtual void reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string>& reason, cta::log::LogContext& lc); + /** * Create into the MigrationReportPacker a report for the nominal end of session * @param lc log context provided by the calling thread. */ - virtual void reportEndOfSession(cta::log::LogContext & lc); - + virtual void reportEndOfSession(cta::log::LogContext& lc); + /** * Function for testing purposes. It is used to tell the report packer that this is the last report * @param lc log context provided by the calling thread. */ - virtual void reportTestGoingToEnd(cta::log::LogContext & lc); - + virtual void reportTestGoingToEnd(cta::log::LogContext& lc); + /** * Create into the MigrationReportPacker a report for an erroneous end of session * @param msg The error message * @param error_code The error code given by the drive * @param lc log context provided by the calling thread. */ - virtual void reportEndOfSessionWithErrors(const std::string msg,int error_code, cta::log::LogContext & lc); + virtual void reportEndOfSessionWithErrors(std::string msg, int error_code, cta::log::LogContext& lc); /** * Immediately report the end of session to the client. @@ -119,143 +118,159 @@ public: * @param error_code The error code given by the drive * @param lc log context provided by the calling thread. */ - virtual void synchronousReportEndWithErrors(const std::string msg,int error_code, cta::log::LogContext & lc); - + virtual void synchronousReportEndWithErrors(const std::string& msg, int error_code, cta::log::LogContext& lc); + void startThreads() { m_workerThread.start(); } + void waitThread() { m_workerThread.wait(); } - + private: class Report { public: - virtual ~Report(){} - virtual void execute(MigrationReportPacker& packer)=0; + virtual ~Report() = default; + + virtual void execute(MigrationReportPacker& packer) = 0; }; - class ReportSuccessful : public Report { + + class ReportSuccessful : public Report { /** * The successful archive job to be pushed in the report packer queue and reported later */ std::unique_ptr<cta::ArchiveJob> m_successfulArchiveJob; public: - ReportSuccessful(std::unique_ptr<cta::ArchiveJob> successfulArchiveJob): - m_successfulArchiveJob(std::move(successfulArchiveJob)) {} + explicit ReportSuccessful(std::unique_ptr<cta::ArchiveJob> successfulArchiveJob) : + m_successfulArchiveJob(std::move(successfulArchiveJob)) {} + void execute(MigrationReportPacker& reportPacker) override; }; - - class ReportSkipped : public Report{ + + class ReportSkipped : public Report { const std::string m_failureLog; /** * The failed archive job we skipped */ std::unique_ptr<cta::ArchiveJob> m_skippedArchiveJob; public: - ReportSkipped(std::unique_ptr<cta::ArchiveJob> skippedArchiveJob, std::string &failureLog): - m_failureLog(failureLog), m_skippedArchiveJob(std::move(skippedArchiveJob)) {} + ReportSkipped(std::unique_ptr<cta::ArchiveJob> skippedArchiveJob, std::string& failureLog) : + m_failureLog(failureLog), m_skippedArchiveJob(std::move(skippedArchiveJob)) {} + void execute(MigrationReportPacker& reportPacker) override; }; - - class ReportTestGoingToEnd : public Report { + + class ReportTestGoingToEnd : public Report { public: - ReportTestGoingToEnd() {} - virtual void execute(MigrationReportPacker& reportPacker) override { - reportPacker.m_continue=false; + ReportTestGoingToEnd() = default; + + void execute(MigrationReportPacker& reportPacker) override { + reportPacker.m_continue = false; reportPacker.m_lc.log(cta::log::DEBUG, "In MigrationReportPacker::ReportTestGoingToEnd::execute(): Reporting session complete."); reportPacker.m_archiveMount->complete(); } }; - + class ReportDriveStatus : public Report { cta::common::dataStructures::DriveStatus m_status; cta::optional<std::string> m_reason; public: - ReportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string> & reason): m_status(status),m_reason(reason) {} + ReportDriveStatus(cta::common::dataStructures::DriveStatus status, cta::optional<std::string> reason) : m_status(status), + m_reason(std::move(reason)) {} + void execute(MigrationReportPacker& reportPacker) override; }; - + class ReportFlush : public Report { drive::compressionStats m_compressStats; - - public: + + public: /* We only can compute the compressed size once we have flushed on the drive * We can get from the drive the number of byte it really wrote to tape * @param nbByte the number of byte it really wrote to tape between * this flush and the previous one * */ - ReportFlush(drive::compressionStats compressStats):m_compressStats(compressStats){} - - void execute(MigrationReportPacker& reportPacker) override; + explicit ReportFlush(drive::compressionStats compressStats) : m_compressStats(compressStats) {} + + void execute(MigrationReportPacker& reportPacker) override; }; - class ReportTapeFull: public Report { - public: - ReportTapeFull() {} - void execute(MigrationReportPacker& reportPacker) override; + + class ReportTapeFull : public Report { + public: + ReportTapeFull() = default; + + void execute(MigrationReportPacker& reportPacker) override; }; + class ReportError : public Report { const std::string m_failureLog; - + /** * The failed archive job to be reported immediately */ std::unique_ptr<cta::ArchiveJob> m_failedArchiveJob; public: - ReportError(std::unique_ptr<cta::ArchiveJob> failedArchiveJob, std::string &failureLog): - m_failureLog(failureLog), m_failedArchiveJob(std::move(failedArchiveJob)){} - + ReportError(std::unique_ptr<cta::ArchiveJob> failedArchiveJob, std::string& failureLog) : + m_failureLog(failureLog), m_failedArchiveJob(std::move(failedArchiveJob)) {} + void execute(MigrationReportPacker& reportPacker) override; }; + class ReportEndofSession : public Report { public: - virtual void execute(MigrationReportPacker& reportPacker) override; + void execute(MigrationReportPacker& reportPacker) override; }; + class ReportEndofSessionWithErrors : public Report { std::string m_message; int m_errorCode; public: - ReportEndofSessionWithErrors(std::string msg,int errorCode): - m_message(msg),m_errorCode(errorCode){} - + ReportEndofSessionWithErrors(std::string msg, int errorCode) : + m_message(std::move(msg)), m_errorCode(errorCode) {} + void execute(MigrationReportPacker& reportPacker) override; }; - - class WorkerThread: public cta::threading::Thread { - MigrationReportPacker & m_parent; + + class WorkerThread : public cta::threading::Thread { + MigrationReportPacker& m_parent; public: - WorkerThread(MigrationReportPacker& parent); - virtual void run(); + explicit WorkerThread(MigrationReportPacker& parent); + + void run() override; } m_workerThread; - + /** * m_fifo is holding all the report waiting to be processed */ cta::threading::BlockingQueue<std::unique_ptr<Report>> m_fifo; - cta::threading::Mutex m_producterProtection; - + /** * Sanity check variable to register if an error has happened * Is set at true as soon as a ReportError has been processed. */ bool m_errorHappened; - + /* bool to keep the inner thread running. Is set at false - * when a end of session (with error) is called + * when an end of session (with error) is called */ bool m_continue; - + /** * The mount object used to send reports */ - cta::ArchiveMount * m_archiveMount; - + cta::ArchiveMount *m_archiveMount; + /** * The successful archive jobs to be reported when flushing */ std::queue<std::unique_ptr<cta::ArchiveJob> > m_successfulArchiveJobs; - + /** * The skipped files (or placeholders list) */ std::queue<cta::catalogue::TapeItemWritten> m_skippedFiles; }; -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/Payload.hpp b/tapeserver/castor/tape/tapeserver/daemon/Payload.hpp index b187e6c00c97bf094318e2991079cf6cee48822f..18c6c833fc2793904002e33aa2db978f196eb5d6 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/Payload.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/Payload.hpp @@ -38,7 +38,7 @@ class Payload public: Payload(size_t capacity): m_data(new (std::nothrow) unsigned char[capacity]),m_totalCapacity(capacity),m_size(0) { - if(NULL == m_data) { + if(nullptr == m_data) { throw cta::exception::MemException("Failed to allocate memory for a new MemBlock!"); } } diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.cpp b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.cpp index 356cbb5a4cf006ef8d517d2979d14854d5bc6908..8b415e5074edc5549179ed6488aa270fbd134f0b 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.cpp @@ -26,12 +26,6 @@ #include <iostream> #include <cxxabi.h> -namespace{ - struct failedReportRecallResult : public cta::exception::Exception{ - failedReportRecallResult(const std::string& s): Exception(s){} - }; -} - using cta::log::LogContext; using cta::log::Param; @@ -42,67 +36,93 @@ namespace daemon { //------------------------------------------------------------------------------ //Constructor //------------------------------------------------------------------------------ -RecallReportPacker::RecallReportPacker(cta::RetrieveMount *retrieveMount, cta::log::LogContext lc): +RecallReportPacker::RecallReportPacker(cta::RetrieveMount *retrieveMount, cta::log::LogContext& lc) : ReportPackerInterface<detail::Recall>(lc), m_workerThread(*this), m_errorHappened(false), m_retrieveMount(retrieveMount), m_tapeThreadComplete(false), m_diskThreadComplete(false) { } + //------------------------------------------------------------------------------ //Destructor //------------------------------------------------------------------------------ -RecallReportPacker::~RecallReportPacker(){ +RecallReportPacker::~RecallReportPacker() { cta::threading::MutexLocker ml(m_producterProtection); } + //------------------------------------------------------------------------------ //reportCompletedJob //------------------------------------------------------------------------------ -void RecallReportPacker::reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob){ +void RecallReportPacker::reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob, cta::log::LogContext& lc) { std::unique_ptr<Report> rep(new ReportSuccessful(std::move(successfulRetrieveJob))); + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportSuccessful"); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportCompletedJob(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); m_fifo.push(rep.release()); } + //------------------------------------------------------------------------------ //reportFailedJob -//------------------------------------------------------------------------------ -void RecallReportPacker::reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex){ +//------------------------------------------------------------------------------ +void RecallReportPacker::reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception& ex, + cta::log::LogContext& lc) { std::string failureLog = cta::utils::getCurrentLocalTime() + " " + cta::utils::getShortHostname() + - " " + ex.getMessageValue(); + " " + ex.getMessageValue(); std::unique_ptr<Report> rep(new ReportError(std::move(failedRetrieveJob), failureLog)); + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportError"); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportFailedJob(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); m_fifo.push(rep.release()); } + //------------------------------------------------------------------------------ //reportEndOfSession //------------------------------------------------------------------------------ -void RecallReportPacker::reportEndOfSession(){ +void RecallReportPacker::reportEndOfSession(cta::log::LogContext& lc) { + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportEndofSession"); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportEndOfSession(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); - m_fifo.push(new ReportEndofSession()); + std::unique_ptr<Report> rep(new ReportEndofSession()); + m_fifo.push(rep.release()); } //------------------------------------------------------------------------------ //reportDriveStatus //------------------------------------------------------------------------------ -void RecallReportPacker::reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string> & reason) { +void RecallReportPacker::reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string>& reason, + cta::log::LogContext& lc) { + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportDriveStatus") + .add("Status", cta::common::dataStructures::toString(status)); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportDriveStatus(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); - m_fifo.push(new ReportDriveStatus(status,reason)); + m_fifo.push(new ReportDriveStatus(status, reason)); } //------------------------------------------------------------------------------ //reportEndOfSessionWithErrors //------------------------------------------------------------------------------ -void RecallReportPacker::reportEndOfSessionWithErrors(const std::string msg,int error_code){ +void RecallReportPacker::reportEndOfSessionWithErrors(const std::string& msg, int error_code, cta::log::LogContext& lc) { + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportEndofSessionWithErrors"); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportEndOfSessionWithErrors(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); - m_fifo.push(new ReportEndofSessionWithErrors(msg,error_code)); + m_fifo.push(new ReportEndofSessionWithErrors(msg, error_code)); } //------------------------------------------------------------------------------ //reportTestGoingToEnd //------------------------------------------------------------------------------ -void RecallReportPacker::reportTestGoingToEnd(){ +void RecallReportPacker::reportTestGoingToEnd(cta::log::LogContext& lc) { + cta::log::ScopedParamContainer params(lc); + params.add("type", "ReportTestGoingToEnd"); + lc.log(cta::log::DEBUG, "In RecallReportPacker::reportTestGoingToEnd(), pushing a report."); cta::threading::MutexLocker ml(m_producterProtection); m_fifo.push(new ReportTestGoingToEnd()); } @@ -110,42 +130,43 @@ void RecallReportPacker::reportTestGoingToEnd(){ //------------------------------------------------------------------------------ //ReportSuccessful::execute //------------------------------------------------------------------------------ -void RecallReportPacker::ReportSuccessful::execute(RecallReportPacker& parent){ - try{ +void RecallReportPacker::ReportSuccessful::execute(RecallReportPacker& parent) { + try { m_successfulRetrieveJob->asyncSetSuccessful(); parent.m_successfulRetrieveJobs.push(std::move(m_successfulRetrieveJob)); } catch (const cta::exception::NoSuchObject &ex){ cta::log::ScopedParamContainer params(parent.m_lc); params.add("ExceptionMSG", ex.getMessageValue()) .add("fileId", m_successfulRetrieveJob->archiveFile.archiveFileID); - parent.m_lc.log(cta::log::WARNING,"In RecallReportPacker::ReportSuccessful::execute(): call to m_successfulRetrieveJob->asyncSetSuccessful() failed, job does not exist in the objectstore."); + parent.m_lc.log(cta::log::WARNING, + "In RecallReportPacker::ReportSuccessful::execute(): call to m_successfulRetrieveJob->asyncSetSuccessful() failed, job does not exist in the objectstore."); } } //------------------------------------------------------------------------------ //ReportEndofSession::execute //------------------------------------------------------------------------------ -void RecallReportPacker::ReportEndofSession::execute(RecallReportPacker& parent){ - parent.setDiskDone(); - if(!parent.errorHappened()){ - parent.m_lc.log(cta::log::INFO,"Nominal RecallReportPacker::EndofSession has been reported"); - if (parent.m_watchdog) { - parent.m_watchdog->addParameter(cta::log::Param("status","success")); +void RecallReportPacker::ReportEndofSession::execute(RecallReportPacker& reportPacker) { + reportPacker.setDiskDone(); + if (!reportPacker.errorHappened()) { + reportPacker.m_lc.log(cta::log::INFO, "Nominal RecallReportPacker::EndofSession has been reported"); + if (reportPacker.m_watchdog) { + reportPacker.m_watchdog->addParameter(cta::log::Param("status", "success")); // We have a race condition here between the processing of this message by // the initial process and the printing of the end-of-session log, triggered // by the end our process. To delay the latter, we sleep half a second here. - usleep(500*1000); + usleep(500 * 1000); } } else { - const std::string& msg ="RecallReportPacker::EndofSession has been reported but an error happened somewhere in the process"; - parent.m_lc.log(cta::log::ERR,msg); - if (parent.m_watchdog) { - parent.m_watchdog->addParameter(cta::log::Param("status","failure")); + const std::string& msg = "RecallReportPacker::EndofSession has been reported but an error happened somewhere in the process"; + reportPacker.m_lc.log(cta::log::ERR, msg); + if (reportPacker.m_watchdog) { + reportPacker.m_watchdog->addParameter(cta::log::Param("status", "failure")); // We have a race condition here between the processing of this message by // the initial process and the printing of the end-of-session log, triggered // by the end our process. To delay the latter, we sleep half a second here. - usleep(500*1000); + usleep(500 * 1000); } } } @@ -160,12 +181,11 @@ bool RecallReportPacker::ReportEndofSession::goingToEnd() { //------------------------------------------------------------------------------ //ReportDriveStatus::execute //------------------------------------------------------------------------------ -void RecallReportPacker::ReportDriveStatus::execute(RecallReportPacker& parent){ - parent.m_retrieveMount->setDriveStatus(m_status,m_reason); - if(m_status==cta::common::dataStructures::DriveStatus::Unmounting) { - parent.setTapeDone(); - parent.setTapeComplete(); - } +void RecallReportPacker::ReportDriveStatus::execute(RecallReportPacker& parent) { + cta::log::ScopedParamContainer params(parent.m_lc); + params.add("status", cta::common::dataStructures::toString(m_status)); + parent.m_lc.log(cta::log::DEBUG, "In RecallReportPacker::ReportDriveStatus::execute(): reporting drive status."); + parent.m_retrieveMount->setDriveStatus(m_status, m_reason); } //------------------------------------------------------------------------------ @@ -178,22 +198,22 @@ bool RecallReportPacker::ReportDriveStatus::goingToEnd() { //------------------------------------------------------------------------------ //ReportEndofSessionWithErrors::execute //------------------------------------------------------------------------------ -void RecallReportPacker::ReportEndofSessionWithErrors::execute(RecallReportPacker& parent){ +void RecallReportPacker::ReportEndofSessionWithErrors::execute(RecallReportPacker& parent) { parent.setDiskDone(); - if(parent.m_errorHappened) { - LogContext::ScopedParam(parent.m_lc,Param("errorCode",m_error_code)); - parent.m_lc.log(cta::log::ERR,m_message); + if (parent.m_errorHappened) { + LogContext::ScopedParam sp(parent.m_lc, Param("errorCode", m_error_code)); + parent.m_lc.log(cta::log::ERR, m_message); } - else{ - const std::string& msg ="RecallReportPacker::EndofSessionWithErrors has been reported but NO error was detected during the process"; - parent.m_lc.log(cta::log::ERR,msg); + else { + const std::string& msg = "RecallReportPacker::EndofSessionWithErrors has been reported but NO error was detected during the process"; + parent.m_lc.log(cta::log::ERR, msg); } if (parent.m_watchdog) { - parent.m_watchdog->addParameter(cta::log::Param("status","failure")); + parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); // We have a race condition here between the processing of this message by // the initial process and the printing of the end-of-session log, triggered // by the end our process. To delay the latter, we sleep half a second here. - usleep(500*1000); + usleep(500 * 1000); } } @@ -207,13 +227,13 @@ bool RecallReportPacker::ReportEndofSessionWithErrors::goingToEnd() { //------------------------------------------------------------------------------ //ReportError::execute //------------------------------------------------------------------------------ -void RecallReportPacker::ReportError::execute(RecallReportPacker& reportPacker){ - reportPacker.m_errorHappened=true; +void RecallReportPacker::ReportError::execute(RecallReportPacker& reportPacker) { + reportPacker.m_errorHappened = true; { cta::log::ScopedParamContainer params(reportPacker.m_lc); params.add("failureLog", m_failureLog) .add("fileId", m_failedRetrieveJob->archiveFile.archiveFileID); - reportPacker.m_lc.log(cta::log::ERR,"In RecallReportPacker::ReportError::execute(): failing retrieve job after exception."); + reportPacker.m_lc.log(cta::log::ERR, "In RecallReportPacker::ReportError::execute(): failing retrieve job after exception."); } try { m_failedRetrieveJob->transferFailed(m_failureLog, reportPacker.m_lc); @@ -221,12 +241,13 @@ void RecallReportPacker::ReportError::execute(RecallReportPacker& reportPacker){ cta::log::ScopedParamContainer params(reportPacker.m_lc); params.add("ExceptionMSG", ex.getMessageValue()) .add("fileId", m_failedRetrieveJob->archiveFile.archiveFileID); - reportPacker.m_lc.log(cta::log::WARNING,"In RecallReportPacker::ReportError::execute(): call to m_failedRetrieveJob->failed() , job does not exist in the objectstore."); - } catch (cta::exception::Exception & ex) { + reportPacker.m_lc.log(cta::log::WARNING, + "In RecallReportPacker::ReportError::execute(): call to m_failedRetrieveJob->failed() , job does not exist in the objectstore."); + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer params(reportPacker.m_lc); params.add("ExceptionMSG", ex.getMessageValue()) .add("fileId", m_failedRetrieveJob->archiveFile.archiveFileID); - reportPacker.m_lc.log(cta::log::ERR,"In RecallReportPacker::ReportError::execute(): call to m_failedRetrieveJob->failed() threw an exception."); + reportPacker.m_lc.log(cta::log::ERR, "In RecallReportPacker::ReportError::execute(): call to m_failedRetrieveJob->failed() threw an exception."); reportPacker.m_lc.logBacktrace(cta::log::ERR, ex.backtrace()); } } @@ -234,40 +255,42 @@ void RecallReportPacker::ReportError::execute(RecallReportPacker& reportPacker){ //------------------------------------------------------------------------------ //WorkerThread::WorkerThread //------------------------------------------------------------------------------ -RecallReportPacker::WorkerThread::WorkerThread(RecallReportPacker& parent): -m_parent(parent) { +RecallReportPacker::WorkerThread::WorkerThread(RecallReportPacker& parent) : + m_parent(parent) { } + //------------------------------------------------------------------------------ //WorkerThread::run //------------------------------------------------------------------------------ -void RecallReportPacker::WorkerThread::run(){ +void RecallReportPacker::WorkerThread::run() { m_parent.m_lc.pushOrReplace(Param("thread", "RecallReportPacker")); m_parent.m_lc.log(cta::log::DEBUG, "Starting RecallReportPacker thread"); bool endFound = false; - std::list <std::unique_ptr<Report>> reportedSuccessfully; + std::list<std::unique_ptr<Report>> reportedSuccessfully; cta::utils::Timer t; - while(1) { + while (true) { std::string debugType; std::unique_ptr<Report> rep(m_parent.m_fifo.pop()); { cta::log::ScopedParamContainer spc(m_parent.m_lc); int demangleStatus; - char * demangledReportType = abi::__cxa_demangle(typeid(*rep.get()).name(), nullptr, nullptr, &demangleStatus); + char *demangledReportType = abi::__cxa_demangle(typeid(*rep.get()).name(), nullptr, nullptr, &demangleStatus); if (!demangleStatus) { spc.add("typeId", demangledReportType); - } else { + } + else { spc.add("typeId", typeid(*rep.get()).name()); } free(demangledReportType); if (rep->goingToEnd()) spc.add("goingToEnd", "true"); - m_parent.m_lc.log(cta::log::DEBUG, "Popping report"); + m_parent.m_lc.log(cta::log::DEBUG, "In RecallReportPacker::WorkerThread::run(): Got a new report."); } // Record whether we found end before calling the potentially exception // throwing execute().) if (rep->goingToEnd()) - endFound=true; + endFound = true; // We can afford to see any report to fail and keep passing the following ones // as opposed to migrations where one failure fails the session. try { @@ -276,40 +299,41 @@ void RecallReportPacker::WorkerThread::run(){ // m_parent.fullCheckAndFinishAsyncExecute will execute the shared half of the // request updates (individual, asynchronous is done in rep->execute(m_parent); if (typeid(*rep) == typeid(RecallReportPacker::ReportSuccessful) - && (m_parent.m_successfulRetrieveJobs.size() >= m_parent.RECALL_REPORT_PACKER_FLUSH_SIZE || t.secs() >= m_parent.RECALL_REPORT_PACKER_FLUSH_TIME )){ - m_parent.m_lc.log(cta::log::INFO,"m_parent.fullCheckAndFinishAsyncExecute()"); + && (m_parent.m_successfulRetrieveJobs.size() >= m_parent.RECALL_REPORT_PACKER_FLUSH_SIZE || + t.secs() >= m_parent.RECALL_REPORT_PACKER_FLUSH_TIME)) { + m_parent.m_lc.log(cta::log::INFO, "m_parent.fullCheckAndFinishAsyncExecute()"); m_parent.fullCheckAndFinishAsyncExecute(); t.reset(); } - } catch(const cta::exception::Exception& e){ + } catch (const cta::exception::Exception& e) { //we get there because to tried to close the connection and it failed //either from the catch a few lines above or directly from rep->execute cta::log::ScopedParamContainer params(m_parent.m_lc); params.add("exceptionWhat", e.getMessageValue()) .add("exceptionType", typeid(e).name()); - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got a CTA exception."); + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received a CTA exception while reporting retrieve mount results."); if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); } - } catch(const std::exception& e){ + } catch (const std::exception& e) { //we get there because to tried to close the connection and it failed //either from the catch a few lines above or directly from rep->execute cta::log::ScopedParamContainer params(m_parent.m_lc); params.add("exceptionWhat", e.what()) .add("exceptionType", typeid(e).name()); - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got a standard exception."); + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received a standard exception while reporting retrieve mount results."); if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); } - } catch(...){ + } catch (...) { //we get there because to tried to close the connection and it failed //either from the catch a few lines above or directly from rep->execute - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got an unknown exception."); + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received an unknown exception while reporting retrieve mount results."); if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); } } if (endFound) break; @@ -318,41 +342,42 @@ void RecallReportPacker::WorkerThread::run(){ // Make sure the last batch of reports got cleaned up. try { m_parent.fullCheckAndFinishAsyncExecute(); - if(m_parent.isDiskDone()){ + if (m_parent.isDiskDone()) { //The m_parent.m_diskThreadComplete is set to true when a ReportEndOfSession or a ReportAndOfSessionWithError //has been put. It is only after the fullCheckandFinishAsyncExecute is finished that we can say to the mount that the disk thread is complete. - m_parent.m_lc.log(cta::log::DEBUG, "In RecallReportPacker::WorkerThread::run(): all disk threads are finished, telling the mount that Disk threads are complete"); + m_parent.m_lc.log(cta::log::DEBUG, + "In RecallReportPacker::WorkerThread::run(): all disk threads are finished, telling the mount that Disk threads are complete"); m_parent.setDiskComplete(); } - } catch(const cta::exception::Exception& e){ - cta::log::ScopedParamContainer params(m_parent.m_lc); - params.add("exceptionWhat", e.getMessageValue()) - .add("exceptionType", typeid(e).name()); - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got a CTA exception."); - if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); - } - } catch(const std::exception& e){ - cta::log::ScopedParamContainer params(m_parent.m_lc); - params.add("exceptionWhat", e.what()) - .add("exceptionType", typeid(e).name()); - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got a standard exception."); - if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); - } - } catch(...){ - m_parent.m_lc.log(cta::log::ERR, "Tried to report and got an unknown exception."); - if (m_parent.m_watchdog) { - m_parent.m_watchdog->addToErrorCount("Error_clientCommunication"); - m_parent.m_watchdog->addParameter(cta::log::Param("status","failure")); - } + } catch (const cta::exception::Exception& e) { + cta::log::ScopedParamContainer params(m_parent.m_lc); + params.add("exceptionWhat", e.getMessageValue()) + .add("exceptionType", typeid(e).name()); + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received a CTA exception while reporting retrieve mount results."); + if (m_parent.m_watchdog) { + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); + } + } catch (const std::exception& e) { + cta::log::ScopedParamContainer params(m_parent.m_lc); + params.add("exceptionWhat", e.what()) + .add("exceptionType", typeid(e).name()); + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received a standard exception while reporting retrieve mount results."); + if (m_parent.m_watchdog) { + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); + } + } catch (...) { + m_parent.m_lc.log(cta::log::ERR, "In RecallReportPacker::WorkerThread::run(): Received an unknown exception while reporting retrieve mount results."); + if (m_parent.m_watchdog) { + m_parent.m_watchdog->addToErrorCount("Error_reporting"); + m_parent.m_watchdog->addParameter(cta::log::Param("status", "failure")); + } } // Drain the fifo in case we got an exception if (!endFound) { - while (1) { + while (true) { std::unique_ptr<Report> report(m_parent.m_fifo.pop()); if (report->goingToEnd()) break; @@ -395,17 +420,17 @@ void RecallReportPacker::setTapeDone() { m_tapeThreadComplete = true; } -void RecallReportPacker::setTapeComplete(){ +void RecallReportPacker::setTapeComplete() { cta::threading::MutexLocker mutexLocker(m_mutex); m_retrieveMount->tapeComplete(); } -void RecallReportPacker::setDiskComplete(){ +void RecallReportPacker::setDiskComplete() { cta::threading::MutexLocker mutexLocker(m_mutex); m_retrieveMount->diskComplete(); } -bool RecallReportPacker::isDiskDone(){ +bool RecallReportPacker::isDiskDone() { cta::threading::MutexLocker mutexLocker(m_mutex); return m_diskThreadComplete; } @@ -425,4 +450,7 @@ bool RecallReportPacker::allThreadsDone() { return m_tapeThreadComplete && m_diskThreadComplete; } -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.hpp b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.hpp index ea8f9f801ddfba594dbbb73b6cbe5c542ede62e7..cb5d4d93cc8a5c90c0b2062ab97250da51728b33 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPacker.hpp @@ -25,12 +25,13 @@ #include "scheduler/RetrieveMount.hpp" #include <memory> +#include <utility> namespace castor { namespace tape { namespace tapeserver { namespace daemon { - + class RecallReportPacker : public ReportPackerInterface<detail::Recall> { public: /** @@ -38,66 +39,73 @@ public: * @param tg the client to whom we report the success/failures * @param lc log context, copied du to threads */ - RecallReportPacker(cta::RetrieveMount *retrieveMount, cta::log::LogContext lc); - + RecallReportPacker(cta::RetrieveMount *retrieveMount, cta::log::LogContext& lc); + virtual ~RecallReportPacker(); - - /** - * Create into the MigrationReportPacker a report for the successful migration - * of migratedFile - * @param migratedFile the file successfully migrated - * @param checksum the checksum the DWT has computed for the file - */ - virtual void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob); - + + /** + * Create into the RecallReportPacker a report for the successful migration + * of migratedFile + * @param successfulRetrieveJob the file successfully retrieved + * @param lc log context provided by the calling thread. + */ + virtual void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob, cta::log::LogContext& lc); + /** - * Create into the MigrationReportPacker a report for the failed migration + * Create into the RecallReportPacker a report for the failed migration * of migratedFile * @param migratedFile the file which failed * @param ex the reason for the failure + * @param lc log context provided by the calling thread. */ - virtual void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex); - + virtual void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception& ex, cta::log::LogContext& lc); + /** - * Create into the MigrationReportPacker a report for the nominal end of session + * Create into the RecallReportPacker a report for the nominal end of session + * @param lc log context provided by the calling thread. */ - virtual void reportEndOfSession(); - + virtual void reportEndOfSession(cta::log::LogContext& lc); + /** * Function for testing purposes. It is used to tell the report packer that this is the last report + * @param lc log context provided by the calling thread. */ - virtual void reportTestGoingToEnd(); - + virtual void reportTestGoingToEnd(cta::log::LogContext& lc); + /** - * Create into the MigrationReportPacker a report for an erroneous end of session + * Create into the RecallReportPacker a report for an erroneous end of session * @param msg The error message * @param error_code The error code given by the drive + * @param lc log context provided by the calling thread. */ - virtual void reportEndOfSessionWithErrors(const std::string msg,int error_code); - + virtual void reportEndOfSessionWithErrors(const std::string& msg, int error_code, cta::log::LogContext& lc); + /** * Report the drive state and set it in the central drive register. This * function is to be used by the tape thread when running. * @param state the new drive state. + * @param reason the comment to a change. + * @param lc log context provided by the calling thread. */ - virtual void reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string> & reason = cta::nullopt); - + virtual void reportDriveStatus(cta::common::dataStructures::DriveStatus status, const cta::optional<std::string>& reason, + cta::log::LogContext& lc); + /** * Flag disk thread as done. */ virtual void setDiskDone(); - + /** * Flag tape thread as done. Set the drive status to draining if needed. */ virtual void setTapeDone(); - + void setTapeComplete(); - + void setDiskComplete(); - + bool isDiskDone(); - + /** * Query the status of disk and tape threads (are they both done?). * @return true if both tape and disk threads are done. @@ -108,43 +116,52 @@ public: * Start the inner thread */ void startThreads() { m_workerThread.start(); } - + /** * Stop the inner thread */ void waitThread() { m_workerThread.wait(); } - + /** * Was there an error? */ bool errorHappened(); - + private: //inner classes use to store content while receiving a report class Report { public: - virtual ~Report(){} - virtual void execute(RecallReportPacker& packer)=0; - virtual bool goingToEnd() {return false;} + virtual ~Report() {} + + virtual void execute(RecallReportPacker& packer) = 0; + + virtual bool goingToEnd() { return false; } }; - class ReportTestGoingToEnd : public Report { + + class ReportTestGoingToEnd : public Report { public: ReportTestGoingToEnd() {} + void execute(RecallReportPacker& reportPacker) override { - reportPacker.m_retrieveMount->diskComplete(); - reportPacker.m_retrieveMount->tapeComplete();} - bool goingToEnd() override {return true;} + reportPacker.m_retrieveMount->diskComplete(); + reportPacker.m_retrieveMount->tapeComplete(); + } + + bool goingToEnd() override { return true; } }; - class ReportSuccessful : public Report { + + class ReportSuccessful : public Report { /** * The successful retrieve job to be reported immediately */ std::unique_ptr<cta::RetrieveJob> m_successfulRetrieveJob; public: - ReportSuccessful(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob): - m_successfulRetrieveJob(std::move(successfulRetrieveJob)){} + ReportSuccessful(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob) : + m_successfulRetrieveJob(std::move(successfulRetrieveJob)) {} + void execute(RecallReportPacker& reportPacker) override; }; + class ReportError : public Report { const std::string m_failureLog; /** @@ -152,82 +169,90 @@ private: */ std::unique_ptr<cta::RetrieveJob> m_failedRetrieveJob; public: - ReportError(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const std::string &failureLog): - m_failureLog(failureLog), m_failedRetrieveJob(std::move(failedRetrieveJob)) {} + ReportError(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, std::string failureLog) : + m_failureLog(std::move(failureLog)), m_failedRetrieveJob(std::move(failedRetrieveJob)) {} void execute(RecallReportPacker& reportPacker) override; }; - + class ReportDriveStatus : public Report { cta::common::dataStructures::DriveStatus m_status; cta::optional<std::string> m_reason; - + public: - ReportDriveStatus(cta::common::dataStructures::DriveStatus status,const cta::optional<std::string> & reason): m_status(status), m_reason(reason) {} + ReportDriveStatus(cta::common::dataStructures::DriveStatus status, cta::optional<std::string> reason) : m_status(status), + m_reason(std::move(reason)) {} + void execute(RecallReportPacker& reportPacker) override; + bool goingToEnd() override; }; - + class ReportEndofSession : public Report { public: - ReportEndofSession(){} + ReportEndofSession() {} + void execute(RecallReportPacker& reportPacker) override; + bool goingToEnd() override; }; + class ReportEndofSessionWithErrors : public Report { std::string m_message; int m_error_code; public: - ReportEndofSessionWithErrors(std::string msg,int error_code): - m_message(msg),m_error_code(error_code){} - + ReportEndofSessionWithErrors(std::string msg, int error_code) : + m_message(std::move(msg)), m_error_code(error_code) {} + void execute(RecallReportPacker& reportPacker) override; + bool goingToEnd() override; }; - - class WorkerThread: public cta::threading::Thread { - RecallReportPacker & m_parent; + + class WorkerThread : public cta::threading::Thread { + RecallReportPacker& m_parent; public: WorkerThread(RecallReportPacker& parent); + void run() override; } m_workerThread; - + cta::threading::Mutex m_producterProtection; - + /** * m_fifo is holding all the report waiting to be processed */ - cta::threading::BlockingQueue<Report*> m_fifo; - + cta::threading::BlockingQueue<Report *> m_fifo; + /** * Is set as true as soon as we process a reportFailedJob * That we can do a sanity check to make sure we always call * the right end of the session */ bool m_errorHappened; - + /** * The mount object used to send reports */ - cta::RetrieveMount * m_retrieveMount; - + cta::RetrieveMount *m_retrieveMount; + /** * The successful reports that were pre-reported asynchronously. * They are collected and completed regularly. */ std::queue<std::unique_ptr<cta::RetrieveJob> > m_successfulRetrieveJobs; - + /** * Tracking of the tape thread end */ bool m_tapeThreadComplete; - + /** * Tracking of the disk thread end */ - bool m_diskThreadComplete; - + bool m_diskThreadComplete; + cta::threading::Mutex m_mutex; /* @@ -237,18 +262,21 @@ private: * @return The number of reports proceeded */ void fullCheckAndFinishAsyncExecute(); - + /* * The limit for successful reports to trigger flush. */ const unsigned int RECALL_REPORT_PACKER_FLUSH_SIZE = 2000; - + /* * The time limit for successful reports to trigger flush. */ const double RECALL_REPORT_PACKER_FLUSH_TIME = 180; }; -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPackerTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPackerTest.cpp index 249f80e87fab67964e78ef0a33ebf8f80e08ce5a..70153b62692c1102f89753596865a50f8f3795f5 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/RecallReportPackerTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/RecallReportPackerTest.cpp @@ -84,12 +84,12 @@ TEST_F(castor_tape_tapeserver_daemon_RecallReportPackerTest, RecallReportPackerN castor::tape::tapeserver::daemon::RecallReportPacker rrp(&retrieveMount,lc); rrp.startThreads(); - rrp.reportCompletedJob(std::move(job1)); - rrp.reportCompletedJob(std::move(job2)); - - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); - - rrp.reportEndOfSession(); + rrp.reportCompletedJob(std::move(job1), lc); + rrp.reportCompletedJob(std::move(job2), lc); + + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); + + rrp.reportEndOfSession(lc); // rrp.reportTestGoingToEnd(); rrp.waitThread(); @@ -133,16 +133,16 @@ TEST_F(castor_tape_tapeserver_daemon_RecallReportPackerTest, RecallReportPackerB castor::tape::tapeserver::daemon::RecallReportPacker rrp(&retrieveMount,lc); rrp.startThreads(); - rrp.reportCompletedJob(std::move(job1)); - rrp.reportCompletedJob(std::move(job2)); + rrp.reportCompletedJob(std::move(job1), lc); + rrp.reportCompletedJob(std::move(job2), lc); const std::string error_msg = "ERROR_TEST_MSG"; const cta::exception::Exception ex(error_msg); - rrp.reportFailedJob(std::move(job3), ex); - - rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); + rrp.reportFailedJob(std::move(job3), ex, lc); + + rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, lc); - rrp.reportEndOfSession(); + rrp.reportEndOfSession(lc); // rrp.reportTestGoingToEnd(); rrp.waitThread(); diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp index 18ff406f5aa6f1b957b54297400aebaf16ec3717..ae2f2c4877ddc18abe6aef84a40c71e4dfeb2bd3 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp @@ -51,20 +51,20 @@ namespace unitTests }; // class castor_tape_tapeserver_daemonTest struct MockRecallReportPacker : public RecallReportPacker { - void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob) override { + void reportCompletedJob(std::unique_ptr<cta::RetrieveJob> successfulRetrieveJob, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); completeJobs++; } - void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex) override { + void reportFailedJob(std::unique_ptr<cta::RetrieveJob> failedRetrieveJob, const cta::exception::Exception & ex, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); failedJobs++; } void disableBulk() override {} - void reportEndOfSession() override { + void reportEndOfSession(cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); endSessions++; } - void reportEndOfSessionWithErrors(const std::string msg, int error_code) override { + void reportEndOfSessionWithErrors(const std::string& msg, int error_code, cta::log::LogContext& lc) override { cta::threading::MutexLocker ml(m_mutex); endSessionsWithError++; } @@ -112,7 +112,7 @@ namespace unitTests virtual void run () { - m_tasks.push(NULL); + m_tasks.push(nullptr); } virtual void push(TapeReadTask* t){ @@ -198,9 +198,9 @@ namespace unitTests DiskWriteTask* diskWriteTask=diskWrite.m_tasks.pop(); TapeReadTask* tapeReadTask=tapeRead.m_tasks.pop(); - //static_cast is needed otherwise compilation fails on SL5 with a raw NULL - ASSERT_EQ(static_cast<DiskWriteTask*>(NULL), diskWriteTask); - ASSERT_EQ(static_cast<TapeReadTask*>(NULL), tapeReadTask); + //static_cast is needed otherwise compilation fails on SL5 with a raw nullptr + ASSERT_EQ(static_cast<DiskWriteTask*>(nullptr), diskWriteTask); + ASSERT_EQ(static_cast<TapeReadTask*>(nullptr), tapeReadTask); delete diskWriteTask; delete tapeReadTask; } diff --git a/tapeserver/castor/tape/tapeserver/daemon/ReportPackerInterface.hpp b/tapeserver/castor/tape/tapeserver/daemon/ReportPackerInterface.hpp index 67781c3afc4cdbdbfa6f4f658424a52830232912..e4c85bae1c3ddbf7a7a0b7eee65c3bd0d091294a 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/ReportPackerInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/ReportPackerInterface.hpp @@ -26,18 +26,20 @@ namespace castor { namespace tape { namespace tapeserver { namespace daemon { - -namespace detail{ - //nameholder - struct Recall{}; - struct Migration{}; - - // Enum describing the type of client. Some clients need batched reports, - // some prefer reports file by file - enum ReportBatching { - ReportInBulk, - ReportByFile - }; + +namespace detail { +//nameholder +struct Recall { +}; +struct Migration { +}; + +// Enum describing the type of client. Some clients need batched reports, +// some prefer reports file by file +enum ReportBatching { + ReportInBulk, + ReportByFile +}; } // Forward declaration to avoid circular inclusions. @@ -47,85 +49,90 @@ class TaskWatchDog; * Utility class that should be inherited privately/protectedly * the type PlaceHolder is either detail::Recall or detail::Migration */ -template <class PlaceHolder> class ReportPackerInterface{ - public : - +template<class PlaceHolder> +class ReportPackerInterface { +public : + // Pass a reference to the watchdog for initial process reporting. - void setWatchdog(TaskWatchDog & wd) { + void setWatchdog(TaskWatchDog& wd) { m_watchdog = &wd; } - protected: - virtual ~ReportPackerInterface() {} - ReportPackerInterface(cta::log::LogContext lc): +protected: + virtual ~ReportPackerInterface() = default; + + explicit ReportPackerInterface(const cta::log::LogContext& lc) : m_lc(lc), - m_reportBatching(detail::ReportInBulk),m_watchdog(NULL) {} - + m_reportBatching(detail::ReportInBulk), m_watchdog(nullptr) {} + /** * Log a set of files independently of the success/failure * @param c The set of files to log * @param msg The message to be append at the end. */ - template <class C> void logReport(const C& c,const std::string& msg){ + template<class C> + void logReport(const C& c, const std::string& msg) { using cta::log::LogContext; using cta::log::Param; - for(typename C::const_iterator it=c.begin();it!=c.end();++it) - { - cta::log::ScopedParamContainer sp(m_lc); - sp.add("fileId",(*it)->fileid()) - .add("NSFSEQ", (*it)->fseq()) - .add("NSHOST", (*it)->nshost()) - .add("NSFILETRANSACTIONID", (*it)->fileTransactionId()); - m_lc.log(cta::log::INFO,msg); - } - } + for (typename C::const_iterator it = c.begin(); it != c.end(); ++it) { + cta::log::ScopedParamContainer sp(m_lc); + sp.add("fileId", (*it)->fileid()) + .add("NSFSEQ", (*it)->fseq()) + .add("NSHOST", (*it)->nshost()) + .add("NSFILETRANSACTIONID", (*it)->fileTransactionId()); + m_lc.log(cta::log::INFO, msg); + } + } /** * Log a set of files independently of the success/failure * @param c The set of files to log * @param msg The message to be append at the end. */ - template <class C> void logReportWithError(const C& c,const std::string& msg){ + template<class C> + void logReportWithError(const C& c, const std::string& msg) { using cta::log::LogContext; using cta::log::Param; - for(typename C::const_iterator it=c.begin();it!=c.end();++it) - { - cta::log::ScopedParamContainer sp(m_lc); - sp.add("fileId",(*it)->fileid()) - .add("NSFSEQ", (*it)->fseq()) - .add("NSHOST", (*it)->nshost()) - .add("NSFILETRANSACTIONID", (*it)->fileTransactionId()) - .add("ErrorMessage", (*it)->errorMessage()) - .add("ErrorCode", (*it)->errorCode()); - m_lc.log(cta::log::INFO,msg); - } + for (typename C::const_iterator it = c.begin(); it != c.end(); ++it) { + cta::log::ScopedParamContainer sp(m_lc); + sp.add("fileId", (*it)->fileid()) + .add("NSFSEQ", (*it)->fseq()) + .add("NSHOST", (*it)->nshost()) + .add("NSFILETRANSACTIONID", (*it)->fileTransactionId()) + .add("ErrorMessage", (*it)->errorMessage()) + .add("ErrorCode", (*it)->errorCode()); + m_lc.log(cta::log::INFO, msg); + } } - + /** * The log context, copied due to threads */ cta::log::LogContext m_lc; - + /** * Define how we should report to the client (by file/in bulk). - */ + */ enum detail::ReportBatching m_reportBatching; - public: +public: /** * Turn off the packing of the reports by the report packer. * This is used for recalls driven by read_tp. */ virtual void disableBulk() { m_reportBatching = detail::ReportByFile; } - + /** * Pointer to the watchdog, so we can communicate communication errors * and end of session results to the initial process */ - TaskWatchDog * m_watchdog; - + TaskWatchDog *m_watchdog; + }; -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp index 01615ec3295f222d146cab2c6771400c8472b17f..77a7bd575856a79499ee2350c73887af4d26702b 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp @@ -16,59 +16,67 @@ */ #include "castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp" +#include "castor/tape/tapeserver/daemon/TapeServerReporter.hpp" +#include "castor/tape/tapeserver/daemon/RecallTaskInjector.hpp" +#include "castor/tape/tapeserver/drive/DriveInterface.hpp" +#include "common/make_unique.hpp" + //------------------------------------------------------------------------------ -//constructor for TapeReadSingleThread +// Constructor for TapeReadSingleThread //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::TapeReadSingleThread::TapeReadSingleThread( castor::tape::tapeserver::drive::DriveInterface& drive, - cta::mediachanger::MediaChangerFacade& mc, - TapeServerReporter& initialProcess, + cta::mediachanger::MediaChangerFacade& mediaChanger, + TapeServerReporter& reporter, const VolumeInfo& volInfo, uint64_t maxFilesRequest, cta::server::ProcessCap& capUtils, RecallWatchDog& watchdog, - cta::log::LogContext& lc, - RecallReportPacker &rrp, + cta::log::LogContext& logContext, + RecallReportPacker& reportPacker, const bool useLbp, const bool useRAO, const bool useEncryption, - const std::string & externalEncryptionKeyScript, + const std::string& externalEncryptionKeyScript, const cta::RetrieveMount& retrieveMount, const uint32_t tapeLoadTimeout) : - TapeSingleThreadInterface<TapeReadTask>(drive, mc, initialProcess, volInfo, - capUtils, lc, useEncryption, externalEncryptionKeyScript,tapeLoadTimeout), + TapeSingleThreadInterface<TapeReadTask>(drive, mediaChanger, reporter, volInfo, + capUtils, logContext, useEncryption, externalEncryptionKeyScript, tapeLoadTimeout), m_maxFilesRequest(maxFilesRequest), m_watchdog(watchdog), - m_rrp(rrp), + m_reportPacker(reportPacker), m_useLbp(useLbp), m_useRAO(useRAO), - m_retrieveMount(retrieveMount){} + m_retrieveMount(retrieveMount) {} //------------------------------------------------------------------------------ //TapeCleaning::~TapeCleaning() //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::TapeReadSingleThread::TapeCleaning::~TapeCleaning() { - m_this.m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::CleaningUp); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::CleaningUp, cta::nullopt, m_this.m_logContext); + // Tell everyone to wrap up the session // We now acknowledge to the task injector that read reached the end. There // will hence be no more requests for more. m_this.m_taskInjector->finish(); //then we log/notify - m_this.m_logContext.log(cta::log::DEBUG, "Starting session cleanup. Signalled end of session to task injector."); + m_this.m_logContext.log(cta::log::DEBUG, "Starting read session cleanup. Signalled end of session to task injector."); m_this.m_stats.waitReportingTime += m_timer.secs(cta::utils::Timer::resetCounter); + // Disable encryption (or at least try) try { if (m_this.m_encryptionControl.disable(m_this.m_drive)) m_this.m_logContext.log(cta::log::INFO, "Turned encryption off before unmounting"); - } catch (cta::exception::Exception & ex) { + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_this.m_logContext); scoped.add("exceptionError", ex.getMessageValue()); m_this.m_logContext.log(cta::log::ERR, "Failed to turn off encryption before unmounting"); } m_this.m_stats.encryptionControlTime += m_timer.secs(cta::utils::Timer::resetCounter); + // Log (safely, exception-wise) the tape alerts (if any) at the end of the session try { m_this.logTapeAlerts(); } catch (...) {} - // Log safely SCSI Metrits + // Log (safely, exception-wise) the tape SCSI metrics at the end of the session try { m_this.logSCSIMetrics(); } catch (...) {} // Log safely errors at the end of the session @@ -87,79 +95,85 @@ castor::tape::tapeserver::daemon::TapeReadSingleThread::TapeCleaning::~TapeClean // drive, which is a fine situation (so timeout exceptions are discarded). // Other exception, where we failed to access the drive somehow are at passed // through. - const uint32_t tapeLoadTimeout = m_this.m_tapeLoadTimeout; + const uint32_t waitMediaInDriveTimeout = m_this.m_tapeLoadTimeout; try { - m_this.m_drive.waitUntilReady(tapeLoadTimeout); - } catch (cta::exception::TimeOut &) {} + m_this.m_drive.waitUntilReady(waitMediaInDriveTimeout); + } catch (cta::exception::TimeOut&) {} if (!m_this.m_drive.hasTapeInPlace()) { m_this.m_logContext.log(cta::log::INFO, "TapeReadSingleThread: No tape to unload"); goto done; } - m_this.m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unloading, cta::nullopt); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unloading, cta::nullopt, m_this.m_logContext); m_this.m_drive.unloadTape(); m_this.m_logContext.log(cta::log::INFO, "TapeReadSingleThread: Tape unloaded"); m_this.m_stats.unloadTime += m_timer.secs(cta::utils::Timer::resetCounter); // And return the tape to the library currentErrorToCount = "Error_tapeDismount"; - m_this.m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting); - m_this.m_mc.dismountTape(m_this.m_volInfo.vid, m_this.m_drive.config.librarySlot()); + m_this.m_reporter.reportState(cta::tape::session::SessionState::Unmounting, cta::tape::session::SessionType::Retrieve); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, m_this.m_logContext); + m_this.m_mediaChanger.dismountTape(m_this.m_volInfo.vid, m_this.m_drive.config.librarySlot()); m_this.m_drive.disableLogicalBlockProtection(); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Up, cta::nullopt, m_this.m_logContext); m_this.m_stats.unmountTime += m_timer.secs(cta::utils::Timer::resetCounter); m_this.m_logContext.log(cta::log::INFO, "TapeReadSingleThread : tape unmounted"); // Report SessionState::ShuttingDown if all tasks finished or // SessionState::DrainingToDisk if there is any DiskWriteWorkerThread still active - m_this.m_initialProcess.reportTapeUnmountedForRetrieve(); + m_this.m_reporter.reportTapeUnmountedForRetrieve(); m_this.m_stats.waitReportingTime += m_timer.secs(cta::utils::Timer::resetCounter); - } catch(const cta::exception::Exception& ex){ - // Something failed during the cleaning + } catch (const cta::exception::Exception& ex) { + // Notify something failed during the cleaning m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; const int logLevel = cta::log::ERR; - const std::string errorMsg = "Exception in TapeReadSingleThread-TapeCleaning when unmounting the tape. Putting the drive down."; + const std::string errorMsg = "Exception in TapeReadSingleThread-TapeCleaning when unmounting/unloading the tape. Putting the drive down."; cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel, errorMsg); - m_this.m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down, reason); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down, reason, m_this.m_logContext); cta::log::ScopedParamContainer scoped(m_this.m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_this.m_logContext.log(logLevel, errorMsg); + + // As we do not throw exceptions from here, the watchdog signalling has + // to occur from here. try { - if (currentErrorToCount.size()) { + if (!currentErrorToCount.empty()) { m_this.m_watchdog.addToErrorCount(currentErrorToCount); } } catch (...) {} } catch (...) { - // Notify something failed during the cleaning - m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; + // Notify something failed during the cleaning const int logLevel = cta::log::ERR; const std::string errorMsg = "Non-Castor exception in TapeReadSingleThread-TapeCleaning when unmounting the tape. Putting the drive down."; - cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel,errorMsg); - m_this.m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down,reason); + cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel, errorMsg); + m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down, reason, m_this.m_logContext); m_this.m_logContext.log(logLevel, errorMsg); try { - if (currentErrorToCount.size()) { + if (!currentErrorToCount.empty()) { m_this.m_watchdog.addToErrorCount(currentErrorToCount); } } catch (...) {} } done: - //then we terminate the global status reporter - m_this.m_initialProcess.finish(); + //then we terminate the global status m_reporter + m_this.m_reporter.finish(); } //------------------------------------------------------------------------------ //TapeReadSingleThread::popAndRequestMoreJobs() //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::TapeReadTask * -castor::tape::tapeserver::daemon::TapeReadSingleThread::popAndRequestMoreJobs(){ - cta::threading::BlockingQueue<TapeReadTask *>::valueRemainingPair +castor::tape::tapeserver::daemon::TapeReadSingleThread::popAndRequestMoreJobs() { + cta::threading::BlockingQueue<TapeReadTask *>::valueRemainingPair vrp = m_tasks.popGetSize(); // If we just passed (down) the half full limit, ask for more // (the remaining value is after pop) - if(0 == vrp.remaining) { + if (0 == vrp.remaining) { // This is a last call: if the task injector comes up empty on this // one, he'll call it the end. m_taskInjector->requestInjection(true); - } else if (vrp.remaining + 1 == m_maxFilesRequest/2) { + } + else if (vrp.remaining + 1 == m_maxFilesRequest / 2) { // This is not a last call m_taskInjector->requestInjection(false); } @@ -171,36 +185,16 @@ castor::tape::tapeserver::daemon::TapeReadSingleThread::popAndRequestMoreJobs(){ //------------------------------------------------------------------------------ std::unique_ptr<castor::tape::tapeFile::ReadSession> castor::tape::tapeserver::daemon::TapeReadSingleThread::openReadSession() { - try{ - std::unique_ptr<castor::tape::tapeFile::ReadSession> rs( - new castor::tape::tapeFile::ReadSession(m_drive,m_volInfo, m_useLbp)); + try { + auto readSession = cta::make_unique<castor::tape::tapeFile::ReadSession>(m_drive, m_volInfo, m_useLbp); //m_logContext.log(cta::log::DEBUG, "Created tapeFile::ReadSession with success"); - - return rs; - }catch(cta::exception::Exception & ex){ - cta::log::ScopedParamContainer scoped(m_logContext); - scoped.add("exceptionMessage", ex.getMessageValue()); - m_logContext.log(cta::log::ERR, "Failed to tapeFile::ReadSession"); - throw cta::exception::Exception("Tape's label is either missing or not valid"); - } -} -//----------------------------------------------------------------------------- -// volumeModeToString -//----------------------------------------------------------------------------- -const char *castor::tape::tapeserver::daemon::TapeReadSingleThread:: -mountTypeToString(const cta::common::dataStructures::MountType mountType) const noexcept { - switch (mountType) { - case cta::common::dataStructures::MountType::Retrieve: - return "Retrieve"; - case cta::common::dataStructures::MountType::ArchiveForUser: - return "ArchiveForUser"; - case cta::common::dataStructures::MountType::ArchiveForRepack: - return "ArchiveForRepack"; - case cta::common::dataStructures::MountType::Label: - return "Label"; - default: - return "UNKNOWN"; + return readSession; + } catch (cta::exception::Exception& ex) { + cta::log::ScopedParamContainer scoped(m_logContext); + scoped.add("exceptionMessage", ex.getMessageValue()); + m_logContext.log(cta::log::ERR, "Failed to tapeFile::ReadSession"); + throw cta::exception::Exception("Tape's label is either missing or not valid"); } } @@ -208,45 +202,53 @@ mountTypeToString(const cta::common::dataStructures::MountType mountType) const //TapeReadSingleThread::run() //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { - m_logContext.pushOrReplace(cta::log::Param("thread", "TapeRead")); + cta::log::ScopedParamContainer threadGlobalParams(m_logContext); + threadGlobalParams.add("thread", "TapeRead"); cta::utils::Timer timer, totalTimer; + // This out-of-try-catch variables allows us to record the stage of the + // process we're in, and to count the error if it occurs. + // We will not record errors for an empty string. This will allow us to + // prevent counting where error happened upstream. std::string currentErrorToCount = "Error_tapeMountForRead"; - try{ + try { // Report the parameters of the session to the main thread typedef cta::log::Param Param; m_watchdog.addParameter(Param("tapeVid", m_volInfo.vid)); - m_watchdog.addParameter(Param("mountType", mountTypeToString(m_volInfo.mountType))); + m_watchdog.addParameter(Param("mountType", toCamelCaseString(m_volInfo.mountType))); m_watchdog.addParameter(Param("mountId", m_volInfo.mountId)); - m_watchdog.addParameter(Param("tapeDrive",m_drive.config.unitName)); - m_watchdog.addParameter(Param("vendor",m_retrieveMount.getVendor())); m_watchdog.addParameter(Param("volReqId", m_volInfo.mountId)); - m_watchdog.addParameter(Param("vo",m_retrieveMount.getVo())); - m_watchdog.addParameter(Param("mediaType",m_retrieveMount.getMediaType())); - m_watchdog.addParameter(Param("tapePool",m_retrieveMount.getPoolName())); - m_watchdog.addParameter(Param("logicalLibrary",m_drive.config.logicalLibrary)); - m_watchdog.addParameter(Param("capacityInBytes",m_retrieveMount.getCapacityInBytes())); - + m_watchdog.addParameter(Param("tapeDrive", m_drive.config.unitName)); + m_watchdog.addParameter(Param("vendor", m_retrieveMount.getVendor())); + m_watchdog.addParameter(Param("vo", m_retrieveMount.getVo())); + m_watchdog.addParameter(Param("mediaType", m_retrieveMount.getMediaType())); + m_watchdog.addParameter(Param("tapePool", m_retrieveMount.getPoolName())); + m_watchdog.addParameter(Param("logicalLibrary", m_drive.config.logicalLibrary)); + m_watchdog.addParameter(Param("capacityInBytes", m_retrieveMount.getCapacityInBytes())); + // Set the tape thread time in the watchdog for total time estimation in case // of crash m_watchdog.updateThreadTimer(totalTimer); - + //pair of brackets to create an artificial scope for the tapeCleaner - { + { + //log and notify + m_logContext.log(cta::log::INFO, "Starting tape read thread"); + // The tape will be loaded // it has to be unloaded, unmounted at all cost -> RAII // will also take care of the TapeServerReporter and of RecallTaskInjector TapeCleaning tapeCleaner(*this, timer); // Before anything, the tape should be mounted - m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Mounting); + m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Mounting, cta::nullopt, m_logContext); cta::log::ScopedParamContainer params(m_logContext); - params.add("vo",m_retrieveMount.getVo()); - params.add("mediaType",m_retrieveMount.getMediaType()); - params.add("tapePool",m_retrieveMount.getPoolName()); - params.add("logicalLibrary",m_drive.config.logicalLibrary); - params.add("mountType",mountTypeToString(m_volInfo.mountType)); - params.add("vendor",m_retrieveMount.getVendor()); - params.add("capacityInBytes",m_retrieveMount.getCapacityInBytes()); - m_logContext.log(cta::log::INFO, "Tape session started"); + params.add("vo", m_retrieveMount.getVo()); + params.add("mediaType", m_retrieveMount.getMediaType()); + params.add("tapePool", m_retrieveMount.getPoolName()); + params.add("logicalLibrary", m_drive.config.logicalLibrary); + params.add("mountType", toCamelCaseString(m_volInfo.mountType)); + params.add("vendor", m_retrieveMount.getVendor()); + params.add("capacityInBytes", m_retrieveMount.getCapacityInBytes()); + m_logContext.log(cta::log::INFO, "Tape session started for read"); mountTapeReadOnly(); currentErrorToCount = "Error_tapeLoad"; cta::utils::Timer tapeLoadTimer; @@ -258,7 +260,7 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("mountTime", m_stats.mountTime); - scoped.add("tapeLoadTime",tapeLoadTime); + scoped.add("tapeLoadTime", tapeLoadTime); m_logContext.log(cta::log::INFO, "Tape mounted and drive ready"); } m_retrieveMount.setTapeMounted(m_logContext); @@ -273,19 +275,20 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { EncryptionControl::SetTag::NO_SET_TAG); if (encryptionStatus.on) { encryptionLogParams.add("encryption", "on") - .add("encryptionKey", encryptionStatus.keyName) - .add("stdout", encryptionStatus.stdout); + .add("encryptionKey", encryptionStatus.keyName) + .add("stdout", encryptionStatus.stdout); m_logContext.log(cta::log::INFO, "Drive encryption enabled for this mount"); - } else { + } + else { encryptionLogParams.add("encryption", "off"); m_logContext.log(cta::log::INFO, "Drive encryption not enabled for this mount"); } } m_stats.encryptionControlTime += timer.secs(cta::utils::Timer::resetCounter); } - catch (cta::exception::Exception &ex) { - cta::log::ScopedParamContainer params(m_logContext); - params.add("ErrorMessage", ex.getMessage().str()); + catch (cta::exception::Exception& ex) { + cta::log::ScopedParamContainer exceptionParams(m_logContext); + exceptionParams.add("ErrorMessage", ex.getMessage().str()); m_logContext.log(cta::log::ERR, "Drive encryption could not be enabled for this mount."); throw; } @@ -295,63 +298,65 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { } // Then we have to initialise the tape read session currentErrorToCount = "Error_tapesCheckLabelBeforeReading"; - std::unique_ptr<castor::tape::tapeFile::ReadSession> rs(openReadSession()); - // From now on, the tasks will identify problems when executed. - currentErrorToCount = ""; + std::unique_ptr<castor::tape::tapeFile::ReadSession> readSession(openReadSession()); m_stats.positionTime += timer.secs(cta::utils::Timer::resetCounter); //and then report { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("positionTime", m_stats.positionTime); scoped.add("useLbp", m_useLbp); - scoped.add("detectedLbp", rs->isTapeWithLbp()); - if (rs->isTapeWithLbp() && !m_useLbp) { - m_logContext.log(cta::log::WARNING, "Tapserver started without LBP support" - " but the tape with LBP label mounted"); + scoped.add("detectedLbp", readSession->isTapeWithLbp()); + + if (readSession->isTapeWithLbp() && !m_useLbp) { + m_logContext.log(cta::log::WARNING, "Tapeserver started without LBP support" + " but the tape with LBP label mounted"); } - switch(m_drive.getLbpToUse()) { + switch (m_drive.getLbpToUse()) { case drive::lbpToUse::crc32cReadOnly: m_logContext.log(cta::log::INFO, "Tape read session session with LBP " - "crc32c in ReadOnly mode successfully started"); + "crc32c in ReadOnly mode successfully started"); break; case drive::lbpToUse::disabled: m_logContext.log(cta::log::INFO, "Tape read session session without LBP " - "successfully started"); + "successfully started"); break; default: m_logContext.log(cta::log::ERR, "Tape read session session with " - "unsupported LBP started"); + "unsupported LBP started"); } } - m_initialProcess.reportState(cta::tape::session::SessionState::Running, - cta::tape::session::SessionType::Retrieve); + + m_reporter.reportState(cta::tape::session::SessionState::Running, + cta::tape::session::SessionType::Retrieve); m_stats.waitReportingTime += timer.secs(cta::utils::Timer::resetCounter); // Then we will loop on the tasks as they get from // the task injector - + // We wait the task injector to finish inserting its first batch // before launching the loop. // We do it with a promise m_taskInjector->waitForFirstTasksInjectedPromise(); + // From now on, the tasks will identify problems when executed. + currentErrorToCount = ""; std::unique_ptr<TapeReadTask> task; - m_rrp.reportDriveStatus(cta::common::dataStructures::DriveStatus::Transferring); - while(true) { + m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Transferring, cta::nullopt, m_logContext); + while (true) { //get a task task.reset(popAndRequestMoreJobs()); m_stats.waitInstructionsTime += timer.secs(cta::utils::Timer::resetCounter); // If we reached the end - if (NULL==task.get()) { + if (nullptr == task) { m_logContext.log(cta::log::DEBUG, "No more files to read from tape"); break; } - // This can lead the the session being marked as corrupt, so we test + // This can lead the session being marked as corrupt, so we test // it in the while loop - task->execute(*rs, m_logContext, m_watchdog,m_stats,timer); + task->execute(*readSession, m_logContext, m_watchdog, m_stats, timer); // Transmit the statistics to the watchdog thread m_watchdog.updateStatsWithoutDeliveryTime(m_stats); // The session could have been corrupted (failed positioning) - if(rs->isCorrupted()) { - throw cta::exception::Exception ("Session corrupted: exiting task execution loop in TapeReadSingleThread. Cleanup will follow."); + if (readSession->isCorrupted()) { + throw cta::exception::Exception("Session corrupted: exiting task execution loop in TapeReadSingleThread. Cleanup will follow."); } } } @@ -361,13 +366,14 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { cta::log::ScopedParamContainer params(m_logContext); params.add("status", "success"); m_stats.totalTime = totalTimer.secs(); - m_rrp.setTapeDone(); - m_rrp.setTapeComplete(); - logWithStat(cta::log::INFO, "Tape thread complete", - params); + m_reportPacker.setTapeDone(); + m_reportPacker.setTapeComplete(); + logWithStat(cta::log::INFO, "Tape thread complete", params); // Report one last time the stats, after unloading/unmounting. m_watchdog.updateStatsWithoutDeliveryTime(m_stats); - } catch(const cta::exception::Exception& e){ + // end of session + log are reported by the last active disk thread + // in DiskWriteThreadPool::DiskWriteWorkerThread::run() + } catch (const cta::exception::Exception& e) { // We can still update the session stats one last time (unmount timings // should have been updated by the RAII cleaner/unmounter). m_watchdog.updateStats(m_stats); @@ -380,22 +386,22 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { params.add("status", "error") .add("ErrorMessage", e.getMessageValue()); m_stats.totalTime = totalTimer.secs(); - logWithStat(cta::log::INFO, "Tape thread complete", - params); + logWithStat(cta::log::INFO, "Tape thread complete for reading", + params); // Also transmit the error step to the watchdog - if (currentErrorToCount.size()) { + if (!currentErrorToCount.empty()) { m_watchdog.addToErrorCount(currentErrorToCount); } // Flush the remaining tasks to cleanly exit. - while(1){ - TapeReadTask* task=m_tasks.pop(); - if(!task) { + while (true) { + TapeReadTask *task = m_tasks.pop(); + if (!task) { break; } task->reportCancellationToDiskTask(); delete task; } - } + } } //------------------------------------------------------------------------------ @@ -403,28 +409,28 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() { //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeReadSingleThread::logWithStat( int level, const std::string& msg, cta::log::ScopedParamContainer& params) { - params.add("type", "read") - .add("tapeVid", m_volInfo.vid) - .add("mountTime", m_stats.mountTime) - .add("positionTime", m_stats.positionTime) - .add("waitInstructionsTime", m_stats.waitInstructionsTime) - .add("readWriteTime", m_stats.readWriteTime) - .add("waitFreeMemoryTime", m_stats.waitFreeMemoryTime) - .add("waitReportingTime", m_stats.waitReportingTime) - .add("unloadTime", m_stats.unloadTime) - .add("unmountTime", m_stats.unmountTime) - .add("encryptionControlTime", m_stats.encryptionControlTime) - .add("transferTime", m_stats.transferTime()) - .add("totalTime", m_stats.totalTime) - .add("dataVolume", m_stats.dataVolume) - .add("headerVolume", m_stats.headerVolume) - .add("files", m_stats.filesCount) - .add("payloadTransferSpeedMBps", m_stats.totalTime?1.0*m_stats.dataVolume - /1000/1000/m_stats.totalTime:0.0) - .add("driveTransferSpeedMBps", m_stats.totalTime?1.0*(m_stats.dataVolume+m_stats.headerVolume) - /1000/1000/m_stats.totalTime:0.0); - m_logContext.moveToTheEndIfPresent("status"); - m_logContext.log(level,msg); + params.add("type", "read") + .add("tapeVid", m_volInfo.vid) + .add("mountTime", m_stats.mountTime) + .add("positionTime", m_stats.positionTime) + .add("waitInstructionsTime", m_stats.waitInstructionsTime) + .add("readWriteTime", m_stats.readWriteTime) + .add("waitFreeMemoryTime", m_stats.waitFreeMemoryTime) + .add("waitReportingTime", m_stats.waitReportingTime) + .add("unloadTime", m_stats.unloadTime) + .add("unmountTime", m_stats.unmountTime) + .add("encryptionControlTime", m_stats.encryptionControlTime) + .add("transferTime", m_stats.transferTime()) + .add("totalTime", m_stats.totalTime) + .add("dataVolume", m_stats.dataVolume) + .add("headerVolume", m_stats.headerVolume) + .add("files", m_stats.filesCount) + .add("payloadTransferSpeedMBps", m_stats.totalTime ? 1.0 * m_stats.dataVolume + / 1000 / 1000 / m_stats.totalTime : 0.0) + .add("driveTransferSpeedMBps", m_stats.totalTime ? 1.0 * (m_stats.dataVolume + m_stats.headerVolume) + / 1000 / 1000 / m_stats.totalTime : 0.0); + m_logContext.moveToTheEndIfPresent("status"); + m_logContext.log(level, msg); } //------------------------------------------------------------------------------ @@ -441,9 +447,9 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::logSCSIMetrics() { std::map<std::string, uint32_t> scsi_nonmedium_metrics_hash = m_drive.getTapeNonMediumErrors(); appendMetricsToScopedParams(scopedContainer, scsi_nonmedium_metrics_hash); logSCSIStats("Logging mount general statistics", - scsi_read_metrics_hash.size() + scsi_nonmedium_metrics_hash.size()); + scsi_read_metrics_hash.size() + scsi_nonmedium_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging mount general statistics"); @@ -454,14 +460,14 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::logSCSIMetrics() { cta::log::ScopedParamContainer scopedContainer(m_logContext); appendDriveAndTapeInfoToScopedParams(scopedContainer); // get drive stats - std::map<std::string,float> scsi_quality_metrics_hash = m_drive.getQualityStats(); + std::map<std::string, float> scsi_quality_metrics_hash = m_drive.getQualityStats(); appendMetricsToScopedParams(scopedContainer, scsi_quality_metrics_hash); - std::map<std::string,uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats(); + std::map<std::string, uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats(); appendMetricsToScopedParams(scopedContainer, scsi_drive_metrics_hash); logSCSIStats("Logging drive statistics", - scsi_quality_metrics_hash.size()+scsi_drive_metrics_hash.size()); + scsi_quality_metrics_hash.size() + scsi_drive_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging drive statistics"); @@ -471,11 +477,11 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::logSCSIMetrics() { try { cta::log::ScopedParamContainer scopedContainer(m_logContext); appendDriveAndTapeInfoToScopedParams(scopedContainer); - std::map<std::string,uint32_t> scsi_metrics_hash = m_drive.getVolumeStats(); + std::map<std::string, uint32_t> scsi_metrics_hash = m_drive.getVolumeStats(); appendMetricsToScopedParams(scopedContainer, scsi_metrics_hash); logSCSIStats("Logging volume statistics", scsi_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging volume statistics"); diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp index 445378b906a379dd1d6222bc0a83c58608621681..4e042379a9c3f6e8c529f1d21c07b0904ab93b39 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp @@ -24,8 +24,6 @@ #include "castor/tape/tapeserver/drive/DriveInterface.hpp" #include "castor/tape/tapeserver/file/File.hpp" #include "castor/tape/tapeserver/daemon/RecallReportPacker.hpp" -#include "castor/tape/tapeserver/daemon/RecallTaskInjector.hpp" -#include "castor/tape/tapeserver/daemon/TapeServerReporter.hpp" #include "castor/tape/tapeserver/daemon/TaskWatchDog.hpp" #include "castor/tape/tapeserver/daemon/VolumeInfo.hpp" #include "common/Timer.hpp" @@ -42,102 +40,101 @@ namespace daemon { //forward declaration class TapeServerReporter; - /** - * This class will execute the different tape read tasks. - * - */ -class TapeReadSingleThread : public TapeSingleThreadInterface<TapeReadTask>{ +class RecallTaskInjector; + +/** + * This class will execute the different tape read tasks. + * + */ +class TapeReadSingleThread : public TapeSingleThreadInterface<TapeReadTask> { public: /** - * Constructor: + * Constructor */ - TapeReadSingleThread(castor::tape::tapeserver::drive::DriveInterface & drive, - cta::mediachanger::MediaChangerFacade &mc, - TapeServerReporter & initialProcess, - const VolumeInfo& volInfo, - uint64_t maxFilesRequest, - cta::server::ProcessCap &capUtils, - RecallWatchDog& watchdog, - cta::log::LogContext & lc, - RecallReportPacker &rrp, - const bool useLbp, - const bool useRAO, - const bool useEncryption, - const std::string & externalEncryptionKeyScript, - const cta::RetrieveMount &retrieveMount, - const uint32_t tapeLoadTimeout); - + TapeReadSingleThread(castor::tape::tapeserver::drive::DriveInterface& drive, + cta::mediachanger::MediaChangerFacade& mediaChanger, + TapeServerReporter& reporter, + const VolumeInfo& volInfo, + uint64_t maxFilesRequest, + cta::server::ProcessCap& capUtils, + RecallWatchDog& watchdog, + cta::log::LogContext& logContext, + RecallReportPacker& reportPacker, + const bool useLbp, + const bool useRAO, + const bool useEncryption, + const std::string& externalEncryptionKeyScript, + const cta::RetrieveMount& retrieveMount, + const uint32_t tapeLoadTimeout); + /** - * Set the task injector. Has to be done that way (and not in the constructor) - * because there is a dependency - * @param ti the task injector + * Sets up the pointer to the task injector. This cannot be done at + * construction time as both task injector and tape write single thread refer to + * each other. This function should be called before starting the threads. + * This is used for signalling problems during mounting. After that, each + * tape write task does the signalling itself, either on tape problem, or + * when receiving an error from the disk tasks via memory blocks. + * @param injector the task injector */ - void setTaskInjector(RecallTaskInjector * ti) { - m_taskInjector = ti; + void setTaskInjector(RecallTaskInjector *injector) { + m_taskInjector = injector; } -private: - - /** - * Returns the string representation of the specified mount type - */ - const char *mountTypeToString(const cta::common::dataStructures::MountType mountType) const - throw(); - - //RAII class for cleaning tape stuff - class TapeCleaning{ +private: + + // RAII class for cleaning tape stuff + class TapeCleaning { TapeReadSingleThread& m_this; // As we are living in the single thread of tape, we can borrow the timer - cta::utils::Timer & m_timer; + cta::utils::Timer& m_timer; public: - TapeCleaning(TapeReadSingleThread& parent, cta::utils::Timer & timer): - m_this(parent), m_timer(timer){} + TapeCleaning(TapeReadSingleThread& parent, cta::utils::Timer& timer) : + m_this(parent), m_timer(timer) {} + ~TapeCleaning(); }; + /** * Pop a task from its tasks and if there is not enough tasks left, it will * ask the task injector for more * @return m_tasks.pop(); */ - TapeReadTask * popAndRequestMoreJobs(); - - /** - * Try to open an tapeFile::ReadSession, if it fails, we got an exception. - * Return an std::unique_ptr will ensure the callee will have the ownershipe - * of the object through unique_ptr's copy constructor - * @return - */ + TapeReadTask *popAndRequestMoreJobs(); + + /** + * Try to open an tapeFile::ReadSession, if it fails, we got an exception. + * Return an std::unique_ptr will ensure the callee will have the ownership + * of the object through unique_ptr's copy constructor + * @return + */ std::unique_ptr<castor::tape::tapeFile::ReadSession> openReadSession(); /** * This function is from Thread, it is the function that will do all the job */ - virtual void run(); + void run() override; /** - * Log msg with the given level, Session time is the time taken by the action - * @param level - * @param msg - * @param sessionTime + * Log m_stats parameters into m_logContext with msg at the given level */ - void logWithStat(int level,const std::string& msg, - cta::log::ScopedParamContainer& params); - + void logWithStat(int level, const std::string& msg, + cta::log::ScopedParamContainer& params); + /** * Number of files a single request to the client might give us. * Used in the loop-back function to ask the task injector to request more job */ const uint64_t m_maxFilesRequest; - + ///a pointer to task injector, thus we can ask him for more tasks - castor::tape::tapeserver::daemon::RecallTaskInjector * m_taskInjector; - + RecallTaskInjector *m_taskInjector{}; + /// Reference to the watchdog, used in run() RecallWatchDog& m_watchdog; - + /// Reference to the RecallReportPacker, used to update tape/drive state during recall - RecallReportPacker & m_rrp; - + RecallReportPacker& m_reportPacker; + /** * The boolean variable describing to use on not to use Logical * Block Protection. @@ -149,23 +146,23 @@ private: * Access Order */ bool m_useRAO; - + /** * The retrieve mount object to get the VO, the tape pool and the density of the tape * on which we are reading */ const cta::RetrieveMount& m_retrieveMount; - + /// Helper virtual function to access the watchdog from parent class - virtual void countTapeLogError(const std::string & error) { + void countTapeLogError(const std::string& error) override { m_watchdog.addToErrorCount(error); } - + protected: /** * Logs SCSI metrics for read session. */ - virtual void logSCSIMetrics(); + void logSCSIMetrics() override; }; // class TapeReadSingleThread } // namespace daemon diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadTask.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadTask.hpp index 85f345fbf52db515c474099a7afc2401a98cb656..c0caeed3b359381144a644714c779d102d5d0b61 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadTask.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadTask.hpp @@ -89,7 +89,7 @@ public: // We will not record errors for an empty string. This will allow us to // prevent counting where error happened upstream. std::string currentErrorToCount = ""; - MemBlock* mb=NULL; + MemBlock* mb = nullptr; try { currentErrorToCount = "Error_tapePositionForRead"; std::unique_ptr<castor::tape::tapeFile::ReadFile> rf(openReadFile(rs,lc)); @@ -146,12 +146,12 @@ public: } // Pass the block to the disk write task m_fifo.pushDataBlock(mb); - mb=NULL; + mb = nullptr; watchdog.notify(blockSize); localStats.waitReportingTime += timer.secs(cta::utils::Timer::resetCounter); } //end of while(stillReading) // We have to signal the end of the tape read to the disk write task. - m_fifo.pushDataBlock(NULL); + m_fifo.pushDataBlock(nullptr); // Log the successful transfer localStats.totalTime = localTime.secs(); // Count the trailer size @@ -234,7 +234,7 @@ private: * @param errorMsg The error message we will give to the client * @param mb The mem block we will use */ - void reportErrorToDiskTask(const std::string& msg,int code,MemBlock* mb = NULL){ + void reportErrorToDiskTask(const std::string& msg, int code, MemBlock* mb = nullptr) { //If we are not provided with a block, allocate it and // fill it up if (!mb) { @@ -245,7 +245,7 @@ private: //mark the block failed and push it (plus signal the end) mb->markAsFailed(msg,code); m_fifo.pushDataBlock(mb); - m_fifo.pushDataBlock(NULL); + m_fifo.pushDataBlock(nullptr); } /** * Open the file on the tape. In case of failure, log and throw diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.cpp index 33889ae032f85f9a70891bb87f2136d065b577c4..b011152530272e507d08f7b2a0434048de9b5d10 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.cpp @@ -23,6 +23,8 @@ #include <sys/types.h> #include <unistd.h> +#include <utility> + namespace castor { namespace tape { namespace tapeserver { @@ -34,57 +36,57 @@ namespace daemon { TapeServerReporter::TapeServerReporter( cta::tape::daemon::TapedProxy& tapeserverProxy, const cta::tape::daemon::TpconfigLine& driveConfig, - const std::string &hostname, - const castor::tape::tapeserver::daemon::VolumeInfo &volume, - cta::log::LogContext lc): - m_threadRunnig(false), + const std::string& hostname, + const castor::tape::tapeserver::daemon::VolumeInfo& volume, + const cta::log::LogContext lc) : + m_threadRunning(false), m_tapeserverProxy(tapeserverProxy), m_lc(lc), m_server(hostname), m_unitName(driveConfig.unitName), m_logicalLibrary(driveConfig.logicalLibrary), m_volume(volume), - m_sessionPid(getpid()){ + m_sessionPid(getpid()) { //change the thread's name in the log - m_lc.pushOrReplace(cta::log::Param("thread","TapeServerReporter")); + m_lc.pushOrReplace(cta::log::Param("thread", "TapeServerReporter")); } - + //------------------------------------------------------------------------------ //finish //------------------------------------------------------------------------------ -void TapeServerReporter::finish(){ - m_fifo.push(NULL); +void TapeServerReporter::finish() { + m_fifo.push(nullptr); } //------------------------------------------------------------------------------ //startThreads //------------------------------------------------------------------------------ -void TapeServerReporter::startThreads(){ +void TapeServerReporter::startThreads() { start(); - m_threadRunnig=true; + m_threadRunning = true; } //------------------------------------------------------------------------------ //waitThreads //------------------------------------------------------------------------------ -void TapeServerReporter::waitThreads(){ - try{ +void TapeServerReporter::waitThreads() { + try { wait(); - m_threadRunnig=false; - }catch(const std::exception& e){ - cta::log::ScopedParamContainer sp(m_lc); - sp.add("what",e.what()); - m_lc.log(cta::log::ERR,"error caught while waiting"); - }catch(...){ - m_lc.log(cta::log::ERR,"unknown error while waiting"); - } + m_threadRunning = false; + } catch (const std::exception& e) { + cta::log::ScopedParamContainer sp(m_lc); + sp.add("what", e.what()); + m_lc.log(cta::log::ERR, "error caught while waiting"); + } catch (...) { + m_lc.log(cta::log::ERR, "unknown error while waiting"); + } } //------------------------------------------------------------------------------ //reportState //------------------------------------------------------------------------------ void TapeServerReporter::reportState(cta::tape::session::SessionState state, - cta::tape::session::SessionType type) { + cta::tape::session::SessionType type) { m_fifo.push(new ReportStateChange(state, type)); } @@ -105,27 +107,37 @@ void TapeServerReporter::reportDiskCompleteForRetrieve() { //------------------------------------------------------------------------------ //run //------------------------------------------------------------------------------ -void TapeServerReporter::run(){ - while(1){ +void TapeServerReporter::run() { + while (true) { std::unique_ptr<Report> currentReport(m_fifo.pop()); - if(NULL==currentReport.get()) { + if (nullptr == currentReport) { break; } - try{ - currentReport->execute(*this); - }catch(const std::exception& e){ + try { + currentReport->execute(*this); + } catch (const std::exception& e) { cta::log::ScopedParamContainer sp(m_lc); - sp.add("what",e.what()); - m_lc.log(cta::log::ERR,"TapeServerReporter error caught"); + sp.add("what", e.what()); + m_lc.log(cta::log::ERR, "TapeServerReporter error caught"); } } } +//------------------------------------------------------------------------------ +// ReportStateChange::bailout()) +//------------------------------------------------------------------------------ +void TapeServerReporter::bailout() { + // Send terminating event to the queue + finish(); + // Consume queue and exit + run(); +} + //------------------------------------------------------------------------------ // ReportStateChange::ReportStateChange()) //------------------------------------------------------------------------------ TapeServerReporter::ReportStateChange::ReportStateChange(cta::tape::session::SessionState state, - cta::tape::session::SessionType type): m_state(state), m_type(type) { } + cta::tape::session::SessionType type) : m_state(state), m_type(type) {} //------------------------------------------------------------------------------ // ReportStateChange::execute()) @@ -138,13 +150,14 @@ void TapeServerReporter::ReportStateChange::execute(TapeServerReporter& parent) // ReportTapeUnmountedForRetrieve::execute()) //------------------------------------------------------------------------------ void TapeServerReporter::ReportTapeUnmountedForRetrieve::execute(TapeServerReporter& parent) { - parent.m_tapeUnmountedForRecall=true; + parent.m_tapeUnmountedForRecall = true; if (parent.m_diskCompleteForRecall) { - parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::ShuttingDown, - cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); - } else { - parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::DrainingToDisk, - cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); + parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::ShuttingDown, + cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); + } + else { + parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::DrainingToDisk, + cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); } } @@ -152,12 +165,15 @@ void TapeServerReporter::ReportTapeUnmountedForRetrieve::execute(TapeServerRepor // ReportDiskCompleteForRetrieve::execute()) //------------------------------------------------------------------------------ void TapeServerReporter::ReportDiskCompleteForRetrieve::execute(TapeServerReporter& parent) { - parent.m_diskCompleteForRecall=true; + parent.m_diskCompleteForRecall = true; if (parent.m_tapeUnmountedForRecall) { - parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::ShuttingDown, - cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); + parent.m_tapeserverProxy.reportState(cta::tape::session::SessionState::ShuttingDown, + cta::tape::session::SessionType::Retrieve, parent.m_volume.vid); } } -}}}} // namespace castor::tape::tapeserver::daemon +} +} +} +} // namespace castor::tape::tapeserver::daemon diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.hpp index 8199100c3547f3574f8905cdceb7e933da293fda..b9543749c9bd548264914717c1ba9ba24abdd4c8 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeServerReporter.hpp @@ -19,7 +19,7 @@ #include "common/threading/Thread.hpp" #include "common/threading/BlockingQueue.hpp" -#include "castor/tape/tapeserver/daemon/VolumeInfo.hpp" +#include "VolumeInfo.hpp" #include "common/log/LogContext.hpp" #include "tapeserver/session/SessionState.hpp" #include "tapeserver/session/SessionType.hpp" @@ -29,18 +29,15 @@ #include <stdint.h> namespace castor { -namespace messages{ - class TapeserverProxy; - } namespace tape { namespace tapeserver { namespace daemon { - + class TapeServerReporter : private cta::threading::Thread { public: /** - * COnstructor + * Constructor * @param tapeserverProxy * @param driveConfig The configuration of the tape drive we are using. * @param hostname The host name of the computer @@ -49,29 +46,34 @@ public: */ TapeServerReporter( cta::tape::daemon::TapedProxy& tapeserverProxy, - const cta::tape::daemon::TpconfigLine &driveConfig, - const std::string &hostname, - const castor::tape::tapeserver::daemon::VolumeInfo &volume, + const cta::tape::daemon::TpconfigLine& driveConfig, + const std::string& hostname, + const castor::tape::tapeserver::daemon::VolumeInfo& volume, cta::log::LogContext lc); - + /** * Put into the waiting list a guard value to signal the thread we want * to stop - */ + */ void finish(); - + + /** + * Consume the waiting list and exit + */ + void bailout(); + /** * Will call TapedProxy::reportState(); */ - void reportState(cta::tape::session::SessionState state, - cta::tape::session::SessionType type); + void reportState(cta::tape::session::SessionState state, + cta::tape::session::SessionType type); /** * Special function managing the special case of retrieves, where disk and * tape thread can finish in different orders (tape part) */ void reportTapeUnmountedForRetrieve(); - + /** * Special function managing the special case of retrieves, where disk and * tape thread can finish in different orders (disk part) @@ -81,10 +83,12 @@ public: //------------------------------------------------------------------------------ //start and wait for thread to finish void startThreads(); + void waitThreads(); - + private: - bool m_threadRunnig; + bool m_threadRunning; + /* This internal mechanism could (should ?) be easily changed to a queue * of {std/boost}::function coupled with bind. For instance, tapeMountedForWrite @@ -95,60 +99,64 @@ private: * (m_fifo.push())(); * But no tr1 neither boost, so, another time ... */ - + class Report { public: - virtual ~Report(){} - virtual void execute(TapeServerReporter&)=0; + virtual ~Report() = default; + + virtual void execute(TapeServerReporter&) = 0; }; - - class ReportStateChange: public Report { + + class ReportStateChange : public Report { public: - ReportStateChange(cta::tape::session::SessionState state, - cta::tape::session::SessionType type); + ReportStateChange(cta::tape::session::SessionState state, + cta::tape::session::SessionType type); + void execute(TapeServerReporter&) override; + private: cta::tape::session::SessionState m_state; cta::tape::session::SessionType m_type; }; - - class ReportTapeUnmountedForRetrieve: public Report { + + class ReportTapeUnmountedForRetrieve : public Report { public: void execute(TapeServerReporter&) override; }; - - class ReportDiskCompleteForRetrieve: public Report { + + class ReportDiskCompleteForRetrieve : public Report { public: void execute(TapeServerReporter&) override; }; + /** * Inherited from Thread, it will do the job : pop a request, execute it * and delete it */ - virtual void run(); - + void run() override; + /** * m_fifo is holding all the report waiting to be processed */ - cta::threading::BlockingQueue<Report*> m_fifo; - + cta::threading::BlockingQueue<Report *> m_fifo; + /** A bunch of references to proxies to send messages to the * outside world when we have to */ cta::tape::daemon::TapedProxy& m_tapeserverProxy; - + /** * Log context, copied because it is in a separated thread */ cta::log::LogContext m_lc; - + /** * Boolean allowing the management of the special case of recall where * end of tape and disk threads can happen in any order (tape side) */ bool m_tapeUnmountedForRecall = false; - + /** * Boolean allowing the management of the special case of recall where * end of tape and disk threads can happen in any order (disk side) @@ -163,4 +171,7 @@ private: }; -}}}} +} +} +} +} diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp index 70628a5ab5507145bde6653cf356f99228f68afc..4cd8972362c80dedf4c1ebf081c9b59f242250a9 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp @@ -34,81 +34,80 @@ #include "tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.hpp" #include "common/Timer.hpp" -namespace castor { -namespace tape { +namespace castor { +namespace tape { namespace tapeserver { -namespace daemon { - - // Forward declaration - class TapeServerReporter; - /** - * This class is the base class for the 2 classes that will be executing - * all tape-{read|write} tasks. The template parameter Task is the type of - * task we are expecting : TapeReadTask or TapeWriteTask - */ -template <class Task> -class TapeSingleThreadInterface : private cta::threading::Thread -{ +namespace daemon { + +// Forward declaration +class TapeServerReporter; + +/** + * This class is the base class for the 2 classes that will be executing + * all tape-{read|write} tasks. The template parameter Task is the type of + * task we are expecting : TapeReadTask or TapeWriteTask + */ +template<class Task> +class TapeSingleThreadInterface : private cta::threading::Thread { private : /** * Utility to change the capabilities of the current tape thread */ - cta::server::ProcessCap &m_capUtils; + cta::server::ProcessCap& m_capUtils; protected: ///the queue of tasks cta::threading::BlockingQueue<Task *> m_tasks; - + /** * An interface to manipulate the drive to manipulate the tape * with the requested vid */ - castor::tape::tapeserver::drive::DriveInterface & m_drive; - + castor::tape::tapeserver::drive::DriveInterface& m_drive; + /** Reference to the mount interface */ - cta::mediachanger::MediaChangerFacade & m_mc; - + cta::mediachanger::MediaChangerFacade& m_mediaChanger; + /** Reference to the Global reporting interface */ - TapeServerReporter & m_initialProcess; - + TapeServerReporter& m_reporter; + ///The volumeID of the tape on which we want to operate const std::string m_vid; ///log context, for ... logging purpose, copied du to thread mechanism cta::log::LogContext m_logContext; - + VolumeInfo m_volInfo; - + /** * Integer to notify the tapeserver if the drive has to be put down or not. */ Session::EndOfSessionAction m_hardwareStatus; - + /** Session statistics */ TapeSessionStats m_stats; /** Encryption helper object */ EncryptionControl m_encryptionControl; - + /** Tape load timeout after which the mount is considered failed. */ uint32_t m_tapeLoadTimeout; - + /** * Try to mount the tape for read-only access, get an exception if it fails */ - void mountTapeReadOnly(){ - cta::log::ScopedParamContainer scoped(m_logContext); - scoped.add("drive_Slot",m_drive.config.librarySlot().str()); + void mountTapeReadOnly() { + cta::log::ScopedParamContainer scoped(m_logContext); + scoped.add("drive_Slot", m_drive.config.librarySlot().str()); try { cta::utils::Timer timer; - m_mc.mountTapeReadOnly(m_volInfo.vid, m_drive.config.librarySlot()); - const std::string modeAsString = "R"; - scoped.add("MCMountTime",timer.secs()).add("mode",modeAsString); - m_logContext.log(cta::log::INFO, "Tape mounted for read-only access"); + m_mediaChanger.mountTapeReadOnly(m_volInfo.vid, m_drive.config.librarySlot()); + const std::string modeAsString = "R"; + scoped.add("MCMountTime", timer.secs()).add("mode", modeAsString); + m_logContext.log(cta::log::INFO, "Tape mounted for read-only access"); } - catch (cta::exception::Exception & ex) { + catch (cta::exception::Exception& ex) { scoped.add("exceptionMessage", ex.getMessageValue()); - m_logContext.log(cta::log::ERR, - "Failed to mount the tape for read-only access"); + m_logContext.log(cta::log::ERR, "Failed to mount the tape for read-only access"); throw; } } @@ -116,24 +115,24 @@ protected: /** * Try to mount the tape for read/write access, get an exception if it fails */ - void mountTapeReadWrite(){ - cta::log::ScopedParamContainer scoped(m_logContext); - scoped.add("drive_Slot",m_drive.config.librarySlot().str()); + void mountTapeReadWrite() { + cta::log::ScopedParamContainer scoped(m_logContext); + scoped.add("drive_Slot", m_drive.config.librarySlot().str()); try { cta::utils::Timer timer; - m_mc.mountTapeReadWrite(m_volInfo.vid, m_drive.config.librarySlot()); - const std::string modeAsString = "RW"; - scoped.add("MCMountTime",timer.secs()).add("mode",modeAsString); - m_logContext.log(cta::log::INFO, "Tape mounted for read/write access"); + m_mediaChanger.mountTapeReadWrite(m_volInfo.vid, m_drive.config.librarySlot()); + const std::string modeAsString = "RW"; + scoped.add("MCMountTime", timer.secs()).add("mode", modeAsString); + m_logContext.log(cta::log::INFO, "Tape mounted for read/write access"); } - catch (cta::exception::Exception & ex) { + catch (cta::exception::Exception& ex) { scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, - "Failed to mount the tape for read/write access"); + "Failed to mount the tape for read/write access"); throw; } } - + /** * After mounting the tape, the drive will say it has no tape inside, * because there was no tape the first time it was opened... @@ -141,21 +140,21 @@ protected: * to tell us he acknowledge it has indeed a tape (get an ex exception in * case of timeout) */ - void waitForDrive(){ + void waitForDrive() { cta::utils::Timer tapeLoadTime; - try{ - // wait tapeLoadTimeout seconds for drive to be ready (the mount call is synchronous, so this just the load operation. + try { + // wait tapeLoadTimeout seconds for drive to be ready (the mount call is synchronous, so this just the load operation). m_drive.waitUntilReady(m_tapeLoadTimeout); - }catch(const cta::exception::Exception& e){ + } catch (const cta::exception::Exception& e) { cta::log::ScopedParamContainer spc(m_logContext); - spc.add("exceptionMessage",e.getMessageValue()) - .add("configuredTapeLoadTimeout",m_tapeLoadTimeout) - .add("tapeLoadTime",tapeLoadTime.secs()); + spc.add("exceptionMessage", e.getMessageValue()) + .add("configuredTapeLoadTimeout", m_tapeLoadTimeout) + .add("tapeLoadTime", tapeLoadTime.secs()); m_logContext.log(cta::log::ERR, "Got timeout or error while waiting for drive to be ready."); throw; } } - + /** * After waiting for the drive, we will dump the tape alert log content, if * not empty @@ -167,21 +166,17 @@ protected: size_t alertNumber = 0; // Log tape alerts in the logs. std::vector<std::string> tapeAlerts = m_drive.getTapeAlerts(tapeAlertCodes); - for (std::vector<std::string>::iterator ta=tapeAlerts.begin(); - ta!=tapeAlerts.end();ta++) - { + for (const auto& ta: tapeAlerts) { cta::log::ScopedParamContainer params(m_logContext); - params.add("tapeAlert",*ta) + params.add("tapeAlert", ta) .add("tapeAlertNumber", alertNumber++) .add("tapeAlertCount", tapeAlerts.size()); m_logContext.log(cta::log::WARNING, "Tape alert detected"); } // Add tape alerts in the tape log parameters std::vector<std::string> tapeAlertsCompact = m_drive.getTapeAlertsCompact(tapeAlertCodes); - for (std::vector<std::string>::iterator tac=tapeAlertsCompact.begin(); - tac!=tapeAlertsCompact.end();tac++) - { - countTapeLogError(std::string("Error_")+*tac); + for (const auto& tac: tapeAlertsCompact) { + countTapeLogError(std::string("Error_") + tac); } return true; } @@ -194,8 +189,8 @@ protected: /** * Function iterating through the map of available SCSI metrics and logging them. */ - void logSCSIStats(const std::string & logTitle, size_t metricsHashLength) { - if(metricsHashLength == 0) { // skip logging entirely if hash is empty. + void logSCSIStats(const std::string& logTitle, size_t metricsHashLength) { + if (metricsHashLength == 0) { // skip logging entirely if hash is empty. m_logContext.log(cta::log::INFO, "SCSI Statistics could not be acquired from drive"); return; } @@ -205,7 +200,7 @@ protected: /** * Function appending Tape VID, drive manufacturer and model and firmware version to the Scoped Container passed. */ - void appendDriveAndTapeInfoToScopedParams(cta::log::ScopedParamContainer &scopedContainer) { + void appendDriveAndTapeInfoToScopedParams(cta::log::ScopedParamContainer& scopedContainer) { drive::deviceInfo di = m_drive.getDeviceInfo(); scopedContainer.add("driveManufacturer", di.vendor); scopedContainer.add("driveType", di.product); @@ -217,45 +212,46 @@ protected: * Function appending SCSI Metrics to the Scoped Container passed. */ template<class N> - static void appendMetricsToScopedParams( cta::log::ScopedParamContainer &scopedContainer, const std::map<std::string,N> & metricsHash) { - for(auto it = metricsHash.cbegin(); it != metricsHash.end(); it++) { + static void appendMetricsToScopedParams(cta::log::ScopedParamContainer& scopedContainer, const std::map<std::string, N>& metricsHash) { + for (auto it = metricsHash.cbegin(); it != metricsHash.end(); it++) { scopedContainer.add(it->first, it->second); - } - } + } + } /** * Helper virtual function allowing the access to the m_watchdog member * in the inherited classes (TapeReadSingleThread and TapeWriteSingleThread) * @param error */ - virtual void countTapeLogError(const std::string & error) = 0; - + virtual void countTapeLogError(const std::string& error) = 0; + public: - + Session::EndOfSessionAction getHardwareStatus() const { return m_hardwareStatus; } + /** * Push into the class a sentinel value to trigger to end the the thread. */ - void finish() { m_tasks.push(NULL); } - + void finish() { m_tasks.push(nullptr); } + /** * Push a new task into the internal queue * @param t the task to push */ - void push(Task * t) { m_tasks.push(t); } - + void push(Task *t) { m_tasks.push(t); } + /** * Start the threads */ - virtual void startThreads(){ start(); } - + virtual void startThreads() { start(); } + /** * Wait for the thread to finish */ virtual void waitThreads() { wait(); } - + /** * Allows to pre-set the time spent waiting for instructions, spent before * the tape thread is started. This is for timing the synchronous task @@ -263,11 +259,11 @@ public: * This function MUST be called before starting the thread. * @param secs time in seconds (double) */ - virtual void setWaitForInstructionsTime(double secs) { - m_stats.waitInstructionsTime = secs; + virtual void setWaitForInstructionsTime(double secs) { + m_stats.waitInstructionsTime = secs; } - virtual castor::tape::tapeserver::drive::DriveInterface* getDriveReference() { + virtual castor::tape::tapeserver::drive::DriveInterface *getDriveReference() { return &m_drive; } @@ -282,16 +278,17 @@ public: * @param lc lc The log context, later on copied * @param tapeLoadTimeout the timeout after which the mount of the tape is considered failed */ - TapeSingleThreadInterface(castor::tape::tapeserver::drive::DriveInterface & drive, - cta::mediachanger::MediaChangerFacade &mc, - TapeServerReporter & tsr, - const VolumeInfo& volInfo, - cta::server::ProcessCap &capUtils,cta::log::LogContext & lc, - const bool useEncryption, - const std::string & externalEncryptionKeyScript, const uint32_t tapeLoadTimeout):m_capUtils(capUtils), - m_drive(drive), m_mc(mc), m_initialProcess(tsr), m_vid(volInfo.vid), m_logContext(lc), - m_volInfo(volInfo),m_hardwareStatus(Session::MARK_DRIVE_AS_UP), - m_encryptionControl(useEncryption, externalEncryptionKeyScript),m_tapeLoadTimeout(tapeLoadTimeout) {} + TapeSingleThreadInterface(castor::tape::tapeserver::drive::DriveInterface& drive, + cta::mediachanger::MediaChangerFacade& mc, + TapeServerReporter& tsr, + const VolumeInfo& volInfo, + cta::server::ProcessCap& capUtils, cta::log::LogContext& lc, + const bool useEncryption, + const std::string& externalEncryptionKeyScript, const uint32_t tapeLoadTimeout) + : m_capUtils(capUtils), + m_drive(drive), m_mediaChanger(mc), m_reporter(tsr), m_vid(volInfo.vid), m_logContext(lc), + m_volInfo(volInfo), m_hardwareStatus(Session::MARK_DRIVE_AS_UP), + m_encryptionControl(useEncryption, externalEncryptionKeyScript), m_tapeLoadTimeout(tapeLoadTimeout) {} }; // class TapeSingleThreadInterface } // namespace daemon diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp index f4fd8189c75b869e185a0c350413a742d1343957..7760be296a1fb97a5b1f4e0a8b7edf8ccfc209c7 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp @@ -16,72 +16,89 @@ */ #include "castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp" +#include "castor/tape/tapeserver/daemon/TapeServerReporter.hpp" #include "castor/tape/tapeserver/daemon/MigrationTaskInjector.hpp" +#include "common/make_unique.hpp" //------------------------------------------------------------------------------ -//constructor +// Constructor for TapeWriteSingleThread //------------------------------------------------------------------------------ castor::tape::tapeserver::daemon::TapeWriteSingleThread::TapeWriteSingleThread( -castor::tape::tapeserver::drive::DriveInterface & drive, - cta::mediachanger::MediaChangerFacade & mc, - TapeServerReporter & tsr, - MigrationWatchDog & mwd, - const VolumeInfo& volInfo, - cta::log::LogContext & lc, - MigrationReportPacker & repPacker, - cta::server::ProcessCap &capUtils, - uint64_t filesBeforeFlush, uint64_t bytesBeforeFlush, - const bool useLbp, const bool useEncryption, - const std::string & externalEncryptionKeyScript, - const cta::ArchiveMount & archiveMount, - const uint64_t tapeLoadTimeout): - TapeSingleThreadInterface<TapeWriteTask>(drive, mc, tsr, volInfo, - capUtils, lc, useEncryption, externalEncryptionKeyScript,tapeLoadTimeout), - m_filesBeforeFlush(filesBeforeFlush), - m_bytesBeforeFlush(bytesBeforeFlush), - m_drive(drive), - m_reportPacker(repPacker), - m_lastFseq(-1), - m_compress(true), - m_useLbp(useLbp), - m_watchdog(mwd), - m_archiveMount(archiveMount){} + castor::tape::tapeserver::drive::DriveInterface& drive, + cta::mediachanger::MediaChangerFacade& mediaChanger, + TapeServerReporter& reporter, + MigrationWatchDog& watchdog, + const VolumeInfo& volInfo, + cta::log::LogContext& logContext, + MigrationReportPacker& reportPacker, + cta::server::ProcessCap& capUtils, + uint64_t filesBeforeFlush, uint64_t bytesBeforeFlush, + const bool useLbp, const bool useEncryption, + const std::string& externalEncryptionKeyScript, + const cta::ArchiveMount& archiveMount, + const uint64_t tapeLoadTimeout) : + TapeSingleThreadInterface<TapeWriteTask>(drive, mediaChanger, reporter, volInfo, + capUtils, logContext, useEncryption, externalEncryptionKeyScript, tapeLoadTimeout), + m_filesBeforeFlush(filesBeforeFlush), + m_bytesBeforeFlush(bytesBeforeFlush), + m_drive(drive), + m_reportPacker(reportPacker), + m_lastFseq(-1), + m_compress(true), + m_useLbp(useLbp), + m_watchdog(watchdog), + m_archiveMount(archiveMount) {} //------------------------------------------------------------------------------ //TapeCleaning::~TapeCleaning() //------------------------------------------------------------------------------ -castor::tape::tapeserver::daemon::TapeWriteSingleThread::TapeCleaning::~TapeCleaning(){ +castor::tape::tapeserver::daemon::TapeWriteSingleThread::TapeCleaning::~TapeCleaning() { + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::CleaningUp, cta::nullopt, m_this.m_logContext); + + // Tell everyone to wrap up the session + // We now acknowledge to the task injector that read reached the end. There + // will hence be no more requests for more. + m_this.m_taskInjector->finish(); + //then we log/notify + m_this.m_logContext.log(cta::log::DEBUG, "Starting write session cleanup. Signalled end of session to task injector."); + m_this.m_stats.waitReportingTime += m_timer.secs(cta::utils::Timer::resetCounter); + // Disable encryption (or at least try) try { if (m_this.m_encryptionControl.disable(m_this.m_drive)) m_this.m_logContext.log(cta::log::INFO, "Turned encryption off before unmounting"); - } catch (cta::exception::Exception & ex) { + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_this.m_logContext); scoped.add("exceptionError", ex.getMessageValue()); m_this.m_logContext.log(cta::log::ERR, "Failed to turn off encryption before unmounting"); } m_this.m_stats.encryptionControlTime += m_timer.secs(cta::utils::Timer::resetCounter); - m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::CleaningUp, cta::nullopt, m_this.m_logContext); - // This out-of-try-catch variables allows us to record the stage of the - // process we're in, and to count the error if it occurs. - // We will not record errors for an empty string. This will allow us to - // prevent counting where error happened upstream. + // Log (safely, exception-wise) the tape alerts (if any) at the end of the session try { m_this.logTapeAlerts(); } catch (...) {} // Log (safely, exception-wise) the tape SCSI metrics at the end of the session - try { m_this.logSCSIMetrics(); } catch(...) {} - m_this.m_initialProcess.reportState(cta::tape::session::SessionState::Unmounting, - cta::tape::session::SessionType::Archive); + try { m_this.logSCSIMetrics(); } catch (...) {} + + // Log safely errors at the end of the session + // This out-of-try-catch variables allows us to record the stage of the + // process we're in, and to count the error if it occurs. + // We will not record errors for an empty string. This will allow us to + // prevent counting where error happened upstream. std::string currentErrorToCount = "Error_tapeUnload"; - try{ + try { // Do the final cleanup // First check that a tape is actually present in the drive. We can get here // after failing to mount (library error) in which case there is nothing to // do (and trying to unmount will only lead to a failure.) + // We give time to the drive for settling after a mount which might have + // just happened. If we time out, then we will simply find no tape in the + // drive, which is a fine situation (so timeout exceptions are discarded). + // Other exception, where we failed to access the drive somehow are at passed + // through. const uint32_t waitMediaInDriveTimeout = m_this.m_tapeLoadTimeout; try { m_this.m_drive.waitUntilReady(waitMediaInDriveTimeout); - } catch (cta::exception::TimeOut &) {} + } catch (cta::exception::TimeOut&) {} if (!m_this.m_drive.hasTapeInPlace()) { m_this.m_logContext.log(cta::log::INFO, "TapeWriteSingleThread: No tape to unload"); goto done; @@ -94,107 +111,100 @@ castor::tape::tapeserver::daemon::TapeWriteSingleThread::TapeCleaning::~TapeClea // And return the tape to the library currentErrorToCount = "Error_tapeDismount"; + m_this.m_reporter.reportState(cta::tape::session::SessionState::Unmounting, cta::tape::session::SessionType::Archive); m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Unmounting, cta::nullopt, m_this.m_logContext); - m_this.m_mc.dismountTape(m_this.m_volInfo.vid, m_this.m_drive.config.librarySlot()); + m_this.m_mediaChanger.dismountTape(m_this.m_volInfo.vid, m_this.m_drive.config.librarySlot()); m_this.m_drive.disableLogicalBlockProtection(); m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Up, cta::nullopt, m_this.m_logContext); m_this.m_stats.unmountTime += m_timer.secs(cta::utils::Timer::resetCounter); m_this.m_logContext.log(cta::log::INFO, "TapeWriteSingleThread : tape unmounted"); - m_this.m_initialProcess.reportState(cta::tape::session::SessionState::ShuttingDown, - cta::tape::session::SessionType::Archive); + m_this.m_reporter.reportState(cta::tape::session::SessionState::ShuttingDown, + cta::tape::session::SessionType::Archive); m_this.m_stats.waitReportingTime += m_timer.secs(cta::utils::Timer::resetCounter); } catch (const cta::exception::Exception& ex) { // Notify something failed during the cleaning m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; const int logLevel = cta::log::ERR; - const std::string errorMsg = "Exception in TapeWriteSingleThread-TapeCleaning. Putting the drive down."; - cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel,errorMsg); - m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down,reason, m_this.m_logContext); + const std::string errorMsg = "Exception in TapeWriteSingleThread-TapeCleaning when unmounting/unloading the tape. Putting the drive down."; + cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel, errorMsg); + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down, reason, m_this.m_logContext); cta::log::ScopedParamContainer scoped(m_this.m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_this.m_logContext.log(logLevel, errorMsg); + // As we do not throw exceptions from here, the watchdog signalling has // to occur from here. try { - if (currentErrorToCount.size()) { + if (!currentErrorToCount.empty()) { m_this.m_watchdog.addToErrorCount(currentErrorToCount); } } catch (...) {} } catch (...) { - // Notify something failed during the cleaning + // Notify something failed during the cleaning const int logLevel = cta::log::ERR; const std::string errorMsg = "Non-Castor exception in TapeWriteSingleThread-TapeCleaning when unmounting the tape. Putting the drive down."; - cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel,errorMsg); - m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; - m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down,reason,m_this.m_logContext); - m_this.m_logContext.log(logLevel,errorMsg); - try { - if (currentErrorToCount.size()) { - m_this.m_watchdog.addToErrorCount(currentErrorToCount); - } - } catch (...) {} + cta::optional<std::string> reason = cta::common::dataStructures::DesiredDriveState::generateReasonFromLogMsg(logLevel, errorMsg); + m_this.m_hardwareStatus = Session::MARK_DRIVE_AS_DOWN; + m_this.m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Down, reason, m_this.m_logContext); + m_this.m_logContext.log(logLevel, errorMsg); + try { + if (!currentErrorToCount.empty()) { + m_this.m_watchdog.addToErrorCount(currentErrorToCount); + } + } catch (...) {} } done: - //then we terminate the global status reporter - m_this.m_initialProcess.finish(); + //then we terminate the global status m_reporter + m_this.m_reporter.finish(); } //------------------------------------------------------------------------------ //setlastFseq //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeWriteSingleThread:: -setlastFseq(uint64_t lastFseq){ - m_lastFseq=lastFseq; +setlastFseq(uint64_t lastFseq) { + m_lastFseq = lastFseq; } + //------------------------------------------------------------------------------ //openWriteSession //------------------------------------------------------------------------------ -std::unique_ptr<castor::tape::tapeFile::WriteSession> +std::unique_ptr<castor::tape::tapeFile::WriteSession> castor::tape::tapeserver::daemon::TapeWriteSingleThread::openWriteSession() { - using cta::log::LogContext; - using cta::log::Param; - typedef LogContext::ScopedParam ScopedParam; - - std::unique_ptr<castor::tape::tapeFile::WriteSession> writeSession; - - ScopedParam sp[]={ - ScopedParam(m_logContext, Param("lastFseq", m_lastFseq)), - ScopedParam(m_logContext, Param("compression", m_compress)), - ScopedParam(m_logContext, Param("useLbp", m_useLbp)), - }; - tape::utils::suppresUnusedVariable(sp); + cta::log::ScopedParamContainer params(m_logContext); + params.add("lastFseq", m_lastFseq) + .add("compression", m_compress) + .add("useLbp", m_useLbp); + try { - writeSession.reset( - new castor::tape::tapeFile::WriteSession(m_drive, m_volInfo, m_lastFseq, - m_compress, m_useLbp) - ); - } - catch (cta::exception::Exception & e) { - ScopedParam sp0(m_logContext, Param("ErrorMessage", e.getMessageValue())); - m_logContext.log(cta::log::ERR, "Failed to start tape write session"); + auto writeSession = cta::make_unique<castor::tape::tapeFile::WriteSession>(m_drive, m_volInfo, m_lastFseq, m_compress, m_useLbp); + + return writeSession; + } catch (cta::exception::Exception& e) { // TODO: log and unroll the session // TODO: add an unroll mode to the tape read task. (Similar to exec, but pushing blocks marked in error) + cta::log::ScopedParamContainer scoped(m_logContext); + scoped.add("exceptionMessage", e.getMessageValue()); + m_logContext.log(cta::log::ERR, "Failed to start tape write session"); throw; } - return writeSession; } + //------------------------------------------------------------------------------ //tapeFlush //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeWriteSingleThread:: -tapeFlush(const std::string& message,uint64_t bytes,uint64_t files, - cta::utils::Timer & timer) -{ +tapeFlush(const std::string& message, uint64_t bytes, uint64_t files, + cta::utils::Timer& timer) { m_drive.flush(); double flushTime = timer.secs(cta::utils::Timer::resetCounter); cta::log::ScopedParamContainer params(m_logContext); params.add("files", files) .add("bytes", bytes) .add("flushTime", flushTime); - m_logContext.log(cta::log::INFO,message); + m_logContext.log(cta::log::INFO, message); m_stats.flushTime += flushTime; - m_reportPacker.reportFlush(m_drive.getCompression(), m_logContext); m_drive.clearCompressionStats(); @@ -231,108 +241,84 @@ logAndCheckTapeAlertsForWrite() { void castor::tape::tapeserver::daemon::TapeWriteSingleThread:: isTapeWritable() const { // check that drive is not write protected - if(m_drive.isWriteProtected()) { - cta::exception::Exception ex; - ex.getMessage() << - "End session with error. Drive is write protected. Aborting labelling..."; - throw ex; - } -} - -//----------------------------------------------------------------------------- -// volumeModeToString -//----------------------------------------------------------------------------- -const char *castor::tape::tapeserver::daemon::TapeWriteSingleThread:: -mountTypeToString(const cta::common::dataStructures::MountType mountType) const noexcept { - switch (mountType) { - case cta::common::dataStructures::MountType::Retrieve: - return "Retrieve"; - case cta::common::dataStructures::MountType::ArchiveForUser: - return "ArchiveForUser"; - case cta::common::dataStructures::MountType::ArchiveForRepack: - return "ArchiveForRepack"; - case cta::common::dataStructures::MountType::Label: - return "Label"; - default: - return "UNKNOWN"; + if (m_drive.isWriteProtected()) { + cta::exception::Exception ex; + ex.getMessage() << + "End session with error. Drive is write protected. Aborting labelling..."; + throw ex; } } //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -//run +// TapeWriteSingleThread::run() //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { cta::log::ScopedParamContainer threadGlobalParams(m_logContext); threadGlobalParams.add("thread", "TapeWrite"); cta::utils::Timer timer, totalTimer; - // This out-of-try-catch variables allows us to record the stage of the + // This out-of-try-catch variables allows us to record the stage of the // process we're in, and to count the error if it occurs. // We will not record errors for an empty string. This will allow us to // prevent counting where error happened upstream. std::string currentErrorToCount = "Error_tapeMountForWrite"; - try - { + try { // Report the parameters of the session to the main thread typedef cta::log::Param Param; m_watchdog.addParameter(Param("tapeVid", m_volInfo.vid)); - m_watchdog.addParameter(Param("mountType", mountTypeToString(m_volInfo.mountType))); + m_watchdog.addParameter(Param("mountType", toCamelCaseString(m_volInfo.mountType))); m_watchdog.addParameter(Param("mountId", m_volInfo.mountId)); m_watchdog.addParameter(Param("volReqId", m_volInfo.mountId)); - - m_watchdog.addParameter(Param("tapeDrive",m_drive.config.unitName)); - m_watchdog.addParameter(Param("vendor",m_archiveMount.getVendor())); - m_watchdog.addParameter(Param("vo",m_archiveMount.getVo())); - m_watchdog.addParameter(Param("mediaType",m_archiveMount.getMediaType())); - m_watchdog.addParameter(Param("tapePool",m_archiveMount.getPoolName())); - m_watchdog.addParameter(Param("logicalLibrary",m_drive.config.logicalLibrary)); - m_watchdog.addParameter(Param("capacityInBytes",m_archiveMount.getCapacityInBytes())); - + m_watchdog.addParameter(Param("tapeDrive", m_drive.config.unitName)); + m_watchdog.addParameter(Param("vendor", m_archiveMount.getVendor())); + m_watchdog.addParameter(Param("vo", m_archiveMount.getVo())); + m_watchdog.addParameter(Param("mediaType", m_archiveMount.getMediaType())); + m_watchdog.addParameter(Param("tapePool", m_archiveMount.getPoolName())); + m_watchdog.addParameter(Param("logicalLibrary", m_drive.config.logicalLibrary)); + m_watchdog.addParameter(Param("capacityInBytes", m_archiveMount.getCapacityInBytes())); + // Set the tape thread time in the watchdog for total time estimation in case // of crash m_watchdog.updateThreadTimer(totalTimer); - + //pair of brackets to create an artificial scope for the tape cleaning { //log and notify m_logContext.log(cta::log::INFO, "Starting tape write thread"); - - // The tape will be loaded + + // The tape will be loaded // it has to be unloaded, unmounted at all cost -> RAII // will also take care of the TapeServerReporter - // TapeCleaning cleaner(*this, timer); - m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Mounting,cta::nullopt, m_logContext); // Before anything, the tape should be mounted - // This call does the logging of the mount + m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Mounting, cta::nullopt, m_logContext); cta::log::ScopedParamContainer params(m_logContext); - params.add("vo",m_archiveMount.getVo()); - params.add("mediaType",m_archiveMount.getMediaType()); - params.add("tapePool",m_archiveMount.getPoolName()); - params.add("logicalLibrary",m_drive.config.logicalLibrary); - params.add("mountType",mountTypeToString(m_volInfo.mountType)); - params.add("vendor",m_archiveMount.getVendor()); - params.add("capacityInBytes",m_archiveMount.getCapacityInBytes()); - m_logContext.log(cta::log::INFO, "Tape session started"); + params.add("vo", m_archiveMount.getVo()); + params.add("mediaType", m_archiveMount.getMediaType()); + params.add("tapePool", m_archiveMount.getPoolName()); + params.add("logicalLibrary", m_drive.config.logicalLibrary); + params.add("mountType", toCamelCaseString(m_volInfo.mountType)); + params.add("vendor", m_archiveMount.getVendor()); + params.add("capacityInBytes", m_archiveMount.getCapacityInBytes()); + m_logContext.log(cta::log::INFO, "Tape session started for write"); mountTapeReadWrite(); currentErrorToCount = "Error_tapeLoad"; cta::utils::Timer tapeLoadTimer; waitForDrive(); double tapeLoadTime = tapeLoadTimer.secs(); currentErrorToCount = "Error_checkingTapeAlert"; - if(logAndCheckTapeAlertsForWrite()) { - throw cta::exception::Exception("Aborting migration session in" - " presence of critical tape alerts"); + if (logAndCheckTapeAlertsForWrite()) { + throw cta::exception::Exception("Aborting write session in" + " presence of critical tape alerts"); } currentErrorToCount = "Error_tapeNotWriteable"; isTapeWritable(); - + m_stats.mountTime += timer.secs(cta::utils::Timer::resetCounter); { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("mountTime", m_stats.mountTime); - scoped.add("tapeLoadTime",tapeLoadTime); + scoped.add("tapeLoadTime", tapeLoadTime); m_logContext.log(cta::log::INFO, "Tape mounted and drive ready"); } m_archiveMount.setTapeMounted(m_logContext); @@ -345,29 +331,30 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { { auto encryptionStatus = m_encryptionControl.enable(m_drive, m_volInfo.vid, EncryptionControl::SetTag::SET_TAG); - if (encryptionStatus.on) { encryptionLogParams.add("encryption", "on") - .add("encryptionKey", encryptionStatus.keyName) - .add("stdout", encryptionStatus.stdout); + .add("encryptionKey", encryptionStatus.keyName) + .add("stdout", encryptionStatus.stdout); m_logContext.log(cta::log::INFO, "Drive encryption enabled for this mount"); - } else { + } + else { encryptionLogParams.add("encryption", "off"); m_logContext.log(cta::log::INFO, "Drive encryption not enabled for this mount"); } } m_stats.encryptionControlTime += timer.secs(cta::utils::Timer::resetCounter); } - catch (cta::exception::Exception &ex) { - cta::log::ScopedParamContainer params(m_logContext); - params.add("ErrorMessage", ex.getMessage().str()); + catch (cta::exception::Exception& ex) { + cta::log::ScopedParamContainer exceptionParams(m_logContext); + exceptionParams.add("ErrorMessage", ex.getMessage().str()); m_logContext.log(cta::log::ERR, "Drive encryption could not be enabled for this mount."); throw; } - currentErrorToCount = "Error_tapePositionForWrite"; // Then we have to initialize the tape write session + currentErrorToCount = "Error_tapePositionForWrite"; std::unique_ptr<castor::tape::tapeFile::WriteSession> writeSession(openWriteSession()); - m_stats.positionTime += timer.secs(cta::utils::Timer::resetCounter); + m_stats.positionTime += timer.secs(cta::utils::Timer::resetCounter); + //and then report { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("positionTime", m_stats.positionTime); @@ -395,29 +382,29 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { } } - m_initialProcess.reportState(cta::tape::session::SessionState::Running, - cta::tape::session::SessionType::Archive); - uint64_t bytes=0; - uint64_t files=0; + m_reporter.reportState(cta::tape::session::SessionState::Running, + cta::tape::session::SessionType::Archive); m_stats.waitReportingTime += timer.secs(cta::utils::Timer::resetCounter); + uint64_t bytes = 0; + uint64_t files = 0; // Tasks handle their error logging themselves. currentErrorToCount = ""; - std::unique_ptr<TapeWriteTask> task; - m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Transferring,cta::nullopt, m_logContext); - while(1) { + std::unique_ptr<TapeWriteTask> task; + m_reportPacker.reportDriveStatus(cta::common::dataStructures::DriveStatus::Transferring, cta::nullopt, m_logContext); + while (true) { //get a task task.reset(m_tasks.pop()); m_stats.waitInstructionsTime += timer.secs(cta::utils::Timer::resetCounter); - //if is the end - if(NULL==task.get()) { + // If we reached the end + if (nullptr == task) { //we flush without asking - tapeFlush("No more data to write on tape, unconditional flushing to the client",bytes,files,timer); + tapeFlush("No more data to write on tape, unconditional flushing to the client", bytes, files, timer); m_stats.flushTime += timer.secs(cta::utils::Timer::resetCounter); cta::log::LogContext::ScopedParam sp0(m_logContext, cta::log::Param("tapeThreadDuration", totalTimer.secs())); m_logContext.log(cta::log::DEBUG, "writing data to tape has finished"); break; } - task->execute(*writeSession,m_reportPacker,m_watchdog,m_logContext,timer); + task->execute(*writeSession, m_reportPacker, m_watchdog, m_logContext, timer); // Add the tasks counts to the session's m_stats.add(task->getTaskStats()); // Transmit the statistics to the watchdog thread @@ -425,16 +412,16 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { // Increase local flush counters (session counters are incremented by // the task) files++; - bytes+=task->fileSize(); + bytes += task->fileSize(); //if one flush counter is above a threshold, then we flush if (files >= m_filesBeforeFlush || bytes >= m_bytesBeforeFlush) { currentErrorToCount = "Error_tapeFlush"; - tapeFlush("Normal flush because thresholds was reached",bytes,files,timer); - files=0; - bytes=0; + tapeFlush("Normal flush because thresholds was reached", bytes, files, timer); + files = 0; + bytes = 0; currentErrorToCount = ""; } - } //end of while(1)) + } //end of while(true)) } // The session completed successfully, and the cleaner (unmount) executed @@ -443,53 +430,52 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { params.add("status", "success"); m_stats.totalTime = totalTimer.secs(); m_stats.deliveryTime = m_stats.totalTime; - logWithStats(cta::log::INFO, "Tape thread complete",params); + logWithStats(cta::log::INFO, "Tape thread complete", params); // Report one last time the stats, after unloading/unmounting. m_watchdog.updateStats(m_stats); //end of session + log m_reportPacker.reportEndOfSession(m_logContext); - } //end of try - catch(const cta::exception::Exception& e){ - //we end there because write session could not be opened + } //end of try + catch (const cta::exception::Exception& e) { + //we end there because write session could not be opened //or because a task failed or because flush failed - + // First off, indicate the problem to the task injector so it does not inject // more work in the pipeline // If the problem did not originate here, we just re-flag the error, and // this has no effect, but if we had a problem with a non-file operation // like mounting the tape, then we have to signal the problem to the disk // side and the task injector, which will trigger the end of session. - m_injector->setErrorFlag(); + m_taskInjector->setErrorFlag(); // We can still update the session stats one last time (unmount timings // should have been updated by the RAII cleaner/unmounter). m_watchdog.updateStatsWithoutDeliveryTime(m_stats); - + // If we reached the end of tape, this is not an error (ENOSPC) try { // If it's not the error we're looking for, we will go about our business // in the catch section. dynamic cast will throw, and we'll do ourselves // if the error code is not the one we want. - const cta::exception::Errnum & en = - dynamic_cast<const cta::exception::Errnum &>(e); - if(en.errorNumber()!= ENOSPC) { + const auto& en = dynamic_cast<const cta::exception::Errnum&>(e); + if (en.errorNumber() != ENOSPC) { throw 0; } // This is indeed the end of the tape. Not an error. - m_watchdog.setErrorCount("Info_tapeFilledUp",1); + m_watchdog.setErrorCount("Info_tapeFilledUp", 1); m_reportPacker.reportTapeFull(m_logContext); } catch (...) { // The error is not an ENOSPC, so it is, indeed, an error. // If we got here with a new error, currentErrorToCount will be non-empty, // and we will pass the error name to the watchdog. - if(currentErrorToCount.size()) { + if (!currentErrorToCount.empty()) { m_watchdog.addToErrorCount(currentErrorToCount); } } - + //first empty all the tasks and circulate mem blocks - while(1) { - std::unique_ptr<TapeWriteTask> task(m_tasks.pop()); - if(task.get()==NULL) { + while (true) { + std::unique_ptr<TapeWriteTask> task(m_tasks.pop()); + if (task == nullptr) { break; } task->circulateMemBlocks(); @@ -498,10 +484,10 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { std::string errorMessage(e.getMessageValue()); int errorCode(666); // Override if we got en ENOSPC error (end of tape) - // This is + // This is try { - const cta::exception::Errnum & errnum = - dynamic_cast<const cta::exception::Errnum &> (e); + const auto& errnum = + dynamic_cast<const cta::exception::Errnum&> (e); if (ENOSPC == errnum.errorNumber()) { errorCode = ENOSPC; errorMessage = "End of migration due to tape full"; @@ -512,17 +498,17 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() { params.add("status", "error") .add("ErrorMessage", errorMessage); m_stats.totalTime = totalTimer.secs(); - logWithStats(cta::log::INFO, "Tape thread complete", - params); - m_reportPacker.reportEndOfSessionWithErrors(errorMessage,errorCode, m_logContext); - } + logWithStats(cta::log::INFO, "Tape thread complete for writing", + params); + m_reportPacker.reportEndOfSessionWithErrors(errorMessage, errorCode, m_logContext); + } } //------------------------------------------------------------------------------ //logWithStats //------------------------------------------------------------------------------ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logWithStats( -int level,const std::string& msg, cta::log::ScopedParamContainer& params){ + int level, const std::string& msg, cta::log::ScopedParamContainer& params) { params.add("type", "write") .add("tapeVid", m_volInfo.vid) .add("mountTime", m_stats.mountTime) @@ -541,10 +527,10 @@ int level,const std::string& msg, cta::log::ScopedParamContainer& params){ .add("dataVolume", m_stats.dataVolume) .add("headerVolume", m_stats.headerVolume) .add("files", m_stats.filesCount) - .add("payloadTransferSpeedMBps", m_stats.totalTime?1.0*m_stats.dataVolume - /1000/1000/m_stats.totalTime:0.0) - .add("driveTransferSpeedMBps", m_stats.totalTime?1.0*(m_stats.dataVolume+m_stats.headerVolume) - /1000/1000/m_stats.totalTime:0.0); + .add("payloadTransferSpeedMBps", m_stats.totalTime ? 1.0 * m_stats.dataVolume + / 1000 / 1000 / m_stats.totalTime : 0.0) + .add("driveTransferSpeedMBps", m_stats.totalTime ? 1.0 * (m_stats.dataVolume + m_stats.headerVolume) + / 1000 / 1000 / m_stats.totalTime : 0.0); m_logContext.moveToTheEndIfPresent("status"); m_logContext.log(level, msg); } @@ -563,9 +549,9 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logSCSIMetrics() { std::map<std::string, uint32_t> scsi_nonmedium_metrics_hash = m_drive.getTapeNonMediumErrors(); appendMetricsToScopedParams(scopedContainer, scsi_nonmedium_metrics_hash); logSCSIStats("Logging mount general statistics", - scsi_write_metrics_hash.size() + scsi_nonmedium_metrics_hash.size()); + scsi_write_metrics_hash.size() + scsi_nonmedium_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging mount general statistics"); @@ -576,14 +562,14 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logSCSIMetrics() { cta::log::ScopedParamContainer scopedContainer(m_logContext); appendDriveAndTapeInfoToScopedParams(scopedContainer); // get drive stats - std::map<std::string,float> scsi_quality_metrics_hash = m_drive.getQualityStats(); + std::map<std::string, float> scsi_quality_metrics_hash = m_drive.getQualityStats(); appendMetricsToScopedParams(scopedContainer, scsi_quality_metrics_hash); - std::map<std::string,uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats(); + std::map<std::string, uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats(); appendMetricsToScopedParams(scopedContainer, scsi_drive_metrics_hash); logSCSIStats("Logging drive statistics", - scsi_quality_metrics_hash.size()+scsi_drive_metrics_hash.size()); + scsi_quality_metrics_hash.size() + scsi_drive_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging drive statistics"); @@ -593,11 +579,11 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logSCSIMetrics() { try { cta::log::ScopedParamContainer scopedContainer(m_logContext); appendDriveAndTapeInfoToScopedParams(scopedContainer); - std::map<std::string,uint32_t> scsi_metrics_hash = m_drive.getVolumeStats(); + std::map<std::string, uint32_t> scsi_metrics_hash = m_drive.getVolumeStats(); appendMetricsToScopedParams(scopedContainer, scsi_metrics_hash); logSCSIStats("Logging volume statistics", scsi_metrics_hash.size()); } - catch (const cta::exception::Exception &ex) { + catch (const cta::exception::Exception& ex) { cta::log::ScopedParamContainer scoped(m_logContext); scoped.add("exceptionMessage", ex.getMessageValue()); m_logContext.log(cta::log::ERR, "Exception in logging volume statistics"); diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp index 17c3c139d567bac909f1d8b9313fab30d2d70209..7e66c6cde75c79f3faced38b939ea9e305343c98 100644 --- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp +++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp @@ -22,7 +22,6 @@ #include "castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp" #include "castor/tape/tapeserver/daemon/TapeWriteTask.hpp" #include "castor/tape/tapeserver/daemon/TaskWatchDog.hpp" -#include "castor/tape/tapeserver/daemon/TapeServerReporter.hpp" #include "castor/tape/tapeserver/drive/DriveInterface.hpp" #include "common/threading/BlockingQueue.hpp" #include "common/threading/Thread.hpp" @@ -32,88 +31,86 @@ #include <iostream> #include <stdio.h> -namespace castor { -namespace tape { +namespace castor { +namespace tape { namespace tapeserver { -namespace daemon { -// forward definition +namespace daemon { + +// forward declaration +class TapeServerReporter; + class MigrationTaskInjector; - + +/** + * This class will execute the different tape write tasks. + * + */ class TapeWriteSingleThread : public TapeSingleThreadInterface<TapeWriteTask> { public: /** * Constructor - * @param drive an interface for manipulating the drive in order - * to write on the tape - * @param vid the volume ID of the tape on which we are going to write - * @param lc - * @param repPacker the object that will send reports to the client - * @param filesBeforeFlush how many file written before flushing on tape - * @param bytesBeforeFlush how many bytes written before flushing on tape - * @param lastFseq the last fSeq - * @param tapeLoadTimeout the timeout after which we consider the tape mount to be failed */ TapeWriteSingleThread( - castor::tape::tapeserver::drive::DriveInterface & drive, - cta::mediachanger::MediaChangerFacade &mc, - TapeServerReporter & tsr, - MigrationWatchDog & mwd, + castor::tape::tapeserver::drive::DriveInterface& drive, + cta::mediachanger::MediaChangerFacade& mediaChanger, + TapeServerReporter& reporter, + MigrationWatchDog& watchdog, const VolumeInfo& volInfo, - cta::log::LogContext & lc, - MigrationReportPacker & repPacker, - cta::server::ProcessCap &capUtils, - uint64_t filesBeforeFlush, uint64_t bytesBeforeFlush, const bool useLbp, + cta::log::LogContext& logContext, + MigrationReportPacker& reportPacker, + cta::server::ProcessCap& capUtils, + uint64_t filesBeforeFlush, + uint64_t bytesBeforeFlush, + const bool useLbp, const bool useEncryption, - const std::string & externalEncryptionKeyScript, - const cta::ArchiveMount & archiveMount, + const std::string& externalEncryptionKeyScript, + const cta::ArchiveMount& archiveMount, const uint64_t tapeLoadTimeout); - - /** - * - * @param lastFseq - */ - void setlastFseq(uint64_t lastFseq); - + /** * Sets up the pointer to the task injector. This cannot be done at - * construction time as both task injector and tape write single thread refer to + * construction time as both task injector and tape write single thread refer to * each other. This function should be called before starting the threads. - * This is used for signalling problems during mounting. After that, each + * This is used for signalling problems during mounting. After that, each * tape write task does the signalling itself, either on tape problem, or * when receiving an error from the disk tasks via memory blocks. * @param injector pointer to the task injector */ - void setTaskInjector(MigrationTaskInjector* injector){ - m_injector = injector; + void setTaskInjector(MigrationTaskInjector *injector) { + m_taskInjector = injector; } -private: - + /** - * Returns the string representation of the specified mount type + * + * @param lastFseq */ - const char *mountTypeToString(const cta::common::dataStructures::MountType mountType) const - throw(); - - class TapeCleaning{ + void setlastFseq(uint64_t lastFseq); + +private: + + // RAII class for cleaning tape stuff + class TapeCleaning { TapeWriteSingleThread& m_this; // As we are living in the single thread of tape, we can borrow the timer - cta::utils::Timer & m_timer; + cta::utils::Timer& m_timer; public: - TapeCleaning(TapeWriteSingleThread& parent, cta::utils::Timer & timer): + TapeCleaning(TapeWriteSingleThread& parent, cta::utils::Timer& timer) : m_this(parent), m_timer(timer) {} + ~TapeCleaning(); }; + /** * Will throw an exception if we cant write on the tape */ void isTapeWritable() const; /** - * Log m_stats parameters into m_logContext with msg at the given level + * Log m_stats parameters into m_logContext with msg at the given level */ - void logWithStats(int level,const std::string& msg, - cta::log::ScopedParamContainer& params); - + void logWithStats(int level, const std::string& msg, + cta::log::ScopedParamContainer& params); + /** * Function to open the WriteSession * If successful, returns a std::unique_ptr on it. A copy of that std::unique_ptr @@ -122,6 +119,7 @@ private: * @return the WriteSession we need to write on tape */ std::unique_ptr<castor::tape::tapeFile::WriteSession> openWriteSession(); + /** * Execute flush on tape, do some log and report the flush to the client * @param message the message the log will register @@ -130,9 +128,9 @@ private: * @param files the number of files that have been written since the last flush * (also for logging) */ - void tapeFlush(const std::string& message,uint64_t bytes,uint64_t files, - cta::utils::Timer & timer); - + void tapeFlush(const std::string& message, uint64_t bytes, uint64_t files, + cta::utils::Timer& timer); + /** * After waiting for the drive, we will dump the tape alert log content, if it * is not empty @@ -140,23 +138,23 @@ private: */ bool logAndCheckTapeAlertsForWrite(); - virtual void run() ; - + void run() override; + //m_filesBeforeFlush and m_bytesBeforeFlush are thresholds for flushing //the first one crossed will trigger the flush on tape - + ///how many file written before flushing on tape const uint64_t m_filesBeforeFlush; - + ///how many bytes written before flushing on tape const uint64_t m_bytesBeforeFlush; ///an interface for manipulating all type of drives castor::tape::tapeserver::drive::DriveInterface& m_drive; - + ///the object that will send reports to the client - MigrationReportPacker & m_reportPacker; - + MigrationReportPacker& m_reportPacker; + /** * the last fseq that has been written on the tape = the starting point * of our session. The last Fseq is computed by subtracting 1 to fSeg @@ -168,53 +166,53 @@ private: * It should be const, but it cant * (because there is no mutable function member in c++) */ - uint64_t m_lastFseq; + uint64_t m_lastFseq; /** * Should the compression be enabled ? This is currently hard coded to true */ const bool m_compress; - + /** * The boolean variable describing to use on not to use Logical * Block Protection. */ const bool m_useLbp; - + /** * Reference to the watchdog, used in run() */ - MigrationWatchDog & m_watchdog; - + MigrationWatchDog& m_watchdog; + /** * Reference to the archive mount object that * stores the virtual organization (vo) of the tape, the tape pool in which the tape is * and the density of the tape */ - const cta::ArchiveMount & m_archiveMount; - + const cta::ArchiveMount& m_archiveMount; + protected: /*** * Helper virtual function to access the watchdog from parent class */ - virtual void countTapeLogError(const std::string & error) { + void countTapeLogError(const std::string& error) override { m_watchdog.addToErrorCount(error); } /** * Logs SCSI metrics for write session. */ - virtual void logSCSIMetrics(); - + void logSCSIMetrics() override; + private: /** * Pointer to the task injector allowing termination signaling */ - MigrationTaskInjector* m_injector; + MigrationTaskInjector *m_taskInjector; }; // class TapeWriteSingleThread } // namespace daemon } // namespace tapeserver -} // namsepace tape +} // namespace tape } // namespace castor diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp index b15b9fb1c49007bb2b5dd07f68094c7388abcf30..ab333db4b1b0ec7f190abba84845f5f04f3c8e09 100644 --- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp +++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp @@ -1159,7 +1159,7 @@ void drive::DriveGeneric::writeBlock(const void * data, size_t count) { { uint8_t * dataWithCrc32c =(new (std::nothrow) uint8_t [count+SCSI::logicBlockProtectionMethod::CRC32CLength]); - if(NULL == dataWithCrc32c) { + if(nullptr == dataWithCrc32c) { throw cta::exception::MemException("Failed to allocate memory " " for a new MemBlock in DriveGeneric::writeBlock!"); } @@ -1213,7 +1213,7 @@ ssize_t drive::DriveGeneric::readBlock(void * data, size_t count) { { uint8_t * dataWithCrc32c =(new (std::nothrow) uint8_t [count+SCSI::logicBlockProtectionMethod::CRC32CLength]); - if(NULL == dataWithCrc32c) { + if(nullptr == dataWithCrc32c) { throw cta::exception::MemException("In DriveGeneric::readBlock: Failed to allocate memory"); } const ssize_t res = m_sysWrapper.read(m_tapeFD, dataWithCrc32c, @@ -1273,7 +1273,7 @@ void drive::DriveGeneric::readExactBlock(void * data, size_t count, const std::s { uint8_t * dataWithCrc32c =(new (std::nothrow) uint8_t [count+SCSI::logicBlockProtectionMethod::CRC32CLength]); - if(NULL == dataWithCrc32c) { + if(nullptr == dataWithCrc32c) { throw cta::exception::MemException("Failed to allocate memory " " for a new MemBlock in DriveGeneric::readBlock!"); } diff --git a/tapeserver/castor/tape/tapeserver/file/BasicReadWriteTest.cpp b/tapeserver/castor/tape/tapeserver/file/BasicReadWriteTest.cpp index 5868df4fef4fdd637ece025088e2f12051e17ba0..3c4aa18a4caff7e9cd0fa576b406b1b808034b99 100644 --- a/tapeserver/castor/tape/tapeserver/file/BasicReadWriteTest.cpp +++ b/tapeserver/castor/tape/tapeserver/file/BasicReadWriteTest.cpp @@ -59,7 +59,7 @@ class BasicRetrieveJob: public cta::RetrieveJob { class BasicArchiveJob: public cta::ArchiveJob { public: BasicArchiveJob(): cta::ArchiveJob(nullptr, - *((cta::catalogue::Catalogue *)NULL), cta::common::dataStructures::ArchiveFile(), + *((cta::catalogue::Catalogue *)nullptr), cta::common::dataStructures::ArchiveFile(), "", cta::common::dataStructures::TapeFile()) { } }; diff --git a/tapeserver/castor/tape/tapeserver/file/FileTest.cpp b/tapeserver/castor/tape/tapeserver/file/FileTest.cpp index c15b069b697ec8b8b8af60d21c0daafb425fcc2d..7cd472b88e063d518bda99fb4ab75b37934d3cd5 100644 --- a/tapeserver/castor/tape/tapeserver/file/FileTest.cpp +++ b/tapeserver/castor/tape/tapeserver/file/FileTest.cpp @@ -44,7 +44,7 @@ namespace unitTests { class TestingArchiveJob: public cta::ArchiveJob { public: TestingArchiveJob(): cta::ArchiveJob(nullptr, - *((cta::catalogue::Catalogue *)NULL), cta::common::dataStructures::ArchiveFile(), + *((cta::catalogue::Catalogue *)nullptr), cta::common::dataStructures::ArchiveFile(), "", cta::common::dataStructures::TapeFile()) { } }; diff --git a/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp b/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp index 58692dcfa04ca9ee3af28df3b56f49b783c187e8..333d34b636b0915a11a6ea28b9e037bddea9909a 100644 --- a/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp +++ b/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp @@ -33,7 +33,7 @@ DIR* System::fakeWrapper::opendir(const char* name) { /* Manage absence of directory */ if (m_directories.end() == m_directories.find(std::string(name))) { errno = ENOENT; - return NULL; + return nullptr; } /* Dirty pointer gymnastics. Good enough for a test harness */ ourDIR * dir = new ourDIR; @@ -55,7 +55,7 @@ struct dirent * System::fakeWrapper::readdir(DIR* dirp) { * opendir. */ if (dir.nextIdx + 1 > m_directories[dir.path].size()) - return NULL; + return nullptr; dir.dent_name = m_directories[dir.path][dir.nextIdx++]; strncpy(dir.dent.d_name, dir.dent_name.c_str(), NAME_MAX); return & (dir.dent); @@ -84,7 +84,7 @@ char * System::fakeWrapper::realpath(const char* name, char* resolved) { */ if (m_realpathes.end() == m_realpathes.find(std::string(name))) { errno = ENOENT; - return NULL; + return nullptr; } strncpy(resolved, m_realpathes[std::string(name)].c_str(), PATH_MAX); return resolved; @@ -190,7 +190,7 @@ castor::tape::tapeserver::drive::DriveInterface * std::map<std::string, castor::tape::tapeserver::drive::DriveInterface *>::iterator drive = m_pathToDrive.find(path); if (m_pathToDrive.end() == drive) { - return NULL; + return nullptr; } else { /* The drive will be deleted by the user, so we remove references to it */ castor::tape::tapeserver::drive::DriveInterface * ret = drive->second; @@ -215,14 +215,13 @@ void System::fakeWrapper::referenceFiles() { * Destructor: delete leftover drive and device objects */ System::fakeWrapper::~fakeWrapper() { - for (auto d=m_pathToDrive.begin(); d!=m_pathToDrive.end(); d++) { - delete d->second; - d->second = NULL; + for (auto & d : m_pathToDrive) { + delete d.second; + d.second = nullptr; } - for (std::map<std::string, stDeviceFile *>::iterator i = m_stFiles.begin(); - i != m_stFiles.end(); ++i) - delete m_stFiles[i->first]; + for (const auto & m_stFile : m_stFiles) + delete m_stFiles[m_stFile.first]; } System::mockWrapper::mockWrapper() { diff --git a/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp b/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp index de40d080faa1bab8458bf8089ed3f72e0b7b1322..a3b80a93ca7937c868969f98716e6ed306231564 100644 --- a/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp +++ b/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp @@ -104,7 +104,7 @@ namespace System { virtual int close(int fd) { return ::close(fd); } virtual int stat(const char * path, struct stat *buf) { return ::stat(path, buf); } virtual castor::tape::tapeserver::drive::DriveInterface * - getDriveByPath(const std::string &) { return NULL; } + getDriveByPath(const std::string &) { return nullptr; } }; /** diff --git a/tapeserver/daemon/CommandLineParams.cpp b/tapeserver/daemon/CommandLineParams.cpp index 57655e51fe60bfba1d1f616d3d91b709733503a9..1f6752fcc4c1baafc1e4ab17735e26c6a3aacc05 100644 --- a/tapeserver/daemon/CommandLineParams.cpp +++ b/tapeserver/daemon/CommandLineParams.cpp @@ -28,12 +28,12 @@ CommandLineParams::CommandLineParams(int argc, char** argv): helpRequested(false){ struct ::option longopts[] = { // { .name, .has_args, .flag, .val } (see getopt.h)) - { "foreground", no_argument, NULL, 'f' }, - { "config", required_argument, NULL, 'c' }, - { "help", no_argument, NULL, 'h' }, - { "stdout", no_argument, NULL, 's' }, - { "log-to-file", required_argument, NULL, 'l' }, - { NULL, 0, NULL, '\0' } + { "foreground", no_argument, nullptr, 'f' }, + { "config", required_argument, nullptr, 'c' }, + { "help", no_argument, nullptr, 'h' }, + { "stdout", no_argument, nullptr, 's' }, + { "log-to-file", required_argument, nullptr, 'l' }, + { nullptr, 0, nullptr, '\0' } }; char c; @@ -42,7 +42,7 @@ CommandLineParams::CommandLineParams(int argc, char** argv): // Prevent getopt from printing out errors on stdout opterr=0; // We ask getopt to not reshuffle argv ('+') - while ((c = getopt_long(argc, argv, "+fsc:l:h", longopts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "+fsc:l:h", longopts, nullptr)) != -1) { switch (c) { case 'f': foreground = true; diff --git a/tapeserver/daemon/DriveHandler.cpp b/tapeserver/daemon/DriveHandler.cpp index 23d9ed04625ade40041d5bef724e427464d4320b..8122af3a969deda4f4a526e10b51582c979cb206 100644 --- a/tapeserver/daemon/DriveHandler.cpp +++ b/tapeserver/daemon/DriveHandler.cpp @@ -35,15 +35,17 @@ #include <set> #include <sys/prctl.h> -namespace cta { namespace tape { namespace daemon { +namespace cta { +namespace tape { +namespace daemon { CTA_GENERATE_EXCEPTION_CLASS(DriveAlreadyExistException); //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -DriveHandler::DriveHandler(const TapedConfiguration & tapedConfig, const TpconfigLine& configline, ProcessManager& pm): - SubprocessHandler(std::string("drive:")+configline.unitName), m_processManager(pm), +DriveHandler::DriveHandler(const TapedConfiguration& tapedConfig, const TpconfigLine& configline, ProcessManager& pm) : + SubprocessHandler(std::string("drive:") + configline.unitName), m_processManager(pm), m_tapedConfig(tapedConfig), m_configLine(configline), m_sessionEndContext(m_processManager.logContext().logger()) { // As the handler is started, its first duty is to create a new subprocess. This @@ -59,24 +61,24 @@ using session::SessionType; // The following structure represents the timeouts expected for each session state transitions // (if needed). // The session type is not taken into account as a given state gets the same timeout regardless -// of the type session it is used in. +// of the type session it is used in. const std::map<SessionState, DriveHandler::Timeout> DriveHandler::m_stateChangeTimeouts = { // Determining the drive is ready takes 1 minute, so waiting 2 should be enough. - {SessionState::Checking, std::chrono::duration_cast<Timeout>(std::chrono::minutes(2))}, + {SessionState::Checking, std::chrono::duration_cast<Timeout>(std::chrono::minutes(2))}, // Scheduling is expected to take little time, so 5 minutes is plenty. When the scheduling // determines there is nothing to do, it will transition to the same state (resetting the timeout). - {SessionState::Scheduling, std::chrono::duration_cast<Timeout>(std::chrono::minutes(5))}, + {SessionState::Scheduling, std::chrono::duration_cast<Timeout>(std::chrono::minutes(5))}, // We expect mounting (mount+load, in fact) the take no more than 10 minutes. - {SessionState::Mounting, std::chrono::duration_cast<Timeout>(std::chrono::minutes(10))}, + {SessionState::Mounting, std::chrono::duration_cast<Timeout>(std::chrono::minutes(10))}, // Like mounting, unmounting is expected to take less than 10 minutes. - {SessionState::Unmounting, std::chrono::duration_cast<Timeout>(std::chrono::minutes(10))}, + {SessionState::Unmounting, std::chrono::duration_cast<Timeout>(std::chrono::minutes(10))}, // Draining to disk is given a grace period of 30 minutes for changing state. {SessionState::DrainingToDisk, std::chrono::duration_cast<Timeout>(std::chrono::minutes(30))}, // We expect the process to exit within 5 minutes of getting in this state. This state // potentially covers the draining of metadata to central storage (if not faster that // unmounting the tape). // TODO: this is set temporarily to 15 minutes while the reporting is not yet parallelized. - {SessionState::ShuttingDown, std::chrono::duration_cast<Timeout>(std::chrono::minutes(15))} + {SessionState::ShuttingDown, std::chrono::duration_cast<Timeout>(std::chrono::minutes(15))} }; //------------------------------------------------------------------------------ @@ -85,7 +87,7 @@ const std::map<SessionState, DriveHandler::Timeout> DriveHandler::m_stateChangeT // The following structure represents heartbeat timeouts expected for each session state with data movement. // TODO: decide on values. const std::map<SessionState, DriveHandler::Timeout> DriveHandler::m_heartbeatTimeouts = { - {SessionState::Running, std::chrono::duration_cast<Timeout>(std::chrono::minutes(1))}, + {SessionState::Running, std::chrono::duration_cast<Timeout>(std::chrono::minutes(1))}, {SessionState::DrainingToDisk, std::chrono::duration_cast<Timeout>(std::chrono::minutes(1))} }; @@ -97,7 +99,7 @@ const std::map<SessionState, DriveHandler::Timeout> DriveHandler::m_heartbeatTim // TODO: decide on values. TODO: bumped up to 15 minutes for the time being as the // efficient retrieve requests pop is not implemented yet. const std::map<SessionState, DriveHandler::Timeout> DriveHandler::m_dataMovementTimeouts = { - {SessionState::Running, std::chrono::duration_cast<Timeout>(std::chrono::minutes(15))}, + {SessionState::Running, std::chrono::duration_cast<Timeout>(std::chrono::minutes(15))}, {SessionState::DrainingToDisk, std::chrono::duration_cast<Timeout>(std::chrono::minutes(15))} }; @@ -139,19 +141,23 @@ SubprocessHandler::ProcessingStatus DriveHandler::fork() { // First prepare a socket pair for this new subprocess m_socketPair.reset(new cta::server::SocketPair()); // and fork - m_pid=::fork(); + m_pid = ::fork(); exception::Errnum::throwOnMinusOne(m_pid, "In DriveHandler::fork(): failed to fork()"); if (!m_pid) { // We are in the child process + m_sessionState = SessionState::StartingUp; + m_lastStateChangeTime = std::chrono::steady_clock::now(); SubprocessHandler::ProcessingStatus ret; ret.forkState = SubprocessHandler::ForkState::child; return ret; - } else { + } + else { // We are in the parent process m_processingStatus.forkState = SubprocessHandler::ForkState::parent; // The subprocess will start by deciding what to do based on previous states. // The child process is not forked yet. m_sessionState = SessionState::PendingFork; + m_lastStateChangeTime = std::chrono::steady_clock::now(); // Compute the next timeout m_processingStatus.nextTimeout = nextTimeout(); // Register our socketpair side for epoll after closing child side. @@ -160,16 +166,16 @@ SubprocessHandler::ProcessingStatus DriveHandler::fork() { // We are now ready to react to timeouts and messages from the child process. return m_processingStatus; } - } catch (cta::exception::Exception & ex) { + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName) .add("Error", ex.getMessageValue()); m_processManager.logContext().log(log::ERR, "Failed to fork drive process. Initiating shutdown with SIGTERM."); // Wipe all previous states as we are shutting down m_processingStatus = SubprocessHandler::ProcessingStatus(); - m_sessionState=SessionState::Shutdown; - m_processingStatus.shutdownComplete=true; - m_processingStatus.forkState=SubprocessHandler::ForkState::parent; + m_sessionState = SessionState::Shutdown; + m_processingStatus.shutdownComplete = true; + m_processingStatus.forkState = SubprocessHandler::ForkState::parent; // Initiate shutdown ::kill(::getpid(), SIGTERM); return m_processingStatus; @@ -179,34 +185,34 @@ SubprocessHandler::ProcessingStatus DriveHandler::fork() { //------------------------------------------------------------------------------ // DriveHandler::nextTimeout //------------------------------------------------------------------------------ -decltype (SubprocessHandler::ProcessingStatus::nextTimeout) DriveHandler::nextTimeout() { +decltype(SubprocessHandler::ProcessingStatus::nextTimeout) DriveHandler::nextTimeout() { // If a timeout is defined, then we compute its expiration time. Else we just give default timeout (end of times). - decltype (SubprocessHandler::ProcessingStatus::nextTimeout) ret=decltype(SubprocessHandler::ProcessingStatus::nextTimeout)::max(); - bool retSet=false; + decltype(SubprocessHandler::ProcessingStatus::nextTimeout) ret = decltype(SubprocessHandler::ProcessingStatus::nextTimeout)::max(); + bool retSet = false; try { - ret=m_lastStateChangeTime+m_stateChangeTimeouts.at(m_sessionState); - retSet=true; - m_timeoutType="StateChange"; + ret = m_lastStateChangeTime + m_stateChangeTimeouts.at(m_sessionState); + retSet = true; + m_timeoutType = "StateChange"; } catch (...) {} try { - auto newRet=m_lastHeartBeatTime+m_heartbeatTimeouts.at(m_sessionState); + auto newRet = m_lastHeartBeatTime + m_heartbeatTimeouts.at(m_sessionState); if (newRet < ret) { - ret=newRet; - retSet=true; - m_timeoutType="Heartbeat"; + ret = newRet; + retSet = true; + m_timeoutType = "Heartbeat"; } } catch (...) {} try { - auto newRet=m_lastDataMovementTime+m_dataMovementTimeouts.at(m_sessionState); + auto newRet = m_lastDataMovementTime + m_dataMovementTimeouts.at(m_sessionState); if (newRet < ret) { - ret=newRet; - retSet=true; - m_timeoutType="DataMovement"; + ret = newRet; + retSet = true; + m_timeoutType = "DataMovement"; } } catch (...) {} if (retSet) { - m_sessionStateWhenTimeoutDecided=m_sessionState; - m_sessionTypeWhenTimeoutDecided=m_sessionType; + m_sessionStateWhenTimeoutDecided = m_sessionState; + m_sessionTypeWhenTimeoutDecided = m_sessionType; } { log::ScopedParamContainer params(m_processManager.logContext()); @@ -232,12 +238,12 @@ void DriveHandler::kill() { if (m_pid != -1) { params.add("SubProcessId", m_pid); // The socket pair will be reopened on the next fork. Clean it up. - if (m_socketPair.get()) { + if (m_socketPair) { m_processManager.removeFile(m_socketPair->getFdForAccess(server::SocketPair::Side::child)); m_socketPair.reset(nullptr); } try { - exception::Errnum::throwOnMinusOne(::kill(m_pid, SIGKILL),"Failed to kill() subprocess"); + exception::Errnum::throwOnMinusOne(::kill(m_pid, SIGKILL), "Failed to kill() subprocess"); int status; // wait for child process exit exception::Errnum::throwOnMinusOne(::waitpid(m_pid, &status, 0), "Failed to waitpid() subprocess"); @@ -245,22 +251,24 @@ void DriveHandler::kill() { params.add("WIFEXITED", WIFEXITED(status)); if (WIFEXITED(status)) { params.add("WEXITSTATUS", WEXITSTATUS(status)); - } else { + } + else { params.add("WIFSIGNALED", WIFSIGNALED(status)); } m_processManager.logContext().log(log::INFO, "In DriveHandler::kill(): sub process completed"); m_sessionEndContext.pushOrReplace({"Error_sessionKilled", "1"}); m_sessionEndContext.pushOrReplace({"killSignal", WTERMSIG(status)}); m_sessionEndContext.pushOrReplace({"status", "failure"}); - m_sessionEndContext.pushOrReplace({"tapeDrive",m_configLine.unitName}); + m_sessionEndContext.pushOrReplace({"tapeDrive", m_configLine.unitName}); m_sessionEndContext.log(cta::log::INFO, "Tape session finished"); m_sessionEndContext.clear(); - m_pid=-1; - } catch (exception::Exception & ex) { + m_pid = -1; + } catch (exception::Exception& ex) { params.add("Exception", ex.getMessageValue()); m_processManager.logContext().log(log::ERR, "In DriveHandler::kill(): failed to kill existing subprocess"); } - } else { + } + else { m_processManager.logContext().log(log::INFO, "In DriveHandler::kill(): no subprocess to kill"); } } @@ -269,17 +277,19 @@ void DriveHandler::kill() { // DriveHandler::processEvent //------------------------------------------------------------------------------ SubprocessHandler::ProcessingStatus DriveHandler::processEvent() { - log::ScopedParamContainer params(m_processManager.logContext()); - params.add("tapeDrive", m_configLine.unitName); + log::ScopedParamContainer scoped(m_processManager.logContext()); + scoped.add("tapeDrive", m_configLine.unitName); + m_lastHeartBeatTime = std::chrono::steady_clock::now(); + // Read from the socket pair try { serializers::WatchdogMessage message; - auto datagram=m_socketPair->receive(); + auto datagram = m_socketPair->receive(); if (!message.ParseFromString(datagram)) { - // Use a the tolerant parser to assess the situation. + // Use the tolerant parser to assess the situation. message.ParsePartialFromString(datagram); - throw cta::exception::Exception(std::string("In SubprocessHandler::ProcessingStatus(): could not parse message: ")+ - message.InitializationErrorString()); + throw cta::exception::Exception(std::string("In SubprocessHandler::ProcessingStatus(): could not parse message: ") + + message.InitializationErrorString()); } // Logs are processed in all cases processLogs(message); @@ -289,55 +299,72 @@ SubprocessHandler::ProcessingStatus DriveHandler::processEvent() { } // If we report a state change, process it (last as this can change the return value) if (message.reportingstate()) { - switch((SessionState)message.sessionstate()) { - case SessionState::StartingUp: - return processStartingUp(message); - case SessionState::Checking: - return processChecking(message); - case SessionState::Scheduling: - return processScheduling(message); - case SessionState::Mounting: - return processMounting(message); - case SessionState::Running: - return processRunning(message); - case SessionState::Unmounting: - return processUnmounting(message); - case SessionState::DrainingToDisk: - return processDrainingToDisk(message); - case SessionState::ShuttingDown: - return processShutingDown(message); - case SessionState::Fatal: - return processFatal(message); - default: - { + // Log a session state change + if (m_sessionState != static_cast<SessionState>(message.sessionstate())) { + scoped.add("PreviousState", session::toString(m_sessionState)) + .add("PreviousType", session::toString(m_sessionType)) + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); + m_processManager.logContext().log(log::INFO, "In DriveHandler::processEvent(): changing session state"); + } + + switch (static_cast<SessionState>(message.sessionstate())) { + case SessionState::Checking: + return processChecking(message); + case SessionState::Scheduling: + return processScheduling(message); + case SessionState::Mounting: + return processMounting(message); + case SessionState::Running: + return processRunning(message); + case SessionState::Unmounting: + return processUnmounting(message); + case SessionState::DrainingToDisk: + return processDrainingToDisk(message); + case SessionState::ShuttingDown: + return processShuttingDown(message); + case SessionState::Fatal: + return processFatal(message); + default: { exception::Exception ex; ex.getMessage() << "In DriveHandler::processEvent(): unexpected session state:" - << session::toString((SessionState)message.sessionstate()); + << session::toString(static_cast<SessionState>(message.sessionstate())); throw ex; } } + + // Update state + m_sessionState = static_cast<SessionState>(message.sessionstate()); + m_sessionType = static_cast<SessionType>(message.sessiontype()); + + m_lastStateChangeTime = std::chrono::steady_clock::now(); } + + // Compute timeout before returning the processing status + m_processingStatus.nextTimeout = nextTimeout(); + return m_processingStatus; - } catch(cta::server::SocketPair::PeerDisconnected & ex) { + } catch (cta::server::SocketPair::PeerDisconnected& ex) { // The peer disconnected: close the socket pair and remove it from the epoll list. - if (m_socketPair.get()) { + if (m_socketPair) { m_processManager.removeFile(m_socketPair->getFdForAccess(server::SocketPair::Side::child)); m_socketPair.reset(nullptr); - } else { + } + else { m_processManager.logContext().log(log::ERR, - "In DriveHandler::processEvent(): internal error. Got a peer disconnect with no socketPair object"); + "In DriveHandler::processEvent(): internal error. Got a peer disconnect with no socketPair object"); } // We expect to be woken up by the child's signal. cta::log::ScopedParamContainer params(m_processManager.logContext()); params.add("Message", ex.getMessageValue()); m_processManager.logContext().log(log::DEBUG, - "In DriveHandler::processEvent(): Got a peer disconnect: closing socket and waiting for SIGCHILD"); + "In DriveHandler::processEvent(): Got a peer disconnect: closing socket and waiting for SIGCHILD"); return m_processingStatus; - } catch(cta::exception::Exception & ex) { + } catch (cta::exception::Exception& ex) { cta::log::ScopedParamContainer params(m_processManager.logContext()); params.add("Message", ex.getMessageValue()); m_processManager.logContext().log(log::ERR, - "In DriveHandler::processEvent(): failed"); + "In DriveHandler::processEvent(): failed"); return m_processingStatus; } } @@ -346,7 +373,7 @@ SubprocessHandler::ProcessingStatus DriveHandler::processEvent() { // DriveHandler::resetToDefault //------------------------------------------------------------------------------ void DriveHandler::resetToDefault(PreviousSession previousSessionState) { - m_pid=-1; + m_pid = -1; m_previousSession = previousSessionState; m_previousType = m_sessionType; m_previousState = m_sessionState; @@ -364,35 +391,6 @@ void DriveHandler::resetToDefault(PreviousSession previousSessionState) { m_processingStatus.sigChild = false; } -//------------------------------------------------------------------------------ -// DriveHandler::processStartingUp -//------------------------------------------------------------------------------ -SubprocessHandler::ProcessingStatus DriveHandler::processStartingUp(serializers::WatchdogMessage& message) { - // We expect to reach this state from pending fork. This is the first signal from the new process. - // Check the transition is expected. This is non-fatal as the drive session has the last word anyway. - log::ScopedParamContainer params(m_processManager.logContext()); - params.add("tapeDrive", m_configLine.unitName); - if (m_sessionState!=SessionState::PendingFork || m_sessionType!=SessionType::Undetermined) { - params.add("ExpectedState", session::toString(SessionState::PendingFork)) - .add("ActualState", session::toString(m_sessionState)) - .add("ExpectedType", session::toString(SessionType::Undetermined)); - m_processManager.logContext().log(log::WARNING, - "In DriveHandler::processStartingUp(): Unexpected session type or status. Killing subprocess if present."); - } - // Record the new state: - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // kill(), when called by the process manager does not keep track of states, - // so here we do it. - m_sessionState = SessionState::Killed; - // We do not expected anything from the subprocess anymore, so the default - // return value is enough. - m_processingStatus.shutdownComplete=true; - m_processingStatus.nextTimeout=m_processingStatus.nextTimeout.max(); - return m_processingStatus; -} - //------------------------------------------------------------------------------ // DriveHandler::processScheduling //------------------------------------------------------------------------------ @@ -401,31 +399,19 @@ SubprocessHandler::ProcessingStatus DriveHandler::processScheduling(serializers: // Check the transition is expected. This is non-fatal as the drive session has the last word anyway. log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - std::set<SessionState> expectedStates = { SessionState::StartingUp, SessionState::Scheduling }; + std::set<SessionState> expectedStates = {SessionState::StartingUp, SessionState::Scheduling}; if (!expectedStates.count(m_sessionState) || m_sessionType != SessionType::Undetermined || - (SessionType)message.sessiontype() != SessionType::Undetermined) { - params.add("PreviousState", session::toString(m_sessionState)) - .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); - m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processScheduling(): unexpected previous state/type."); - } else if (m_sessionState != SessionState::Scheduling) { - // If we see a session state change, it's worth logging (at least in debug mode) + static_cast<SessionType>(message.sessiontype()) != SessionType::Undetermined) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "In DriveHandler::processScheduling(): state change."); + "WARNING: In DriveHandler::processScheduling(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = ""; return m_processingStatus; } @@ -433,33 +419,21 @@ SubprocessHandler::ProcessingStatus DriveHandler::processScheduling(serializers: // DriveHandler::processChecking //------------------------------------------------------------------------------ SubprocessHandler::ProcessingStatus DriveHandler::processChecking(serializers::WatchdogMessage& message) { - // We expect to come from statup/undefined and to get into checking/cleanup + // We expect to come from startup/undefined and to get into checking/cleanup // As usual, subprocess has the last word. log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - if (m_sessionState!=SessionState::StartingUp || m_sessionType!=SessionType::Undetermined|| - (SessionType)message.sessiontype()!=SessionType::Cleanup) { + if (m_sessionState != SessionState::StartingUp || m_sessionType != SessionType::Undetermined || + static_cast<SessionType>(message.sessiontype()) != SessionType::Cleanup) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processChecking(): unexpected previous state/type."); - } else if (m_sessionState != SessionState::Checking) { - // If we see a session state change, it's worth logging (at least in debug mode) - params.add("PreviousState", session::toString(m_sessionState)) - .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); - m_processManager.logContext().log(log::DEBUG, - "In DriveHandler::processChecking(): state change."); + "WARNING: In DriveHandler::processChecking(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = ""; return m_processingStatus; } @@ -471,32 +445,19 @@ SubprocessHandler::ProcessingStatus DriveHandler::processMounting(serializers::W // As usual, subprocess has the last word. log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - std::set<SessionType> expectedNewTypes= { SessionType::Archive, SessionType::Retrieve, SessionType::Label }; - if (m_sessionState!=SessionState::Scheduling || - m_sessionType!=SessionType::Undetermined|| - !expectedNewTypes.count((SessionType)message.sessiontype())) { - params.add("PreviousState", session::toString(m_sessionState)) - .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); - m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processMounting(): unexpected previous state/type."); - } else if (m_sessionState != SessionState::Checking) { - // If we see a session state change, it's worth logging (at least in debug mode) + std::set<SessionType> expectedNewTypes = {SessionType::Archive, SessionType::Retrieve, SessionType::Label}; + if (m_sessionState != SessionState::Scheduling || + m_sessionType != SessionType::Undetermined || + !expectedNewTypes.count(static_cast<SessionType>(message.sessiontype()))) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())) - .add("tapeVid", message.vid()); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "In DriveHandler::processMounting(): state change."); + "WARNING: In DriveHandler::processMounting(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=message.vid(); - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = message.vid(); return m_processingStatus; } @@ -509,38 +470,20 @@ SubprocessHandler::ProcessingStatus DriveHandler::processRunning(serializers::Wa // As usual, subprocess has the last word. log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - std::set<SessionState> expectedStates = { SessionState::Mounting, SessionState::Running }; - std::set<SessionType> expectedTypes = { SessionType::Archive, SessionType::Retrieve, SessionType::Label }; + std::set<SessionState> expectedStates = {SessionState::Mounting, SessionState::Running}; + std::set<SessionType> expectedTypes = {SessionType::Archive, SessionType::Retrieve, SessionType::Label}; if (!expectedStates.count(m_sessionState) || - !expectedTypes.count(m_sessionType)|| - (m_sessionType!=(SessionType)message.sessiontype())) { + !expectedTypes.count(m_sessionType) || + (m_sessionType != static_cast<SessionType>(message.sessiontype()))) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processMounting(): unexpected previous state/type."); - } else if (m_sessionState != SessionState::Checking) { - // If we see a session state change, it's worth logging (at least in debug mode) - params.add("PreviousState", session::toString(m_sessionState)) - .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); - m_processManager.logContext().log(log::DEBUG, - "In DriveHandler::processRunning(): state change."); - } - // Record session state change time and reset other counters. - if (m_sessionState!=(SessionState)message.sessionstate()) { - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_lastDataMovementTime=std::chrono::steady_clock::now(); - m_lastHeartBeatTime=std::chrono::steady_clock::now(); + "WARNING: In DriveHandler::processMounting(): unexpected previous state/type."); } - // Record the state in all cases. Child process knows better. - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=message.vid(); - // We can now compute the timeout and check for potential exceeding of timeout - m_processingStatus.nextTimeout = nextTimeout(); + + m_sessionVid = message.vid(); return m_processingStatus; } @@ -554,27 +497,23 @@ SubprocessHandler::ProcessingStatus DriveHandler::processUnmounting(serializers: log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); std::set<std::tuple<SessionState, SessionType>> expectedStateTypes = - { - std::make_tuple( SessionState::Running, SessionType::Archive ), - std::make_tuple( SessionState::Running, SessionType::Retrieve ), - std::make_tuple( SessionState::Running, SessionType::Label ), - std::make_tuple( SessionState::Checking, SessionType::Cleanup ) - }; + { + std::make_tuple(SessionState::Running, SessionType::Archive), + std::make_tuple(SessionState::Running, SessionType::Retrieve), + std::make_tuple(SessionState::Running, SessionType::Label), + std::make_tuple(SessionState::Checking, SessionType::Cleanup) + }; // (all types of sessions can unmount). if (!expectedStateTypes.count(std::make_tuple(m_sessionState, m_sessionType))) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processUnmounting(): unexpected previous state/type."); + "WARNING: In DriveHandler::processUnmounting(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=message.vid(); - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = message.vid(); return m_processingStatus; } @@ -590,43 +529,35 @@ SubprocessHandler::ProcessingStatus DriveHandler::processDrainingToDisk(serializ SessionType::Retrieve != m_sessionType) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processDrainingToDisk(): unexpected previous state/type."); + "WARNING: In DriveHandler::processDrainingToDisk(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = ""; return m_processingStatus; } //------------------------------------------------------------------------------ -// DriveHandler::processShutingDown +// DriveHandler::processShuttingDown //------------------------------------------------------------------------------ -SubprocessHandler::ProcessingStatus DriveHandler::processShutingDown(serializers::WatchdogMessage& message) { +SubprocessHandler::ProcessingStatus DriveHandler::processShuttingDown(serializers::WatchdogMessage& message) { // This status transition is expected from unmounting, and only for retrieve sessions. // As usual, subprocess has the last word. log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - std::set<SessionState> expectedStates = { SessionState::Unmounting, SessionState::DrainingToDisk }; + std::set<SessionState> expectedStates = {SessionState::Unmounting, SessionState::DrainingToDisk}; if (!expectedStates.count(m_sessionState)) { params.add("PreviousState", session::toString(m_sessionState)) .add("PreviousType", session::toString(m_sessionType)) - .add("NewState", session::toString((SessionState)message.sessionstate())) - .add("NewType", session::toString((SessionType)message.sessiontype())); + .add("NewState", session::toString(static_cast<SessionState>(message.sessionstate()))) + .add("NewType", session::toString(static_cast<SessionType>(message.sessiontype()))); m_processManager.logContext().log(log::DEBUG, - "WARNING: In DriveHandler::processShutingDown(): unexpected previous state/type."); + "WARNING: In DriveHandler::processShuttingDown(): unexpected previous state/type."); } - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); + + m_sessionVid = ""; return m_processingStatus; } @@ -638,26 +569,22 @@ SubprocessHandler::ProcessingStatus DriveHandler::processFatal(serializers::Watc // shut down (central storage unavailable). log::ScopedParamContainer params(m_processManager.logContext()); params.add("tapeDrive", m_configLine.unitName); - m_sessionState=(SessionState)message.sessionstate(); - m_sessionType=(SessionType)message.sessiontype(); - m_sessionVid=""; - // Set the timeout for this state - m_lastStateChangeTime=std::chrono::steady_clock::now(); - m_processingStatus.nextTimeout=nextTimeout(); - m_processingStatus.shutdownRequested=true; + m_sessionVid = ""; + m_processingStatus.shutdownRequested = true; m_processManager.logContext().log(log::CRIT, - "In DriveHandler::processFatal(): shutting down after fatal failure."); + "In DriveHandler::processFatal(): shutting down after fatal failure."); return m_processingStatus; } + //------------------------------------------------------------------------------ // DriveHandler::processLogs //------------------------------------------------------------------------------ void DriveHandler::processLogs(serializers::WatchdogMessage& message) { // Accumulate the logs added (if any) - for (auto & log: message.addedlogparams()) { + for (auto& log: message.addedlogparams()) { m_sessionEndContext.pushOrReplace({log.name(), log.value()}); } - for (auto & log: message.deletedlogparams()) { + for (auto& log: message.deletedlogparams()) { m_sessionEndContext.erase(log); } } @@ -667,13 +594,13 @@ void DriveHandler::processLogs(serializers::WatchdogMessage& message) { //------------------------------------------------------------------------------ void DriveHandler::processBytes(serializers::WatchdogMessage& message) { // In all cases, this is a heartbeat. - m_lastHeartBeatTime=std::chrono::steady_clock::now(); + m_lastHeartBeatTime = std::chrono::steady_clock::now(); // Record data moved totals if needed. - if (m_totalTapeBytesMoved != message.totaltapebytesmoved()|| + if (m_totalTapeBytesMoved != message.totaltapebytesmoved() || m_totalDiskBytesMoved != message.totaldiskbytesmoved()) { - if (message.totaltapebytesmoved()<m_totalTapeBytesMoved|| - message.totaldiskbytesmoved()<m_totalDiskBytesMoved) { + if (message.totaltapebytesmoved() < m_totalTapeBytesMoved || + message.totaldiskbytesmoved() < m_totalDiskBytesMoved) { log::ScopedParamContainer params(m_processManager.logContext()); params.add("PreviousTapeBytesMoved", m_totalTapeBytesMoved) .add("PreviousDiskBytesMoved", m_totalDiskBytesMoved) @@ -681,13 +608,13 @@ void DriveHandler::processBytes(serializers::WatchdogMessage& message) { .add("NewDiskBytesMoved", message.totaldiskbytesmoved()); m_processManager.logContext().log(log::DEBUG, "WARNING: In DriveHandler::processRunning(): total bytes moved going backwards"); } - m_totalTapeBytesMoved=message.totaltapebytesmoved(); - m_totalDiskBytesMoved=message.totaldiskbytesmoved(); - m_lastDataMovementTime=std::chrono::steady_clock::now(); + m_totalTapeBytesMoved = message.totaltapebytesmoved(); + m_totalDiskBytesMoved = message.totaldiskbytesmoved(); + m_lastDataMovementTime = std::chrono::steady_clock::now(); } // Update next timeout if required. Next operations might not do it. - m_processingStatus.nextTimeout=nextTimeout(); + m_processingStatus.nextTimeout = nextTimeout(); } //------------------------------------------------------------------------------ @@ -702,19 +629,19 @@ SubprocessHandler::ProcessingStatus DriveHandler::processSigChild() { params.add("tapeDrive", m_configLine.unitName); if (-1 == m_pid) return m_processingStatus; int processStatus; - int rc=::waitpid(m_pid, &processStatus, WNOHANG); + int rc = ::waitpid(m_pid, &processStatus, WNOHANG); // Check there was no error. try { exception::Errnum::throwOnMinusOne(rc); - } catch (exception::Exception &ex) { - cta::log::ScopedParamContainer params(m_processManager.logContext()); - params.add("pid", m_pid) + } catch (exception::Exception& ex) { + cta::log::ScopedParamContainer scoped(m_processManager.logContext()); + scoped.add("pid", m_pid) .add("tapeDrive", m_configLine.unitName) .add("Message", ex.getMessageValue()) .add("SessionState", session::toString(m_sessionState)) .add("SessionType", toString(m_sessionType)); m_processManager.logContext().log(log::WARNING, - "In DriveHandler::processSigChild(): failed to get child process exit code. Doing nothing as we are unable to determine if it is still running or not."); + "In DriveHandler::processSigChild(): failed to get child process exit code. Doing nothing as we are unable to determine if it is still running or not."); return m_processingStatus; } if (rc) { @@ -722,7 +649,7 @@ SubprocessHandler::ProcessingStatus DriveHandler::processSigChild() { // We did collect the exit code of our child process // How well did it finish? (exit() or killed?) // The socket pair will be reopened on the next fork. Clean it up. - if (m_socketPair.get()) { + if (m_socketPair) { m_processManager.removeFile(m_socketPair->getFdForAccess(server::SocketPair::Side::child)); m_socketPair.reset(nullptr); } @@ -735,12 +662,14 @@ SubprocessHandler::ProcessingStatus DriveHandler::processSigChild() { if (m_sessionState != SessionState::Shutdown) { m_processManager.logContext().log(log::INFO, "Drive subprocess exited. Will spawn a new one."); resetToDefault(PreviousSession::Up); - m_processingStatus.forkRequested=true; - } else { + m_processingStatus.forkRequested = true; + } + else { m_processManager.logContext().log(log::INFO, "Drive subprocess exited. Will not spawn new one as we are shutting down."); - m_processingStatus.forkRequested=false; + m_processingStatus.forkRequested = false; } - } else { + } + else { params.add("IfSignaled", WIFSIGNALED(processStatus)) .add("TermSignal", WTERMSIG(processStatus)) .add("CoreDump", WCOREDUMP(processStatus)); @@ -752,17 +681,18 @@ SubprocessHandler::ProcessingStatus DriveHandler::processSigChild() { // If we are shutting down, we should not request a new session. if (m_sessionState != SessionState::Shutdown) { m_processManager.logContext().log(log::INFO, "Drive subprocess crashed. Will spawn a new one."); - m_processingStatus.forkRequested=true; - } else { + m_processingStatus.forkRequested = true; + } + else { m_processManager.logContext().log(log::INFO, "Drive subprocess crashed. Will not spawn new one as we are shutting down."); - m_processingStatus.forkRequested=false; + m_processingStatus.forkRequested = false; } m_sessionEndContext.pushOrReplace({"Error_sessionKilled", "1"}); m_sessionEndContext.pushOrReplace({"killSignal", WTERMSIG(processStatus)}); m_sessionEndContext.pushOrReplace({"status", "failure"}); } // In all cases we log the end of the session. - m_sessionEndContext.pushOrReplace({"tapeDrive",m_configLine.unitName}); + m_sessionEndContext.pushOrReplace({"tapeDrive", m_configLine.unitName}); m_sessionEndContext.moveToTheEndIfPresent("status"); m_sessionEndContext.log(cta::log::INFO, "Tape session finished"); m_sessionEndContext.clear(); @@ -783,8 +713,8 @@ SubprocessHandler::ProcessingStatus DriveHandler::processTimeout() { if (-1 == m_pid) { m_processManager.logContext().log(log::ERR, "In DriveHandler::processTimeout(): Received timeout without child process present."); m_processManager.logContext().log(log::INFO, "Re-launching child process."); - m_processingStatus.forkRequested=true; - m_processingStatus.nextTimeout=m_processingStatus.nextTimeout.max(); + m_processingStatus.forkRequested = true; + m_processingStatus.nextTimeout = m_processingStatus.nextTimeout.max(); // Record the status of the session for cleanup startup (not needed here) m_previousState = SessionState::Shutdown; m_previousType = SessionType::Undetermined; @@ -794,7 +724,7 @@ SubprocessHandler::ProcessingStatus DriveHandler::processTimeout() { } auto now = std::chrono::steady_clock::now(); params.add("SessionState", session::toString(m_sessionState)) - .add("SesssionType", session::toString(m_sessionType)) + .add("SessionType", session::toString(m_sessionType)) .add("TimeoutType", m_timeoutType) .add("SessionTypeWhenTimeoutDecided", session::toString(m_sessionTypeWhenTimeoutDecided)) .add("SessionStateWhenTimeoutDecided", session::toString(m_sessionStateWhenTimeoutDecided)) @@ -805,20 +735,20 @@ SubprocessHandler::ProcessingStatus DriveHandler::processTimeout() { .add("ThisTimeout", std::chrono::duration_cast<std::chrono::seconds>(m_processingStatus.nextTimeout.time_since_epoch()).count()); // Log timeouts (if we have any) try { - decltype (SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = - m_lastStateChangeTime + m_stateChangeTimeouts.at(m_sessionState); + decltype(SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = + m_lastStateChangeTime + m_stateChangeTimeouts.at(m_sessionState); std::chrono::duration<double> timeToTimeout = nextTimeout - now; params.add("BeforeStateChangeTimeout_s", timeToTimeout.count()); } catch (...) {} try { - decltype (SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = - m_lastDataMovementTime + m_dataMovementTimeouts.at(m_sessionState); + decltype(SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = + m_lastDataMovementTime + m_dataMovementTimeouts.at(m_sessionState); std::chrono::duration<double> timeToTimeout = nextTimeout - now; params.add("BeforeDataMovementTimeout_s", timeToTimeout.count()); } catch (...) {} try { - decltype (SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = - m_lastHeartBeatTime + m_heartbeatTimeouts.at(m_sessionState); + decltype(SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout = + m_lastHeartBeatTime + m_heartbeatTimeouts.at(m_sessionState); std::chrono::duration<double> timeToTimeout = nextTimeout - now; params.add("BeforeHeartbeatTimeout_s", timeToTimeout.count()); } catch (...) {} @@ -826,12 +756,12 @@ SubprocessHandler::ProcessingStatus DriveHandler::processTimeout() { params.add("SubprocessId", m_pid); exception::Errnum::throwOnMinusOne(::kill(m_pid, SIGKILL)); m_processManager.logContext().log(log::WARNING, "In DriveHandler::processTimeout(): Killed subprocess."); - } catch (exception::Exception & ex) { + } catch (exception::Exception& ex) { params.add("Error", ex.getMessageValue()); m_processManager.logContext().log(log::ERR, "In DriveHandler::processTimeout(): Failed to kill subprocess."); } // We now should receive the sigchild, so we ask nothing from process manager - m_processingStatus.nextTimeout=m_processingStatus.nextTimeout.max(); + m_processingStatus.nextTimeout = m_processingStatus.nextTimeout.max(); return m_processingStatus; } @@ -854,15 +784,15 @@ int DriveHandler::runChild() { // Set the thread name for process ID: std::string threadName = "cta-tpd-"; - threadName+=m_configLine.unitName; + threadName += m_configLine.unitName; prctl(PR_SET_NAME, threadName.c_str()); // Create the channel to talk back to the parent process. cta::tape::daemon::DriveHandlerProxy driveHandlerProxy(*m_socketPair); - std::string hostname=cta::utils::getShortHostname(); + std::string hostname = cta::utils::getShortHostname(); - auto &lc=m_processManager.logContext(); + auto& lc = m_processManager.logContext(); { log::ScopedParamContainer params(lc); params.add("backendPath", m_tapedConfig.backendPath.value()); @@ -871,14 +801,14 @@ int DriveHandler::runChild() { // Before anything, we need to check we have access to the scheduler's central storage std::unique_ptr<SchedulerDBInit_t> sched_db_init; try { - std::string processName="DriveProcess-"; - processName+=m_configLine.unitName; + std::string processName = "DriveProcess-"; + processName += m_configLine.unitName; log::ScopedParamContainer params(lc); params.add("processName", processName); lc.log(log::DEBUG, "In DriveHandler::runChild(): will create agent entry. Enabling leaving non-empty agent behind."); sched_db_init.reset(new SchedulerDBInit_t(processName, m_tapedConfig.backendPath.value(), m_processManager.logContext().logger(), true)); - } catch (cta::exception::Exception &ex) { - log::ScopedParamContainer param (lc); + } catch (cta::exception::Exception& ex) { + log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to connect to objectstore or failed to instantiate agent entry. Reporting fatal error."); driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); @@ -887,11 +817,11 @@ int DriveHandler::runChild() { } std::unique_ptr<SchedulerDB_t> sched_db; try { - if(!m_catalogue) { + if (!m_catalogue) { m_catalogue = createCatalogue("DriveHandler::runChild()"); } sched_db = sched_db_init->getSchedDB(*m_catalogue, lc.logger()); - } catch(cta::exception::Exception &ex) { + } catch (cta::exception::Exception& ex) { log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to instantiate catalogue. Reporting fatal error."); @@ -901,19 +831,19 @@ int DriveHandler::runChild() { } lc.log(log::DEBUG, "In DriveHandler::runChild(): will create scheduler."); cta::Scheduler scheduler(*m_catalogue, *sched_db, m_tapedConfig.mountCriteria.value().maxFiles, - m_tapedConfig.mountCriteria.value().maxBytes); + m_tapedConfig.mountCriteria.value().maxBytes); // Before launching the transfer session, we validate that the scheduler is reachable. lc.log(log::DEBUG, "In DriveHandler::runChild(): will ping scheduler."); try { scheduler.ping(lc); - } catch (const cta::catalogue::WrongSchemaVersionException &ex) { - log::ScopedParamContainer param (lc); + } catch (const cta::catalogue::WrongSchemaVersionException& ex) { + log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): catalogue MAJOR version mismatch. Reporting fatal error."); driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; - } catch (cta::exception::Exception &ex) { - log::ScopedParamContainer param (lc); + } catch (cta::exception::Exception& ex) { + log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to ping central storage before session. Reporting fatal error."); driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); @@ -930,18 +860,18 @@ int DriveHandler::runChild() { // Get hold of the scheduler. try { cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=m_configLine.unitName; - driveInfo.logicalLibrary=m_configLine.logicalLibrary; - driveInfo.host=hostname; + driveInfo.driveName = m_configLine.unitName; + driveInfo.logicalLibrary = m_configLine.logicalLibrary; + driveInfo.host = hostname; scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, lc); cta::common::dataStructures::SecurityIdentity securityIdentity; cta::common::dataStructures::DesiredDriveState driveState; driveState.up = false; driveState.forceDown = false; - driveState.setReasonFromLogMsg(logLevel,errorMsg); - scheduler.setDesiredDriveState(securityIdentity, m_configLine.unitName,driveState, lc); + driveState.setReasonFromLogMsg(logLevel, errorMsg); + scheduler.setDesiredDriveState(securityIdentity, m_configLine.unitName, driveState, lc); return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; - } catch (cta::exception::Exception &ex) { + } catch (cta::exception::Exception& ex) { log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to set the drive down. Reporting fatal error."); @@ -953,27 +883,27 @@ int DriveHandler::runChild() { // 2) If the previous session crashed, we might want to run a cleaner session, depending // on the previous state - std::set<SessionState> statesRequiringCleaner = { SessionState::Mounting, - SessionState::Running, SessionState::Unmounting }; + std::set<SessionState> statesRequiringCleaner = {SessionState::Mounting, + SessionState::Running, SessionState::Unmounting}; if (m_previousSession == PreviousSession::Crashed && statesRequiringCleaner.count(m_previousState)) { - if (!m_previousVid.size()) { + if (m_previousVid.empty()) { int logLevel = log::ERR; std::string errorMsg = "In DriveHandler::runChild(): Should run cleaner but VID is missing. Putting the drive down."; lc.log(log::ERR, errorMsg); try { cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=m_configLine.unitName; - driveInfo.logicalLibrary=m_configLine.logicalLibrary; - driveInfo.host=hostname; + driveInfo.driveName = m_configLine.unitName; + driveInfo.logicalLibrary = m_configLine.logicalLibrary; + driveInfo.host = hostname; scheduler.reportDriveStatus(driveInfo, cta::common::dataStructures::MountType::NoMount, cta::common::dataStructures::DriveStatus::Down, lc); cta::common::dataStructures::SecurityIdentity securityIdentity; cta::common::dataStructures::DesiredDriveState driveState; driveState.up = false; driveState.forceDown = false; - driveState.setReasonFromLogMsg(logLevel,errorMsg); + driveState.setReasonFromLogMsg(logLevel, errorMsg); scheduler.setDesiredDriveState(securityIdentity, m_configLine.unitName, driveState, lc); return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; - } catch (cta::exception::Exception &ex) { + } catch (cta::exception::Exception& ex) { log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to set the drive down. Reporting fatal error."); @@ -1009,14 +939,14 @@ int DriveHandler::runChild() { // } try { scheduler.ping(lc); - } catch (const cta::catalogue::WrongSchemaVersionException &ex) { - log::ScopedParamContainer param (lc); + } catch (const cta::catalogue::WrongSchemaVersionException& ex) { + log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild() before cleanerSession: catalogue MAJOR version mismatch. Reporting fatal error."); driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; - } catch (cta::exception::Exception &ex) { - log::ScopedParamContainer param (lc); + } catch (cta::exception::Exception& ex) { + log::ScopedParamContainer param(lc); param.add("errorMessage", ex.getMessageValue()); lc.log(log::CRIT, "In DriveHandler::runChild() before cleanerSession: failed to ping central storage before session. Reporting fatal error."); driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); @@ -1036,7 +966,8 @@ int DriveHandler::runChild() { *m_catalogue, scheduler); return cleanerSession.execute(); - } else { + } + else { // The next session will be a normal session (no crash with a mounted tape before). // Capabilities management. cta::server::ProcessCap capUtils; @@ -1049,17 +980,17 @@ int DriveHandler::runChild() { castor::tape::tapeserver::daemon::DataTransferConfig dataTransferConfig; dataTransferConfig.bufsz = m_tapedConfig.bufferSizeBytes.value(); dataTransferConfig.bulkRequestMigrationMaxBytes = - m_tapedConfig.archiveFetchBytesFiles.value().maxBytes; + m_tapedConfig.archiveFetchBytesFiles.value().maxBytes; dataTransferConfig.bulkRequestMigrationMaxFiles = - m_tapedConfig.archiveFetchBytesFiles.value().maxFiles; + m_tapedConfig.archiveFetchBytesFiles.value().maxFiles; dataTransferConfig.bulkRequestRecallMaxBytes = - m_tapedConfig.retrieveFetchBytesFiles.value().maxBytes; + m_tapedConfig.retrieveFetchBytesFiles.value().maxBytes; dataTransferConfig.bulkRequestRecallMaxFiles = - m_tapedConfig.retrieveFetchBytesFiles.value().maxFiles; + m_tapedConfig.retrieveFetchBytesFiles.value().maxFiles; dataTransferConfig.maxBytesBeforeFlush = - m_tapedConfig.archiveFlushBytesFiles.value().maxBytes; + m_tapedConfig.archiveFlushBytesFiles.value().maxBytes; dataTransferConfig.maxFilesBeforeFlush = - m_tapedConfig.archiveFlushBytesFiles.value().maxFiles; + m_tapedConfig.archiveFlushBytesFiles.value().maxFiles; dataTransferConfig.nbBufs = m_tapedConfig.bufferCount.value(); dataTransferConfig.nbDiskThreads = m_tapedConfig.nbDiskThreads.value(); dataTransferConfig.useLbp = true; @@ -1085,12 +1016,12 @@ int DriveHandler::runChild() { // Before setting the desired state as down, we have to make sure the drive exists in the registry. // this is done by reporting the drive as down first. cta::common::dataStructures::DriveInfo driveInfo; - driveInfo.driveName=m_configLine.unitName; - driveInfo.logicalLibrary=m_configLine.logicalLibrary; - driveInfo.host=hostname; + driveInfo.driveName = m_configLine.unitName; + driveInfo.logicalLibrary = m_configLine.logicalLibrary; + driveInfo.host = hostname; // Checking the drive does not already exist in the database - if(!scheduler.checkDriveCanBeCreated(driveInfo, lc)) { + if (!scheduler.checkDriveCanBeCreated(driveInfo, lc)) { driveHandlerProxy.reportState(tape::session::SessionState::Fatal, tape::session::SessionType::Undetermined, ""); return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; } @@ -1107,7 +1038,7 @@ int DriveHandler::runChild() { driveState.up = false; driveState.forceDown = false; scheduler.createTapeDriveStatus(driveInfo, driveState, common::dataStructures::MountType::NoMount, - common::dataStructures::DriveStatus::Down, m_configLine, securityIdentity, lc); + common::dataStructures::DriveStatus::Down, m_configLine, securityIdentity, lc); // Get the drive state to see if there is a reason or not, we don't want to change the reason // why a drive is down at the startup of the tapeserver. If it's setted up a previous Reason From Log @@ -1122,7 +1053,7 @@ int DriveHandler::runChild() { scheduler.setDesiredDriveState(securityIdentity, m_configLine.unitName, driveState, lc); scheduler.reportDriveConfig(m_configLine, m_tapedConfig, lc); - } catch (cta::exception::Exception & ex) { + } catch (cta::exception::Exception& ex) { params.add("Message", ex.getMessageValue()) .add("Backtrace", ex.backtrace()); lc.log(log::CRIT, "In DriveHandler::runChild(): failed to set drive down"); @@ -1162,7 +1093,7 @@ SubprocessHandler::ProcessingStatus DriveHandler::shutdown() { return m_processingStatus; }; // TODO: improve in the future (preempt the child process) - auto &lc = m_processManager.logContext(); + auto& lc = m_processManager.logContext(); log::ScopedParamContainer params(lc); params.add("tapeDrive", m_configLine.unitName); lc.log(log::INFO, "In DriveHandler::shutdown(): simply killing the process."); @@ -1197,9 +1128,10 @@ SubprocessHandler::ProcessingStatus DriveHandler::shutdown() { if (statesRequiringCleaner.count(m_sessionState)) { if (!m_sessionVid.size()) { lc.log(log::ERR, "In DriveHandler::shutdown(): Should run cleaner but VID is missing. Do nothing."); - } else { - log::ScopedParamContainer params(m_processManager.logContext()); - params.add("tapeVid", m_sessionVid) + } + else { + log::ScopedParamContainer scoped(m_processManager.logContext()); + scoped.add("tapeVid", m_sessionVid) .add("tapeDrive", m_configLine.unitName) .add("sessionState", session::toString(m_sessionState)) .add("sessionType", session::toString(m_sessionType)); @@ -1273,10 +1205,10 @@ int DriveHandler::setDriveDownForShutdown(const std::unique_ptr<cta::Scheduler>& return castor::tape::tapeserver::daemon::Session::MARK_DRIVE_AS_DOWN; } -std::unique_ptr<cta::catalogue::Catalogue> DriveHandler::createCatalogue(const std::string & methodCaller){ +std::unique_ptr<cta::catalogue::Catalogue> DriveHandler::createCatalogue(const std::string& methodCaller) { log::ScopedParamContainer params(m_processManager.logContext()); params.add("fileCatalogConfigFile", m_tapedConfig.fileCatalogConfigFile.value()); - params.add("caller",methodCaller); + params.add("caller", methodCaller); m_processManager.logContext().log(log::DEBUG, "In DriveHandler::createCatalogue(): will get catalogue login information."); const cta::rdbms::Login catalogueLogin = cta::rdbms::Login::parseFile(m_tapedConfig.fileCatalogConfigFile.value()); const uint64_t nbConns = 1; @@ -1295,4 +1227,6 @@ DriveHandler::~DriveHandler() { } -}}} // namespace cta::tape::daemon +} +} +} // namespace cta::tape::daemon diff --git a/tapeserver/daemon/DriveHandler.hpp b/tapeserver/daemon/DriveHandler.hpp index 08f6f83208ae26360509e6179bf912a16a586c3a..57d6294b0f74c2f7a4a03c772fb3e69d829feef6 100644 --- a/tapeserver/daemon/DriveHandler.hpp +++ b/tapeserver/daemon/DriveHandler.hpp @@ -28,32 +28,45 @@ #include "scheduler/Scheduler.hpp" #include <memory> -namespace cta { namespace tape { namespace daemon { +namespace cta { +namespace tape { +namespace daemon { /** * Handler for tape drive session subprocesses. On process/session will handle * at most one tape mount. Child process will either return a clean/unclean */ -class DriveHandler: public SubprocessHandler { +class DriveHandler : public SubprocessHandler { public: - DriveHandler(const TapedConfiguration & tapedConfig, const TpconfigLine & configline, ProcessManager & pm); - virtual ~DriveHandler(); + DriveHandler(const TapedConfiguration& tapedConfig, const TpconfigLine& configline, ProcessManager& pm); + + ~DriveHandler() override; + SubprocessHandler::ProcessingStatus getInitialStatus() override; + SubprocessHandler::ProcessingStatus fork() override; + void postForkCleanup() override; + int runChild() override; + SubprocessHandler::ProcessingStatus shutdown() override; + void kill() override; + SubprocessHandler::ProcessingStatus processEvent() override; + SubprocessHandler::ProcessingStatus processSigChild() override; + SubprocessHandler::ProcessingStatus processTimeout() override; + private: /** Reference to the process manager*/ - cta::tape::daemon::ProcessManager & m_processManager; + cta::tape::daemon::ProcessManager& m_processManager; /** The parameters */ - const TapedConfiguration & m_tapedConfig; + const TapedConfiguration& m_tapedConfig; /** This drive's parameters */ - const TpconfigLine & m_configLine; + const TpconfigLine& m_configLine; /** Possible outcomes of the previous session/child process. */ enum class PreviousSession { Initiating, ///< The process is the first to run after daemon startup. A cleanup will be run beforehand. @@ -62,7 +75,7 @@ private: Crashed ///< The previous process was killed or crashed. The next session will be a cleanup. }; /** Representation of the outcome of the previous session/child process. */ - PreviousSession m_previousSession=PreviousSession::Initiating; + PreviousSession m_previousSession = PreviousSession::Initiating; /** Representation of the last know state of the previous session (useful for crashes) */ session::SessionState m_previousState = session::SessionState::StartingUp; /** Representation of the last know type of the previous session (useful for crashes) */ @@ -70,7 +83,7 @@ private: /** Previous VID, that can help the unmount process */ std::string m_previousVid; /** Representation of the status of the current process. */ - session::SessionState m_sessionState=session::SessionState::PendingFork; + session::SessionState m_sessionState = session::SessionState::PendingFork; int setDriveDownForShutdown(const std::unique_ptr<cta::Scheduler>& scheduler, cta::log::LogContext* lc); @@ -79,26 +92,33 @@ private: * @param previousSessionState outcome to be considered for the next run. */ void resetToDefault(PreviousSession previousSessionState); + /** Helper function to handle Scheduling state report */ - SubprocessHandler::ProcessingStatus processStartingUp(serializers::WatchdogMessage & message); - /** Helper function to handle Scheduling state report */ - SubprocessHandler::ProcessingStatus processScheduling(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processScheduling(serializers::WatchdogMessage& message); + /** Helper function to handle Checking state report */ - SubprocessHandler::ProcessingStatus processChecking(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processChecking(serializers::WatchdogMessage& message); + /** Helper function to handle Mounting state report */ - SubprocessHandler::ProcessingStatus processMounting(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processMounting(serializers::WatchdogMessage& message); + /** Helper function to handle Running state report */ - SubprocessHandler::ProcessingStatus processRunning(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processRunning(serializers::WatchdogMessage& message); + /** Helper function to handle Unmounting state report */ - SubprocessHandler::ProcessingStatus processUnmounting(serializers::WatchdogMessage & message); - /** Helper function to handle DraingingToDisk state report */ - SubprocessHandler::ProcessingStatus processDrainingToDisk(serializers::WatchdogMessage & message); - /** Helper function to handle ClosingDown state report */ - SubprocessHandler::ProcessingStatus processShutingDown(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processUnmounting(serializers::WatchdogMessage& message); + + /** Helper function to handle DrainingToDisk state report */ + SubprocessHandler::ProcessingStatus processDrainingToDisk(serializers::WatchdogMessage& message); + + /** Helper function to handle ShuttingDown state report */ + SubprocessHandler::ProcessingStatus processShuttingDown(serializers::WatchdogMessage& message); + /** Helper function to handle Fatal state report */ - SubprocessHandler::ProcessingStatus processFatal(serializers::WatchdogMessage & message); + SubprocessHandler::ProcessingStatus processFatal(serializers::WatchdogMessage& message); + /** Current session's type */ - session::SessionType m_sessionType=session::SessionType::Undetermined; + session::SessionType m_sessionType = session::SessionType::Undetermined; /** Current session's VID */ std::string m_sessionVid; /** Current session's parameters: they are accumulated during session's lifetime @@ -126,26 +146,32 @@ private: session::SessionType m_sessionTypeWhenTimeoutDecided; /** State when current timeout was set */ session::SessionState m_sessionStateWhenTimeoutDecided; + /** Computation of the next timeout (depending on the state) */ - decltype (SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout(); + decltype(SubprocessHandler::ProcessingStatus::nextTimeout) nextTimeout(); + /** How much data did we see moving the session so far? (tape) */ - uint64_t m_totalTapeBytesMoved=0; + uint64_t m_totalTapeBytesMoved = 0; /** How much data did we see moving the session so far? (disk) */ - uint64_t m_totalDiskBytesMoved=0; + uint64_t m_totalDiskBytesMoved = 0; /** PID for the subprocess */ - pid_t m_pid=-1; + pid_t m_pid = -1; /** Socket pair allowing communication with the subprocess */ std::unique_ptr<cta::server::SocketPair> m_socketPair; + /** Helper function accumulating logs */ - void processLogs(serializers::WatchdogMessage & message); + void processLogs(serializers::WatchdogMessage& message); + /** Helper function accumulating bytes transferred */ - void processBytes(serializers::WatchdogMessage & message); + void processBytes(serializers::WatchdogMessage& message); - std::unique_ptr<cta::catalogue::Catalogue> createCatalogue(const std::string & methodCaller); + std::unique_ptr<cta::catalogue::Catalogue> createCatalogue(const std::string& methodCaller); std::unique_ptr<cta::catalogue::Catalogue> m_catalogue; }; // TODO: remove/merge ChildProcess. -}}} // namespace cta::tape::daemon +} +} +} // namespace cta::tape::daemon diff --git a/tapeserver/readtp/ReadtpCmd.cpp b/tapeserver/readtp/ReadtpCmd.cpp index fd40070389198b1ec32f4d920336e965762470f7..2fc2b6ca0ed03d1eab66d88938cd36272cc58dc6 100644 --- a/tapeserver/readtp/ReadtpCmd.cpp +++ b/tapeserver/readtp/ReadtpCmd.cpp @@ -202,7 +202,7 @@ std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(castor::tape::tapeserver::drive::createDrive(driveInfo, m_sysWrapper)); - if(NULL == drive.get()) { + if(nullptr == drive.get()) { cta::exception::Exception ex; ex.getMessage() << "Failed to instantiate drive object"; throw ex; diff --git a/tapeserver/readtp/ReadtpCmdLineArgs.cpp b/tapeserver/readtp/ReadtpCmdLineArgs.cpp index 3f409ffc2bd637f41d0fffab3d9ad145849112e9..ab01ec8d1cb6135f182fa977d638a1ac5f069050 100644 --- a/tapeserver/readtp/ReadtpCmdLineArgs.cpp +++ b/tapeserver/readtp/ReadtpCmdLineArgs.cpp @@ -51,10 +51,10 @@ ReadtpCmdLineArgs::ReadtpCmdLineArgs(const int argc, char *const *const argv): m_fSeqRangeList = TapeFileSequenceParser::parse(argv[2]); static struct option longopts[] = { - {"destination_files", required_argument, NULL, 'f'}, - {"xroot_private_key", required_argument, NULL, 'p'}, - {"help", no_argument, NULL, 'h'}, - {NULL , 0, NULL, 0} + {"destination_files", required_argument, nullptr, 'f'}, + {"xroot_private_key", required_argument, nullptr, 'p'}, + {"help", no_argument, nullptr, 'h'}, + {nullptr, 0, nullptr, 0} }; opterr = 0; diff --git a/tapeserver/readtp/TapeFseqRangeListSequence.cpp b/tapeserver/readtp/TapeFseqRangeListSequence.cpp index fd92984194c60069dca627f90a1d448a111c8455..edea8d0d70b2d256606dd61bab3df7902e587d6c 100644 --- a/tapeserver/readtp/TapeFseqRangeListSequence.cpp +++ b/tapeserver/readtp/TapeFseqRangeListSequence.cpp @@ -35,7 +35,7 @@ namespace readtp { //------------------------------------------------------------------------------ TapeFseqRangeListSequence::TapeFseqRangeListSequence() { - reset(NULL); + reset(nullptr); } @@ -55,7 +55,7 @@ void TapeFseqRangeListSequence::reset( const TapeFseqRangeList *const list) { m_list = list; - if(m_list == NULL) { + if(m_list == nullptr) { m_isFinite = true; m_totalSize = 0; } else { @@ -90,7 +90,7 @@ void TapeFseqRangeListSequence::reset( // hasMore //------------------------------------------------------------------------------ bool TapeFseqRangeListSequence::hasMore() const throw() { - if(m_list != NULL) { + if(m_list != nullptr) { return m_nbSequence.hasMore(); } else { return false; diff --git a/tapeserver/tapelabel/TapeLabelCmd.cpp b/tapeserver/tapelabel/TapeLabelCmd.cpp index fd33b880ed9c28fed54b1d72ba537e0a7ee49fae..7465fcdf2d8592d0e85c9342bcdb217ae11b3b6b 100644 --- a/tapeserver/tapelabel/TapeLabelCmd.cpp +++ b/tapeserver/tapelabel/TapeLabelCmd.cpp @@ -486,7 +486,7 @@ std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(castor::tape::tapeserver::drive::createDrive(driveInfo, m_sysWrapper)); - if(NULL == drive.get()) { + if(nullptr == drive.get()) { cta::exception::Exception ex; ex.getMessage() << "Failed to instantiate drive object"; throw ex; diff --git a/tapeserver/tapelabel/TapeLabelCmdLineArgs.cpp b/tapeserver/tapelabel/TapeLabelCmdLineArgs.cpp index 9d7f43bbcb77d049261c3356c61586a24d085883..52eae629e3b1b870bf42e0af14b33fa9a37513b2 100644 --- a/tapeserver/tapelabel/TapeLabelCmdLineArgs.cpp +++ b/tapeserver/tapelabel/TapeLabelCmdLineArgs.cpp @@ -36,12 +36,12 @@ TapeLabelCmdLineArgs::TapeLabelCmdLineArgs(const int argc, char *const *const ar help(false), m_debug(false), m_force(false) { static struct option longopts[] = { - {"vid", required_argument, NULL, 'v'}, - {"oldlabel", required_argument, NULL, 'o'}, - {"debug", no_argument, NULL, 'd'}, - {"force", no_argument, NULL, 'f'}, - {"help", no_argument, NULL, 'h'}, - {NULL , 0, NULL, 0} + {"vid", required_argument, nullptr, 'v'}, + {"oldlabel", required_argument, nullptr, 'o'}, + {"debug", no_argument, nullptr, 'd'}, + {"force", no_argument, nullptr, 'f'}, + {"help", no_argument, nullptr, 'h'}, + {nullptr, 0, nullptr, 0} }; // Prevent getopt() from printing an error message if it does not recognize @@ -50,7 +50,7 @@ TapeLabelCmdLineArgs::TapeLabelCmdLineArgs(const int argc, char *const *const ar int opt = 0; - while((opt = getopt_long(argc, argv, ":v:o:hdf", longopts, NULL)) != -1) { + while((opt = getopt_long(argc, argv, ":v:o:hdf", longopts, nullptr)) != -1) { switch(opt) { case 'v': if (strlen(optarg) > CA_MAXVIDLEN) { diff --git a/tapeserver/tapelabel/TapeLabelCmdLineArgsTest.cpp b/tapeserver/tapelabel/TapeLabelCmdLineArgsTest.cpp index 88b5b93742f230726d8acb78e7cced396e954167..ee0e20a2983cb221ed0e15b5ce163afe25af155e 100644 --- a/tapeserver/tapelabel/TapeLabelCmdLineArgsTest.cpp +++ b/tapeserver/tapelabel/TapeLabelCmdLineArgsTest.cpp @@ -30,7 +30,7 @@ protected: struct Argcv { int argc; char **argv; - Argcv(): argc(0), argv(NULL) { + Argcv(): argc(0), argv(nullptr) { } }; typedef std::list<Argcv*> ArgcvList; @@ -76,7 +76,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, help_short) { args->argv = new char *[3]; args->argv[0] = dupString("cta-tape-label"); args->argv[1] = dupString("-h"); - args->argv[2] = NULL; + args->argv[2] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -94,7 +94,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, help_long) { args->argv = new char *[3]; args->argv[0] = dupString("cta-tape-label"); args->argv[1] = dupString("--help"); - args->argv[2] = NULL; + args->argv[2] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -114,7 +114,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, debug_short) { args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); args->argv[3] = dupString("-d"); - args->argv[4] = NULL; + args->argv[4] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -134,7 +134,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, debug_long) { args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); args->argv[3] = dupString("--debug"); - args->argv[4] = NULL; + args->argv[4] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -154,7 +154,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, force_short) { args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); args->argv[3] = dupString("-f"); - args->argv[4] = NULL; + args->argv[4] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -174,7 +174,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, force_long) { args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); args->argv[3] = dupString("--force"); - args->argv[4] = NULL; + args->argv[4] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -193,7 +193,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, vid_short) { args->argv[0] = dupString("cta-tape-label"); args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); - args->argv[3] = NULL; + args->argv[3] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -211,7 +211,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, vid_long) { args->argv[0] = dupString("cta-tape-label"); args->argv[1] = dupString("--vid"); args->argv[2] = dupString("VID001"); - args->argv[3] = NULL; + args->argv[3] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -228,7 +228,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, vid_missed) { args->argv = new char *[3]; args->argv[0] = dupString("cta-tape-label"); args->argv[1] = dupString("--vid"); - args->argv[2] = NULL; + args->argv[2] = nullptr; ASSERT_THROW(TapeLabelCmdLineArgs cmdLine(args->argc, args->argv), cta::exception::CommandLineNotParsed); @@ -246,7 +246,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, oldVid_short) { args->argv[2] = dupString("VID001"); args->argv[3] = dupString("-o"); args->argv[4] = dupString("VID002"); - args->argv[5] = NULL; + args->argv[5] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -268,7 +268,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, oldVid_long) { args->argv[2] = dupString("VID001"); args->argv[3] = dupString("--oldlabel"); args->argv[4] = dupString("VID002"); - args->argv[5] = NULL; + args->argv[5] = nullptr; TapeLabelCmdLineArgs cmdLine(args->argc, args->argv); @@ -289,7 +289,7 @@ TEST_F(cta_tapeserver_tapelabel_TapeLabelCmdLineArgsTest, oldVid_missed) { args->argv[1] = dupString("-v"); args->argv[2] = dupString("VID001"); args->argv[3] = dupString("-o"); - args->argv[4] = NULL; + args->argv[4] = nullptr; ASSERT_THROW(TapeLabelCmdLineArgs cmdLine(args->argc, args->argv), cta::exception::CommandLineNotParsed);