lockfile: Implementation for Windows platform.
authorGurucharan Shetty <gshetty@nicira.com>
Thu, 13 Feb 2014 18:50:00 +0000 (10:50 -0800)
committerGurucharan Shetty <gshetty@nicira.com>
Thu, 13 Feb 2014 22:09:31 +0000 (14:09 -0800)
Start with a simple implementation that does not support
symbolic links.

Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/lockfile.c

index d8f3952..2774177 100644 (file)
@@ -44,6 +44,7 @@ struct lockfile {
     dev_t device;
     ino_t inode;
     int fd;
+    HANDLE lock_handle;
 };
 
 /* Lock table.
@@ -58,8 +59,14 @@ static struct hmap *const lock_table OVS_GUARDED_BY(lock_table_mutex)
     = &lock_table__;
 
 static void lockfile_unhash(struct lockfile *);
-static int lockfile_try_lock(const char *name, pid_t *pidp,
-                             struct lockfile **lockfilep);
+#ifdef _WIN32
+static int lockfile_try_lock_windows(const char *name, pid_t *pidp,
+                                     struct lockfile **lockfilep);
+static void lockfile_unlock_windows(struct lockfile * lockfile);
+#else
+static int lockfile_try_lock_posix(const char *name, pid_t *pidp,
+                                   struct lockfile **lockfilep);
+#endif
 
 /* Returns the name of the lockfile that would be created for locking a file
  * named 'filename_'.  The caller is responsible for freeing the returned name,
@@ -110,7 +117,11 @@ lockfile_lock(const char *file, struct lockfile **lockfilep)
     lock_name = lockfile_name(file);
 
     ovs_mutex_lock(&lock_table_mutex);
-    error = lockfile_try_lock(lock_name, &pid, lockfilep);
+#ifdef _WIN32
+    error = lockfile_try_lock_windows(lock_name, &pid, lockfilep);
+#else
+    error = lockfile_try_lock_posix(lock_name, &pid, lockfilep);
+#endif
     ovs_mutex_unlock(&lock_table_mutex);
 
     if (error) {
@@ -138,7 +149,11 @@ lockfile_unlock(struct lockfile *lockfile)
 {
     if (lockfile) {
         ovs_mutex_lock(&lock_table_mutex);
+#ifdef _WIN32
+        lockfile_unlock_windows(lockfile);
+#else
         lockfile_unhash(lockfile);
+#endif
         ovs_mutex_unlock(&lock_table_mutex);
 
         COVERAGE_INC(lockfile_unlock);
@@ -218,8 +233,78 @@ lockfile_register(const char *name, dev_t device, ino_t inode, int fd)
     return lockfile;
 }
 
+#ifdef _WIN32
+static void
+lockfile_unlock_windows(struct lockfile *lockfile)
+    OVS_REQUIRES(&lock_table_mutex)
+{
+    if (lockfile->fd >= 0) {
+        OVERLAPPED overl;
+        overl.hEvent = 0;
+        overl.Offset = 0;
+        overl.OffsetHigh = 0;
+        UnlockFileEx(lockfile->lock_handle, 0, 1, 0, &overl);
+
+        close(lockfile->fd);
+        lockfile->fd = -1;
+    }
+}
+
+static int
+lockfile_try_lock_windows(const char *name, pid_t *pidp,
+                          struct lockfile **lockfilep)
+    OVS_REQUIRES(&lock_table_mutex)
+{
+    HANDLE lock_handle;
+    BOOL retval;
+    OVERLAPPED overl;
+    struct lockfile *lockfile;
+    int fd;
+
+    *pidp = 0;
+
+    fd = open(name, O_RDWR | O_CREAT, 0600);
+    if (fd < 0) {
+        VLOG_WARN("%s: failed to open lock file: %s",
+                   name, ovs_strerror(errno));
+        return errno;
+    }
+
+    lock_handle = (HANDLE)_get_osfhandle(fd);
+    if (lock_handle < 0) {
+        VLOG_WARN("%s: failed to get the file handle: %s",
+                   name, ovs_strerror(errno));
+        return errno;
+    }
+
+    /* Lock the file 'name' for the region that includes just the first
+     * byte. */
+    overl.hEvent = 0;
+    overl.Offset = 0;
+    overl.OffsetHigh = 0;
+    retval = LockFileEx(lock_handle, LOCKFILE_EXCLUSIVE_LOCK
+                        | LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, &overl);
+    if (!retval) {
+        char *msg_buf = ovs_lasterror_to_string();
+        VLOG_WARN("Failed to lock file : %s", msg_buf);
+        LocalFree(msg_buf);
+        return EEXIST;
+    }
+
+    lockfile = xmalloc(sizeof *lockfile);
+    lockfile->name = xstrdup(name);
+    lockfile->fd = fd;
+    lockfile->lock_handle = lock_handle;
+
+    *lockfilep = lockfile;
+    return 0;
+}
+#endif
+
+#ifndef _WIN32
 static int
-lockfile_try_lock(const char *name, pid_t *pidp, struct lockfile **lockfilep)
+lockfile_try_lock_posix(const char *name, pid_t *pidp,
+                        struct lockfile **lockfilep)
     OVS_REQUIRES(&lock_table_mutex)
 {
     struct flock l;
@@ -276,4 +361,4 @@ lockfile_try_lock(const char *name, pid_t *pidp, struct lockfile **lockfilep)
     }
     return error;
 }
-
+#endif