TapeDaemon.hpp 14.4 KB
Newer Older
Steven Murray's avatar
Steven Murray committed
1
/******************************************************************************
2
 *         castor/tape/tapeserver/daemon/TapeDaemon.hpp
Steven Murray's avatar
Steven Murray committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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 Steven.Murray@cern.ch
 *****************************************************************************/

25
#pragma once
Steven Murray's avatar
Steven Murray committed
26

27
#include "castor/common/CastorConfiguration.hpp"
Steven Murray's avatar
Steven Murray committed
28
29
#include "castor/exception/Exception.hpp"
#include "castor/exception/InvalidConfigEntry.hpp"
Steven Murray's avatar
Steven Murray committed
30
#include "castor/exception/NoEntry.hpp"
31
#include "castor/legacymsg/NsProxyFactory.hpp"
32
#include "castor/legacymsg/RmcProxyFactory.hpp"
33
34
#include "castor/legacymsg/VdqmProxy.hpp"
#include "castor/legacymsg/VmgrProxy.hpp"
35
#include "castor/messages/TapeserverProxyFactory.hpp"
Steven Murray's avatar
Steven Murray committed
36
#include "castor/server/Daemon.hpp"
37
#include "castor/server/ProcessCap.hpp"
38
#include "castor/tape/reactor/ZMQReactor.hpp"
39
#include "castor/tape/tapeserver/daemon/DriveCatalogue.hpp"
40
#include "castor/tape/utils/DriveConfigMap.hpp"
41
#include "castor/tape/utils/utils.hpp"
42
#include "castor/utils/utils.hpp"
Steven Murray's avatar
Steven Murray committed
43
44
45
46

#include <iostream>
#include <list>
#include <map>
47
#include <poll.h>
48
#include <stdint.h>
Steven Murray's avatar
Steven Murray committed
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <string>

namespace castor     {
namespace tape       {
namespace tapeserver {
namespace daemon     {

/**
 * Daemon responsible for reading and writing data from and to one or more tape
 * drives drives connected to a tape server.
 */
class TapeDaemon : public castor::server::Daemon {

public:

  /**
   * Constructor.
   *
67
68
   * @param argc The argc of main().
   * @param argv The argv of main().
Steven Murray's avatar
Steven Murray committed
69
70
71
   * @param stdOut Stream representing standard out.
   * @param stdErr Stream representing standard error.
   * @param log The object representing the API of the CASTOR logging system.
72
   * @param driveConfig The configuration of the tape drives.
73
74
   * @param vdqm Proxy object representing the vdqmd daemon.
   * @param vmgr Proxy object representing the vmgrd daemon.
75
76
   * @param rmcFactory Factory to create proxy objects representing the rmcd
   * daemon.
77
78
   * @param reactor The reactor responsible for dispatching the I/O events of
   * the parent process of the tape server daemon.
79
   * @param capUtils Object providing utilities for working UNIX capabilities.
Steven Murray's avatar
Steven Murray committed
80
   */
81
82
83
84
85
86
  TapeDaemon(
    const int argc,
    char **const argv,
    std::ostream &stdOut,
    std::ostream &stdErr,
    log::Logger &log,
87
    const utils::DriveConfigMap &driveConfigs,
88
89
    legacymsg::VdqmProxy &vdqm,
    legacymsg::VmgrProxy &vmgr,
90
    legacymsg::RmcProxyFactory &rmcFactory,
91
    messages::TapeserverProxyFactory &tapeserverProxyFactory,
Daniele Kruse's avatar
Daniele Kruse committed
92
    legacymsg::NsProxyFactory &nsProxyFactory,
93
    reactor::ZMQReactor &reactor,
94
    castor::server::ProcessCap &capUtils);
Steven Murray's avatar
Steven Murray committed
95
96
97
98
99
100
101
102
103

  /**
   * Destructor.
   */
  ~TapeDaemon() throw();

  /**
   * The main entry function of the daemon.
   *
Steven Murray's avatar
Steven Murray committed
104
   * @return The return code of the process.
Steven Murray's avatar
Steven Murray committed
105
   */
Steven Murray's avatar
Steven Murray committed
106
  int main() throw();
107
  
108
protected:
Steven Murray's avatar
Steven Murray committed
109

110
  /**
Steven Murray's avatar
Steven Murray committed
111
   * Returns the name of the host on which the daemon is running.
112
   */
113
  std::string getHostName() const;
114

Steven Murray's avatar
Steven Murray committed
115
116
  /**
   * Exception throwing main() function.
Steven Murray's avatar
Steven Murray committed
117
118
119
   *
   * @param argc The number of command-line arguments.
   * @param argv The array of command-line arguments.
Steven Murray's avatar
Steven Murray committed
120
   */
121
  void exceptionThrowingMain(const int argc, char **const argv);
Steven Murray's avatar
Steven Murray committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

  /**
   * Logs the start of the daemon.
   */
  void logStartOfDaemon(const int argc, const char *const *const argv) throw();

  /**
   * Creates a string that contains the specified command-line arguments
   * separated by single spaces.
   *
   * @param argc The number of command-line arguments.
   * @param argv The array of command-line arguments.
   */
  std::string argvToString(const int argc, const char *const *const argv)
    throw();

Steven Murray's avatar
Steven Murray committed
138
139
140
141
142
143
144
145
146
147
148
  /**
   * Idempotent method that closes the socket used to send commands to the
   * ProcessForker.
   */
  void closeProcessForkerCmdSenderSocket() throw();

  /**
   * Idempotent method that destroys the ZMQ context.
   */
  void destroyZmqContext() throw();

149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  /**
   * Sets the dumpable attribute of the current process to true.
   */
  void setDumpable();

  /**
   * Sets the capabilities of the current process.
   *
   * @text The string representation the capabilities that the current
   * process should have.
   */
  void setProcessCapabilities(const std::string &text);

  /**
   * Forks the ProcessForker.
   */
  void forkProcessForker();

  /**
   * Runs the ProcessForker.
   *
   * @param cmdReceiverSocket The socket used to receive commands for the
   * ProcessForker.
   */
  void runProcessForker(const int cmdReceiverSocket);

Steven Murray's avatar
Steven Murray committed
175
  /**
Steven Murray's avatar
Steven Murray committed
176
   * Blocks the signals that should not asynchronously disturb the daemon.
Steven Murray's avatar
Steven Murray committed
177
   */
178
  void blockSignals() const;
Steven Murray's avatar
Steven Murray committed
179

180
181
182
183
  /**
   * Registers the tape drives controlled by the tape server daemon with the
   * vdqmd daemon.
   */
184
  void registerTapeDrivesWithVdqm() ;
185
186
187
188

  /**
   * Registers the specified tape drive with ethe vdqmd daemon.
   */
189
  void registerTapeDriveWithVdqm(const std::string &unitName);
190

191
192
193
194
195
  /**
   * Initialises the ZMQ context.
   */
  void initZmqContext();

196
  /**
Steven Murray's avatar
Steven Murray committed
197
   * Sets up the reactor.
198
   */
199
  void setUpReactor() ;
200

201
202
203
204
  /**
   * Creates the handler to accept connections from the vdqmd daemon and
   * registers it with the reactor.
   */
205
  void createAndRegisterVdqmAcceptHandler() ;
206
207
208
209
210

  /**
   * Creates the handler to accept connections from the admin commands and
   * registers it with the reactor.
   */
211
  void createAndRegisterAdminAcceptHandler() ;
212

213
214
215
216
217
218
  /**
   * Creates the handler to accept connections from the label tape
   * command-line tool and registers it with the reactor.
   */
  void createAndRegisterLabelCmdAcceptHandler();

219
220
221
222
223
  /**
   * Creates the handler to discuss through zmq socket to the forked sessions
   */
  void createAndRegisterTapeMessageHandler();
  
224
  /**
Steven Murray's avatar
Steven Murray committed
225
   * The main event loop of the daemon.
226
   */
227
  void mainEventLoop() ;
228
229

  /**
230
   * Handles any pending events.
231
   *
232
   * @return True if the main event loop should continue, else false.
233
   */
234
  bool handleEvents() ;
235
236
237
238

  /**
   * Handles any pending signals.
   *
239
   * @return True if the main event loop should continue, else false.
240
241
242
243
244
245
246
247
   */
  bool handlePendingSignals() throw();

  /**
   * Reaps any zombie processes.
   */
  void reapZombies() throw();

248
  /**
249
   * Handles the specified reaped process.
250
   *
251
   * @param pid The process ID of the child process.
252
253
   * @param waitpidStat The status information given by a call to waitpid().
   */
254
255
256
257
258
259
260
261
262
  void handleReapedProcess(const pid_t pid, const int waitpidStat) throw();

  /**
   * Handles the specified reaped ProcessForker.
   *
   * @param pid The process ID of the child process.
   * @param waitpidStat The status information given by a call to waitpid().
   */
  void handleReapedProcessForker(const pid_t pid, const int waitpidStat)
263
    throw();
264
265

  /**
266
267
268
269
270
271
272
273
274
   * Handles the specified reaped session.
   *
   * @param pid The process ID of the child process.
   * @param waitpidStat The status information given by a call to waitpid().
   */
  void handleReapedSession(const pid_t pid, const int waitpidStat) throw();

  /**
   * Logs the fact that the specified child process has terminated.
275
   *
276
   * @param pid The process ID of the child process.
277
278
   * @param waitpidStat The status information given by a call to waitpid().
   */
279
280
  void logChildProcessTerminated(const pid_t pid, const int waitpidStat)
    throw();
281

282
283
284
285
286
  /**
   * Dispatches the appropriate post-processor of repaed sessions based on
   * the specified session type.
   *
   * @sessionType The type of the reaped session.
287
   * @param pid The process ID of the reaped session.
288
289
   * @param waitpidStat The status information given by a call to waitpid().
   */
290
  void dispatchReapedSessionHandler(
291
   const DriveCatalogueEntry::SessionType sessionType,
292
   const pid_t pid,
293
294
   const int waitpidStat);

Steven Murray's avatar
Steven Murray committed
295
296
297
  /**
   * Does the required post processing for the specified reaped session.
   *
298
   * @param pid The process ID of the reaped session.
299
300
   * @param waitpidStat The status information given by a call to waitpid().
   */
301
  void handleReapedDataTransferSession(const pid_t pid,
302
    const int waitpidStat);
303
304
305

  /**
   * Sets the state of the tape drive asscoiated with the specified
Steven Murray's avatar
Steven Murray committed
306
   * child process to down within the vdqmd daemon.
307
   *
Steven Murray's avatar
Steven Murray committed
308
   * @param pid The process ID of the child process.
309
   * @param driveConfig The configuration of the tape drive.
310
   */
311
  void setDriveDownInVdqm(const pid_t pid,
312
    const utils::DriveConfig &driveConfig);
Daniele Kruse's avatar
Daniele Kruse committed
313
314
315
316
317
318
319
320
321
322
323
  
  /**
   * Marshals the specified source tape rc reply message structure into the
   * specified destination buffer.
   *
   * @param dst    The destination buffer.
   * @param dstLen The length of the destination buffer.
   * @param rc     The return code to reply.
   * @return       The total length of the header.
   */
  size_t marshalTapeRcReplyMsg(char *const dst, const size_t dstLen,
324
    const int rc) ;
Daniele Kruse's avatar
Daniele Kruse committed
325
  
326
  /**
327
   * Handles the specified reaped session.
328
   *
329
   * @param pid The process ID of the reaped session.
330
331
   * @param waitpidStat The status information given by a call to waitpid().
   */
332
  void handleReapedLabelSession(const pid_t pid, const int waitpidStat);
333

334
335
336
337
  /**
   * Request the vdqmd daemon to release the tape drive associated with the
   * session child-process with the specified process ID.
   *
338
   * @param driveConfig The configuration of the tape drive.
339
   * @param pid The process ID of the session child-process.
340
   */
341
  void requestVdqmToReleaseDrive(const utils::DriveConfig &driveConfig,
342
    const pid_t pid);
343

344
345
346
347
  /**
   * Notifies the vdqm that the tape associated with the session child-process
   * with the specified process ID has been unmounted.
   *
348
349
   * @param driveConfig The configuration of the tape drive.
   * @param vid The identifier of the unmounted volume.
350
   * @param pid The process ID of the session child-process.
351
   */
352
  void notifyVdqmTapeUnmounted(const utils::DriveConfig &driveConfig,
353
    const std::string &vid, const pid_t pid);
354

355
  /**
Steven Murray's avatar
Steven Murray committed
356
   * Forks a data-transfer process for every tape drive entry in the
357
   * tape drive catalogue that is waiting for such a fork to be carried out.
358
359
360
361
362
   *
   * There may be more than one child-process to fork because there may be
   * more than one tape drive connected to the tape server and the previous
   * call to m_reactor.handleEvents() handled requests to start a mount
   * session on more than one of the connected tape drives.
363
   */
364
  void forkDataTransferSessions() throw();
365

366
  /**
Steven Murray's avatar
Steven Murray committed
367
   * Forks a data-transfer process for the specified tape drive.
368
   *
369
   * @param drive The tape-drive entry in the tape-drive catalogue.
370
   */ 
371
  void forkDataTransferSession(DriveCatalogueEntry *drive) throw();
372
373

  /**
Steven Murray's avatar
Steven Murray committed
374
375
   * Runs the data-transfer session.  This method is to be called within the
   * child process responsible for running the data-transfer session.
376
   *
377
378
   * @param drive The catalogue entry of the tape drive to be used during the
   * session.
379
   */
380
  void runDataTransferSession(const DriveCatalogueEntry *drive) throw();
381

382
383
384
385
386
387
388
389
390
391
392
393
394
395
  /**
   * Forks a label-session child-process for every tape drive entry in the
   * tape drive catalogue that is waiting for such a fork to be carried out.
   *
   * There may be more than one child-process to fork because there may be
   * more than one tape drive connected to the tape server and the previous
   * call to m_reactor.handleEvents() handled requests to start a label
   * session on more than one of the connected tape drives.
   */
  void forkLabelSessions() throw();

  /**
   * Forks a label-session child-process for the specified tape drive.
   *
396
   * @param drive The tape-drive entry in the tape-drive catalogue.
397
   */
Daniele Kruse's avatar
Daniele Kruse committed
398
  void forkLabelSession(DriveCatalogueEntry *drive) throw();
399
400
401
402
403

  /**
   * Runs the label session.  This method is to be called within the child
   * process responsible for running the label session.
   *
404
405
   * @param drive The catalogue entry of the tape drive to be used during the
   * session.
406
407
   * @param labelCmdConnection The file descriptor of the connection with the
   * command-line tool castor-tape-label.
408
   */
Daniele Kruse's avatar
Daniele Kruse committed
409
  void runLabelSession(const DriveCatalogueEntry *drive,
410
    const int labelCmdConnection) throw();
411

412
413
414
415
416
417
  /**
   * Catalogue used to keep track of both the initial and current state of
   * each tape drive being controlled by the tapeserverd daemon.
   */
  DriveCatalogue m_driveCatalogue;

418
419
420
421
422
423
424
425
426
427
  /**
   * The argc of main().
   */
  const int m_argc;

  /**
   * The argv of main().
   */
  char **const m_argv;

428
429
430
431
432
  /**
   * The configuration of the tape drives.
   */
  const utils::DriveConfigMap m_driveConfigs;

433
  /**
434
   * Proxy object representing the vdqmd daemon.
435
   */
436
  legacymsg::VdqmProxy &m_vdqm;
437

438
  /**
439
   * Proxy object representing the vmgrd daemon.
440
   */
441
  legacymsg::VmgrProxy &m_vmgr;
442
443

  /**
444
   * Factory to create proxy objects representing the rmcd daemon.
445
   */
446
  legacymsg::RmcProxyFactory &m_rmcFactory;
Daniele Kruse's avatar
Daniele Kruse committed
447
448
449
450
  
  /**
   * The proxy object representing the tapeserver daemon.
   */
451
  messages::TapeserverProxyFactory &m_tapeserverFactory;
Daniele Kruse's avatar
Daniele Kruse committed
452
453
454
455
456
  
  /**
   * The proxy object representing the nameserver daemon.
   */
  legacymsg::NsProxyFactory &m_nsFactory;
457

458
459
460
461
  /**
   * The reactor responsible for dispatching the file-descriptor event-handlers
   * of the tape server daemon.
   */
462
  reactor::ZMQReactor &m_reactor;
463

464
465
466
  /**
   * Object providing utilities for working UNIX capabilities.
   */
467
  castor::server::ProcessCap &m_capUtils;
468

Steven Murray's avatar
Steven Murray committed
469
  /**
470
   * The program name of the daemon.
Steven Murray's avatar
Steven Murray committed
471
472
473
   */
  const std::string m_programName;

474
  /**
475
   * The name of the host on which the daemon is running.  This name is
476
477
478
479
   * needed to fill in messages to be sent to the vdqmd daemon.
   */
  const std::string m_hostName;

480
481
482
483
484
485
486
487
488
489
  /**
   * The socket used to send commands to the ProcessForker.
   */
  int m_processForkerCmdSenderSocket;

  /**   
   * The process identifier of the ProcessForker.
   */
  pid_t m_processForkerPid;

490
491
492
493
494
  /**
   * The ZMQ context.
   */
  void *m_zmqContext;

Steven Murray's avatar
Steven Murray committed
495
496
497
498
499
500
501
}; // class TapeDaemon

} // namespace daemon
} // namespace tapeserver
} // namespace tape
} // namespace castor