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
4f040a9b
Commit
4f040a9b
authored
Nov 05, 2014
by
Steven Murray
Browse files
A cleaner is now always ran when you type /etc/init.d/tapeserverd stop
parent
7bea3a41
Changes
14
Hide whitespace changes
Inline
Side-by-side
castor/messages/ForkCleaner.proto
View file @
4f040a9b
...
...
@@ -29,4 +29,7 @@ message ForkCleaner {
// Description of the tape associated with the drive
required
string
vid
=
5
;
// Description of the cleaner job
required
uint32
drivereadydelayinseconds
=
6
;
}
castor/tape/tapeserver/daemon/CatalogueCleanerSession.cpp
View file @
4f040a9b
...
...
@@ -35,9 +35,11 @@ castor::tape::tapeserver::daemon::CatalogueCleanerSession *
const
tape
::
utils
::
DriveConfig
&
driveConfig
,
ProcessForkerProxy
&
processForker
,
const
std
::
string
&
vid
,
const
time_t
assignmentTime
)
{
const
time_t
assignmentTime
,
const
uint32_t
driveReadyDelayInSeconds
)
{
const
pid_t
pid
=
processForker
.
forkCleaner
(
driveConfig
,
vid
);
const
pid_t
pid
=
processForker
.
forkCleaner
(
driveConfig
,
vid
,
driveReadyDelayInSeconds
);
return
new
CatalogueCleanerSession
(
log
,
...
...
castor/tape/tapeserver/daemon/CatalogueCleanerSession.hpp
View file @
4f040a9b
...
...
@@ -54,6 +54,8 @@ public:
* be set to the empty string.
* @param assignmentTime The time at which a job was assigned to the tape
* drive.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
* @return A newly created CatalogueCleanerSession object.
*/
static
CatalogueCleanerSession
*
create
(
...
...
@@ -62,7 +64,8 @@ public:
const
tape
::
utils
::
DriveConfig
&
driveConfig
,
ProcessForkerProxy
&
processForker
,
const
std
::
string
&
vid
,
const
time_t
assignmentTime
);
const
time_t
assignmentTime
,
const
uint32_t
driveReadyDelayInSeconds
);
/**
* Handles a tick in time. Time driven actions such as alarms should be
...
...
castor/tape/tapeserver/daemon/CatalogueDrive.cpp
View file @
4f040a9b
...
...
@@ -524,7 +524,8 @@ void castor::tape::tapeserver::daemon::CatalogueDrive::receivedLabelJob(
// createCleaner
//-----------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
createCleaner
(
const
std
::
string
&
vid
,
const
time_t
assignmentTime
)
{
const
std
::
string
&
vid
,
const
time_t
assignmentTime
,
const
uint32_t
driveReadyDelayInSeconds
)
{
try
{
// Create a cleaner session
m_session
=
CatalogueCleanerSession
::
create
(
...
...
@@ -533,7 +534,8 @@ void castor::tape::tapeserver::daemon::CatalogueDrive::createCleaner(
m_config
,
m_processForker
,
vid
,
assignmentTime
);
assignmentTime
,
driveReadyDelayInSeconds
);
}
catch
(
castor
::
exception
::
Exception
&
ne
)
{
castor
::
exception
::
Exception
ex
;
ex
.
getMessage
()
<<
"Failed to create cleaner session: "
<<
...
...
@@ -591,7 +593,9 @@ void castor::tape::tapeserver::daemon::CatalogueDrive::sessionFailed() {
session
->
sessionFailed
();
if
(
CatalogueSession
::
SESSION_TYPE_CLEANER
!=
session
->
getType
())
{
createCleaner
(
session
->
getVid
(),
session
->
getAssignmentTime
());
const
uint32_t
driveReadyDelayInSeconds
=
60
;
createCleaner
(
session
->
getVid
(),
session
->
getAssignmentTime
(),
driveReadyDelayInSeconds
);
}
else
{
changeState
(
DRIVE_STATE_DOWN
);
m_vdqm
.
setDriveDown
(
m_hostName
,
m_config
.
unitName
,
m_config
.
dgn
);
...
...
@@ -605,7 +609,9 @@ void castor::tape::tapeserver::daemon::CatalogueDrive::sessionFailed() {
session
->
sessionFailed
();
changeState
(
DRIVE_STATE_WAITSHUTDOWNCLEANER
);
createCleaner
(
session
->
getVid
(),
session
->
getAssignmentTime
());
const
uint32_t
driveReadyDelayInSeconds
=
60
;
createCleaner
(
session
->
getVid
(),
session
->
getAssignmentTime
(),
driveReadyDelayInSeconds
);
}
break
;
case
DRIVE_STATE_WAITSHUTDOWNCLEANER
:
...
...
@@ -803,44 +809,58 @@ time_t castor::tape::tapeserver::daemon::CatalogueDrive::
// shutdown
//------------------------------------------------------------------------------
void
castor
::
tape
::
tapeserver
::
daemon
::
CatalogueDrive
::
shutdown
()
{
const
DriveState
previousState
=
m_state
;
// If there is no running session
if
(
NULL
==
m_session
)
{
changeState
(
DRIVE_STATE_SHUTDOWN
);
if
(
DRIVE_STATE_DOWN
!=
previousState
)
{
m_vdqm
.
setDriveDown
(
m_hostName
,
m_config
.
unitName
,
m_config
.
dgn
);
}
changeState
(
DRIVE_STATE_WAITSHUTDOWNCLEANER
);
return
;
}
// Create a cleaner process to make 100% sure the tape drive is empty
const
std
::
string
vid
=
""
;
// Empty string means VID is not known
const
time_t
assignmentTime
=
time
(
NULL
);
const
uint32_t
driveReadyDelayInSeconds
=
0
;
createCleaner
(
vid
,
assignmentTime
,
driveReadyDelayInSeconds
);
changeState
(
DRIVE_STATE_WAITSHUTDOWNKILL
);
// Else there is a running session
}
else
{
const
pid_t
sessionPid
=
m_session
->
getPid
();
const
CatalogueSession
::
Type
sessionType
=
m_session
->
getType
();
const
char
*
sessionTypeStr
=
CatalogueSession
::
sessionTypeToStr
(
sessionType
);
// If the running session is a cleaner
if
(
CatalogueSession
::
SESSION_TYPE_CLEANER
==
m_session
->
getType
())
{
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
unitName
));
params
.
push_back
(
log
::
Param
(
"sessionType"
,
sessionTypeStr
));
params
.
push_back
(
log
::
Param
(
"sessionPid"
,
sessionPid
));
changeState
(
DRIVE_STATE_WAITSHUTDOWNCLEANER
);
// Kill the non-cleaner session
if
(
kill
(
sessionPid
,
SIGKILL
))
{
const
std
::
string
message
=
castor
::
utils
::
errnoToString
(
errno
);
params
.
push_back
(
log
::
Param
(
"message"
,
message
));
m_log
(
LOG_ERR
,
"Failed to kill non-cleaner session whilst shutting down"
,
params
);
// Else the running session is not a cleaner
}
else
{
// Nothing else can be done, mark drive as shutdown and return
changeState
(
DRIVE_STATE_SHUTDOWN
);
changeState
(
DRIVE_STATE_WAITSHUTDOWNKILL
);
return
;
}
m_log
(
LOG_WARNING
,
"Sent SIGKILL to tape-session child-process"
,
params
);
const
pid_t
sessionPid
=
m_session
->
getPid
();
const
CatalogueSession
::
Type
sessionType
=
m_session
->
getType
();
const
char
*
sessionTypeStr
=
CatalogueSession
::
sessionTypeToStr
(
sessionType
);
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
m_config
.
unitName
));
params
.
push_back
(
log
::
Param
(
"sessionType"
,
sessionTypeStr
));
params
.
push_back
(
log
::
Param
(
"sessionPid"
,
sessionPid
));
// Kill the non-cleaner session
if
(
kill
(
sessionPid
,
SIGKILL
))
{
const
std
::
string
message
=
castor
::
utils
::
errnoToString
(
errno
);
params
.
push_back
(
log
::
Param
(
"message"
,
message
));
m_log
(
LOG_ERR
,
"Failed to kill non-cleaner session whilst shutting"
" down"
,
params
);
// Nothing else can be done, mark drive as shutdown
changeState
(
DRIVE_STATE_SHUTDOWN
);
}
else
{
m_log
(
LOG_WARNING
,
"Sent SIGKILL to tape-session child-process"
,
params
);
}
}
// Else the running session is not a cleaner
}
// Else there is a running session
}
//------------------------------------------------------------------------------
...
...
castor/tape/tapeserver/daemon/CatalogueDrive.hpp
View file @
4f040a9b
...
...
@@ -333,8 +333,11 @@ public:
* @param The assignment time associated with the tape drive or 0 if not
* known. The assignment time is given as the number of seconds elapsed
* since the Epoch.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
*/
void
createCleaner
(
const
std
::
string
&
vid
,
const
time_t
assignmentTime
);
void
createCleaner
(
const
std
::
string
&
vid
,
const
time_t
assignmentTime
,
const
uint32_t
driveReadyDelayInSeconds
);
/**
* Moves the state of the tape drive to DRIVE_STATE_UP if the
...
...
castor/tape/tapeserver/daemon/CleanerSession.cpp
View file @
4f040a9b
...
...
@@ -32,13 +32,15 @@ castor::tape::tapeserver::daemon::CleanerSession::CleanerSession(
castor
::
log
::
Logger
&
log
,
const
utils
::
DriveConfig
&
driveConfig
,
System
::
virtualWrapper
&
sysWrapper
,
const
std
::
string
&
vid
)
:
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
)
:
m_capUtils
(
capUtils
),
m_mc
(
mc
),
m_log
(
log
),
m_driveConfig
(
driveConfig
),
m_sysWrapper
(
sysWrapper
),
m_vid
(
vid
)
{
m_vid
(
vid
),
m_driveReadyDelayInSeconds
(
driveReadyDelayInSeconds
)
{
}
//------------------------------------------------------------------------------
...
...
@@ -69,11 +71,15 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
}
//temporization to allow for actions to complete
try
{
drive
->
waitUntilReady
(
60
);
//wait 1 minute for a possible ongoing mount to complete or for an IO operation to complete
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
log
::
Param
params
[]
=
{
log
::
Param
(
"message"
,
ex
.
getMessage
().
str
())};
m_log
(
LOG_INFO
,
"Cleaner session caught a non-fatal exception while waiting for the drive to become ready. One of the reasons we get here is if the drive has no tape inside."
,
params
);
if
(
0
!=
m_driveReadyDelayInSeconds
)
{
try
{
drive
->
waitUntilReady
(
m_driveReadyDelayInSeconds
);
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
log
::
Param
params
[]
=
{
log
::
Param
(
"message"
,
ex
.
getMessage
().
str
())};
m_log
(
LOG_INFO
,
"Cleaner session caught a non-fatal exception whilst"
" waiting for the drive to become ready. One of the reasons we get here"
" is if the drive has no tape inside."
,
params
);
}
}
//here we check if the drive contains a tape: if not, there's nothing to clean
...
...
castor/tape/tapeserver/daemon/CleanerSession.hpp
View file @
4f040a9b
...
...
@@ -55,6 +55,8 @@ namespace daemon {
* @param sysWrapper Object representing the operating system.
* @param vid The volume identifier of the mounted tape if known,
* else the empty string.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
*/
CleanerSession
(
server
::
ProcessCap
&
capUtils
,
...
...
@@ -62,7 +64,8 @@ namespace daemon {
castor
::
log
::
Logger
&
log
,
const
utils
::
DriveConfig
&
driveConfig
,
System
::
virtualWrapper
&
sysWrapper
,
const
std
::
string
&
vid
);
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
);
/**
* Execute the session and return the type of action to be performed
...
...
@@ -118,6 +121,12 @@ namespace daemon {
* string.
*/
const
std
::
string
m_vid
;
/**
* The maximum number of seconds to wait for the drive to be raedy with a
* tape inside of it.
*/
const
uint32_t
m_driveReadyDelayInSeconds
;
};
// class CleanerSession
...
...
castor/tape/tapeserver/daemon/ProcessForker.cpp
View file @
4f040a9b
...
...
@@ -289,6 +289,8 @@ castor::tape::tapeserver::daemon::ProcessForker::MsgHandlerResult
std
::
list
<
log
::
Param
>
params
;
params
.
push_back
(
log
::
Param
(
"unitName"
,
rqst
.
unitname
()));
params
.
push_back
(
log
::
Param
(
"vid"
,
rqst
.
vid
()));
params
.
push_back
(
log
::
Param
(
"driveReadyDelayInSeconds"
,
rqst
.
drivereadydelayinseconds
()));
m_log
(
LOG_INFO
,
"ProcessForker handling ForkCleaner message"
,
params
);
// Fork a label session
...
...
@@ -492,7 +494,8 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
m_log
,
driveConfig
,
sWrapper
,
rqst
.
vid
());
rqst
.
vid
(),
rqst
.
drivereadydelayinseconds
());
return
cleanerSession
.
execute
();
}
catch
(
castor
::
exception
::
Exception
&
ex
)
{
throw
ex
;
...
...
castor/tape/tapeserver/daemon/ProcessForkerConnectionHandler.cpp
View file @
4f040a9b
...
...
@@ -241,7 +241,9 @@ void castor::tape::tapeserver::daemon::ProcessForkerConnectionHandler::
const
std
::
string
vid
=
drive
.
getVidForCleaner
();
const
time_t
assignmentTime
=
drive
.
getAssignmentTimeForCleaner
();
drive
.
sessionFailed
();
return
drive
.
createCleaner
(
vid
,
assignmentTime
);
const
uint32_t
driveReadyDelayInSeconds
=
60
;
return
drive
.
createCleaner
(
vid
,
assignmentTime
,
driveReadyDelayInSeconds
);
}
default:
// Should never happen
...
...
castor/tape/tapeserver/daemon/ProcessForkerProxy.hpp
View file @
4f040a9b
...
...
@@ -81,10 +81,12 @@ public:
* tape in the drive if there is in fact a tape in the drive and its volume
* identifier is known. If the volume identifier is not known then this
* parameter should be set to an empty string.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
* @return The process identifier of the newly forked session.
*/
virtual
pid_t
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
)
=
0
;
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
)
=
0
;
};
// class ProcessForkerProxy
...
...
castor/tape/tapeserver/daemon/ProcessForkerProxyDummy.cpp
View file @
4f040a9b
...
...
@@ -55,7 +55,8 @@ pid_t castor::tape::tapeserver::daemon::ProcessForkerProxyDummy::
// forkCleaner
//------------------------------------------------------------------------------
pid_t
castor
::
tape
::
tapeserver
::
daemon
::
ProcessForkerProxyDummy
::
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
)
{
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
)
{
// This is a dummy method and so intentionally does nothing
return
0
;
}
castor/tape/tapeserver/daemon/ProcessForkerProxyDummy.hpp
View file @
4f040a9b
...
...
@@ -82,19 +82,17 @@ public:
/**
* Forks a cleaner session for the specified tape drive.
*
* PLEASE NOTE that this method is a dummy method and intentionally does
* nothing.
*
* @param driveConfig The configuration of the tape drive.
* @param vid If known then this string specifies the volume identifier of the
* tape in the drive if there is in fact a tape in the drive and its volume
* identifier is known. If the volume identifier is not known then this
* parameter should be set to an empty string.
* @return The process identifier of the newly forked session which will
* always be 0 because this is a dummy method.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
* @return The process identifier of the newly forked session.
*/
pid_t
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
);
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
);
};
// class ProcessForkerProxySocket
...
...
castor/tape/tapeserver/daemon/ProcessForkerProxySocket.cpp
View file @
4f040a9b
...
...
@@ -183,10 +183,12 @@ castor::messages::ForkLabel castor::tape::tapeserver::daemon::
// forkCleaner
//------------------------------------------------------------------------------
pid_t
castor
::
tape
::
tapeserver
::
daemon
::
ProcessForkerProxySocket
::
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
)
{
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
)
{
// Request the process forker to fork a label session
const
messages
::
ForkCleaner
rqst
=
createForkCleanerMsg
(
driveConfig
,
vid
);
const
messages
::
ForkCleaner
rqst
=
createForkCleanerMsg
(
driveConfig
,
vid
,
driveReadyDelayInSeconds
);
ProcessForkerUtils
::
writeFrame
(
m_socketFd
,
rqst
);
// Read back the reply
...
...
@@ -205,7 +207,8 @@ pid_t castor::tape::tapeserver::daemon::ProcessForkerProxySocket::
//------------------------------------------------------------------------------
castor
::
messages
::
ForkCleaner
castor
::
tape
::
tapeserver
::
daemon
::
ProcessForkerProxySocket
::
createForkCleanerMsg
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
)
{
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
)
{
messages
::
ForkCleaner
msg
;
// Description of the tape drive
...
...
@@ -214,5 +217,8 @@ castor::messages::ForkCleaner castor::tape::tapeserver::daemon::
// Description of the tape
msg
.
set_vid
(
vid
);
// Description of the cleaner job
msg
.
set_drivereadydelayinseconds
(
driveReadyDelayInSeconds
);
return
msg
;
}
castor/tape/tapeserver/daemon/ProcessForkerProxySocket.hpp
View file @
4f040a9b
...
...
@@ -96,16 +96,18 @@ public:
/**
* Forks a cleaner session for the specified tape drive.
*
*
* @param driveConfig The configuration of the tape drive.
* @param vid If known then this string specifies the volume identifier of the
* tape in the drive if there is in fact a tape in the drive and its volume
* identifier is known. If the volume identifier is not known then this
* parameter should be set to an empty string.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
* @return The process identifier of the newly forked session.
*/
pid_t
forkCleaner
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
);
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
);
private:
...
...
@@ -193,10 +195,13 @@ private:
* @param driveConfig The configuration of the tape drive.
* @param vid The volume identifier of the tape associated with the tape
* drive.
* @param driveReadyDelayInSeconds The maximum number of seconds to wait for
* the drive to be raedy with a tape inside of it.
* @return The message.
*/
messages
::
ForkCleaner
createForkCleanerMsg
(
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
);
const
utils
::
DriveConfig
&
driveConfig
,
const
std
::
string
&
vid
,
const
uint32_t
driveReadyDelayInSeconds
);
};
// class ProcessForkerProxySocket
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment