summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen D. Huston <shuston@apache.org>2008-10-07 15:19:50 +0000
committerStephen D. Huston <shuston@apache.org>2008-10-07 15:19:50 +0000
commit4eb2dca5b9ae07228f542cd798b44cc44ea96c09 (patch)
tree9d1de3abe8bca9ff0617432056217bfab12b00f5
parentcdae2a877123056b69a91dd8ca2196577654de2d (diff)
downloadqpid-python-4eb2dca5b9ae07228f542cd798b44cc44ea96c09.tar.gz
Abstract native file-locking and directory detection/creation to portable classes LockFile and FileSysDir; resolves QPID-1148
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@702513 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--cpp/src/Makefile.am4
-rw-r--r--cpp/src/qpid/DataDir.cpp20
-rw-r--r--cpp/src/qpid/broker/Daemon.cpp23
-rwxr-xr-xcpp/src/qpid/sys/FileSysDir.h62
-rw-r--r--cpp/src/qpid/sys/LockFile.h55
-rwxr-xr-xcpp/src/qpid/sys/posix/FileSysDir.cpp54
-rwxr-xr-xcpp/src/qpid/sys/posix/LockFile.cpp89
-rw-r--r--cpp/src/qpid/sys/posix/LockFile.h58
-rw-r--r--cpp/src/qpid/sys/windows/FileSysDir.cpp53
-rwxr-xr-xcpp/src/qpid/sys/windows/LockFile.cpp83
10 files changed, 405 insertions, 96 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index f9c6e74bd8..92cdb782a3 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -71,6 +71,8 @@ posix_plat_src = \
qpid/sys/posix/IOHandle.cpp \
qpid/sys/posix/Socket.cpp \
qpid/sys/posix/AsynchIO.cpp \
+ qpid/sys/posix/FileSysDir.cpp \
+ qpid/sys/posix/LockFile.cpp \
qpid/sys/posix/Time.cpp \
qpid/sys/posix/Thread.cpp \
qpid/sys/posix/Shlib.cpp \
@@ -85,7 +87,6 @@ posix_plat_hdr = \
qpid/sys/posix/PrivatePosix.h \
qpid/sys/posix/Mutex.h \
qpid/sys/posix/Fork.h \
- qpid/sys/posix/LockFile.h \
qpid/sys/posix/PollableCondition.h \
qpid/sys/posix/IntegerTypes.h
@@ -593,6 +594,7 @@ nobase_include_HEADERS = \
qpid/sys/ConnectionOutputHandlerPtr.h \
qpid/sys/DeletionManager.h \
qpid/sys/Dispatcher.h \
+ qpid/sys/FileSysDir.h \
qpid/sys/IntegerTypes.h \
qpid/sys/IOHandle.h \
qpid/sys/LockPtr.h \
diff --git a/cpp/src/qpid/DataDir.cpp b/cpp/src/qpid/DataDir.cpp
index 18b52b9b8f..4d61d22219 100644
--- a/cpp/src/qpid/DataDir.cpp
+++ b/cpp/src/qpid/DataDir.cpp
@@ -21,12 +21,7 @@
#include "Exception.h"
#include "DataDir.h"
#include "qpid/log/Statement.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <cerrno>
-#include <unistd.h>
+#include "qpid/sys/FileSysDir.h"
namespace qpid {
@@ -40,16 +35,9 @@ DataDir::DataDir (std::string path) :
return;
}
- const char *cpath = dirPath.c_str ();
- struct stat s;
- if (::stat(cpath, &s)) {
- if (errno == ENOENT) {
- if (::mkdir(cpath, 0755))
- throw Exception ("Can't create data directory: " + path);
- }
- else
- throw Exception ("Data directory not found: " + path);
- }
+ sys::FileSysDir dir(dirPath);
+ if (!dir.exists())
+ dir.mkdir();
std::string lockFileName(path);
lockFileName += "/lock";
lockFile = std::auto_ptr<sys::LockFile>(new sys::LockFile(lockFileName, true));
diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp
index 1796c8db04..8790653c8d 100644
--- a/cpp/src/qpid/broker/Daemon.cpp
+++ b/cpp/src/qpid/broker/Daemon.cpp
@@ -168,22 +168,14 @@ void Daemon::ready(uint16_t port) { // child
LockFile lf(lockFile, true);
/*
- * Rewritten using low-level IO, for compatibility
- * with earlier Boost versions, i.e. 103200.
- */
- /*
* Write the PID to the lockfile.
*/
- pid_t pid = getpid();
- int desired_write = sizeof(pid_t);
- if ( desired_write > ::write(lf.fd, & pid, desired_write) ) {
- throw Exception("Cannot write lock file "+lockFile);
- }
+ lf.writePid();
/*
* Write the port number to the parent.
*/
- desired_write = sizeof(uint16_t);
+ int desired_write = sizeof(uint16_t);
if ( desired_write > ::write(pipeFds[1], & port, desired_write) ) {
throw Exception("Error writing to parent." );
}
@@ -198,16 +190,7 @@ void Daemon::ready(uint16_t port) { // child
pid_t Daemon::getPid(string _pidDir, uint16_t port) {
string name = pidFile(_pidDir, port);
LockFile lf(name, false);
- pid_t pid;
-
- /*
- * Rewritten using low-level IO, for compatibility
- * with earlier Boost versions, i.e. 103200.
- */
- int desired_read = sizeof(pid_t);
- if ( desired_read > ::read(lf.fd, & pid, desired_read) ) {
- throw Exception("Cannot read lock file " + name);
- }
+ pid_t pid = lf.readPid();
if (kill(pid, 0) < 0 && errno != EPERM) {
unlink(name.c_str());
throw Exception("Removing stale lock file "+name);
diff --git a/cpp/src/qpid/sys/FileSysDir.h b/cpp/src/qpid/sys/FileSysDir.h
new file mode 100755
index 0000000000..ffe7823f0a
--- /dev/null
+++ b/cpp/src/qpid/sys/FileSysDir.h
@@ -0,0 +1,62 @@
+#ifndef QPID_SYS_FILESYSDIR_H
+#define QPID_SYS_FILESYSDIR_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <string>
+
+namespace qpid {
+namespace sys {
+
+/**
+ * @class FileSysDir
+ *
+ * Represents a filesystem directory accessible from the local host.
+ * This class simply checks existence of, and creates, a directory. It could
+ * be added to later to list contents, etc.
+ */
+class FileSysDir
+{
+ const std::string dirPath;
+
+ public:
+
+ FileSysDir (std::string path) : dirPath(path) {}
+ ~FileSysDir () {}
+
+ /**
+ * Check to see if the directory exists and is a directory. Throws an
+ * exception if there is an error checking existence or if the path
+ * exists but is not a directory.
+ *
+ * @retval true if the path exists and is a directory.
+ * @retval false if the path does not exist.
+ */
+ bool exists (void) const;
+
+ void mkdir(void);
+
+ std::string getPath () { return dirPath; }
+};
+
+}} // namespace qpid::sys
+
+#endif /*!QPID_SYS_FILESYSDIR_H*/
diff --git a/cpp/src/qpid/sys/LockFile.h b/cpp/src/qpid/sys/LockFile.h
index f06cd6a47d..2ff8c2f6d4 100644
--- a/cpp/src/qpid/sys/LockFile.h
+++ b/cpp/src/qpid/sys/LockFile.h
@@ -19,7 +19,60 @@
*
*/
-#include "posix/LockFile.h"
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+#include "IntegerTypes.h"
+
+namespace qpid {
+namespace sys {
+
+class LockFilePrivate;
+
+/**
+ * @class LockFile
+ *
+ * LockFile represents a locked file suitable for a coarse-grain system
+ * lock. For example, the broker uses this to ensure that only one broker
+ * runs. A common usage idiom is to store the current "owner" process ID
+ * in the lock file - if the lock file exists, but the stored process ID
+ * doesn't, the old owner has probably died without cleaning up the lock
+ * file.
+ */
+class LockFile : private boost::noncopyable
+{
+ boost::shared_ptr<LockFilePrivate> impl;
+
+ std::string path;
+ bool created;
+
+public:
+ LockFile(const std::string& path_, bool create);
+ ~LockFile();
+
+ /**
+ * Read the process ID from the lock file. This method assumes that
+ * if there is a process ID in the file, it was written there by
+ * writePid(); thus, it's at the start of the file.
+ *
+ * Throws an exception if there is an error reading the file.
+ *
+ * @returns The stored process ID. No validity check is done on it.
+ */
+ pid_t readPid(void) const;
+
+ /**
+ * Write the current process's ID to the lock file. It's written at
+ * the start of the file and will overwrite any other content that
+ * may be in the file.
+ *
+ * Throws an exception if the write fails.
+ */
+ void writePid(void);
+};
+
+}} /* namespace qpid::sys */
#endif /*!_sys_LockFile_h*/
diff --git a/cpp/src/qpid/sys/posix/FileSysDir.cpp b/cpp/src/qpid/sys/posix/FileSysDir.cpp
new file mode 100755
index 0000000000..22dc487e74
--- /dev/null
+++ b/cpp/src/qpid/sys/posix/FileSysDir.cpp
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/FileSysDir.h"
+#include "qpid/sys/StrError.h"
+#include "qpid/Exception.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <cerrno>
+#include <unistd.h>
+
+namespace qpid {
+namespace sys {
+
+bool FileSysDir::exists (void) const
+{
+ const char *cpath = dirPath.c_str ();
+ struct stat s;
+ if (::stat(cpath, &s)) {
+ if (errno == ENOENT) {
+ return false;
+ }
+ throw qpid::Exception (strError(errno) +
+ ": Can't check directory: " + dirPath);
+ }
+ if (S_ISDIR(s.st_mode))
+ return true;
+ throw qpid::Exception(dirPath + " is not a directory");
+}
+
+void FileSysDir::mkdir(void)
+{
+ if (::mkdir(dirPath.c_str(), 0755))
+ throw Exception ("Can't create directory: " + dirPath);
+}
+
+}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/posix/LockFile.cpp b/cpp/src/qpid/sys/posix/LockFile.cpp
new file mode 100755
index 0000000000..af9ecd7d66
--- /dev/null
+++ b/cpp/src/qpid/sys/posix/LockFile.cpp
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright (c) 2008 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/LockFile.h"
+
+#include <string>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "check.h"
+
+namespace qpid {
+namespace sys {
+
+class LockFilePrivate {
+ friend class LockFile;
+
+ int fd;
+
+public:
+ LockFilePrivate(int f) : fd(f) {}
+};
+
+LockFile::LockFile(const std::string& path_, bool create)
+ : path(path_), created(create) {
+
+ errno = 0;
+ int flags=create ? O_WRONLY|O_CREAT|O_NOFOLLOW : O_RDWR;
+ int fd = ::open(path.c_str(), flags, 0644);
+ if (fd < 0) throw ErrnoException("Cannot open " + path, errno);
+ if (::lockf(fd, F_TLOCK, 0) < 0) {
+ ::close(fd);
+ throw ErrnoException("Cannot lock " + path, errno);
+ }
+ impl.reset(new LockFilePrivate(fd));
+}
+
+LockFile::~LockFile() {
+ if (impl) {
+ int f = impl->fd;
+ if (f >= 0) {
+ (void) ::lockf(f, F_ULOCK, 0); // Suppress warnings about ignoring return value.
+ ::close(f);
+ impl->fd = -1;
+ }
+ }
+}
+
+pid_t LockFile::readPid(void) const {
+ if (!impl)
+ throw Exception("Lock file not open");
+
+ pid_t pid;
+ int desired_read = sizeof(pid_t);
+ if (desired_read > ::read(impl->fd, &pid, desired_read) ) {
+ throw Exception("Cannot read lock file " + path);
+ }
+ return pid;
+}
+
+void LockFile::writePid(void) {
+ if (!impl)
+ throw Exception("Lock file not open");
+
+ pid_t pid = getpid();
+ int desired_write = sizeof(pid_t);
+ if (desired_write > ::write(impl->fd, &pid, desired_write)) {
+ throw Exception("Cannot write lock file " + path);
+ }
+}
+
+}} /* namespace qpid::sys */
diff --git a/cpp/src/qpid/sys/posix/LockFile.h b/cpp/src/qpid/sys/posix/LockFile.h
deleted file mode 100644
index 027735e759..0000000000
--- a/cpp/src/qpid/sys/posix/LockFile.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _sys_posix_LockFile_h
-#define _sys_posix_LockFile_h
-
-#include "check.h"
-
-#include <boost/noncopyable.hpp>
-#include <string>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-/*
- *
- * Copyright (c) 2008 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-namespace qpid {
-namespace sys {
-
-class LockFile : private boost::noncopyable {
-public:
- LockFile(const std::string& path_, bool create):
- path(path_), fd(-1), created(create) {
- errno = 0;
- int flags=create ? O_WRONLY|O_CREAT|O_NOFOLLOW : O_RDWR;
- fd = ::open(path.c_str(), flags, 0644);
- if (fd < 0) throw ErrnoException("Cannot open " + path, errno);
- if (::lockf(fd, F_TLOCK, 0) < 0) throw ErrnoException("Cannot lock " + path, errno);
- }
-
- ~LockFile() {
- if (fd >= 0) {
- (void) ::lockf(fd, F_ULOCK, 0); // Suppress warnings about ignoring return value.
- ::close(fd);
- }
- }
-
- std::string path;
- int fd;
- bool created;
-};
-
-}
-}
-#endif /*!_sys_posix_LockFile_h*/
diff --git a/cpp/src/qpid/sys/windows/FileSysDir.cpp b/cpp/src/qpid/sys/windows/FileSysDir.cpp
new file mode 100644
index 0000000000..88f1637d48
--- /dev/null
+++ b/cpp/src/qpid/sys/windows/FileSysDir.cpp
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright (c) 2006 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/FileSysDir.h"
+#include "qpid/sys/StrError.h"
+#include "qpid/Exception.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <direct.h>
+#include <errno.h>
+
+namespace qpid {
+namespace sys {
+
+bool FileSysDir::exists (void) const
+{
+ const char *cpath = dirPath.c_str ();
+ struct _stat s;
+ if (::_stat(cpath, &s)) {
+ if (errno == ENOENT) {
+ return false;
+ }
+ throw qpid::Exception (strError(errno) +
+ ": Can't check directory: " + dirPath);
+ }
+ if (s.st_mode & _S_IFDIR)
+ return true;
+ throw qpid::Exception(dirPath + " is not a directory");
+}
+
+void FileSysDir::mkdir(void)
+{
+ if (::_mkdir(dirPath.c_str()) == -1)
+ throw Exception ("Can't create directory: " + dirPath);
+}
+
+}} // namespace qpid::sys
diff --git a/cpp/src/qpid/sys/windows/LockFile.cpp b/cpp/src/qpid/sys/windows/LockFile.cpp
new file mode 100755
index 0000000000..9804020167
--- /dev/null
+++ b/cpp/src/qpid/sys/windows/LockFile.cpp
@@ -0,0 +1,83 @@
+/*
+ *
+ * Copyright (c) 2008 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "qpid/sys/LockFile.h"
+#include "check.h"
+
+#include <windows.h>
+
+namespace qpid {
+namespace sys {
+
+class LockFilePrivate {
+ friend class LockFile;
+
+ HANDLE fd;
+
+public:
+ LockFilePrivate(HANDLE f) : fd(f) {}
+};
+
+LockFile::LockFile(const std::string& path_, bool create)
+ : path(path_), created(create) {
+
+ HANDLE h = CreateFile(path.c_str(),
+ GENERIC_READ|GENERIC_WRITE,
+ 0, /* Disable opens by any other attempter */
+ 0, /* Default security */
+ OPEN_ALWAYS, /* Create if needed */
+ FILE_FLAG_DELETE_ON_CLOSE, /* Delete file when closed */
+ NULL);
+ QPID_WINDOWS_CHECK_NOT(h, INVALID_HANDLE_VALUE);
+ impl.reset(new LockFilePrivate(h));
+}
+
+LockFile::~LockFile() {
+ if (impl) {
+ if (impl->fd != INVALID_HANDLE_VALUE) {
+ CloseHandle(impl->fd);
+ }
+ }
+}
+
+pid_t LockFile::readPid(void) const {
+ if (!impl)
+ throw Exception("Lock file not open");
+
+ pid_t pid;
+ DWORD desired_read = sizeof(pid_t);
+ DWORD actual_read = 0;
+ if (!ReadFile(impl->fd, &pid, desired_read, &actual_read, 0)) {
+ throw Exception("Cannot read lock file " + path);
+ }
+ return pid;
+}
+
+void LockFile::writePid(void) {
+ if (!impl)
+ throw Exception("Lock file not open");
+
+ pid_t pid = GetCurrentProcessId();
+ DWORD desired_write = sizeof(pid_t);
+ DWORD written = 0;
+ if (!WriteFile(impl->fd, &pid, desired_write, &written, 0)) {
+ throw Exception("Cannot write lock file " + path);
+ }
+}
+
+}} /* namespace qpid::sys */