discover: Maintain a backlog of status updates
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Wed, 14 Dec 2016 03:44:23 +0000 (14:44 +1100)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Tue, 20 Dec 2016 05:40:22 +0000 (16:40 +1100)
Add status updates to a persistent list in the discover_server struct,
and send each client the backlog on connect. This avoids clients missing
useful messages from early init. Clients will only show this in the
backlog screen to avoid flooding the client's status line.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
discover/boot.c
discover/device-handler.c
discover/discover-server.c
lib/pb-protocol/pb-protocol.c
lib/types/types.h
ui/ncurses/nc-cui.c
ui/ncurses/nc-statuslog.c

index da7b946fcbb2dc2628b7df892fa4b752fca81a4c..fab4b61cd681d4a3aac00464641936029388e4e2 100644 (file)
@@ -45,6 +45,7 @@ static void __attribute__((format(__printf__, 4, 5))) update_status(
        va_end(ap);
 
        status.type = type;
        va_end(ap);
 
        status.type = type;
+       status.backlog = false;
 
        pb_debug("boot status: [%d] %s\n", type, status.message);
 
 
        pb_debug("boot status: [%d] %s\n", type, status.message);
 
index a73a7ce590abe65c7463899f369d7d3c7b549195..48bfa0e237cfd410415d83a265fbbc0bed5a2284 100644 (file)
@@ -442,6 +442,7 @@ static void _device_handler_vstatus(struct device_handler *handler,
 
        status.type = type;
        status.message = talloc_vasprintf(handler, fmt, ap);
 
        status.type = type;
        status.message = talloc_vasprintf(handler, fmt, ap);
+       status.backlog = false;
 
        device_handler_status(handler, &status);
 
 
        device_handler_status(handler, &status);
 
@@ -617,6 +618,7 @@ static void countdown_status(struct device_handler *handler,
        status.type = STATUS_INFO;
        status.message = talloc_asprintf(handler,
                        _("Booting in %d sec: %s"), sec, opt->option->name);
        status.type = STATUS_INFO;
        status.message = talloc_asprintf(handler,
                        _("Booting in %d sec: %s"), sec, opt->option->name);
+       status.backlog = false;
 
        device_handler_status(handler, &status);
 
 
        device_handler_status(handler, &status);
 
index ad184f66a43559fcc78707b7aa69c204bfec69f2..a3087b3335d423fa1e01fc25ab6bfe705a23933f 100644 (file)
@@ -28,6 +28,7 @@ struct discover_server {
        struct waitset *waitset;
        struct waiter *waiter;
        struct list clients;
        struct waitset *waitset;
        struct waiter *waiter;
        struct list clients;
+       struct list status;
        struct device_handler *device_handler;
 };
 
        struct device_handler *device_handler;
 };
 
@@ -282,6 +283,7 @@ static int discover_server_process_message(void *arg)
 static int discover_server_process_connection(void *arg)
 {
        struct discover_server *server = arg;
 static int discover_server_process_connection(void *arg)
 {
        struct discover_server *server = arg;
+       struct statuslog_entry *entry;
        int fd, rc, i, n_devices;
        struct client *client;
 
        int fd, rc, i, n_devices;
        struct client *client;
 
@@ -333,6 +335,10 @@ static int discover_server_process_connection(void *arg)
                }
        }
 
                }
        }
 
+       /* send status backlog to client */
+       list_for_each_entry(&server->status, entry, list)
+               write_boot_status_message(server, client, entry->status);
+
        return 0;
 }
 
        return 0;
 }
 
@@ -368,8 +374,26 @@ void discover_server_notify_device_remove(struct discover_server *server,
 void discover_server_notify_boot_status(struct discover_server *server,
                struct status *status)
 {
 void discover_server_notify_boot_status(struct discover_server *server,
                struct status *status)
 {
+       struct statuslog_entry *entry;
        struct client *client;
 
        struct client *client;
 
+       /* Duplicate the status struct to add to the backlog */
+       entry = talloc(server, struct statuslog_entry);
+       if (!entry) {
+               pb_log("Failed to allocated saved status!\n");
+       } else {
+               entry->status = talloc(entry, struct status);
+               if (entry->status) {
+                       entry->status->type = status->type;
+                       entry->status->message = talloc_strdup(entry->status,
+                                                              status->message);
+                       entry->status->backlog = true;
+                       list_add_tail(&server->status, &entry->list);
+               } else {
+                       talloc_free(entry);
+               }
+       }
+
        list_for_each_entry(&server->clients, client, list)
                write_boot_status_message(server, client, status);
 }
        list_for_each_entry(&server->clients, client, list)
                write_boot_status_message(server, client, status);
 }
@@ -410,6 +434,7 @@ struct discover_server *discover_server_init(struct waitset *waitset)
        server->waiter = NULL;
        server->waitset = waitset;
        list_init(&server->clients);
        server->waiter = NULL;
        server->waitset = waitset;
        list_init(&server->clients);
+       list_init(&server->status);
 
        unlink(PB_SOCKET_PATH);
 
 
        unlink(PB_SOCKET_PATH);
 
index 8bc8820d8f5833274a6f80322d2d476ccaf7d97d..65a1e93408d834d0449d458d0806e3ef50be66f6 100644 (file)
@@ -217,8 +217,9 @@ int pb_protocol_boot_len(const struct boot_command *boot)
 
 int pb_protocol_boot_status_len(const struct status *status)
 {
 
 int pb_protocol_boot_status_len(const struct status *status)
 {
-       return  4 +
+       return  4 +     /* type */
                4 + optional_strlen(status->message) +
                4 + optional_strlen(status->message) +
+               4 +     /* backlog */
                4;
 }
 
                4;
 }
 
@@ -410,6 +411,9 @@ int pb_protocol_serialise_boot_status(const struct status *status,
 
        pos += pb_protocol_serialise_string(pos, status->message);
 
 
        pos += pb_protocol_serialise_string(pos, status->message);
 
+       *(bool *)pos = __cpu_to_be32(status->backlog);
+       pos += sizeof(bool);
+
        assert(pos <= buf + buf_len);
        (void)buf_len;
 
        assert(pos <= buf + buf_len);
        (void)buf_len;
 
@@ -847,6 +851,10 @@ int pb_protocol_deserialise_boot_status(struct status *status,
        if (read_string(status, &pos, &len, &status->message))
                goto out;
 
        if (read_string(status, &pos, &len, &status->message))
                goto out;
 
+       /* backlog */
+       status->backlog = *(bool *)pos;
+       pos += sizeof(status->backlog);
+
        rc = 0;
 
 out:
        rc = 0;
 
 out:
index 506510b1fbbfc0775a3999e701a0158f5da3ebc4..63f1b213c19261687e9ebd9c85272c0327882c59 100644 (file)
@@ -76,6 +76,12 @@ struct status {
                STATUS_ERROR,
        } type;
        char    *message;
                STATUS_ERROR,
        } type;
        char    *message;
+       bool    backlog;
+};
+
+struct statuslog_entry {
+       struct status           *status;
+       struct list_item        list;
 };
 
 struct interface_info {
 };
 
 struct interface_info {
index 93b2e43eebf0847bd5498746ccbe28e8028b20c4..b4f74a793e73f906b3aaaa68b22d7deb66587a75 100644 (file)
@@ -714,7 +714,9 @@ static void cui_update_status(struct status *status, void *arg)
 
        statuslog_append_steal(cui, cui->statuslog, status);
 
 
        statuslog_append_steal(cui, cui->statuslog, status);
 
-       nc_scr_status_printf(cui->current, "%s", status->message);
+       /* Ignore status messages from the backlog */
+       if (!status->backlog)
+               nc_scr_status_printf(cui->current, "%s", status->message);
 }
 
 static void cui_update_mm_title(struct cui *cui)
 }
 
 static void cui_update_mm_title(struct cui *cui)
index 1943f39afbee6b5921d05143d958e7ae6ee79e7a..623aa5501c031af76be9342b6670ea3320859cc1 100644 (file)
 
 static const int max_status_entry = 10000;
 
 
 static const int max_status_entry = 10000;
 
-struct statuslog_entry {
-       struct status           *status;
-       struct list_item        list;
-};
-
 struct statuslog {
        struct list             status;
        int                     n_status;
 struct statuslog {
        struct list             status;
        int                     n_status;