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
......@@ -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