Drive.hpp 12.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/******************************************************************************
 *                      Drive.hpp
 *
 * This file is part of the Castor project.
 * See http://castor.web.cern.ch/castor
 *
 * Copyright (C) 2003  CERN
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * 
 *
 * @author Castor Dev team, castor-dev@cern.ch
 *****************************************************************************/
24

Eric Cano's avatar
Eric Cano committed
25
26
#pragma once

27
28
29
30
31
#include "../SCSI/Device.hpp"
#include "../SCSI/Structures.hpp"
#include "../SCSI/Exception.hpp"
#include "../System/Wrapper.hpp"
#include "../Exception/Exception.hpp"
32

33
#include "mtio_add.hpp"
34

35
/**
Eric Cano's avatar
Eric Cano committed
36
37
 * Class wrapping the tape server. Has to be templated (and hence fully in .hh)
 * to allow unit testing against system wrapper.
38
 */
Eric Cano's avatar
Eric Cano committed
39
namespace Tape {
40

41
42
43
  /**
   * Compressions statistics container, returned by Drive::getCompression()
   */
44
  class compressionStats {
45
  public:
46
47
48
49

    compressionStats() :
    fromHost(0), fromTape(0), toHost(0), toTape(0) {
    }
50
51
52
53
54
    uint64_t fromHost;
    uint64_t fromTape;
    uint64_t toHost;
    uint64_t toTape;
  };
55

56
57
58
  /**
   * Device information, returned by getDeviceInfo()
   */
59
  class deviceInfo {
60
61
62
63
  public:
    std::string vendor;
    std::string product;
    std::string productRevisionLevel;
64
    std::string serialNumber;
65
  };
66

67
68
69
70
71
72
  /**
   * Position info, returning both the logical position and the 
   * buffer writing status.
   * Returned by getPositionInfo()
   */
  class positionInfo {
73
  public:
74
75
76
77
78
    uint32_t currentPosition;
    uint32_t oldestDirtyObject;
    uint32_t dirtyObjectsCount;
    uint32_t dirtyBytesCount;
  };
79

80
  /**
81
   * 
82
83
84
85
86
87
88
89
   */
  class driveStatus {
    bool ready;
    bool writeProtection;
    /* TODO: Error condition */
    bool eod;
    bool bot;
  };
90

91
92
93
94
  class tapeError {
    std::string error;
    /* TODO: error code. See gettperror and get_sk_msg in CAStor */
  };
95

Eric Cano's avatar
Eric Cano committed
96
  /**
97
98
99
100
101
102
   * Class abstracting the tape drives. This class is templated to allow the use
   * of unrelated test harness and real system. The test harness is made up of 
   * a classes with virtual tables, but the real system wrapper has the real
   * system call directly into inline functions. This allows testing on a "fake"
   * system without paying performance price when calling system calls in the 
   * production system.
Eric Cano's avatar
Eric Cano committed
103
   */
Eric Cano's avatar
Eric Cano committed
104
  class DriveGeneric {
Eric Cano's avatar
Eric Cano committed
105
  public:
Eric Cano's avatar
Eric Cano committed
106
    DriveGeneric(SCSI::DeviceInfo di, System::virtualWrapper & sw);
107

108
    /* Operations to be used by the higher levels */
109

110
111
112
113
114
115
116
    /**
     * Return comulative log counter values from the log pages related to
     * the drive statistics about data movements to/from the tape. 
     * Data fields fromHost, toDrive are related to the write operation and
     * fields toHost, fromDrive are related to the read operation.
     * @return compressionStats
     */
Eric Cano's avatar
Eric Cano committed
117
    virtual compressionStats getCompression() throw (Exception) = 0;
118

119
120
121
122
123
    /**
     * Reset all statistics about data movements on the drive.
     * All comulative and threshold log counter values will be reset to their
     * default values as specified in that pages reset behavior section.
     */
124
125
    virtual void clearCompressionStats() throw (Exception);

126
127
    /**
     * Information about the drive. The vendor id is used in the user labels of the files.
128
     * @return    The deviceInfo structure with the information about the drive.
129
     */
130
131
    virtual deviceInfo getDeviceInfo() throw (Exception);

132
133
134
135
    /**
     * Information about the serial number of the drive. 
     * @return   Right-aligned ASCII data for the vendor-assigned serial number.
     */
136
137
    virtual std::string getSerialNumber() throw (Exception);

138
    /**
139
140
141
142
     * Position to logical object identifier (i.e. block address). 
     * This function is blocking: the immediate bit is not set.
     * The device server will not return status until the locate operation
     * has completed.
143
144
     * @param blockId The blockId, represented in local endianness.
     */
145
    virtual void positionToLogicalObject(uint32_t blockId) throw (Exception);
146

147
148
149
150
151
152
    /**
     * Return logical position of the drive. This is the address of the next object
     * to read or write.
     * @return positionInfo class. This contains the logical position, plus information
     * on the dirty data still in the write buffer.
     */
153
154
    virtual positionInfo getPositionInfo() throw (Exception);

155
156
157
158
159
    /**
     * Get tape alert information from the drive. There is a quite long list of possible tape alerts.
     * They are described in SSC-4, section 4.2.20: TapeAlert application client interface
     * @return list of tape alerts descriptions. They are simply used for logging.
     */
160
161
    virtual std::vector<std::string> getTapeAlerts() throw (Exception);

162
    /**
163
164
165
166
167
168
169
170
171
172
173
     * Set the tape density and compression. 
     * We use MODE SENSE/SELECT Device Configuration (10h) mode page.
     * As soon as there is no definition in SPC-4 or SSC-3 it depends on the 
     * drives documentation. 
     * 
     * @param densityCode  The tape specific density code.
     *                     If it is 0 (default) than we use the density code 
     *                     detected by the drive itself means no changes.
     *                                
     * @param compression  The boolean variable to enable or disable compression
     *                     on the drive for the tape. By default it is enabled.
174
     */
175
    virtual void setDensityAndCompression(unsigned char densityCode = 0,
176
177
            bool compression = true) throw (Exception);

178
179
180
181
    /**
     * Get drive status.
     * @return structure containing various booleans, and error conditions.
     */
182
183
184
185
    virtual driveStatus getDriveStatus() throw (Exception) {
      throw Exception("Not implemented");
    }

186
    /**
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
     * getTapeError: get SENSE buffer from patched version of the driver
     * or fall back to other information and report tape statuses.
     * Statuses were in CAStor struct sk_info sk_codmsg[] = { 
     * 	{"No sense", ETNOSNS},
     *  {"Recovered error", 0},
     *  {"Not ready", 0},
     *  {"Medium error", ETPARIT},
     *  {"Hardware error", ETHWERR},
     *  {"Illegal request", ETHWERR},
     *  {"Unit attention", ETHWERR},
     *  {"Data protect", 0},
     *  {"Blank check", ETBLANK},
     *  {"Vendor unique", 0},
     *  {"Copy aborted", 0},
     *  {"Aborted command", 0},
     *  {"Equal", 0},
     *  {"Volume overflow", ENOSPC},
     *  {"Miscompare", 0},
     *  {"Reserved", 0},
     *  {"SCSI handshake failure", ETHWERR},
     *  {"Timeout", ETHWERR},
     *  {"EOF hit", 0},
     *  {"EOT hit", ETBLANK},
     *  {"Length error", ETCOMPA},
     *  {"BOT hit", ETUNREC},
     *  {"Wrong tape media", ETCOMPA}
     * @return error code and string containing the error description
214
     */
215
216
217
218
    virtual tapeError getTapeError() throw (Exception) {
      throw Exception("Not implemented");
    }

219
    /**
220
     * Set the buffer write switch in the st driver. This is directly matching a configuration
221
     * parameter in CASTOR, so this function has to be public and usable by a higher level
222
223
     * layer, unless the parameter turns out to be disused.
     * @param bufWrite: value of the buffer write switch
224
     */
225
226
    virtual void setSTBufferWrite(bool bufWrite) throw (Exception);

227
228
    /**
     * Jump to end of media. This will use setSTFastMTEOM() to disable MT_ST_FAST_MTEOM.
Eric Cano's avatar
Eric Cano committed
229
230
231
232
     * (See TapeServer's handbook for details). This is used to rebuild the MIR (StorageTek)
     * or tape directory (IBM).
     * Tape directory rebuild is described only for IBM but currently applied to 
     * all tape drives.
233
234
     * TODO: synchronous? Timeout?
     */
235
    virtual void fastSpaceToEOM(void) throw (Exception);
236

237
    /**
Eric Cano's avatar
Eric Cano committed
238
     * Rewind tape.
239
     */
240
    virtual void rewind(void) throw (Exception);
241

Eric Cano's avatar
Eric Cano committed
242
243
244
245
    /**
     * Jump to end of data. EOM in ST driver jargon, end of data (which is more accurate)
     * in SCSI terminology).
     */
246
    virtual void spaceToEOM(void) throw (Exception);
247

Eric Cano's avatar
Eric Cano committed
248
    /**
249
     * Space count file marks backwards.
Eric Cano's avatar
Eric Cano committed
250
251
     * @param count
     */
252
    virtual void spaceFileMarksBackwards(size_t count) throw (Exception);
253

Eric Cano's avatar
Eric Cano committed
254
    /**
255
     * Space count file marks forward.
Eric Cano's avatar
Eric Cano committed
256
257
     * @param count
     */
258
    virtual void spaceFileMarksForward(size_t count) throw (Exception);
259

Eric Cano's avatar
Eric Cano committed
260
261
262
263
    /**
     * Space count blocks backwards.
     * @param count
     */
264
    virtual void spaceBlocksBackwards(size_t count) throw (Exception);
265

Eric Cano's avatar
Eric Cano committed
266
267
268
269
    /**
     * Space count blocks forward.
     * @param count
     */
270
    virtual void spaceBlocksForward(size_t count) throw (Exception);
271

Eric Cano's avatar
Eric Cano committed
272
273
274
    /**
     * Unload the tape.
     */
275
    virtual void unloadTape(void) throw (Exception);
276

Eric Cano's avatar
Eric Cano committed
277
278
279
280
    /**
     * Synch call to the tape drive. This function will not return before the 
     * data in the drive's buffer is actually comitted to the medium.
     */
281
    virtual void sync(void) throw (Exception);
282

Eric Cano's avatar
Eric Cano committed
283
284
285
286
287
    /**
     * Write count file marks. The function does not return before the file marks 
     * are committed to medium.
     * @param count
     */
288
    virtual void writeSyncFileMarks(size_t count) throw (Exception);
289

Eric Cano's avatar
Eric Cano committed
290
291
292
293
294
    /**
     * Write count file marks asynchronously. The file marks are just added to the drive's
     * buffer and the function return immediately.
     * @param count
     */
295
    virtual void writeImmediateFileMarks(size_t count) throw (Exception);
Eric Cano's avatar
Eric Cano committed
296
297
298
299
300
301

    /**
     * Write a data block to tape.
     * @param data pointer the the data block
     * @param count size of the data block
     */
302
    virtual void writeBlock(const unsigned char * data, size_t count) throw (Exception);
303

Eric Cano's avatar
Eric Cano committed
304
305
306
307
308
    /**
     * Read a data block from tape.
     * @param data pointer the the data block
     * @param count size of the data block
     */
309
    virtual void readBlock(unsigned char * data, size_t count) throw (Exception);
310

Eric Cano's avatar
Eric Cano committed
311
    virtual ~DriveGeneric() {
312
      if (-1 != m_tapeFD)
313
        m_sysWrapper.close(m_tapeFD);      
Eric Cano's avatar
Eric Cano committed
314
    }
315
316

    void SCSI_inquiry();
Eric Cano's avatar
Eric Cano committed
317
318
319
    
    /**
     */
320
  protected:
Eric Cano's avatar
Eric Cano committed
321
    SCSI::DeviceInfo m_SCSIInfo;
322
    int m_tapeFD; 
323
    Tape::System::virtualWrapper & m_sysWrapper;
Eric Cano's avatar
Eric Cano committed
324
    struct mtget m_mtInfo;
325
  private:
326
327
328
329
330
331
332
    /**
     * Set the MTFastEOM option of the ST driver. This function is used only internally in 
     * mounttape (in CAStor), so it could be a private function, not visible to 
     * the higher levels of the software (TODO: protected?).
     * @param fastMTEOM the option switch.
     */
    virtual void setSTFastMTEOM(bool fastMTEOM) throw (Exception);
333
    void SCSI_inquiry(int fd);
Eric Cano's avatar
Eric Cano committed
334
  };
335

Eric Cano's avatar
Eric Cano committed
336
  class DriveT10000 : public DriveGeneric {
337
  public:
338

Eric Cano's avatar
Eric Cano committed
339
    DriveT10000(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
340
    }
341
342

    virtual compressionStats getCompression() throw (Exception);
343
  };
344

Eric Cano's avatar
Eric Cano committed
345
  class DriveLTO : public DriveGeneric {
346
347
  public:

Eric Cano's avatar
Eric Cano committed
348
    DriveLTO(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
349
    }
350
351

    virtual compressionStats getCompression() throw (Exception);
352
  };
353

Eric Cano's avatar
Eric Cano committed
354
  class DriveIBM3592 : public DriveGeneric {
355
  public:
356

Eric Cano's avatar
Eric Cano committed
357
    DriveIBM3592(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
358
    }
359
360
361

    virtual compressionStats getCompression() throw (Exception);
  };
Eric Cano's avatar
Eric Cano committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  
  class Drive {
  public:
    Drive(SCSI::DeviceInfo di, System::virtualWrapper & sw): m_drive(NULL) {
      if (di.product.find("T10000")) {
        m_drive = new DriveT10000(di, sw);
      } else if (di.product.find("ULT" || di.product.find("Ultrium"))) {
        m_drive = new DriveLTO(di, sw);
      } else if (di.product.find("03592")) {
        m_drive = new DriveIBM3592(di, sw);
      } else {
        throw Tape::Exception(std::string("Unsupported drive type: ")+di.product);
      }
    }
    ~Drive() {
      delete m_drive;
    }
    operator DriveGeneric &() {
      return *m_drive;
    }
  private:
    DriveGeneric * m_drive;
  };
  
Eric Cano's avatar
Eric Cano committed
386
}