Skip to content
Snippets Groups Projects
Commit 80addb0b authored by Victor Kotlyar's avatar Victor Kotlyar
Browse files

added first implementations for the labels HDR1, EOF1, HDR2, EOF2, UHL1, UTL1.

added untitests for them.
added prelabeled picture in the doc.
cosmetic changes and fix for syntax errors.
parent e3ec3832
Branches
Tags
No related merge requests found
......@@ -489,6 +489,17 @@ descriptors are contained in tape blocks of 80 bytes. All data is in ASCII nowad
\end{center}
\end{table}
\begin{table}[H]
\textbf{\caption{AUL prelabeled tape with one HDR1}}
\begin{center}
\begin{tabular}{ |c|c|c| }
\hline
VOL1 & \cellcolor{orange}HDR1(PRELABEL) & \cellcolor{green} TM \\
\hline
\end{tabular}
\end{center}
\end{table}
\begin{table}[H]
\textbf{\caption{The structure of the volume label}}
......@@ -543,7 +554,8 @@ CAStor example for the beginning of the tape:
0-3 & 4 & 0x00 & Header label: the caracters "HDR1 or EOF1" \\
\hline
4-20 & 17 & 0x04 & File identifier: hexadecimal CAStor NS file ID.
nsgetpath -x can be used to find the CASTOR full path name. Aligned to left. \\
nsgetpath -x can be used to find the CASTOR full path name. Aligned to left.
In case of prelabeled tape 'PRELABEL' is used instead of file ID.\\
\hline
21-26 & 6 & 0x15 & The volume serial number of the tape.\\
\hline
......@@ -598,6 +610,23 @@ CAStor example for the second file on the tape:
\end{small}
\end{table}
\begin{minipage}{\linewidth}
CAStor example for the empty tape with PRELABEL and one HDR1 is used:
\begin{small}
\begin{verbatim}
00000000 56 4f 4c 31 56 35 32 30 30 31 20 20 20 20 20 20 |VOL1V52001 |
00000010 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000020 20 20 20 20 20 72 6f 6f 74 20 20 20 20 20 20 20 | root |
00000030 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000040 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 33 | 3|
00000050 48 44 52 31 50 52 45 4c 41 42 45 4c 20 20 20 20 |HDR1PRELABEL |
00000060 20 20 20 20 20 56 35 32 30 30 31 30 30 30 31 30 | V5200100010|
00000070 30 30 31 30 30 30 31 30 30 30 31 33 32 33 34 30 |0010001000132340|
00000080 31 33 32 33 34 20 30 30 30 30 30 30 43 41 53 54 |13234 000000CAST|
00000090 4f 52 20 32 2e 31 2e 31 33 20 20 20 20 20 20 20 |OR 2.1.13 |
\end{verbatim}
\end{small}
\end{minipage}
\begin{table}[H]
\textbf{\caption{The structure of the HDR2, EOF2 labels}}
......@@ -611,21 +640,24 @@ CAStor example for the second file on the tape:
0-3 & 4 & 0x00 & Header label: the caracters "HDR2 or EOF2" \\
\hline
4 & 1 & 0x04 & Record format. An alphabetic character that indicates the
format of the records in the associated data set. For the AUL it could be only: F - fixed length.\\
format of the records in the associated data set. For the AUL it could be only: F - fixed length
(U - was used for HDR2 for prelabeled tapes)\\
\hline
5-9 & 5 & 0x05 & Block length in bytes (maximum). For the block size greater than 100000 the value is 00000. \\
\hline
10-14 & 5 & 0x0A & Record length in bytes (maximum). For the record size greater than 100000 the value is 00000. \\
\hline
15 & 1 & 0x0F & Depends on the tape density values are following: '2' for D800, '3' for D1600, '4' for D6250 \\
15 & 1 & 0x0F & Tape density. Depends on the tape density values are following: '2' for D800, '3' for D1600, '4' for D6250 \\
\hline
16-33 & 18 & 0x10 & Reserved \\
\hline
34 & 1 & 0x22 & 'P' if the drive configured to use compression (i.e. xxxGC) \\
34 & 2 & 0x22 & Tape recording technique. The only technique available for 9-track tape is odd parity with no translation.
For a magnetic tape subsystem with Improved Data Recording Capability, the values are: 'P '- Record data in compacted format,
' ' - Record data in standard uncompacted format. For CASTOR is is 'P' if the drive configured to use compression (i.e. xxxGC) \\
\hline
35-49 & 15 & 0x23 & Reserved \\
35-49 & 14 & 0x24 & Reserved \\
\hline
50-51 & 2 & 0x32 & '00' for AL and AUL tapes \\
50-51 & 2 & 0x32 & Buffer offset '00' for AL and AUL tapes \\
\hline
52-79 & 28 & 0x34 & Reserved \\
\hline
......@@ -654,23 +686,23 @@ CAStor example for the first file on the tape:
\hline
Bytes & Length & Offset & \multicolumn{1}{c|}{Content} \\
\hline \hline
0-3 & 4 & 0x00 & User header label: the caracters "UHL1 or UTL1" \\
0-3 & 4 & 0x00 & User header label: the caracters "UHL1 or UTL1". \\
\hline
4-13 & 10 & 0x04 & Actual file sequence number \\
4-13 & 10 & 0x04 & Actual file sequence number ( '0' padded from left ). \\
\hline
14-23 & 10 & 0x0E & Actual block size \\
14-23 & 10 & 0x0E & Actual block size ( '0' padded from left ). \\
\hline
24-33 & 10 & 0x18 & Actual record length \\
24-33 & 10 & 0x18 & Actual record length ( '0' padded from left ). \\
\hline
34-41 & 8 & 0x22 & Site : domain name uppercase \\
34-41 & 8 & 0x22 & Site : a part of the domain name uppercase.\\
\hline
42-51 & 10 & 0x2A & Tape mover host name uppercase \\
42-51 & 10 & 0x2A & Tape mover host name uppercase without domain name. \\
\hline
52-59 & 8 & 0x34 & Drive manufacturer \\
52-59 & 8 & 0x34 & Drive manufacturer. \\
\hline
60-67 & 8 & 0x3C & Drive model (first 8 bytes from the field PRODUCT IDENTIFICATION in the SCSI INQUIRY replay) \\
60-67 & 8 & 0x3C & Drive model (first 8 bytes from the field PRODUCT IDENTIFICATION in the SCSI INQUIRY replay). \\
\hline
68-79 & 12 & 0x44 & Drive serial number \\
68-79 & 12 & 0x44 & Drive serial number. \\
\hline
\end{tabularx}
\end{center}
......@@ -686,24 +718,6 @@ CAStor example for the second file on the tape:
\end{small}
\end{table}
\begin{minipage}{\linewidth}
CAStor example for the empty tape with PRELABEL and one HDR1 is used:
\begin{small}
\begin{verbatim}
00000000 56 4f 4c 31 56 35 32 30 30 31 20 20 20 20 20 20 |VOL1V52001 |
00000010 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000020 20 20 20 20 20 72 6f 6f 74 20 20 20 20 20 20 20 | root |
00000030 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 | |
00000040 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 33 | 3|
00000050 48 44 52 31 50 52 45 4c 41 42 45 4c 20 20 20 20 |HDR1PRELABEL |
00000060 20 20 20 20 20 56 35 32 30 30 31 30 30 30 31 30 | V5200100010|
00000070 30 30 31 30 30 30 31 30 30 30 31 33 32 33 34 30 |0010001000132340|
00000080 31 33 32 33 34 20 30 30 30 30 30 30 43 41 53 54 |13234 000000CAST|
00000090 4f 52 20 32 2e 31 2e 31 33 20 20 20 20 20 20 20 |OR 2.1.13 |
\end{verbatim}
\end{small}
\end{minipage}
\subsubsection{File block management}
Some files tapes have mixed block sizes,
......
......@@ -22,37 +22,333 @@
#include "Structures.hh"
#include "../Exception/Exception.hh"
#include <time.h>
#include <stdio.h>
void Tape::AULFile::VOL1::fill(std::string vsn) {
setString(label, "VOL1");
setString(VSN, vsn);
setString(lblStandart,"3");
setString(lblStandard, "3");
setString(ownerID, "CASTOR"); /* TODO: check do we need CASTOR's STAGERSUPERUSER */
}
void Tape::AULFile::VOL1::verify() {
if (cmpString(label,"VOL1"))
throw Tape::Exceptions::Errnum(std::string("Failed check for the VOL1: ")+
Tape::AULFile::toString(label));
if (!cmpString(VSN,""))
throw Tape::Exceptions::Errnum(std::string("Failed check for the VSN: ") +
Tape::AULFile::toString(VSN));
if (cmpString(lblStandart,"3"))
throw Tape::Exceptions::Errnum(
std::string("Failed check for the label standart: ") +
Tape::AULFile::toString(lblStandart));
if (cmpString(ownerID,"CASTOR"))
throw Tape::Exceptions::Errnum(
std::string("Failed check for the ownerID: ") +
Tape::AULFile::toString(ownerID));
/* now we check all other fields which must be spaces */
if (cmpString(accessibility,""))
throw Tape::Exceptions::Errnum("accessibility is not empty");
if (cmpString(reserved1,""))
if (cmpString(label, "VOL1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the VOL1: ") +
Tape::AULFile::toString(label));
if (!cmpString(VSN, ""))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the VSN: ") +
Tape::AULFile::toString(VSN));
if (cmpString(lblStandard, "3"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the label standard: ") +
Tape::AULFile::toString(lblStandard));
if (cmpString(ownerID, "CASTOR"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the ownerID: ") +
Tape::AULFile::toString(ownerID));
/* now we verify all other fields which must be spaces */
if (cmpString(accessibility, ""))
throw Tape::Exceptions::Errnum("accessibility is not empty");
if (cmpString(reserved1, ""))
throw Tape::Exceptions::Errnum("reserved1 is not empty");
if (cmpString(implID,""))
if (cmpString(implID, ""))
throw Tape::Exceptions::Errnum("implID is not empty");
if (cmpString(reserved2,""))
throw Tape::Exceptions::Errnum("reserved2 is not empty");
if (cmpString(reserved2, ""))
throw Tape::Exceptions::Errnum("reserved2 is not empty");
}
void Tape::AULFile::HDR1EOF1::fillCommon(
std::string _fileId, std::string _VSN, int _fSeq) {
setString(fileId, _fileId);
setString(VSN, _VSN);
setInt(fSeq, _fSeq);
// fill the predefined values
setString(fSec, "0001");
setString(genNum, "0001");
setString(verNumOfGen, "00");
setDate(creationDate);
/**
* TODO: current_time += (retentd * 86400); to check do we really need
* retend retention period in days which means a file may be overwritten only
* if it is expired. Default is 0, which means that the file may be
* overwritten immediately.
*/
setDate(expirationDate);
setString(sysCode, "CASTOR 7.7.77"); /* TODO: CASTOR BASEVERSION */
}
void Tape::AULFile::HDR1EOF1::verifyCommon()
const throw (Tape::Exceptions::Errnum) {
if (!cmpString(fileId, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the fileId: ") +
Tape::AULFile::toString(fileId));
if (!cmpString(VSN, ""))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the VSN: ") +
Tape::AULFile::toString(VSN));
if (cmpString(fSec, "0001"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the fSec: ") +
Tape::AULFile::toString(fSec));
if (!cmpString(fSeq, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the fSeq: ") +
Tape::AULFile::toString(fSeq));
if (cmpString(genNum, "0001"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the genNum: ") +
Tape::AULFile::toString(genNum));
if (cmpString(verNumOfGen, "00"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the verNumOfGen: ") +
Tape::AULFile::toString(verNumOfGen));
if (!cmpString(creationDate, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the creationDate: ") +
Tape::AULFile::toString(creationDate));
if (!cmpString(expirationDate, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the expirationDate: ") +
Tape::AULFile::toString(expirationDate));
if (cmpString(accessibility, ""))
throw Tape::Exceptions::Errnum("accessibility is not empty");
if (!cmpString(sysCode, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the sysCode: ") +
Tape::AULFile::toString(sysCode));
if (cmpString(reserved, ""))
throw Tape::Exceptions::Errnum("reserved is not empty");
}
void Tape::AULFile::HDR1::fill(
std::string _fileId,
std::string _VSN,
int _fSeq) {
setString(label, "HDR1");
setString(blockCount, "000000");
fillCommon(_fileId, _VSN, _fSeq);
}
void Tape::AULFile::HDR1::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "HDR1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the HDR1: ") +
Tape::AULFile::toString(label));
if (cmpString(blockCount, "000000"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the blockCount: ") +
Tape::AULFile::toString(blockCount));
verifyCommon();
}
void Tape::AULFile::HDR1PRELABEL::fill(std::string _VSN) {
setString(label, "HDR1");
setString(blockCount, "000000");
fillCommon(std::string("PRELABEL"), _VSN, 1);
}
void Tape::AULFile::HDR1PRELABEL::verify()
const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "HDR1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the HDR1: ") +
Tape::AULFile::toString(label));
if (cmpString(blockCount, "000000"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the blockCount: ") +
Tape::AULFile::toString(blockCount));
if (cmpString(fileId, "PRELABEL"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the PRELABEL: ") +
Tape::AULFile::toString(fileId));
verifyCommon();
}
void Tape::AULFile::EOF1::fill(
std::string _fileId, std::string _VSN, int _fSeq, int _blockCount) {
setString(label, "EOF1");
setInt(blockCount, _blockCount);
fillCommon(_fileId, _VSN, _fSeq);
}
void Tape::AULFile::EOF1::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "EOF1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the EOF1: ") +
Tape::AULFile::toString(label));
if (!cmpString(blockCount, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the blockCount: ") +
Tape::AULFile::toString(blockCount));
verifyCommon();
}
void Tape::AULFile::HDR2EOF2::fillCommon(int _blockLength, bool driveHasCompression) {
setString(recordFormat, "F");
if (_blockLength < 100000) {
setInt(blockLength, _blockLength);
setInt(recordLength, _blockLength);
} else {
setInt(blockLength, 0);
setInt(recordLength, 0);
}
if (driveHasCompression) setString(recTechnique,"P ");
setString(aulId, "00");
}
void Tape::AULFile::HDR2EOF2::verifyCommon()
const throw (Tape::Exceptions::Errnum) {
if (cmpString(recordFormat, "F"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the recordFormat: ") +
Tape::AULFile::toString(recordFormat));
if (!cmpString(blockLength, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the blockLength: ") +
Tape::AULFile::toString(blockLength));
if (!cmpString(recordLength, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the recordLength: ") +
Tape::AULFile::toString(recordLength));
if (cmpString(aulId, "00"))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the aulId: ") +
Tape::AULFile::toString(aulId));
if (cmpString(reserved1, ""))
throw Tape::Exceptions::Errnum("reserved1 is not empty");
if (cmpString(reserved2, ""))
throw Tape::Exceptions::Errnum("reserved2 is not empty");
if (cmpString(reserved3, ""))
throw Tape::Exceptions::Errnum("reserved2 is not empty");
}
void Tape::AULFile::HDR2::fill(int _blockLength, bool driveHasCompression) {
setString(label, "HDR2");
fillCommon(_blockLength, driveHasCompression);
}
void Tape::AULFile::HDR2::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "HDR2"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the HDR2: ") +
Tape::AULFile::toString(label));
verifyCommon();
}
void Tape::AULFile::EOF2::fill(int _blockLength, bool driveHasCompression) {
setString(label, "EOF2");
fillCommon(_blockLength, driveHasCompression);
}
void Tape::AULFile::EOF2::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "EOF2"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the EOF2: ") +
Tape::AULFile::toString(label));
verifyCommon();
}
void Tape::AULFile::UHL1UTL1::fillCommon(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo) {
setInt(actualfSeq, fSeq);
setInt(actualBlockSize, blockSize);
setInt(actualRecordLength, blockSize);
setString(site, siteName);
setString(moverHost, hostName);
setString(driveVendor, deviceInfo.vendor);
setString(driveModel, deviceInfo.product);
setString(serialNumber, deviceInfo.serialNumber);
}
void Tape::AULFile::UHL1UTL1::verifyCommon()
const throw (Tape::Exceptions::Errnum){
if (!cmpString(actualfSeq, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the actualfSeq: ") +
Tape::AULFile::toString(actualfSeq));
if (!cmpString(actualBlockSize, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the actualBlockSize: ") +
Tape::AULFile::toString(actualBlockSize));
if (!cmpString(actualRecordLength, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for the actualRecordLength: ") +
Tape::AULFile::toString(actualRecordLength));
if (!cmpString(site, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for site: ") +
Tape::AULFile::toString(site));
if (!cmpString(moverHost, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for moverHost: ") +
Tape::AULFile::toString(moverHost));
if (!cmpString(driveVendor, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for driveVendor: ") +
Tape::AULFile::toString(driveVendor));
if (!cmpString(driveModel, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for driveModel: ") +
Tape::AULFile::toString(driveModel));
if (!cmpString(serialNumber, ""))
throw Tape::Exceptions::Errnum(
std::string("Failed verify for serialNumber: ") +
Tape::AULFile::toString(serialNumber));
}
void Tape::AULFile::UHL1::fill(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo) {
setString(label, "UHL1");
fillCommon(fSeq, blockSize, siteName, hostName, deviceInfo);
}
void Tape::AULFile::UHL1::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "UHL1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the UHL1: ") +
Tape::AULFile::toString(label));
verifyCommon();
}
void Tape::AULFile::UTL1::fill(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo) {
setString(label, "UTL1");
fillCommon(fSeq, blockSize, siteName, hostName, deviceInfo);
}
void Tape::AULFile::UTL1::verify() const throw (Tape::Exceptions::Errnum) {
if (cmpString(label, "UTL1"))
throw Tape::Exceptions::Errnum(std::string("Failed verify for the UTL1: ") +
Tape::AULFile::toString(label));
verifyCommon();
}
......@@ -23,58 +23,374 @@
#pragma once
#include <string>
#include "string.h"
#include "../Drive/Drive.hh"
namespace Tape {
namespace AULFile {
/**
* Helper template to fill with space a structure.
* @param s pointer the struct/class.
*/
template <typename C>
void spaceStruct(C * s) {
memset (s, 0x20, sizeof(C));
memset(s, 0x20, sizeof (C));
}
template <size_t n>
/**
* Templated helper function to get std::string from the char array
* padded with spaces.
* Templated helper function to get std::string from the char array
* not terminated by '\0'.
*
* @param t array pointer to the char array.
* @return std::string for the char array
*/
std::string toString(char(& t)[n]) {
std::string toString(const char(& t)[n]) {
std::string r;
r.assign(t,n);
r.assign(t, n);
return r;
}
class VOL1 {
public:
VOL1() { spaceStruct(this);}
private:
char label[4]; // The characters VOL1.
char VSN[6]; // The Volume Serial Number.
char accessibility[1];// A space indicates that the volume is authorized.
char reserved1[13]; // Reserved.
char implID[13]; // The Implementation Identifier - spaces.
char ownerID[14]; // CASTOR or stagesuperuser name padded with spaces.
char reserved2[28]; // Reserved */
char lblStandart[1]; // The label standart level - ASCII 3 for the CASTOR
public:
VOL1() {
spaceStruct(this);
}
private:
char label[4]; // The characters VOL1.
char VSN[6]; // The Volume Serial Number.
char accessibility[1]; // A space indicates that the volume is authorized.
char reserved1[13]; // Reserved.
char implID[13]; // The Implementation Identifier - spaces.
char ownerID[14]; // CASTOR or stagesuperuser name padded with spaces.
char reserved2[28]; // Reserved
char lblStandard[1]; // The label standard level - ASCII 3 for the CASTOR
public:
/**
* Fills up all fields of the VOL1 structure with proper values and data provided.
* @param VSN the tape serial number
*/
void fill(std::string _VSN);
/**
* @return VSN the tape serial number
*/
inline std::string getVSN() {
return toString(VSN);
}
/**
* Throws an exception if the structure does not match expectations.
*/
void verify();
};
// The common part of the HDR1, EOF1 and PRELEBEL HDR1 labels
class HDR1EOF1 {
public:
HDR1EOF1() {
spaceStruct(this);
}
protected:
char label[4]; // The characters HDR1.
char fileId[17]; // The CASTOR NS file Id in ACSII hex or PRELABEL
char VSN[6]; // The Volume Serial Number.
char fSec[4]; // The file section number - '0001'.
char fSeq[4]; // The file sequence number is modulus by 10000.
char genNum[4]; // The generation number - '0001'.
char verNumOfGen[2]; // The version number of generation - '00'.
char creationDate[6]; // The creation date in cyyddd form.
char expirationDate[6];// The expiration date in cyyddd form.
char accessibility[1]; // The security status of the data set - space.
char blockCount[6]; // In the HDR1 is always '000000'.
char sysCode[13]; // The system ID code - 'CASTOR '+CASTORBASEVERSION
char reserved[7]; // Reserved
/**
* Fills up all common fields of the HDR1, EOF1 and PRELABEL HDR1
* structures with proper values and data provided.
*
* @param fileId The CASTOR NS file Id in ACSII hex.
* @param VSN The tape serial number.
* @param fSeq The file sequence number on the tape.
*/
void fillCommon(std::string _fileId, std::string _VSN, int _fSeq);
/**
* Throws an exception if the common field of the structures does
* not match expectations.
*/
void verifyCommon() const throw (Tape::Exceptions::Errnum);
public:
/**
* @return VSN the tape serial number
*/
inline std::string getVSN() {
return toString(VSN);
}
/**
* @return The CASTOR NS file Id
*/
inline std::string getFileId() {
return toString(fileId);
}
/**
* @return The file sequence number
*/
inline std::string getfSeq() {
return toString(fSeq);
}
/**
* @return The number of block written on tape per file
*/
inline std::string getBlockCount() {
return toString(blockCount);
}
};
class HDR1 : public HDR1EOF1 {
public:
/**
* Fills up only a few fields of the HDR1 structure with proper values
* and data provided.
*
* @param fileId The CASTOR NS file Id in ACSII hex.
* @param VSN The tape serial number.
* @param fSeq The file sequence number on the tape.
*/
void fill(std::string _fileId, std::string _VSN, int _fSeq);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
class EOF1 : public HDR1EOF1 {
public:
/**
* Fills up only a few fields of the EOF1 structure with proper values
* and data provided.
*
* @param fileId The CASTOR NS file Id in ACSII hex.
* @param VSN The tape serial number.
* @param fSeq The file sequence number on the tape.
* @param blockCount The number of written data blocks. It is
* modulus by 1000000.
*/
void fill(std::string _fileId,
std::string _VSN, int _fSeq, int _blockCount);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
class HDR1PRELABEL : public HDR1EOF1 {
public:
/**
* Fills up only a few fields of the HDR1 structure with proper values
* and data provided.
*
* @param VSN The tape serial number.
*/
void fill(std::string _VSN);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
// The common part of the HDR2 and EOF2 labels
class HDR2EOF2 {
public:
HDR2EOF2() {
spaceStruct(this);
}
protected:
char label[4]; // The characters HDR2.
char recordFormat[1]; // The record format is 'F' for the CASTOR AUL.
char blockLength[5]; // If it is greater than 100000 it set as '00000'.
char recordLength[5]; // If it is greater than 100000 it set as '00000'.
char tapeDensity[1]; // The tape density code. Not used or verified.
char reserved1[18]; // Reserved
char recTechnique[2]; // The tape recording technique. 'P ' for xxxGC
// drives (only on the real tapes on we do not see
// it with MHVTL setup).
char reserved2[14]; // Reserved
char aulId[2]; // CASTOR specific for the AUL format - '00'.
char reserved3[28]; // Reserved
/**
* Fills up all common fields of the HDR2 and EOF2 structures
* with proper values and data provided.
*
* @param blockLength The CASTOR block size.
* @param driveHasCompression The boolean to set If the drive is
* configured to use compression or not.
*/
void fillCommon(int blockLength, bool driveHasCompression);
/**
* Throws an exception if the structure does not match expectations.
*/
void verifyCommon() const throw (Tape::Exceptions::Errnum);
public:
/**
* @return The block length
*/
inline std::string getBlockLength() {
return toString(blockLength);
}
};
class HDR2 : public HDR2EOF2 {
public:
/**
* Fills up a few specific fields fields of the HDR2 structure
* with proper values and data provided.
*
* @param blockLength The CASTOR block size.
* @param driveHasCompression The boolean to set If the drive is
* configured to use compression or not.
* By default it si true.
*/
void fill(int blockLength, bool compression = true);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
class EOF2 : public HDR2EOF2 {
public:
/**
* Fills up only a few specific fields of the HDR2 structure
* with proper values and data provided.
*
* @param blockLength The CASTOR block size.
* @param driveHasCompression The boolean to set If the drive is
* configured to use compression or not.
* By default it si true.
*/
void fill(int blockLength, bool compression = true);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
// The common part of the UHL1 and UTL1 labels
class UHL1UTL1 {
public:
UHL1UTL1() {
spaceStruct(this);
}
protected:
char label[4]; // The characters UHL1.
char actualfSeq[10]; // The actual file sequence number.
char actualBlockSize[10]; // The actual block size.
char actualRecordLength[10];// The actual record length.
char site[8]; // The domain name uppercase without level 1.
char moverHost[10]; // The tape mover host name uppercase.
char driveVendor[8]; // The drive manufacturer.
char driveModel[8]; // The first 8 bytes from drive identification
char serialNumber[12]; // The drive serial number.
/**
* Fills up all common fields of the UHL1 and UTL1 structure with proper
* values and data provided.
*
* @param fSeq The file sequence number.
* @param blockSize The block size.
* @param siteName The domain name uppercase without level 1 (.ch)
* @param hostName The tape mover host name uppercase
* @param deviceInfo The structure with the tape drive information.
*/
void fillCommon(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo);
/**
* Throws an exception if the common part structure does
* not match expectations.
*/
void verifyCommon() const throw (Tape::Exceptions::Errnum);
public:
/**
* @return The block size
*/
inline std::string getBlockSize() {
return toString(actualBlockSize);
}
/**
* @return The file sequence number
*/
inline std::string getfSeq() {
return toString(actualfSeq);
}
};
class UHL1 : public UHL1UTL1 {
public:
/**
* Fills up only specific fields of the UHL1 structure with proper values
* and data provided.
*
* @param fSeq The file sequence number.
* @param blockSize The block size.
* @param siteName The domain name uppercase without level 1 (.ch)
* @param hostName The tape mover host name uppercase
* @param deviceInfo The structure with the tape drive information.
*/
void fill(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
class UTL1 : public UHL1UTL1 {
public:
/**
* Fills up only specific fields of the UTL1 structure with proper values
* and data provided.
*
* @param fSeq The file sequence number.
* @param blockSize The block size.
* @param siteName The domain name uppercase without level 1 (.ch)
* @param hostName The tape mover host name uppercase
* @param deviceInfo The structure with the tape drive information.
*/
void fill(int fSeq,
int blockSize,
std::string siteName,
std::string hostName,
Tape::deviceInfo deviceInfo);
/**
* Throws an exception if the structure does not match expectations.
*/
void verify() const throw (Tape::Exceptions::Errnum);
};
template <size_t n>
/**
* Templated helper function to set a space padded string into a
......@@ -83,19 +399,55 @@ namespace Tape {
void setString(char(& t)[n], const std::string & s) {
size_t written = s.copy(t, n);
if (written < n) {
memset(&t[written],' ', n - written);
memset(&t[written], ' ', n - written);
}
}
template <size_t n>
/**
* Templated helper function to set a '0' padded from left integer into a
* fixed sized field of a header structure. If the integer is bigger than
* char array modulus will be used.
*/
void setInt(char(& t)[n], const int i) {
char format[6]; // buffer big enough to handle any size
sprintf(format, "%%.%dd", (int) n);
char buf[n + 1];
long mod = 1;
for (unsigned int j = 0; j < n; j++) mod *= 10;
sprintf(buf, format, i % mod);
memcpy(t, buf, n);
}
template <size_t n>
/**
* Templated helper function to compare a string with space padded string.
*
* @return Returns an integer equal to zero if strings match
*/
int cmpString(char(& t)[n], const std::string & s) {
int cmpString(const char(& t)[n], const std::string & s) {
char forCmp[n];
setString(forCmp,s);
return strncmp(forCmp,t,n);
setString(forCmp, s);
return strncmp(forCmp, t, n);
}
/**
* Helper function to set a current date into a fixed sized field of a
* header structure. The date format is cyyddd, where:
* c = century (blank=19; 0=20; 1=21; etc.)
* yy= year (00-99) ddd = day (001-366)
*/
inline void setDate(char(& t)[6]) {
time_t current_time;
struct tm localTime;
time(&current_time);
localtime_r(&current_time, &localTime);
char bufDate[7];
sprintf(bufDate, "%c%.2d%.3d", localTime.tm_year / 100 ? '0' : ' ',
localTime.tm_year % 100, localTime.tm_yday + 1);
memcpy(t, bufDate, 6);
}
}
}
......@@ -25,21 +25,170 @@
#include "Structures.hh"
namespace UnitTests {
TEST(FILE_Structures, VOL1) {
Tape::AULFile::VOL1 vol1Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof(vol1Label));
/* test that verify throws exceptions */
ASSERT_EQ(80U, sizeof (vol1Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
vol1Label.verify();
});
});
vol1Label.fill("test");
ASSERT_NO_THROW({
vol1Label.verify();
});
ASSERT_EQ("test ",vol1Label.getVSN());
ASSERT_EQ("test ", vol1Label.getVSN());
}
TEST(FILE_Structures, HDR1) {
Tape::AULFile::HDR1 hdr1Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (hdr1Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
hdr1Label.verify();
});
hdr1Label.fill("AABBCC", "test", 12345);
ASSERT_NO_THROW({
hdr1Label.verify();
});
ASSERT_EQ("test ", hdr1Label.getVSN());
ASSERT_EQ("AABBCC ", hdr1Label.getFileId());
ASSERT_EQ("2345", hdr1Label.getfSeq());
}
TEST(FILE_Structures, HDR1PRELABEL) {
Tape::AULFile::HDR1PRELABEL hdr1Prelabel;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (hdr1Prelabel));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
hdr1Prelabel.verify();
});
hdr1Prelabel.fill("TEST");
ASSERT_NO_THROW({
hdr1Prelabel.verify();
});
ASSERT_EQ("TEST ", hdr1Prelabel.getVSN());
ASSERT_EQ("PRELABEL ", hdr1Prelabel.getFileId());
ASSERT_EQ("0001", hdr1Prelabel.getfSeq());
}
TEST(FILE_Structures, EOF1) {
Tape::AULFile::EOF1 eof1Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (eof1Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
eof1Label.verify();
});
eof1Label.fill("AABBCC", "test", 12345, 7654);
ASSERT_NO_THROW({
eof1Label.verify();
});
ASSERT_EQ("test ", eof1Label.getVSN());
ASSERT_EQ("AABBCC ", eof1Label.getFileId());
ASSERT_EQ("2345", eof1Label.getfSeq());
ASSERT_EQ("007654", eof1Label.getBlockCount());
}
TEST(FILE_Structures, HDR2) {
Tape::AULFile::HDR2 hdr2Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (hdr2Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
hdr2Label.verify();
});
hdr2Label.fill(262144);
ASSERT_NO_THROW({
hdr2Label.verify();
});
ASSERT_EQ("00000", hdr2Label.getBlockLength());
hdr2Label.fill(32760);
ASSERT_EQ("32760", hdr2Label.getBlockLength());
}
TEST(FILE_Structures, EOF2) {
Tape::AULFile::EOF2 eof2Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (eof2Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
eof2Label.verify();
});
eof2Label.fill(262144);
ASSERT_NO_THROW({
eof2Label.verify();
});
ASSERT_EQ("00000", eof2Label.getBlockLength());
eof2Label.fill(32760);
ASSERT_EQ("32760", eof2Label.getBlockLength());
}
TEST(FILE_Structures, UHL1) {
Tape::AULFile::UHL1 uhl1Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (uhl1Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
uhl1Label.verify();
});
Tape::deviceInfo deviceInfo;
deviceInfo.vendor = "TEST";
deviceInfo.serialNumber = "XXYYTEST";
deviceInfo.product = "TEST DRIVE";
uhl1Label.fill(12345, 262144,
std::string("CERN"), std::string("TESTMOVER"), deviceInfo);
ASSERT_NO_THROW({
uhl1Label.verify();
});
ASSERT_EQ("0000262144", uhl1Label.getBlockSize());
ASSERT_EQ("0000012345", uhl1Label.getfSeq());
}
TEST(FILE_Structures, UTL1) {
Tape::AULFile::UTL1 utl1Label;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U, sizeof (utl1Label));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
utl1Label.verify();
});
Tape::deviceInfo deviceInfo;
deviceInfo.vendor = "TEST";
deviceInfo.serialNumber = "XXYYTEST";
deviceInfo.product = "TEST DRIVE";
utl1Label.fill(12345, 262144,
std::string("CERN"), std::string("TESTMOVER"), deviceInfo);
ASSERT_NO_THROW({
utl1Label.verify();
});
ASSERT_EQ("0000262144", utl1Label.getBlockSize());
ASSERT_EQ("0000012345", utl1Label.getfSeq());
}
}
......@@ -142,7 +142,7 @@ namespace System {
int ioctlModSelect6(sg_io_hdr_t * sgio_h);
/**
* This function handles INQUIRY CDB and prepares the standart inquiry
* This function handles INQUIRY CDB and prepares the standard inquiry
* replay or the unit serial number vital product data replay.
*
* @param sgio_h The pointer to the sg_io_hdr_t structure with
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment