Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
dCache
cta
Commits
969d71fb
Commit
969d71fb
authored
Feb 21, 2014
by
Steven Murray
Browse files
The tapeserverd daemon now uses the Reactor pattern.
parent
697ebe54
Changes
14
Hide whitespace changes
Inline
Side-by-side
castor/tape/legacymsg/CommonMarshal.cpp
View file @
969d71fb
/******************************************************************************
* castor/tape/legacymsg/Common.cpp
* castor/tape/legacymsg/Common
Marshal
.cpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
...
...
castor/tape/tapeserver/daemon/CMakeLists.txt
View file @
969d71fb
add_executable
(
tapeserverd TapeDaemon.cpp TapeDaemonMain.cpp
)
add_executable
(
tapeserverd
TapeDaemon.cpp
TapeDaemonMain.cpp
Vdqm.cpp
VdqmAcceptHandler.cpp
VdqmConnectionHandler.cpp
VdqmImpl.cpp
)
target_link_libraries
(
tapeserverd Exception SCSI System Utils File castorcommon
castorclient
)
target_link_libraries
(
tapeserverd
Exception
SCSI
System
Utils
File
castorcommon
castorclient
castortapelegacymsg
)
add_library
(
tapeserver ClientInterface.cpp MountSession.cpp
)
...
...
castor/tape/tapeserver/daemon/Constants.hpp
0 → 100644
View file @
969d71fb
/******************************************************************************
* castor/tape/tapeserver/daemon/Constants.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 Steven.Murray@cern.ch
*****************************************************************************/
#ifndef CASTOR_TAPE_TAPESERVER_DAEMON_CONSTANTS_HPP
#define CASTOR_TAPE_TAPESERVER_DAEMON_CONSTANTS_HPP 1
namespace
castor
{
namespace
tape
{
namespace
tapeserver
{
namespace
daemon
{
/**
* The TCP/IP port on which the tape server daemon listens for incoming
* connections from the VDQM server.
*/
const
unsigned
short
TAPE_SERVER_LISTENING_PORT
=
5070
;
}
// namespace daemon
}
// namespace tapeserver
}
// namespace tape
}
// namespace castor
#endif // CASTOR_TAPE_TAPESERVER_DAEMON_CONSTANTS_HPP
castor/tape/tapeserver/daemon/TapeDaemon.cpp
View file @
969d71fb
...
...
@@ -22,16 +22,15 @@
* @author Steven.Murray@cern.ch
*****************************************************************************/
#include
"castor/PortNumbers.hpp"
#include
"castor/exception/Errnum.hpp"
#include
"castor/exception/BadAlloc.hpp"
#include
"castor/exception/Internal.hpp"
#include
"castor/exception/InvalidArgument.hpp"
#include
"castor/io/io.hpp"
#include
"castor/tape/tapeserver/daemon/Constants.hpp"
#include
"castor/tape/tapeserver/daemon/TapeDaemon.hpp"
#include
"castor/tape/tapeserver/daemon/VdqmAcceptHandler.hpp"
#include
"castor/tape/utils/utils.hpp"
#include
"castor/utils/SmartFd.hpp"
#include
"h/common.h"
#include
<algorithm>
#include
<limits.h>
...
...
@@ -46,9 +45,9 @@
// constructor
//------------------------------------------------------------------------------
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
TapeDaemon
::
TapeDaemon
(
std
::
ostream
&
stdOut
,
std
::
ostream
&
stdErr
,
log
::
Logger
&
log
)
throw
(
castor
::
exception
::
Exception
)
:
castor
::
server
::
Daemon
(
stdOut
,
stdErr
,
log
),
std
::
ostream
&
stdOut
,
std
::
ostream
&
stdErr
,
log
::
Logger
&
log
,
Vdqm
&
vdqm
,
io
::
PollReactor
&
reactor
)
throw
(
castor
::
exception
::
Exception
)
:
castor
::
server
::
Daemon
(
stdOut
,
stdErr
,
log
),
m_vdqm
(
vdqm
),
m_reactor
(
reactor
),
m_programName
(
"tapeserverd"
)
{
}
...
...
@@ -92,14 +91,11 @@ void castor::tape::tapeserver::daemon::TapeDaemon::exceptionThrowingMain(
logStartOfDaemon
(
argc
,
argv
);
parseCommandLine
(
argc
,
argv
);
// Daemonize if not configiured to run in the foreground
parseTpconfig
();
daemonizeIfNotRunInForeground
();
blockSignals
();
castor
::
utils
::
SmartFd
listenSock
(
io
::
createListenerSock
(
TAPE_SERVER_LISTENING_PORT
));
mainEventLoop
(
listenSock
.
get
());
setUpReactor
();
mainEventLoop
();
}
//------------------------------------------------------------------------------
...
...
@@ -116,6 +112,47 @@ void castor::tape::tapeserver::daemon::TapeDaemon::logStartOfDaemon(
m_log
(
LOG_INFO
,
msg
.
str
(),
params
);
}
//------------------------------------------------------------------------------
// parseTpconfig
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
parseTpconfig
()
throw
(
castor
::
exception
::
Exception
)
{
utils
::
TpconfigLines
tpconfigLines
;
utils
::
parseTpconfigFile
(
TPCONFIGPATH
,
tpconfigLines
);
logTpconfigLines
(
tpconfigLines
);
// Extract the tape-drive names from the TPCONFIG file
std
::
list
<
std
::
string
>
driveNames
;
utils
::
extractTpconfigDriveNames
(
tpconfigLines
,
driveNames
);
}
//------------------------------------------------------------------------------
// logTpconfigLines
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
logTpconfigLines
(
const
utils
::
TpconfigLines
&
lines
)
throw
()
{
for
(
utils
::
TpconfigLines
::
const_iterator
itor
=
lines
.
begin
();
itor
!=
lines
.
end
();
itor
++
)
{
logTpconfigLine
(
*
itor
);
}
}
//------------------------------------------------------------------------------
// logTpconfigLine
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
logTpconfigLine
(
const
utils
::
TpconfigLine
&
line
)
throw
()
{
log
::
Param
params
[]
=
{
log
::
Param
(
"unitName"
,
line
.
mUnitName
),
log
::
Param
(
"deviceGroup"
,
line
.
mDeviceGroup
),
log
::
Param
(
"systemDevice"
,
line
.
mSystemDevice
),
log
::
Param
(
"density"
,
line
.
mDensity
),
log
::
Param
(
"initialStatus"
,
line
.
mInitialStatus
),
log
::
Param
(
"controlMethod"
,
line
.
mControlMethod
),
log
::
Param
(
"devType"
,
line
.
mDevType
)};
m_log
(
LOG_INFO
,
"TPCONFIG line"
,
params
);
}
//------------------------------------------------------------------------------
// argvToString
//------------------------------------------------------------------------------
...
...
@@ -162,97 +199,52 @@ void castor::tape::tapeserver::daemon::TapeDaemon::blockSignals() const
}
//------------------------------------------------------------------------------
//
mainEventLoop
//
setUpReactor
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
mainEventLoop
(
const
int
listenSock
)
throw
(
castor
::
exception
::
Exception
)
{
bool
continueMainEventLoop
=
true
;
while
(
continueMainEventLoop
)
{
handleAPossibleVdqmRequest
(
listenSock
);
continueMainEventLoop
=
handlePendingSignals
();
::
usleep
(
100000
);
// Sleep for a tenth of a second
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
setUpReactor
()
throw
(
castor
::
exception
::
Exception
)
{
castor
::
utils
::
SmartFd
listenSock
;
try
{
listenSock
.
reset
(
io
::
createListenerSock
(
TAPE_SERVER_LISTENING_PORT
));
}
catch
(
castor
::
exception
::
Exception
&
ne
)
{
castor
::
exception
::
Exception
ex
(
ne
.
code
());
ex
.
getMessage
()
<<
"Failed to create socket to listen for vdqm connections"
": "
<<
ne
.
getMessage
().
str
();
throw
ex
;
}
std
::
auto_ptr
<
VdqmAcceptHandler
>
acceptHandler
;
try
{
acceptHandler
.
reset
(
new
VdqmAcceptHandler
(
listenSock
.
get
(),
m_reactor
,
m_log
,
m_vdqm
));
listenSock
.
release
();
}
catch
(
std
::
bad_alloc
&
ba
)
{
castor
::
exception
::
BadAlloc
ex
;
ex
.
getMessage
()
<<
"Failed to create the event handler for accepting vdqm connections"
": "
<<
ba
.
what
();
throw
ex
;
}
m_reactor
.
registerHandler
(
acceptHandler
.
get
());
acceptHandler
.
release
();
}
//------------------------------------------------------------------------------
//
handleAPossibleVdqmRequest
//
mainEventLoop
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
handleAPossibleVdqmRequest
(
const
int
listenSock
)
throw
()
{
struct
pollfd
fds
[
1
];
// poll() of the main event loop should always look at the accept socket
fds
[
0
].
fd
=
listenSock
;
fds
[
0
].
events
=
POLLRDNORM
;
fds
[
0
].
revents
=
0
;
if
(
-
1
==
poll
(
fds
,
1
,
0
))
{
const
int
pollErrno
=
errno
;
log
::
Param
params
[]
=
{
log
::
Param
(
"errno"
,
pollErrno
),
log
::
Param
(
"message"
,
sstrerror
(
pollErrno
))};
m_log
(
LOG_ERR
,
"Failed to handle a pending vdqm request: poll() failed"
,
params
);
return
;
}
// If the vdqm daemon is connecting to the listening socket
if
(
fds
[
0
].
revents
&
POLLRDNORM
)
{
try
{
castor
::
utils
::
SmartFd
connection
(
io
::
acceptConnection
(
listenSock
,
1
));
char
hostName
[
io
::
HOSTNAMEBUFLEN
];
const
io
::
IpAndPort
peerIpAndPort
=
io
::
getPeerIpPort
(
connection
.
get
());
io
::
getPeerHostName
(
connection
.
get
(),
hostName
);
log
::
Param
params
[]
=
{
log
::
Param
(
"Port"
,
peerIpAndPort
.
getPort
()),
log
::
Param
(
"HostName"
,
hostName
),
log
::
Param
(
"socketFd"
,
connection
.
get
())};
m_log
(
LOG_INFO
,
"Accepted vdqm connection"
,
params
);
checkIsAdminHost
(
connection
.
get
());
// TEMPORARY: For now we simply close the vdqm connection
close
(
connection
.
release
());
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
log
::
Param
params
[]
=
{
log
::
Param
(
"code"
,
ex
.
code
()),
log
::
Param
(
"message"
,
ex
.
getMessage
().
str
())};
m_log
(
LOG_ERR
,
"Failed to handle a pending vdqm request"
,
params
);
}
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
mainEventLoop
()
throw
(
castor
::
exception
::
Exception
)
{
while
(
handleEvents
())
{
}
}
//-----------------------------------------------------------------------------
// checkisAdminHost
//-----------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
checkIsAdminHost
(
const
int
connection
)
throw
(
castor
::
exception
::
Exception
)
{
char
peerHost
[
CA_MAXHOSTNAMELEN
+
1
];
// isadminhost fills in peerHost
const
int
rc
=
isadminhost
(
connection
,
peerHost
);
if
(
rc
==
-
1
&&
serrno
!=
SENOTADMIN
)
{
castor
::
exception
::
Internal
ex
;
ex
.
getMessage
()
<<
"Failed to lookup connection: Host="
<<
peerHost
;
throw
ex
;
}
if
(
*
peerHost
==
'\0'
)
{
castor
::
exception
::
Exception
ex
(
EINVAL
);
ex
.
getMessage
()
<<
"Peer host name is an empty string"
;
throw
ex
;
}
if
(
rc
!=
0
)
{
castor
::
exception
::
Exception
ex
(
SENOTADMIN
);
ex
.
getMessage
()
<<
"Unauthorized admin host: Host="
<<
peerHost
;
throw
ex
;
}
//------------------------------------------------------------------------------
// handleEvents
//------------------------------------------------------------------------------
bool
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
::
handleEvents
()
throw
(
castor
::
exception
::
Exception
)
{
const
int
timeout
=
100
;
// 100 milliseconds
m_reactor
.
handleEvents
(
timeout
);
return
handlePendingSignals
();
}
//------------------------------------------------------------------------------
...
...
@@ -270,6 +262,10 @@ bool castor::tape::tapeserver::daemon::TapeDaemon::handlePendingSignals()
// While there is a pending signal to be handled
while
(
0
<
(
sig
=
sigtimedwait
(
&
allSignals
,
&
sigInfo
,
&
immedTimeout
)))
{
switch
(
sig
)
{
case
SIGINT
:
// Signal number 2
m_log
(
LOG_INFO
,
"Gracefully stopping because SIGINT was received"
);
continueMainEventLoop
=
false
;
break
;
case
SIGTERM
:
// Signal number 15
m_log
(
LOG_INFO
,
"Gracefully stopping because SIGTERM was received"
);
continueMainEventLoop
=
false
;
...
...
castor/tape/tapeserver/daemon/TapeDaemon.hpp
View file @
969d71fb
...
...
@@ -27,7 +27,10 @@
#include
"castor/exception/Exception.hpp"
#include
"castor/exception/InvalidConfigEntry.hpp"
#include
"castor/io/PollReactor.hpp"
#include
"castor/server/Daemon.hpp"
#include
"castor/tape/tapeserver/daemon/Vdqm.hpp"
#include
"castor/tape/utils/utils.hpp"
#include
<stdint.h>
#include
<iostream>
...
...
@@ -56,9 +59,12 @@ public:
* @param stdOut Stream representing standard out.
* @param stdErr Stream representing standard error.
* @param log The object representing the API of the CASTOR logging system.
* @param vdqm The object representing the vdqmd daemon.
* @param reactor The reactor responsible for dispatching the I/O events of
* the parent process of the tape server daemon.
*/
TapeDaemon
(
std
::
ostream
&
stdOut
,
std
::
ostream
&
stdErr
,
log
::
Logger
&
log
)
throw
(
castor
::
exception
::
Exception
);
TapeDaemon
(
std
::
ostream
&
stdOut
,
std
::
ostream
&
stdErr
,
log
::
Logger
&
log
,
Vdqm
&
vdqm
,
io
::
PollReactor
&
reactor
)
throw
(
castor
::
exception
::
Exception
);
/**
* Destructor.
...
...
@@ -76,12 +82,6 @@ public:
private:
/**
* The TCP/IP port on which the tape server daemon listens for incoming
* connections from the VDQM server.
*/
static
const
unsigned
short
TAPE_SERVER_LISTENING_PORT
=
5003
;
/**
* Exception throwing main() function.
*/
...
...
@@ -93,6 +93,22 @@ private:
*/
void
logStartOfDaemon
(
const
int
argc
,
const
char
*
const
*
const
argv
)
throw
();
/**
* Parses the /etc/castor/TPCONFIG files in order to determine the drives
* attached to the tape server.
*/
void
parseTpconfig
()
throw
(
castor
::
exception
::
Exception
);
/**
* Writes the specified list of TPCONFIG lines to the logging system.
*/
void
logTpconfigLines
(
const
utils
::
TpconfigLines
&
lines
)
throw
();
/**
* Writes the specified TPCONFIG lines to the logging system.
*/
void
logTpconfigLine
(
const
utils
::
TpconfigLine
&
line
)
throw
();
/**
* Creates a string that contains the specified command-line arguments
* separated by single spaces.
...
...
@@ -110,33 +126,27 @@ private:
void
blockSignals
()
const
throw
(
castor
::
exception
::
Exception
);
/**
* The main event loop of the tape-server daemon.
*
* @patam listenSock The file-descriptor of the listening socket.
* Sets up the reactor to listen for an accept connection from the vdqmd
* daemon.
*/
void
mainEventLoop
(
const
int
listenSock
)
throw
(
castor
::
exception
::
Exception
);
void
setUpReactor
()
throw
(
castor
::
exception
::
Exception
);
/**
* Handle a pending vdqm request if there is one.
*
* @patam listenSock The file-descriptor of the listening socket.
* The main event loop of the tape-server daemon.
*/
void
handleAPossibleVdqmRequest
(
const
int
listenSock
)
throw
(
);
void
mainEventLoop
()
throw
(
castor
::
exception
::
Exception
);
/**
* Throws an exception if the peer host associated with the specified
* connection is not an admin host.
* Handles any pending events.
*
* @
param connection The file descriptor of the connection
.
* @
return True if the main event loop should continue, else false
.
*/
void
checkIsAdminHost
(
const
int
connection
)
throw
(
castor
::
exception
::
Exception
);
bool
handleEvents
()
throw
(
castor
::
exception
::
Exception
);
/**
* Handles any pending signals.
*
* @return True if the main event lo
p
p should continue, else false.
* @return True if the main event lo
o
p should continue, else false.
*/
bool
handlePendingSignals
()
throw
();
...
...
@@ -145,11 +155,86 @@ private:
*/
void
reapZombies
()
throw
();
/**
* The object representing the vdqmd daemon.
*/
Vdqm
&
m_vdqm
;
/**
* The reactor responsible for dispatching the file-descriptor event-handlers
* of the tape server daemon.
*/
io
::
PollReactor
&
m_reactor
;
/**
* The program name of the tape daemon.
*/
const
std
::
string
m_programName
;
/**
* The status of a drive as described by the following FSTN:
*
* start daemon /
* ------ send VDQM_UNIT_UP ----------------
* | INIT |--------------------->| DOWN |<-------------------
* ------ ---------------- |
* | | ^ |
* | | | |
* | | tpconfig up | tpconfig down |
* | | | |
* | start daemon / v | |
* | send VDQM_UNIT_DOWN ---------------- |
* ------------------------>| UP | |
* ---------------- |
* | ^ |
* | | |
* | vdqm job / | SIGCHLD [success] |
* | fork | |
* | | |
* v | |
* ---------------- SIGCHLD [fail] |
* | RUNNING |--------------------
* ----------------
*
* When the tapeserverd daemon is started, depdending on the initial state
* column of /etc/castor/TPCONFIG, the daemon sends either a VDQM_UNIT_UP
* or VDQM_UNIT_DOWN status message to the vdqmd daemon.
*
* A tape operator toggle the state of tape drive between DOWN and UP
* using the tpconfig adminstration tool.
*
* The tape daemon can receive a job from the vdqmd daemon when the drive
* is in the UP state. On reception of the job the daemon forks a child
* process to manage the tape mount and data transfer tasks necessary to
* fulfill the vdqm job. The drive is now in the RUNNING state.
*
* Once the vdqm job has been carried out, the child process completes
* and the drive either returns to the UP state if there were no
* problems or DOWN state if there were.
*/
enum
DriveStatus
{
DRIVE_INIT
,
DRIVE_DOWN
,
DRIVE_UP
,
DRIVE_RUNNING
};
/**
* Structure used to store the initial and current status of a drive.
*
* The initial status of a drive defined in the initial status column of the
* /etc/castor/TPCONFIG file.
*/
struct
InitialAndCurrentDriveStatus
{
DriveStatus
initialStatus
;
DriveStatus
currentStatus
;
};
/**
* Type that maps drive unit-name to drive initial and current status.
*/
typedef
std
::
map
<
std
::
string
,
DriveStatus
>
DriveStatusMap
;
/**
* Map from drive unit-name to drive status.
*/
DriveStatusMap
m_drives
;
};
// class TapeDaemon
}
// namespace daemon
...
...
castor/tape/tapeserver/daemon/TapeDaemonMain.cpp
View file @
969d71fb
...
...
@@ -21,21 +21,21 @@
*
* @author Steven.Murray@cern.ch
*****************************************************************************/
#include
"castor/log/LoggerImplementation.hpp"
#include
"castor/io/PollReactorImpl.hpp"
#include
"castor/tape/tapeserver/daemon/TapeDaemon.hpp"
#include
"castor/tape/tapeserver/daemon/VdqmImpl.hpp"
//------------------------------------------------------------------------------
// main
//------------------------------------------------------------------------------
int
main
(
const
int
argc
,
char
**
const
argv
)
{
using
namespace
castor
::
tape
::
tapeserver
::
daemon
;
castor
::
log
::
LoggerImplementation
log
(
"tapeserverd"
);
castor
::
tape
::
tapeserver
::
daemon
::
TapeDaemon
daemon
(
std
::
cout
,
std
::
cerr
,
log
);
VdqmImpl
vdqm
;
castor
::
io
::
PollReactorImpl
reactor
(
log
);
TapeDaemon
daemon
(
std
::
cout
,
std
::
cerr
,
log
,
vdqm
,
reactor
);
return
daemon
.
main
(
argc
,
argv
);
}
castor/tape/tapeserver/daemon/Vdqm.cpp
0 → 100644
View file @
969d71fb
/******************************************************************************
* castor/tape/tapeserver/daemon/Vdqm.cpp
*
* 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
*****************************************************************************/
#include
"castor/tape/tapeserver/daemon/Vdqm.hpp"
//-----------------------------------------------------------------------------
// destructor
//-----------------------------------------------------------------------------
castor
::
tape
::
tapeserver
::
daemon
::
Vdqm
::~
Vdqm
()
throw
()
{
}
castor/tape/tapeserver/daemon/Vdqm.hpp
0 → 100644
View file @
969d71fb
/******************************************************************************
* castor/tape/tapeserver/daemon/Vdqm.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 Steven.Murray@cern.ch
*****************************************************************************/
#ifndef CASTOR_TAPE_TAPESERVER_DAEMON_VDQM_HPP
#define CASTOR_TAPE_TAPESERVER_DAEMON_VDQM_HPP 1
#include
"castor/exception/Exception.hpp"
#include
"castor/tape/legacymsg/RtcpJobRqstMsgBody.hpp"
namespace
castor
{
namespace
tape
{
namespace
tapeserver
{
namespace
daemon
{
/**
* Proxy class representing the vdqm daemon.
*/