Skip to content
GitLab
Menu
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
e651c8ac
Commit
e651c8ac
authored
Dec 08, 2014
by
Steven Murray
Browse files
Factorized VdqmDriveSynchronizer out from CatalogueDrive
parent
c6bafdea
Changes
11
Hide whitespace changes
Inline
Side-by-side
castor/castor.conf
View file @
e651c8ac
...
...
@@ -597,6 +597,11 @@
#
#TapeServer MaxFilesBeforeFlush 200
# The time interval in seconds to wait between attempts to keep the vdqmd
# daemon synchronized with the state of a tape drive within the catalogue of the
# tapeserverd daemon.
#TapeServer VdqmDriveSyncInterval 600
## Tape Bridge Clients: dumptp, readtp and writetp #############################
# The inclusive low port of the tapebridge client callback port number range.
...
...
castor/tape/tapeserver/daemon/CMakeLists.txt
View file @
e651c8ac
...
...
@@ -67,7 +67,8 @@ add_library(castorTapeServerDaemon
TpconfigLine.cpp
TpconfigLines.cpp
VdqmAcceptHandler.cpp
VdqmConnectionHandler.cpp
)
VdqmConnectionHandler.cpp
VdqmDriveSynchronizer.cpp
)
target_link_libraries
(
castorTapeServerDaemon castormessages castortapereactor
)
add_dependencies
(
castorTapeServerDaemon castormessagesprotobuf
)
...
...
castor/tape/tapeserver/daemon/Catalogue.cpp
View file @
e651c8ac
...
...
@@ -141,9 +141,7 @@ void castor::tape::tapeserver::daemon::Catalogue::enterDriveConfig(
// Insert it
m_drives
[
driveConfig
.
getUnitName
()]
=
new
CatalogueDrive
(
m_netTimeout
,
m_log
,
m_processForker
,
m_cupv
,
m_vdqm
,
m_vmgr
,
m_hostName
,
driveConfig
,
DRIVE_STATE_DOWN
,
m_catalogueConfig
.
waitJobTimeoutInSecs
,
m_catalogueConfig
.
mountTimeoutInSecs
,
m_catalogueConfig
.
blockMoveTimeoutInSecs
);
DRIVE_STATE_DOWN
,
m_catalogueConfig
);
// Else the drive is already in the catalogue
}
else
{
castor
::
exception
::
Exception
ex
;
...
...
castor/tape/tapeserver/daemon/CatalogueConfig.cpp
View file @
e651c8ac
...
...
@@ -30,9 +30,10 @@
// constructor
//------------------------------------------------------------------------------
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueConfig
::
CatalogueConfig
()
throw
()
:
waitJobTimeoutInSecs
(
0
),
mountTimeoutInSecs
(
0
),
blockMoveTimeoutInSecs
(
0
)
{
waitJobTimeoutSecs
(
0
),
mountTimeoutSecs
(
0
),
blockMoveTimeoutSecs
(
0
),
vdqmDriveSyncIntervalSecs
(
0
)
{
}
//------------------------------------------------------------------------------
...
...
@@ -45,12 +46,14 @@ castor::tape::tapeserver::daemon::CatalogueConfig
common
::
CastorConfiguration
::
getConfig
();
CatalogueConfig
config
;
config
.
waitJobTimeoutInSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"WaitJobTimeout"
,
(
time_t
)
TAPESERVER_WAITJOBTIMEOUT_DEFAULT
,
log
);
config
.
mountTimeoutInSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"MountTimeout"
,
(
time_t
)
TAPESERVER_MOUNTTIMEOUT_DEFAULT
,
log
);
config
.
blockMoveTimeoutInSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"BlkMoveTimeout"
,
(
time_t
)
TAPESERVER_BLKMOVETIMEOUT_DEFAULT
,
log
);
config
.
waitJobTimeoutSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"WaitJobTimeout"
,
TAPESERVER_WAITJOBTIMEOUT
,
log
);
config
.
mountTimeoutSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"MountTimeout"
,
TAPESERVER_MOUNTTIMEOUT
,
log
);
config
.
blockMoveTimeoutSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"BlkMoveTimeout"
,
TAPESERVER_BLKMOVETIMEOUT
,
log
);
config
.
vdqmDriveSyncIntervalSecs
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"VdqmDriveSyncInterval"
,
TAPESERVER_VDQMDRIVESYNCINTERVAL
,
log
);
return
config
;
}
castor/tape/tapeserver/daemon/CatalogueConfig.hpp
View file @
e651c8ac
...
...
@@ -43,19 +43,26 @@ struct CatalogueConfig {
* The maximum time in seconds that the data-transfer session can take to get
* the transfer job from the client.
*/
time_t
waitJobTimeout
In
Secs
;
time_t
waitJobTimeoutSecs
;
/**
* The maximum time in seconds that the data-transfer session can take to
* mount a tape.
*/
time_t
mountTimeout
In
Secs
;
time_t
mountTimeoutSecs
;
/**
* The maximum time in seconds the data-transfer session of tapeserverd can
* cease to move data blocks
*/
time_t
blockMoveTimeoutInSecs
;
time_t
blockMoveTimeoutSecs
;
/**
* The time interval in seconds to wait between attempts to keep the vdqmd
* daemon synchronized with the state of a tape drive within the catalogue of
* the tapeserverd daemon.
*/
time_t
vdqmDriveSyncIntervalSecs
;
/**
* Constructor that sets all integer member-variables to 0 and all string
...
...
castor/tape/tapeserver/daemon/CatalogueDrive.cpp
View file @
e651c8ac
...
...
@@ -47,9 +47,7 @@ castor::tape::tapeserver::daemon::CatalogueDrive::CatalogueDrive(
const
std
::
string
&
hostName
,
const
DriveConfig
&
config
,
const
CatalogueDriveState
state
,
const
time_t
waitJobTimeoutInSecs
,
const
time_t
mountTimeoutInSecs
,
const
time_t
blockMoveTimeoutInSecs
)
const
CatalogueConfig
&
catalogueConfig
)
throw
()
:
m_netTimeout
(
netTimeout
),
m_log
(
log
),
...
...
@@ -60,10 +58,12 @@ castor::tape::tapeserver::daemon::CatalogueDrive::CatalogueDrive(
m_hostName
(
hostName
),
m_config
(
config
),
m_state
(
state
),
m_waitJobTimeoutInSecs
(
waitJobTimeoutInSecs
),
m_mountTimeoutInSecs
(
mountTimeoutInSecs
),
m_blockMoveTimeoutInSecs
(
blockMoveTimeoutInSecs
),
m_session
(
NULL
)
{
m_waitJobTimeoutSecs
(
catalogueConfig
.
waitJobTimeoutSecs
),
m_mountTimeoutSecs
(
catalogueConfig
.
mountTimeoutSecs
),
m_blockMoveTimeoutSecs
(
catalogueConfig
.
blockMoveTimeoutSecs
),
m_session
(
NULL
),
m_vdqmDriveSynchronizer
(
log
,
vdqm
,
hostName
,
config
,
catalogueConfig
.
vdqmDriveSyncIntervalSecs
)
{
}
//------------------------------------------------------------------------------
...
...
@@ -84,139 +84,11 @@ bool castor::tape::tapeserver::daemon::CatalogueDrive::handleTick() {
return
false
;
// Do no continue the main event loop
}
syncVdqmWithDriveStateWhenNecessary
(
);
m_vdqmDriveSynchronizer
.
sync
(
m_state
);
return
true
;
// Continue the main event loop
}
//------------------------------------------------------------------------------
// syncVdqmWithDriveStateWhenNecessary
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
syncVdqmWithDriveStateWhenNecessary
()
{
std
::
string
errMsg
;
try
{
if
(
600.0
<
m_syncVdqmTimer
.
secs
())
{
m_syncVdqmTimer
.
reset
();
syncVdqmWithDriveStateIfOutOfSync
();
}
return
;
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
errMsg
=
ex
.
getMessage
().
str
();
}
catch
(
std
::
exception
&
se
)
{
errMsg
=
se
.
what
();
}
catch
(...)
{
errMsg
=
"Caught an unknown exception"
;
}
// Reaching here means an exception was thrown
// Failing to synchronise the vdqm with the drive state is not fatal
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"message"
,
errMsg
));
m_log
(
LOG_WARNING
,
"Failed to synchronise vdqm with drive state"
,
params
);
}
//------------------------------------------------------------------------------
// syncVdqmWithDriveStateIfOutOfSync
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
syncVdqmWithDriveStateIfOutOfSync
()
{
// If the drive is UP and therefore ready for new work
if
(
DRIVE_STATE_UP
==
m_state
)
{
// Query the vdqmd daemon for the state of the drive
const
int
vdqmDriveStatus
=
m_vdqm
.
getDriveStatus
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
const
bool
vdqmDriveRunning
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_ASSIGN
);
const
bool
vdqmDriveRelease
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_RELEASE
|
VDQM_UNIT_UNKNOWN
);
const
bool
vdqmDriveBadUnknown
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_UNKNOWN
);
// If the vdqmd daemon thinks the drive is not read for new work
//
// We explicitely do not check (vdqmstate == UP|FREE) here, since
// VDQM changes the state to UP|BUSY before contacting tape daemon.
// The latter should not reset the state to UP|FREE in that case.
if
(
vdqmDriveRunning
||
vdqmDriveRelease
||
vdqmDriveBadUnknown
)
{
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatus"
,
vdqmDriveStatus
));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatusStr"
,
vdqmDriveStatusToString
(
vdqmDriveStatus
)));
m_log
(
LOG_WARNING
,
"Vdqm is out of sync with drive status"
,
params
);
syncVdqmWithDriveState
();
}
}
}
//------------------------------------------------------------------------------
// syncVdqmWithDriveState
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
syncVdqmWithDriveState
()
{
m_vdqm
.
setDriveUp
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
const
int
vdqmDriveStatus
=
m_vdqm
.
getDriveStatus
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatus"
,
vdqmDriveStatus
));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatusStr"
,
vdqmDriveStatusToString
(
vdqmDriveStatus
)));
m_log
(
LOG_WARNING
,
"Forced drive UP in vdqm"
,
params
);
}
//------------------------------------------------------------------------------
// vdqmDriveStatusToString
//------------------------------------------------------------------------------
std
::
string
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
vdqmDriveStatusToString
(
int
status
)
{
std
::
ostringstream
oss
;
appendBitIfSet
(
VDQM_UNIT_UP
,
"UP"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_DOWN
,
"DOWN"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_WAITDOWN
,
"WAITDOWN"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_ASSIGN
,
"ASSIGN"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_RELEASE
,
"RELEASE"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_BUSY
,
"BUSY"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_FREE
,
"FREE"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_UNKNOWN
,
"UNKNOWN"
,
status
,
oss
);
appendBitIfSet
(
VDQM_UNIT_ERROR
,
"ERROR"
,
status
,
oss
);
if
(
status
)
{
if
(
!
oss
.
str
().
empty
())
{
oss
<<
"|"
;
}
oss
<<
"leftovers=0x"
<<
std
::
hex
<<
status
;
}
return
oss
.
str
();
}
//------------------------------------------------------------------------------
// appendBitIfSet
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
appendBitIfSet
(
const
int
bitMask
,
const
std
::
string
bitMaskName
,
int
&
bitSet
,
std
::
ostringstream
&
bitSetStringStream
)
{
if
(
bitSet
&
bitMask
)
{
if
(
!
bitSetStringStream
.
str
().
empty
())
{
bitSetStringStream
<<
"|"
;
}
bitSetStringStream
<<
bitMaskName
;
bitSet
-=
bitMask
;
}
}
//------------------------------------------------------------------------------
// deleteSession
//------------------------------------------------------------------------------
...
...
@@ -572,9 +444,9 @@ void castor::tape::tapeserver::daemon::CatalogueDrive::receivedVdqmJob(
m_vmgr
,
m_cupv
,
m_hostName
,
m_waitJobTimeout
In
Secs
,
m_mountTimeout
In
Secs
,
m_blockMoveTimeout
In
Secs
,
m_waitJobTimeoutSecs
,
m_mountTimeoutSecs
,
m_blockMoveTimeoutSecs
,
m_processForker
);
m_session
=
dynamic_cast
<
CatalogueSession
*>
(
transferSession
);
m_vdqm
.
assignDrive
(
m_hostName
,
m_config
.
getUnitName
(),
job
.
dgn
,
...
...
castor/tape/tapeserver/daemon/CatalogueDrive.hpp
View file @
e651c8ac
...
...
@@ -31,12 +31,14 @@
#include "castor/legacymsg/VmgrProxy.hpp"
#include "castor/log/Logger.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueCleanerSession.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueConfig.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueDriveState.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueLabelSession.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueSession.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueTransferSession.hpp"
#include "castor/tape/tapeserver/daemon/DriveConfig.hpp"
#include "castor/tape/tapeserver/daemon/ProcessForkerProxy.hpp"
#include "castor/tape/tapeserver/daemon/VdqmDriveSynchronizer.hpp"
#include <iostream>
#include <memory>
...
...
@@ -72,12 +74,8 @@ public:
* name is needed to fill in messages to be sent to the vdqmd daemon.
* @param config The configuration of the tape drive.
* @param state The initial state of the tape drive.
* @param waitJobTimeoutInSecs The maximum time in seconds that the
* data-transfer session can take to get the transfer job from the client.
* @param mountTimeoutInSecs The maximum time in seconds that the
* data-transfer session can take to mount a tape.
* @param blockMoveTimeoutInSecs The maximum time in seconds that the
* data-transfer session can cease to move data blocks.
* @param catalogueConfig The CASTOR configuration parameters to be used by
* the catalogue.
*/
CatalogueDrive
(
const
int
netTimeout
,
...
...
@@ -89,9 +87,7 @@ public:
const
std
::
string
&
hostName
,
const
DriveConfig
&
config
,
const
CatalogueDriveState
state
,
const
time_t
waitJobTimeoutInSecs
,
const
time_t
mountTimeoutInSecs
,
const
time_t
blockMoveTimeoutInSecs
)
throw
();
const
CatalogueConfig
&
catalogueConfig
)
throw
();
/**
* Destructor
...
...
@@ -385,19 +381,19 @@ private:
* The maximum time in seconds that the data-transfer session can take to get
* the transfer job from the client.
*/
const
time_t
m_waitJobTimeout
In
Secs
;
const
time_t
m_waitJobTimeoutSecs
;
/**
* The maximum time in seconds that the data-transfer session can take to
* mount a tape.
*/
const
time_t
m_mountTimeout
In
Secs
;
const
time_t
m_mountTimeoutSecs
;
/**
* The maximum time in seconds that the data-transfer session can cease to
* move data blocks.
*/
const
time_t
m_blockMoveTimeout
In
Secs
;
const
time_t
m_blockMoveTimeoutSecs
;
/**
* The session metadata associated to the drive catalogue entry
...
...
@@ -405,52 +401,10 @@ private:
CatalogueSession
*
m_session
;
/**
*
Timer used to decide when to
sy
n
chroni
se
the vdqm
with current
stat
us
of
i
* this drive.
*
Object responsible for
sychroni
zing
the vdqm
d daemon with the
stat
e
of
* this
catalogue tape-
drive.
*/
castor
::
utils
::
Timer
m_syncVdqmTimer
;
/**
* If enough time as past then this method synchronises the vdqmd daemon with
* the state of this drive.
*/
void
syncVdqmWithDriveStateWhenNecessary
();
/**
* If this drive is UP and the vdqmd daemon thinks otherwise then this method
* synchronises the vdqm with the state of this drive.
*/
void
syncVdqmWithDriveStateIfOutOfSync
();
/**
* Synchronises the vdqmd daemon with the state of this drive.
*/
void
syncVdqmWithDriveState
();
/**
* Returns the string representation of the specified drive status from the
* vdqmd daemon.
*
* @param The drive status.
* @return The string representation.
*/
std
::
string
vdqmDriveStatusToString
(
int
status
);
/**
* This is a helper method for vdqmDriveStatusToString().
*
* If the specified bit mask is set within the specified bit set then this
* method appends the specified name of the bit mask to the end of the
* specified string stream representation of the bit set. This method also
* modifies the bit set by unsetting the bit mask if it was set.
*
* @param bitMask The bit mask to be tested against the bit set.
* @param bitMaskName The name of the bit mask.
* @param bitSet In/out parameter: The bit set.
* @param bitSetStringStream The string stream representation of the bit set.
*/
void
appendBitIfSet
(
const
int
bitMask
,
const
std
::
string
bitName
,
int
&
bitSet
,
std
::
ostringstream
&
bitSetStringStream
);
VdqmDriveSynchronizer
m_vdqmDriveSynchronizer
;
/**
* Checks that there is a tape session currently associated with the
...
...
castor/tape/tapeserver/daemon/Constants.hpp
View file @
e651c8ac
...
...
@@ -54,31 +54,38 @@ const unsigned short TAPESERVER_INTERNAL_LISTENING_PORT = 54322;
* The compile-time default value for the maximum time in seconds that the
* data-transfer session can take to get the transfer job from the client.
*/
const
time_t
TAPESERVER_WAITJOBTIMEOUT
_DEFAULT
=
60
;
// 1 minute
const
time_t
TAPESERVER_WAITJOBTIMEOUT
=
60
;
// 1 minute
/**
* The compile-time default value for the maximum time in seconds that the
* data-transfer session can take to mount a tape.
*/
const
time_t
TAPESERVER_MOUNTTIMEOUT
_DEFAULT
=
900
;
// 15 minutes
const
time_t
TAPESERVER_MOUNTTIMEOUT
=
900
;
// 15 minutes
/**
* The compile-time default value for the maximum time in seconds the
* data-transfer session of tapeserverd can cease to move data blocks.
*/
const
time_t
TAPESERVER_BLKMOVETIMEOUT_DEFAULT
=
1800
;
// 30 minutes
const
time_t
TAPESERVER_BLKMOVETIMEOUT
=
1800
;
// 30 minutes
/**
* The time interval in seconds to wait between attempts to keep the vdqmd
* daemon synchronized with the state of a tape drive within the catalogue of
* the tapeserverd daemon.
*/
const
time_t
TAPESERVER_VDQMDRIVESYNCINTERVAL
=
600
;
// 10 minutes
/**
* The compile-time default value for the number of disk threads in
* the thread pool serving disk accesses.
*/
const
uint32_t
TAPESERVER_NB_DISK_THREAD
_DEFAULT
=
10
;
const
uint32_t
TAPESERVER_NB_DISK_THREAD
=
10
;
/**
* The compile-time default value for the memory buffers exchanged between
* tape and disk threads.
*/
const
size_t
TAPESERVER_BUFSZ
_DEFAULT
=
5
*
1024
*
1024
;
const
size_t
TAPESERVER_BUFSZ
=
5
*
1024
*
1024
;
/**
* The compile time timeout value for the potentially DB based calls to the client.
...
...
castor/tape/tapeserver/daemon/DataTransferConfig.cpp
View file @
e651c8ac
...
...
@@ -56,7 +56,7 @@ castor::tape::tapeserver::daemon::DataTransferConfig
config
.
bufsz
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"BufSize"
,
castor
::
tape
::
tapeserver
::
daemon
::
TAPESERVER_BUFSZ
_DEFAULT
,
log
);
castor
::
tape
::
tapeserver
::
daemon
::
TAPESERVER_BUFSZ
,
log
);
config
.
nbBufs
=
castorConf
.
getConfEntInt
<
uint32_t
>
(
"TapeServer"
,
"NbBufs"
,
log
);
config
.
bulkRequestMigrationMaxBytes
=
castorConf
.
getConfEntInt
(
...
...
@@ -79,7 +79,7 @@ castor::tape::tapeserver::daemon::DataTransferConfig
(
uint64_t
)
TAPEBRIDGE_MAXFILESBEFOREFLUSH
,
log
);
config
.
nbDiskThreads
=
castorConf
.
getConfEntInt
(
"TapeServer"
,
"NbDiskThreads"
,
castor
::
tape
::
tapeserver
::
daemon
::
TAPESERVER_NB_DISK_THREAD
_DEFAULT
,
log
);
castor
::
tape
::
tapeserver
::
daemon
::
TAPESERVER_NB_DISK_THREAD
,
log
);
config
.
remoteFileProtocol
=
castorConf
.
getConfEntString
(
"TapeServer"
,
"RemoteFileProtocol"
,
"RFIO"
,
log
);
config
.
xrootPrivateKey
=
castorConf
.
getConfEntString
(
...
...
castor/tape/tapeserver/daemon/VdqmDriveSynchronizer.cpp
0 → 100644
View file @
e651c8ac
/******************************************************************************
*
* 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
*****************************************************************************/
#include "castor/exception/Exception.hpp"
#include "castor/tape/tapeserver/daemon/VdqmDriveSynchronizer.hpp"
#include "h/vdqm_constants.h"
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor
::
tape
::
tapeserver
::
daemon
::
VdqmDriveSynchronizer
::
VdqmDriveSynchronizer
(
log
::
Logger
&
log
,
legacymsg
::
VdqmProxy
&
vdqm
,
const
std
::
string
&
hostName
,
const
DriveConfig
&
config
,
const
time_t
syncIntervalSecs
)
throw
()
:
m_log
(
log
),
m_vdqm
(
vdqm
),
m_hostName
(
hostName
),
m_config
(
config
),
m_syncIntervalSecs
(
syncIntervalSecs
)
{
}
//------------------------------------------------------------------------------
// sync
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
VdqmDriveSynchronizer
::
sync
(
const
CatalogueDriveState
catalogueDriveState
)
{
std
::
string
errMsg
;
try
{
return
exceptionThrowingSync
(
catalogueDriveState
);
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
errMsg
=
ex
.
getMessage
().
str
();
}
catch
(
std
::
exception
&
se
)
{
errMsg
=
se
.
what
();
}
catch
(...)
{
errMsg
=
"Caught an unknown exception"
;
}
// Reaching here means an exception was thrown
// Failing to synchronise the vdqm with the drive state is not fatal
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"message"
,
errMsg
));
m_log
(
LOG_WARNING
,
"Failed to synchronise vdqm with drive state"
,
params
);
}
//------------------------------------------------------------------------------
// exceptionThrowingSync
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
VdqmDriveSynchronizer
::
exceptionThrowingSync
(
const
CatalogueDriveState
catalogueDriveState
)
{
// If the synchronization interval has expired
if
(
m_syncIntervalSecs
<
m_syncTimer
.
secs
())
{
m_syncTimer
.
reset
();
// If the tape drive is UP and ready for work
if
(
DRIVE_STATE_UP
==
catalogueDriveState
)
{
syncIfDriveNotUpInVdqm
();
}
}
}
//------------------------------------------------------------------------------
// syncIfDriveNotUpInVdqm
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
VdqmDriveSynchronizer
::
syncIfDriveNotUpInVdqm
()
{
// Query the vdqmd daemon for the state of the drive
const
int
vdqmDriveStatus
=
m_vdqm
.
getDriveStatus
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
const
bool
vdqmDriveRunning
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_ASSIGN
);
const
bool
vdqmDriveRelease
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_RELEASE
|
VDQM_UNIT_UNKNOWN
);
const
bool
vdqmDriveBadUnknown
=
vdqmDriveStatus
==
(
VDQM_UNIT_UP
|
VDQM_UNIT_BUSY
|
VDQM_UNIT_UNKNOWN
);
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatus"
,
vdqmDriveStatus
));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatusStr"
,
vdqmDriveStatusToString
(
vdqmDriveStatus
)));
m_log
(
LOG_DEBUG
,
"Got drive status from vdqm"
,
params
);
// If the vdqmd daemon thinks the drive is not read for new work
//
// We explicitely do not check (vdqmstate == UP|FREE) here, since
// VDQM changes the state to UP|BUSY before contacting tape daemon.
// The latter should not reset the state to UP|FREE in that case.
if
(
vdqmDriveRunning
||
vdqmDriveRelease
||
vdqmDriveBadUnknown
)
{
m_log
(
LOG_WARNING
,
"Vdqm is out of sync with drive status"
,
params
);
unconditionallySync
();
}
}
//------------------------------------------------------------------------------
// unconditionallySync
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
VdqmDriveSynchronizer
::
unconditionallySync
()
{
m_vdqm
.
setDriveUp
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
const
int
vdqmDriveStatus
=
m_vdqm
.
getDriveStatus
(
m_hostName
,
m_config
.
getUnitName
(),
m_config
.
getDgn
());
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
getUnitName
()));
params
.
push_back
(
log
::
Param
(
"dgn"
,
m_config
.
getDgn
()));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatus"
,
vdqmDriveStatus
));
params
.
push_back
(
log
::
Param
(
"vdqmDriveStatusStr"
,
vdqmDriveStatusToString
(
vdqmDriveStatus
)));