Catalogue.cpp 12 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/******************************************************************************
 *
 * 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.
 *
 *
 *
21
 * @author Castor Dev team, castor-dev@cern.ch
22
23
 *****************************************************************************/

24
#include "castor/tape/tapeserver/daemon/Catalogue.hpp"
25
#include "castor/tape/tapeserver/daemon/Constants.hpp"
26
#include "castor/utils/utils.hpp"
27
28

#include <string.h>
Daniele Kruse's avatar
Daniele Kruse committed
29
#include <time.h>
30

31
32
33
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
34
castor::tape::tapeserver::daemon::Catalogue::Catalogue(
35
  const int netTimeout,
36
37
  log::Logger &log,
  ProcessForkerProxy &processForker,
38
  legacymsg::CupvProxy &cupv,
39
  legacymsg::VdqmProxy &vdqm,
40
  legacymsg::VmgrProxy &vmgr,
41
  const std::string &hostName,
42
43
  const CatalogueConfig &catalogueConfig,
  System::virtualWrapper &sysWrapper):
44
  m_netTimeout(netTimeout),
45
46
  m_log(log),
  m_processForker(processForker),
47
  m_cupv(cupv),
48
  m_vdqm(vdqm),
49
  m_vmgr(vmgr),
50
  m_hostName(hostName),
51
52
  m_catalogueConfig(catalogueConfig),
  m_sysWrapper(sysWrapper) {
53
54
}

55
56
57
//-----------------------------------------------------------------------------
// destructor
//-----------------------------------------------------------------------------
58
castor::tape::tapeserver::daemon::Catalogue::~Catalogue() throw() {
59
60
61
  // Close any label-command connections that are still owned by the
  // tape-drive catalogue
  for(DriveMap::const_iterator itor = m_drives.begin(); itor != m_drives.end();
62
63
    itor++) {
    const CatalogueDrive *const drive = itor->second;
64

Daniele Kruse's avatar
Daniele Kruse committed
65
    delete drive;
Steven Murray's avatar
Steven Murray committed
66
67
68
  }
}

69
//-----------------------------------------------------------------------------
70
// handleTick
71
//-----------------------------------------------------------------------------
72
bool castor::tape::tapeserver::daemon::Catalogue::handleTick() {
73
74
75
  for(DriveMap::const_iterator itor = m_drives.begin(); itor != m_drives.end();
    itor++) {
    CatalogueDrive *const drive = itor->second;
76
77
78
79

    if(!drive->handleTick()) {
      return false; // Do not continue the main event loop
    }
80
  }
81
82

  return true; // Continue the main event loop
83
84
}

85
86
87
88
89
90
//------------------------------------------------------------------------------
// allDrivesAreShutdown
//------------------------------------------------------------------------------
bool castor::tape::tapeserver::daemon::Catalogue::allDrivesAreShutdown()
  const throw() {
  try {
91
92
    for(DriveMap::const_iterator itor = m_drives.begin();
      itor != m_drives.end(); itor++) {
93
      CatalogueDrive *const drive = itor->second;
94
      if(DRIVE_STATE_SHUTDOWN != drive->getState()) {
95
96
97
98
99
100
101
102
103
        return false;
      }
    }
    return true;
  } catch(...) {
    return false;
  }
}

104
//-----------------------------------------------------------------------------
105
// populate
106
//-----------------------------------------------------------------------------
107
void castor::tape::tapeserver::daemon::Catalogue::populate(
108
  const DriveConfigMap &driveConfigs)  {
109
  try {
110
    for(DriveConfigMap::const_iterator itor = driveConfigs.begin();
111
112
      itor != driveConfigs.end(); itor++) {
      const std::string &unitName = itor->first;
113
      const DriveConfig &driveConfig = itor->second;
114
115

      // Sanity check
116
      if(unitName != driveConfig.getUnitName()) {
117
118
119
        // This should never happen
        castor::exception::Exception ex;
        ex.getMessage() << "Unit name mismatch: expected=" << unitName <<
120
          " actual=" << driveConfig.getUnitName();
121
122
123
124
125
126
127
128
129
        throw ex;
      }
      enterDriveConfig(driveConfig);
    }
  } catch(castor::exception::Exception &ne) {
    castor::exception::Exception ex;
    ex.getMessage() << "Failed to populate tape-drive catalogue: " <<
      ne.getMessage().str();
    throw ex;
130
131
132
133
  }
}

//-----------------------------------------------------------------------------
134
// enterDriveConfig
135
//-----------------------------------------------------------------------------
136
void castor::tape::tapeserver::daemon::Catalogue::enterDriveConfig(
137
  const DriveConfig &driveConfig)  {
138

139
  DriveMap::iterator itor = m_drives.find(driveConfig.getUnitName());
140
141
142
143

  // If the drive is not in the catalogue
  if(m_drives.end() == itor) {
    // Insert it
144
    m_drives[driveConfig.getUnitName()] = new CatalogueDrive(m_netTimeout,
145
      m_log, m_processForker, m_cupv, m_vdqm, m_vmgr, m_hostName, driveConfig,
146
      DRIVE_STATE_DOWN, m_catalogueConfig, m_sysWrapper);
147
148
  // Else the drive is already in the catalogue
  } else {
149
    castor::exception::Exception ex;
150
151
    ex.getMessage() <<
      "Failed to enter tape-drive configuration into tape-drive catalogue"
152
      ": Duplicate drive-entry: unitName=" << driveConfig.getUnitName();
153
154
155
156
    throw ex;
  }
}

157
158
159
//-----------------------------------------------------------------------------
// getUnitNames
//-----------------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
160
std::list<std::string>
161
  castor::tape::tapeserver::daemon::Catalogue::getUnitNames() const  {
162
163
164
165
166
167
168
169
170
171
  std::list<std::string> unitNames;

  for(DriveMap::const_iterator itor = m_drives.begin();
    itor != m_drives.end(); itor++) {
    unitNames.push_back(itor->first);
  }

  return unitNames;
}

172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//-----------------------------------------------------------------------------
// shutdown
//-----------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::Catalogue::shutdown() {
  // Request sessions to shutdown
  for(DriveMap::iterator itor = m_drives.begin();
    itor != m_drives.end(); itor++) {
    CatalogueDrive *const drive = itor->second;
    try {
      drive->shutdown();
    } catch(castor::exception::Exception &ex) {
      log::Param params[] = {log::Param("message", ex.getMessage().str())};
      m_log(LOG_ERR, "Failed to shutdown session", params);
    }
  }
}

189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//-----------------------------------------------------------------------------
// killSessions
//-----------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::Catalogue::killSessions() {
  for(DriveMap::iterator itor = m_drives.begin();
    itor != m_drives.end(); itor++) {
    CatalogueDrive *const drive = itor->second;
    try {
      drive->killSession();
    } catch(castor::exception::Exception &ex) {
      log::Param params[] = {log::Param("message", ex.getMessage().str())};
      m_log(LOG_ERR, "Failed to kill session", params);
    }
  }
}

Daniele Kruse's avatar
Daniele Kruse committed
205
//-----------------------------------------------------------------------------
206
// findDrive
Daniele Kruse's avatar
Daniele Kruse committed
207
//-----------------------------------------------------------------------------
208
209
const castor::tape::tapeserver::daemon::CatalogueDrive
  &castor::tape::tapeserver::daemon::Catalogue::findDrive(
210
211
212
    const std::string &unitName) const {
  std::ostringstream task;
  task << "find tape drive in catalogue by unit name: unitName=" << unitName;
Daniele Kruse's avatar
Daniele Kruse committed
213

214
215
216
217
218
  DriveMap::const_iterator itor = m_drives.find(unitName);
  if(m_drives.end() == itor) {
    castor::exception::Exception ex;
    ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
    throw ex;
Daniele Kruse's avatar
Daniele Kruse committed
219
220
  }

221
222
223
224
225
226
  if(NULL == itor->second) {
    // Should never get here
    castor::exception::Exception ex;
    ex.getMessage() << "Failed to " << task <<
      ": Pointer to drive entry is unexpectedly NULL";
    throw ex;
Daniele Kruse's avatar
Daniele Kruse committed
227
228
  }

229
  const CatalogueDrive &drive = *(itor->second);
230
  const DriveConfig &driveConfig = drive.getConfig();
231

232
  // Sanity check
233
  if(unitName != driveConfig.getUnitName()) {
234
235
236
237
    // Should never get here
    castor::exception::Exception ex;
    ex.getMessage() << "Failed to " << task <<
      ": Found inconsistent entry in tape-drive catalogue"
238
      ": Unit name mismatch: actual=" << driveConfig.getUnitName();
239
    throw ex;
240
241
  }

242
  return drive;
243
244
}

245
//-----------------------------------------------------------------------------
246
// findDrive
Steven Murray's avatar
Steven Murray committed
247
//-----------------------------------------------------------------------------
248
249
castor::tape::tapeserver::daemon::CatalogueDrive
  &castor::tape::tapeserver::daemon::Catalogue::findDrive(
250
251
252
  const std::string &unitName) {
  std::ostringstream task;
  task << "find tape drive in catalogue by unit name: unitName=" << unitName;
Steven Murray's avatar
Steven Murray committed
253

254
  DriveMap::iterator itor = m_drives.find(unitName);
Steven Murray's avatar
Steven Murray committed
255
256
  if(m_drives.end() == itor) {
    castor::exception::Exception ex;
257
258
259
260
261
262
263
264
265
    ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
    throw ex;
  }

  if(NULL == itor->second) {
    // Should never get here
    castor::exception::Exception ex;
    ex.getMessage() << "Failed to " << task <<
      ": Pointer to drive entry is unexpectedly NULL";
Steven Murray's avatar
Steven Murray committed
266
267
    throw ex;
  }
268

269
  CatalogueDrive &drive = *(itor->second);
270
  const DriveConfig &driveConfig = drive.getConfig();
Steven Murray's avatar
Steven Murray committed
271
272

  // Sanity check
273
  if(unitName != driveConfig.getUnitName()) {
Steven Murray's avatar
Steven Murray committed
274
275
    // This should never happen
    castor::exception::Exception ex;
276
    ex.getMessage() << "Failed to " << task <<
Steven Murray's avatar
Steven Murray committed
277
278
      ": Found inconsistent entry in tape-drive catalogue"
      ": Unit name mismatch: expected=" << unitName <<
279
      " actual=" << driveConfig.getUnitName();
Steven Murray's avatar
Steven Murray committed
280
281
282
283
    throw ex;
  }

  return drive;
284
285
}

286
//-----------------------------------------------------------------------------
287
// findDrive
288
//-----------------------------------------------------------------------------
289
290
const castor::tape::tapeserver::daemon::CatalogueDrive
  &castor::tape::tapeserver::daemon::Catalogue::findDrive(
291
    const pid_t sessionPid) const {
292
293
294
295
296
297
298
299
300
301
302
303
304
305
  std::ostringstream task;
  task << "find tape drive in catalogue by session pid: sessionPid=" <<
    sessionPid;

  for(DriveMap::const_iterator itor = m_drives.begin(); itor != m_drives.end();
    itor++) {

    if(NULL == itor->second) {
      // Should never get here
      castor::exception::Exception ex;
      ex.getMessage() << "Failed to " << task.str() <<
        ": Encountered NULL drive-entry pointer: unitName=" <<  itor->first;
      throw ex;
    }
306

307
    const CatalogueDrive &drive = *(itor->second);
308
    try {
309
      const CatalogueSession &session = drive.getSession();
310
      if(sessionPid == session.getPid()) {
311
312
313
        return drive;
      }
    } catch(...) {
314
      // Ignore any exceptions thrown by getSession()
Steven Murray's avatar
Steven Murray committed
315
    }
316
  }
317

318
  castor::exception::Exception ex;
319
  ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
320
  throw ex;
321
322
}

323
//-----------------------------------------------------------------------------
324
// findDrive
325
//-----------------------------------------------------------------------------
326
327
castor::tape::tapeserver::daemon::CatalogueDrive
  &castor::tape::tapeserver::daemon::Catalogue::findDrive(
328
329
330
331
    const pid_t sessionPid) {
  std::ostringstream task;
  task << "find tape drive in catalogue by session pid: sessionPid=" <<
    sessionPid;
Steven Murray's avatar
Steven Murray committed
332

333
334
  for(DriveMap::iterator itor = m_drives.begin(); itor != m_drives.end();
    itor++) {
335

336
337
338
339
340
341
342
    if(NULL == itor->second) {
      // Should never get here
      castor::exception::Exception ex;
      ex.getMessage() << "Failed to " << task.str() <<
        ": Encountered NULL drive-entry pointer: unitName=" <<  itor->first;
      throw ex;
    }
343

344
    CatalogueDrive &drive = *(itor->second);
345
    try {
346
      const CatalogueSession &session = drive.getSession();
347
      if(sessionPid == session.getPid()) {
348
349
350
351
        return drive;
      }
    } catch(...) {
      // Ignore any exceptions thrown by getSessionPid()
Steven Murray's avatar
Steven Murray committed
352
    }
353
  }
Steven Murray's avatar
Steven Murray committed
354

355
  castor::exception::Exception ex;
356
  ex.getMessage() << "Failed to " << task.str() << ": Entry does not exist";
357
  throw ex;
358
}