/*
* @project The CERN Tape Archive (CTA)
* @copyright Copyright(C) 2003-2021 CERN
* @license This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#pragma once
#include "common/processCap/ProcessCap.hpp"
#include "castor/tape/tapeserver/daemon/MigrationReportPacker.hpp"
#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"
#include "castor/tape/tapeserver/file/File.hpp"
#include "common/Timer.hpp"
#include
#include
namespace castor {
namespace tape {
namespace tapeserver {
namespace daemon {
// forward definition
class MigrationTaskInjector;
class TapeWriteSingleThread : public TapeSingleThreadInterface {
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,
const VolumeInfo& volInfo,
cta::log::LogContext & lc,
MigrationReportPacker & repPacker,
cta::server::ProcessCap &capUtils,
uint64_t filesBeforeFlush, uint64_t bytesBeforeFlush, const bool useLbp,
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
* 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 pointer to the task injector
*/
void setTaskInjector(MigrationTaskInjector* injector){
m_injector = injector;
}
private:
/**
* Returns the string representation of the specified mount type
*/
const char *mountTypeToString(const cta::common::dataStructures::MountType mountType) const
throw();
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;
public:
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
*/
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
* will give the caller the ownership of the opened session (see unique_ptr
* copy constructor, which has a move semantic)
* @return the WriteSession we need to write on tape
*/
std::unique_ptr openWriteSession();
/**
* Execute flush on tape, do some log and report the flush to the client
* @param message the message the log will register
* @param bytes the number of bytes that have been written since the last flush
* (for logging)
* @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);
/**
* After waiting for the drive, we will dump the tape alert log content, if it
* is not empty
* @return true if any critical for write alert was detected
*/
bool logAndCheckTapeAlertsForWrite();
virtual void run() ;
//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;
/**
* 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
* of the first file to migrate we receive. That part is done by the
* MigrationTaskInjector.::synchronousInjection. Thus, we compute it into
* that function and retrieve/set it within DataTransferSession executeWrite
* after we make sure synchronousInjection returned true.
*
* It should be const, but it cant
* (because there is no mutable function member in c++)
*/
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;
/**
* 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;
protected:
/***
* Helper virtual function to access the watchdog from parent class
*/
virtual void countTapeLogError(const std::string & error) {
m_watchdog.addToErrorCount(error);
}
/**
* Logs SCSI metrics for write session.
*/
virtual void logSCSIMetrics();
private:
/**
* Pointer to the task injector allowing termination signaling
*/
MigrationTaskInjector* m_injector;
}; // class TapeWriteSingleThread
} // namespace daemon
} // namespace tapeserver
} // namsepace tape
} // namespace castor