Welcome to little lamb

Code » anopa » commit d3e7c8d

start: Add support of gets-ready to wait for 'U'

author Olivier Brunel
2015-03-15 20:06:21 UTC
committer Olivier Brunel
2015-04-04 12:47:36 UTC
parent 0d3e5ea8c32a426fe3cecc0d52c9ace4ae1ef9bf

start: Add support of gets-ready to wait for 'U'

If a file gets-ready exists then aa-start will wait for 'U' (instead of
'u'), i.e. wait for the service to be ready. Events 'u' and 'd' will be
announced, but only as information.

doc/aa-start.pod +10 -3
doc/anopa.pod +6 -0
src/anopa/start-stop.c +19 -2
src/include/anopa/service.h +3 -0
src/libanopa/exec_longrun.c +13 -1
src/libanopa/service.c +7 -3

diff --git a/doc/aa-start.pod b/doc/aa-start.pod
index 2605481..f426f97 100644
--- a/doc/aa-start.pod
+++ b/doc/aa-start.pod
@@ -58,9 +58,16 @@ fifodir of the service, then checks (with B<s6>) if the service is already up or
 not. If so, it disconnects and the service is announced as already up and
 process continues as expected.
 
-If not, B<aa-start>(1) sends the command to bring it up and removes the I<down>
-file (if present). It then waits for event 'u' to be triggered, to (disconnect
-and) announce the service as started.
+If not, B<aa-start>(1) then checks whether there's a file I<gets-ready> in the
+servicedir. It then sends the command to bring it up and removes the I<down>
+file (if present).
+
+If there was no I<gets-ready> file, it waits for event 'u' to be triggered, then
+(disconnects from the fifodir and) announce the service as started. If there was
+one, it will then wait for event 'U' to be triggered instead, announcing the
+service as ready instead. (A message will be shown on event 'u' as information
+only. Note that should event 'd' occur, a message will also be shown, but
+B<aa-start>(1) will still keep waiting for event 'U'.)
 
 =head1 STARTING A ONE-SHOT SERVICE
 
diff --git a/doc/anopa.pod b/doc/anopa.pod
index 2122219..9af8976 100644
--- a/doc/anopa.pod
+++ b/doc/anopa.pod
@@ -128,6 +128,12 @@ used to send notifications when the service goes up/down.
 If such a file exists, the default state of the service is considered down, not
 up, and it isn't automatically started by B<s6-supervise>.
 
+=item An optional, empty, regular file named I<gets-ready>
+
+This is B<anopa>-specific, and if present indicates to B<aa-start>(1) that the
+service supports readiness, so it will wait for event 'U' (instead of 'u') when
+starting it.
+
 =back
 
 =head2 ONE-SHOT SERVICES
diff --git a/src/anopa/start-stop.c b/src/anopa/start-stop.c
index 9eb052e..8795fd7 100644
--- a/src/anopa/start-stop.c
+++ b/src/anopa/start-stop.c
@@ -685,10 +685,27 @@ handle_longrun (aa_mode mode, uint16 id, char event)
     }
 
     si = list_get (&aa_main_list, i);
-    aa_service (si)->ft_id = 0;
+    if (mode == AA_MODE_START && aa_service (si)->gets_ready)
+    {
+        if (event == 'u' || event == 'd')
+        {
+            clear_draw ();
+            aa_bs_noflush (AA_OUT, aa_service_name (aa_service (si)));
+            aa_bs_noflush (AA_OUT, ": ");
+            aa_bs_flush (AA_OUT, (event == 'u')
+                    ? "Started; Getting ready...\n"
+                    : "Down; Will restart...\n");
+            return 0;
+        }
+        /* event == 'U' */
+        aa_unsubscribe_for (id);
+    }
 
+    aa_service (si)->ft_id = 0;
     put_title (1, aa_service_name (aa_service (si)),
-            (mode == AA_MODE_START) ? "Started" : "Stopped", 1);
+            (mode == AA_MODE_START) ?
+            ((aa_service (si)->gets_ready) ? "Ready" : "Started")
+            : "Stopped", 1);
     ++nb_done;
     --nb_wait_longrun;
 
diff --git a/src/include/anopa/service.h b/src/include/anopa/service.h
index 0e73b0d..38503c0 100644
--- a/src/include/anopa/service.h
+++ b/src/include/anopa/service.h
@@ -11,6 +11,7 @@
 
 #define AA_START_FILENAME           "start"
 #define AA_STOP_FILENAME            "stop"
+#define AA_GETS_READY_FILENAME      "gets-ready"
 
 extern genalloc aa_services;
 extern stralloc aa_names;
@@ -60,6 +61,7 @@ typedef struct
     aa_service_status st;
     /* longrun */
     uint16 ft_id;
+    int gets_ready;
     /* oneshot */
     int fd_in;
     int fd_out;
@@ -84,5 +86,6 @@ extern int  aa_prepare_mainlist (aa_prepare_cb prepare_cb, aa_exec_cb exec_cb);
 extern void aa_scan_mainlist (aa_scan_cb scan_cb, aa_mode mode);
 extern int  aa_exec_service (int si, aa_mode mode);
 extern int  aa_get_longrun_info (uint16 *id, char *event);
+extern int  aa_unsubscribe_for (uint16 id);
 
 #endif /* AA_SERVICE_H */
diff --git a/src/libanopa/exec_longrun.c b/src/libanopa/exec_longrun.c
index 8dd0e62..c867648 100644
--- a/src/libanopa/exec_longrun.c
+++ b/src/libanopa/exec_longrun.c
@@ -28,7 +28,10 @@ _exec_longrun (int si, aa_mode mode)
     byte_copy (fifodir + l_sn + 1, sizeof (S6_SUPERVISE_EVENTDIR), S6_SUPERVISE_EVENTDIR);
 
     tain_addsec_g (&deadline, 1);
-    s->ft_id = ftrigr_subscribe_g (&_aa_ft, fifodir, event, 0, &deadline);
+    s->ft_id = ftrigr_subscribe_g (&_aa_ft, fifodir,
+            (is_start && s->gets_ready) ? "[udU]" : event,
+            (is_start && s->gets_ready) ? FTRIGR_REPEAT : 0,
+            &deadline);
     if (s->ft_id == 0)
     {
         /* this could happen e.g. if the servicedir isn't in scandir, if
@@ -186,3 +189,12 @@ aa_get_longrun_info (uint16 *id, char *event)
     i = -1;
     return 0;
 }
+
+int
+aa_unsubscribe_for (uint16 id)
+{
+    tain_t deadline;
+
+    tain_addsec_g (&deadline, 1);
+    return ftrigr_unsubscribe_g (&_aa_ft, id, &deadline);
+}
diff --git a/src/libanopa/service.c b/src/libanopa/service.c
index 76114d7..491395d 100644
--- a/src/libanopa/service.c
+++ b/src/libanopa/service.c
@@ -138,14 +138,13 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf
 
     {
         aa_service_status *svst = &aa_service (si)->st;
-        struct stat st;
         int l_sn = strlen (aa_service_name (aa_service (si)));
-        char buf[l_sn + 5];
+        char buf[l_sn + 1 + sizeof (AA_GETS_READY_FILENAME)];
 
         byte_copy (buf, l_sn, aa_service_name (aa_service (si)));
         byte_copy (buf + l_sn, 5, "/run");
 
-        if (stat (buf, &st) < 0)
+        if (access (buf, F_OK) < 0)
         {
             if (errno != ENOENT)
                 return -ERR_IO;
@@ -153,7 +152,12 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_load_fail_cb lf
                 svst->type = AA_TYPE_ONESHOT;
         }
         else
+        {
             svst->type = AA_TYPE_LONGRUN;
+
+            byte_copy (buf + l_sn, 1 + sizeof (AA_GETS_READY_FILENAME), "/" AA_GETS_READY_FILENAME);
+            aa_service (si)->gets_ready = (access (buf, F_OK) == 0) ? 1 : 0;
+        }
     }
 
     {