Signed-off-by: Liu Yuan <namei.u...@gmail.com>
---
 sheep/cluster/local.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 54 insertions(+), 2 deletions(-)

diff --git a/sheep/cluster/local.c b/sheep/cluster/local.c
index 6d0af68..c9c0ede 100644
--- a/sheep/cluster/local.c
+++ b/sheep/cluster/local.c
@@ -16,6 +16,7 @@
 #include <sys/file.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <limits.h>
 
 #include "cluster.h"
 #include "event.h"
@@ -27,6 +28,10 @@
 #define LOCAL_MAX_NODES 1024
 
 static const char *shmfile = "/tmp/sheepdog_shm";
+static const char *lockdir = "/tmp/sheepdog_locks/";
+/* we have to use sd_lock because flock isn't thread exclusive */
+static struct sd_lock lock = SD_LOCK_INITIALIZER;
+
 static int shmfd;
 static int sigfd;
 static int block_event_pos;
@@ -99,14 +104,25 @@ static inline void node_insert(struct sd_node *new, struct 
rb_root *root)
                panic("insert duplicate %s", node_to_str(new));
 }
 
+static int xflock(int fd, int operation)
+{
+       int ret;
+
+       do {
+               ret = flock(fd, operation);
+       } while (ret < 0 && (errno == EAGAIN || errno == EINTR));
+
+       return ret;
+}
+
 static void shm_queue_lock(void)
 {
-       flock(shmfd, LOCK_EX);
+       xflock(shmfd, LOCK_EX);
 }
 
 static void shm_queue_unlock(void)
 {
-       flock(shmfd, LOCK_UN);
+       xflock(shmfd, LOCK_UN);
 }
 
 static size_t get_nodes(struct local_node *n)
@@ -544,15 +560,51 @@ static int local_init(const char *option)
                return -1;
        }
 
+       ret = xmkdir(lockdir, sd_def_dmode);
+       if (ret < 0) {
+               sd_err("failed to create lockdir %s, %m", lockdir);
+               return -1;
+       }
+
+       ret = purge_directory(lockdir);
+       if (ret < 0) {
+               sd_err("failed to purge lockdir %s, %m", lockdir);
+               return -1;
+       }
+
        return 0;
 }
 
 static void local_lock(uint64_t lock_id)
 {
+       char path[PATH_MAX];
+       int fd;
+
+       sd_write_lock(&lock);
+       snprintf(path, sizeof(path), "%s%016"PRIx64, lockdir, lock_id);
+       fd = open(path, O_RDONLY | O_CREAT, sd_def_fmode);
+       if (fd < 0)
+               panic("failed to open %s, %m", path);
+
+       if (xflock(fd, LOCK_EX) < 0)
+               panic("lock file failed %s, %m", path);
+       close(fd);
 }
 
 static void local_unlock(uint64_t lock_id)
 {
+       char path[PATH_MAX];
+       int fd;
+
+       snprintf(path, sizeof(path), "%s%016"PRIx64, lockdir, lock_id);
+       fd = open(path, O_RDONLY, sd_def_fmode);
+       if (fd < 0)
+               panic("failed to open %s, %m", path);
+
+       if (xflock(fd, LOCK_UN) < 0)
+               panic("unlock file failed %s, %m", path);
+       close(fd);
+       sd_unlock(&lock);
 }
 
 static int local_update_node(struct sd_node *node)
-- 
1.7.9.5

-- 
sheepdog mailing list
sheepdog@lists.wpkg.org
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to