Drive.hpp 12.3 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
 */
39
40
41
namespace castor {
namespace tape {
namespace drives {
42

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

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

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

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

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

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

Eric Cano's avatar
Eric Cano committed
98
  /**
99
100
101
102
103
104
   * 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
105
   */
Eric Cano's avatar
Eric Cano committed
106
  class DriveGeneric {
Eric Cano's avatar
Eric Cano committed
107
  public:
Eric Cano's avatar
Eric Cano committed
108
    DriveGeneric(SCSI::DeviceInfo di, System::virtualWrapper & sw);
109

110
    /* Operations to be used by the higher levels */
111

112
113
114
115
116
117
118
    /**
     * 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
119
    virtual compressionStats getCompression() throw (Exception) = 0;
120

121
122
123
124
125
    /**
     * 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.
     */
126
127
    virtual void clearCompressionStats() throw (Exception);

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

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

140
    /**
141
142
143
144
     * 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.
145
146
     * @param blockId The blockId, represented in local endianness.
     */
147
    virtual void positionToLogicalObject(uint32_t blockId) throw (Exception);
148

149
150
151
152
153
154
    /**
     * 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.
     */
155
156
    virtual positionInfo getPositionInfo() throw (Exception);

157
158
159
160
161
    /**
     * 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.
     */
162
163
    virtual std::vector<std::string> getTapeAlerts() throw (Exception);

164
    /**
165
166
167
168
169
170
171
172
173
174
175
     * 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.
176
     */
177
    virtual void setDensityAndCompression(unsigned char densityCode = 0,
178
179
            bool compression = true) throw (Exception);

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

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
214
215
     * 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
216
     */
217
218
219
220
    virtual tapeError getTapeError() throw (Exception) {
      throw Exception("Not implemented");
    }

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

229
230
    /**
     * Jump to end of media. This will use setSTFastMTEOM() to disable MT_ST_FAST_MTEOM.
Eric Cano's avatar
Eric Cano committed
231
232
233
234
     * (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.
235
236
     * TODO: synchronous? Timeout?
     */
237
    virtual void fastSpaceToEOM(void) throw (Exception);
238

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

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

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

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

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

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

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

Eric Cano's avatar
Eric Cano committed
279
280
281
282
    /**
     * 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.
     */
283
    virtual void sync(void) throw (Exception);
284

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

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

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

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

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

    void SCSI_inquiry();
Eric Cano's avatar
Eric Cano committed
319
320
321
    
    /**
     */
322
  protected:
Eric Cano's avatar
Eric Cano committed
323
    SCSI::DeviceInfo m_SCSIInfo;
324
    int m_tapeFD; 
325
    castor::tape::System::virtualWrapper & m_sysWrapper;
Eric Cano's avatar
Eric Cano committed
326
    struct mtget m_mtInfo;
327
  private:
328
329
330
331
332
333
334
    /**
     * 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);
335
    void SCSI_inquiry(int fd);
Eric Cano's avatar
Eric Cano committed
336
  };
337

Eric Cano's avatar
Eric Cano committed
338
  class DriveT10000 : public DriveGeneric {
339
  public:
340

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

    virtual compressionStats getCompression() throw (Exception);
345
  };
346

Eric Cano's avatar
Eric Cano committed
347
  class DriveLTO : public DriveGeneric {
348
349
  public:

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

    virtual compressionStats getCompression() throw (Exception);
354
  };
355

Eric Cano's avatar
Eric Cano committed
356
  class DriveIBM3592 : public DriveGeneric {
357
  public:
358

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

    virtual compressionStats getCompression() throw (Exception);
  };
Eric Cano's avatar
Eric Cano committed
364
365
366
367
368
369
370
371
372
373
374
  
  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 {
375
        throw Exception(std::string("Unsupported drive type: ")+di.product);
Eric Cano's avatar
Eric Cano committed
376
377
378
379
380
381
382
383
384
385
386
387
      }
    }
    ~Drive() {
      delete m_drive;
    }
    operator DriveGeneric &() {
      return *m_drive;
    }
  private:
    DriveGeneric * m_drive;
  };
  
388
389
390
} // namespace drives
} // namespace tape
} // namespace castor