You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by sh...@apache.org on 2008/10/07 17:19:50 UTC

svn commit: r702513 - in /incubator/qpid/trunk/qpid/cpp/src: ./ qpid/ qpid/broker/ qpid/sys/ qpid/sys/posix/ qpid/sys/windows/

Author: shuston
Date: Tue Oct  7 08:19:50 2008
New Revision: 702513

URL: http://svn.apache.org/viewvc?rev=702513&view=rev
Log:
Abstract native file-locking and directory detection/creation to portable classes LockFile and FileSysDir; resolves QPID-1148

Added:
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp   (with props)
Removed:
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.h
Modified:
    incubator/qpid/trunk/qpid/cpp/src/Makefile.am
    incubator/qpid/trunk/qpid/cpp/src/qpid/DataDir.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Daemon.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/LockFile.h

Modified: incubator/qpid/trunk/qpid/cpp/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/Makefile.am?rev=702513&r1=702512&r2=702513&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Tue Oct  7 08:19:50 2008
@@ -71,6 +71,8 @@
   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 @@
   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 @@
   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 \

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/DataDir.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/DataDir.cpp?rev=702513&r1=702512&r2=702513&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/DataDir.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/DataDir.cpp Tue Oct  7 08:19:50 2008
@@ -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 @@
         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));

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Daemon.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Daemon.cpp?rev=702513&r1=702512&r2=702513&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Daemon.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Daemon.cpp Tue Oct  7 08:19:50 2008
@@ -168,22 +168,14 @@
     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 @@
 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);

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h?rev=702513&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h Tue Oct  7 08:19:50 2008
@@ -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*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/FileSysDir.h
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/LockFile.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/LockFile.h?rev=702513&r1=702512&r2=702513&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/LockFile.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/LockFile.h Tue Oct  7 08:19:50 2008
@@ -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*/
 

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp?rev=702513&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp Tue Oct  7 08:19:50 2008
@@ -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

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/FileSysDir.cpp
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp?rev=702513&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp Tue Oct  7 08:19:50 2008
@@ -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 */

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/posix/LockFile.cpp
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp?rev=702513&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/FileSysDir.cpp Tue Oct  7 08:19:50 2008
@@ -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

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp?rev=702513&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp Tue Oct  7 08:19:50 2008
@@ -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 */

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/LockFile.cpp
------------------------------------------------------------------------------
    svn:executable = *