make mt-sosd use async remove, stat, copy
[archipelago] / xseg / peers / user / peer.c
index 978d7f0..779beaf 100644 (file)
@@ -8,6 +8,9 @@
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
 #ifdef MT
 #include <pthread.h>
 #endif
@@ -395,6 +398,7 @@ static void* thread_loop(void *arg)
                xseg_cancel_wait(xseg, peer->portno_start);
                XSEGLOG2(&lc, I, "Thread %u woke up\n", (unsigned int) (t- peer->thread));
        }
+       wake_up_next_thread(peer);
        return NULL;
 }
 
@@ -530,7 +534,7 @@ malloc_fail:
        peer->portno_end= (xport) portno_end;
        port = xseg_bind_port(peer->xseg, peer->portno_start, NULL);
        if (!port){
-               printf("cannot bind to port %ld\n", peer->portno_start);
+               printf("cannot bind to port %u\n", (unsigned int) peer->portno_start);
                return NULL;
        }
 
@@ -539,7 +543,7 @@ malloc_fail:
                struct xseg_port *tmp;
                tmp = xseg_bind_port(peer->xseg, p, (void *)xseg_get_signal_desc(peer->xseg, port));
                if (!tmp){
-                       printf("cannot bind to port %ld\n", p);
+                       printf("cannot bind to port %u\n", (unsigned int) p);
                        return NULL;
                }
        }
@@ -563,13 +567,63 @@ malloc_fail:
        return peer;
 }
 
+int pidfile_remove(char *path, int fd)
+{
+       close(fd);
+       return (unlink(path));
+}
+
+int pidfile_write(int pid_fd)
+{
+       char buf[16];
+       snprintf(buf, sizeof(buf), "%ld", syscall(SYS_gettid));
+       buf[15] = 0;
+       
+       lseek(pid_fd, 0, SEEK_SET);
+       int ret = write(pid_fd, buf, strlen(buf));
+       return ret;
+}
+
+int pidfile_read(char *path, pid_t *pid)
+{
+       char buf[16], *endptr;
+       *pid = 0;
+
+       int fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return -1;
+       int ret = read(fd, buf, 15);
+       buf[15]=0;
+       close(fd);
+       if (ret < 0)
+               return -1;
+       else{
+               *pid = strtol(buf, &endptr, 10);
+               if (endptr != &buf[ret]){
+                       *pid = 0;
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int pidfile_open(char *path, pid_t *old_pid)
+{
+       //nfs version > 3
+       int fd = open(path, O_CREAT|O_EXCL|O_WRONLY);
+       if (fd < 0){
+               if (errno == -EEXIST)
+                       pidfile_read(path, old_pid);
+       }
+       return fd;
+}
 
 int main(int argc, char *argv[])
 {
        struct peerd *peer = NULL;
        //parse args
        char *spec = "";
-       int i, r;
+       int i, r, daemonize = 0;
        long portno_start = -1, portno_end = -1, portno = -1;
        //set defaults here
        uint32_t nr_ops = 16;
@@ -577,6 +631,9 @@ int main(int argc, char *argv[])
        unsigned int debug_level = 0;
        uint32_t defer_portno = NoPort;
        char *logfile = NULL;
+       char *pidfile = NULL;
+       pid_t old_pid;
+       int pid_fd = -1;
 
        //capture here -g spec, -n nr_ops, -p portno, -t nr_threads -v verbose level
        // -dp xseg_portno to defer blocking requests
@@ -633,11 +690,42 @@ int main(int argc, char *argv[])
                        i += 1;
                        continue;
                }
+               if (!strcmp(argv[i], "-d")) {
+                       daemonize = 1;
+                       continue;
+               }
+               if (!strcmp(argv[i], "--pidfile") && i + 1 < argc ) {
+                       pidfile = argv[i+1];
+                       i += 1;
+                       continue;
+               }
 
        }
        init_logctx(&lc, argv[0], debug_level, logfile);
        XSEGLOG2(&lc, D, "Main thread has tid %ld.\n", syscall(SYS_gettid));
        
+       if (pidfile){
+               pid_fd = pidfile_open(pidfile, &old_pid);
+               if (pid_fd < 0) {
+                       if (old_pid) {
+                               XSEGLOG2(&lc, E, "Daemon already running, pid: %d.", old_pid);
+                       } else {
+                               XSEGLOG2(&lc, E, "Cannot open or create pidfile");
+                       }
+                       return -1;
+               }
+       }
+       
+       if (daemonize){
+               if (daemon(0, 1) < 0){
+                       XSEGLOG2(&lc, E, "Cannot daemonize");
+                       r = -1;
+                       goto out;
+               }
+       }
+
+       pidfile_write(pid_fd);
+       
        //TODO perform argument sanity checks
        verbose = debug_level;
        if (portno != -1) {
@@ -648,19 +736,25 @@ int main(int argc, char *argv[])
        setup_signals();
        //TODO err check
        peer = peerd_init(nr_ops, spec, portno_start, portno_end, nr_threads, defer_portno);
-       if (!peer)
-               return -1;
+       if (!peer){
+               r = -1;
+               goto out;
+       }
        r = custom_peer_init(peer, argc, argv);
        if (r < 0)
-               return -1;
+               goto out;
 #ifdef MT
        peerd_start_threads(peer);
 #endif
 
 #ifdef ST_THREADS
        st_thread_t st = st_thread_create(peerd_loop, peer, 1, 0);
-       return st_thread_join(st, NULL);
+       r = st_thread_join(st, NULL);
 #else
-       return peerd_loop(peer);
+       r = peerd_loop(peer);
 #endif
+out:
+       if (pid_fd > 0)
+               pidfile_remove(pidfile, pid_fd);
+       return r;
 }