TapeSingleThreadInterface.hpp 7.24 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
/****************************************************************************** 
 *
 * 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
 *****************************************************************************/
23
24
25
26
27
28
/* 
 * Author: dcome
 *
 * Created on March 18, 2014, 4:28 PM
 */

29
#pragma once
30

31
32
#include "castor/legacymsg/RmcProxy.hpp"
#include "castor/log/LogContext.hpp"
33
#include "castor/server/ProcessCap.hpp"
34
35
#include "castor/server/Threading.hpp"
#include "castor/server/BlockingQueue.hpp"
36
#include "castor/tape/tapeserver/drive/DriveInterface.hpp"
37
#include "castor/tape/tapeserver/client/ClientInterface.hpp"
38
#include "castor/tape/utils/Timer.hpp"
39
#include "castor/tape/tapeserver/daemon/TapeSessionStats.hpp"
40

41
42
namespace castor     {
namespace tape       {
43
namespace tapeserver {
44
45
namespace daemon     {

46
  // Forward declaration
David COME's avatar
David COME committed
47
  class TapeServerReporter;
48
49
50
51
52
  /** 
   * This class is the base class for the 2 classes that will be executing 
   * all tape-{read|write} tasks. The template parameter Task is the type of 
   * task we are expecting : TapeReadTask or TapeWriteTask
   */
53
template <class Task>
54
class TapeSingleThreadInterface : private castor::server::Thread
55
{
56
private :
57
58
59
  /**
   * Utility to change the capabilities of the current tape thread
   */
60
  castor::server::ProcessCap &m_capUtils;
61
protected:
62
  ///the queue of tasks 
63
  castor::server::BlockingQueue<Task *> m_tasks;
64
65
66
67
68
  
  /**
   * An interface to manipulate the drive to manipulate the tape
   * with the requested vid 
   */
69
  castor::tape::tapeserver::drives::DriveInterface & m_drive;
70
  
71
  /** Reference to the mount interface */
72
73
  castor::legacymsg::RmcProxy & m_rmc;
  
74
  /** Reference to the Global reporting interface */
75
  TapeServerReporter & m_initialProcess;
76
  
77
78
79
80
  ///The volumeID of the tape on which we want to operate  
  const std::string m_vid;

  ///log context, for ... logging purpose, copied du to thread mechanism 
81
  castor::log::LogContext m_logContext;
82
83
  
  client::ClientInterface::VolumeInfo m_volInfo;
84
85
  
  /**
Eric Cano's avatar
WIP    
Eric Cano committed
86
87
88
   * Integer to notify the tapeserver if the drive has to be put down or not.
   * 0 means everything all right, any other value means we have to set it to 
   * down at the end of the session.
89
90
   */
  int m_hardarwareStatus;
Eric Cano's avatar
WIP    
Eric Cano committed
91
92
  
  /** Session statistics */
93
  TapeSessionStats m_stats;
94
 
95
96
97
98
  /**
   * This function will try to set the cap_sys_rawio capability that is needed
   * for by tape thread to access /dev/nst
   */
99
100
  void setCapabilities(){
    try {
101
      m_capUtils.setProcText("cap_sys_rawio+ep");
102
      log::LogContext::ScopedParam sp(m_logContext,
103
        log::Param("capabilities", m_capUtils.getProcText()));
104
105
106
      m_logContext.log(LOG_INFO, "Set process capabilities for using tape");
    } catch(const castor::exception::Exception &ne) {
      m_logContext.log(LOG_ERR,
107
        "Failed to set process capabilities for using the tape ");
108
109
    }
  }
110
  
Eric Cano's avatar
WIP    
Eric Cano committed
111
  /**
112
113
114
115
116
117
118
119
120
121
122
   * Try to mount the tape, get an exception if it fails 
   */
  void mountTape(castor::legacymsg::RmcProxy::MountMode mode){
    castor::log::ScopedParamContainer scoped(m_logContext); 
    scoped.add("vid",m_volInfo.vid)
          .add("drive_Slot",m_drive.librarySlot);
    try {
      tape::utils::Timer timer;
        m_rmc.mountTape(m_volInfo.vid, m_drive.librarySlot,
                mode);
        const std::string modeAsString = std::string("R")+ ((mode==legacymsg::RmcProxy::MOUNT_MODE_READWRITE) ? "W" : "");
123
        scoped.add("RMCMountTime",timer.secs()).add("mode",modeAsString);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
        m_logContext.log(LOG_INFO, "Tape Mounted");
        
    }
    catch (castor::exception::Exception & ex) {
      scoped.add("exception_message", ex.getMessageValue())
            .add("exception_code",ex.code());
      m_logContext.log(LOG_ERR, "Failed to mount the tape");
      throw;
    }
  }
  
  /**
   * After mounting the tape, the drive will say it has no tape inside,
   * because there was no tape the first time it was opened... 
   * That function will wait a certain amount of time for the drive 
   * to tell us he acknowledge it has indeed a tap (get an ex exception in 
   * case of timeout)
   */
  void waitForDrive(){
    try{
      tape::utils::Timer timer;
      // wait 600 drive is ready
      m_drive.waitUntilReady(600);
147
      log::LogContext::ScopedParam sp0(m_logContext, log::Param("loadTime", timer.secs()));
148
149
150
    }catch(const castor::exception::Exception& e){
      log::LogContext::ScopedParam sp01(m_logContext, log::Param("exception_code", e.code()));
      log::LogContext::ScopedParam sp02(m_logContext, log::Param("exception_message", e.getMessageValue()));
151
      m_logContext.log(LOG_INFO, "Got timeout or error while waiting for drive to be ready.");
152
153
154
      throw;
    }
  }
155
public:
156
157
158
159
  
  int getHardwareStatus() const {
    return m_hardarwareStatus;
  }
160
161
162
  /**
   * Push into the class a sentinel value to trigger to end the the thread.
   */
163
  void finish() { m_tasks.push(NULL); }
164
165
166
167
168
  
  /**
   * Push a new task into the internal queue
   * @param t the task to push
   */
169
170
  void push(Task * t) { m_tasks.push(t); }
  
171
172
173
  /**
   * Start the threads
   */
174
175
  virtual void startThreads(){ start(); }
  
176
177
178
  /**
   *  Wait for the thread to finish
   */
Eric Cano's avatar
WIP    
Eric Cano committed
179
180
181
182
183
184
185
186
187
188
189
190
191
  virtual void waitThreads() { wait(); }
  
  /**
   * Allows to pre-set the time spent waiting for instructions, spent before
   * the tape thread is started. This is for timing the synchronous task 
   * injection done before session startup.
   * This function MUST be called before starting the thread.
   * @param secs time in seconds (double)
   */
  virtual void setWaitForInstructionsTime(double secs) { 
    m_stats.waitInstructionsTime = secs; 
  }

192
193
194
195
  /**
   * Constructor
   * @param drive An interface to manipulate the drive to manipulate the tape
   * with the requested vid
196
197
198
199
200
   * @param rmc The media changer (=robot) that will (un)load/(un)mount the tape
   * @param gsr
   * @param volInfo All we need to know about the tape we are manipulating 
   * @param capUtils
   * @param lc lc The log context, later on copied
201
   */
202
  TapeSingleThreadInterface(castor::tape::tapeserver::drives::DriveInterface & drive,
203
    castor::legacymsg::RmcProxy & rmc,
204
    TapeServerReporter & tsr,
205
    const client::ClientInterface::VolumeInfo& volInfo,
206
    castor::server::ProcessCap &capUtils,castor::log::LogContext & lc):m_capUtils(capUtils),
207
    m_drive(drive), m_rmc(rmc), m_initialProcess(tsr), m_vid(volInfo.vid), m_logContext(lc),
Eric Cano's avatar
WIP    
Eric Cano committed
208
    m_volInfo(volInfo),m_hardarwareStatus(0) {}
209
}; // class TapeSingleThreadInterface
210

211
212
213
214
} // namespace daemon
} // namespace tapeserver
} // namespace tape
} // namespace castor
215