Commit 0d38d0c8 authored by Steven Murray's avatar Steven Murray
Browse files

Created the following class:

    castor::utils::SmartFd

This class should eventually replace the folowing class:

    castor::tape::utils::SmartFd
parent 0a091aff
......@@ -244,6 +244,7 @@ set (CLIENT_LIB_SRC_FILES
stager/NsFileId.cpp
stager/BulkRequestResult.cpp
stager/FileResult.cpp
utils/SmartFd.cpp
utils/utils.cpp
vdqm/ClientIdentification.cpp
vdqm/TapeDrive.cpp
......
/******************************************************************************
* castor/utils/SmartFd.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 Nicola.Bessone@cern.ch Steven.Murray@cern.ch
*****************************************************************************/
#include "castor/utils/SmartFd.hpp"
#include <errno.h>
#include <unistd.h>
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
castor::utils::SmartFd::SmartFd() throw():
m_fd(-1), m_closedCallback(NULL) {
}
//-----------------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------------
castor::utils::SmartFd::SmartFd(const int fd) throw():
m_fd(fd), m_closedCallback(NULL) {
}
//-----------------------------------------------------------------------------
// setClosedCallback
//-----------------------------------------------------------------------------
void castor::utils::SmartFd::setClosedCallback(ClosedCallback closedCallback)
throw() {
m_closedCallback = closedCallback;
}
//-----------------------------------------------------------------------------
// reset
//-----------------------------------------------------------------------------
void castor::utils::SmartFd::reset(const int fd = -1) throw() {
// If the new file descriptor is not the one already owned
if(fd != m_fd) {
// If this SmartFd still owns a file descriptor, then close it
if(m_fd >= 0) {
close(m_fd);
if(m_closedCallback) {
try {
(*m_closedCallback)(m_fd);
} catch(...) {
// Ignore any exception thrown my the m_closedCallback function
// because this reset function maybe called by the destructor of
// SmartFd
}
}
}
// Take ownership of the new file descriptor
m_fd = fd;
}
}
//-----------------------------------------------------------------------------
// SmartFd assignment operator
//-----------------------------------------------------------------------------
castor::utils::SmartFd &castor::utils::SmartFd::operator=(SmartFd& obj)
throw() {
reset(obj.release());
return *this;
}
//-----------------------------------------------------------------------------
// destructor
//-----------------------------------------------------------------------------
castor::utils::SmartFd::~SmartFd() {
reset();
}
//-----------------------------------------------------------------------------
// get
//-----------------------------------------------------------------------------
int castor::utils::SmartFd::get() const throw() {
return m_fd;
}
//-----------------------------------------------------------------------------
// release
//-----------------------------------------------------------------------------
int castor::utils::SmartFd::release() throw(castor::exception::Exception) {
// If this SmartFd does not own a file descriptor
if(m_fd < 0) {
castor::exception::Exception ex(EPERM);
ex.getMessage() <<
"Smart file-descriptor does not own a file-descriptor";
throw(ex);
}
const int tmpFd = m_fd;
// A negative number indicates this SmartFd does not own a file descriptor
m_fd = -1;
return tmpFd;
}
/******************************************************************************
* castor/utils/SmartFd.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 Nicola.Bessone@cern.ch Steven.Murray@cern.ch
*****************************************************************************/
#ifndef CASTOR_UTILS_SMARTFD
#define CASTOR_UTILS_SMARTFD
#include "castor/exception/Exception.hpp"
namespace castor {
namespace utils {
/**
* A smart file descriptor that owns a basic file descriptor. When the smart
* file descriptor goes out of scope, it will close the file descriptor it
* owns.
*/
class SmartFd {
public:
/**
* A pointer to a callback function that will called by the Smart
* immediately after the SmartFd has closed the file-descriptor it owns.
*
* Please note that any exception thrown by this function will be ignored
* because this function maybe called by the destructor of SmartFd.
*
* @param closedFd The value of the file descriptor that was closed.
*/
typedef void (*ClosedCallback)(int closedFd);
/**
* Constructor.
*
*/
SmartFd() throw();
/**
* Constructor.
*
* @param fd The file descriptor to be owned by the smart file
* descriptor.
*/
SmartFd(const int fd) throw();
/**
* Sets the function to be called back by the SmartFd immediately after
* the SmartFd has closed the file-descriptor it owns.
*
* Setting the callback function to NULL means that no function will be
* called.
*
* Please note any exception thrown by the callback function will be
* ignored because the callback function maybe called by the destructor of
* SmartFd.
*
* @param closedCallback This function will be called immediately after
* the SmartFd has closed the file-descriptor it owns.
* Please note that any exception thrown by this
* function will be ignored because this function
* maybe called by the destructor of SmartFd.
*/
void setClosedCallback(ClosedCallback closedCallback) throw();
/**
* Take ownership of the specified file descriptor, closing the previously
* owned file descriptor if there is one and it is not the same as the one
* specified.
*
* @param fd The file descriptor to be owned, defaults to -1 if not
* specified, where a negative number means this SmartFd does not
* own a file descriptor.
*/
void reset(const int fd) throw();
/**
* SmartFd assignment operator.
*
* This function does the following:
* <ul>
* <li> Calls release on the previous owner (obj);
* <li> Closes the file descriptor of this object if it already owns one.
* <li> Makes this object the owner of the file descriptor released from
* the previous owner (obj).
* </ul>
*/
SmartFd &operator=(SmartFd& obj) throw();
/**
* Destructor.
*
* Closes the owned file descriptor if there is one.
*/
~SmartFd();
/**
* Returns the owned file descriptor or a negative number if this SmartFd
* does not own a file descriptor.
*
* @return The owned file desccriptor.
*/
int get() const throw();
/**
* Releases the owned file descriptor.
*
* @return The released file descriptor.
*/
int release() throw(castor::exception::Exception);
private:
/**
* The owned file descriptor. A negative value means this SmartFd does not
* own a file descriptor..
*/
int m_fd;
/**
* The function to be called immediately after the SmartFd has closed its
* file-descriptor. A value of null means no function will be called.
*/
ClosedCallback m_closedCallback;
/**
* Private copy-constructor to prevent users from trying to create a new
* copy of an object of this class.
* Not implemented so that it cannot be called
*/
SmartFd(const SmartFd &obj) throw();
}; // class SmartFd
} // namespace utils
} // namespace castor
#endif // CASTOR_TAPE_UTILS_SMARTFD
/******************************************************************************
* castor/utils/SmartFd.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/utils/SmartFd.hpp"
#include <gtest/gtest.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
namespace unitTests {
class castor_utils_SmartFdTest : public ::testing::Test {
protected:
static int s_fd;
static bool s_closedCallbackWasCalled;
virtual void SetUp() {
s_fd = -1;
s_closedCallbackWasCalled = false;
}
virtual void TearDown() {
}
static void closedCallback(int closedfd) {
s_fd = closedfd;
s_closedCallbackWasCalled = true;
}
};
int castor_utils_SmartFdTest::s_fd = -1;
bool castor_utils_SmartFdTest::s_closedCallbackWasCalled = false;
TEST_F(castor_utils_SmartFdTest, testClosedCallback) {
using namespace castor::utils;
ASSERT_EQ(-1, s_fd);
ASSERT_EQ(false, s_closedCallbackWasCalled);
int fd = socket(PF_LOCAL, SOCK_STREAM, 0);
ASSERT_NE(-1, fd);
{
SmartFd sfd(fd);
sfd.setClosedCallback(closedCallback);
}
ASSERT_EQ(fd, s_fd);
ASSERT_EQ(true, s_closedCallbackWasCalled);
}
} // namespace unitTests
......@@ -37,6 +37,7 @@ add_executable(castorUnitTests
../castor/tape/tapeserver/exception/ExceptionTest.cpp
../castor/tape/tapeserver/file/StructuresTest.cpp
../castor/tape/tapeserver/threading/ThreadingTests.cpp
../castor/utils/SmartFdTest.cpp
../castor/utils/UtilsTest.cpp
)
set_property(SOURCE ../SCSI/StructuresTest.cpp
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment