X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fdevice-handler.c;h=a73a7ce590abe65c7463899f369d7d3c7b549195;hp=87a46c72a0e2f8a5b0fa71309ee922ce28d07e78;hb=78819395e5aa0dbd0c484f7a2512fcf04b87bbf2;hpb=8ed7af65d5eaea57a62c26bef6267047cf3c95ea diff --git a/discover/device-handler.c b/discover/device-handler.c index 87a46c7..a73a7ce 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -46,6 +46,14 @@ enum default_priority { DEFAULT_PRIORITY_DISABLED = 0xff, }; +struct progress_info { + unsigned int percentage; + unsigned long size; /* size in bytes */ + + const struct process_info *procinfo; + struct list_item list; +}; + struct device_handler { struct discover_server *server; int dry_run; @@ -72,6 +80,9 @@ struct device_handler { struct boot_task *pending_boot; bool pending_boot_is_default; + + struct list progress; + unsigned int n_progress; }; static int mount_device(struct discover_device *dev); @@ -114,6 +125,12 @@ const struct discover_device *device_handler_get_device( return handler->devices[index]; } +struct network *device_handler_get_network( + const struct device_handler *handler) +{ + return handler->network; +} + struct discover_boot_option *discover_boot_option_create( struct discover_context *ctx, struct discover_device *device) @@ -308,6 +325,8 @@ struct device_handler *device_handler_init(struct discover_server *server, list_init(&handler->unresolved_boot_options); + list_init(&handler->progress); + /* set up our mount point base */ pb_mkdir_recursive(mount_base()); @@ -481,6 +500,110 @@ void device_handler_status_err(struct device_handler *handler, va_end(ap); } +void device_handler_status_download(struct device_handler *handler, + const struct process_info *procinfo, + unsigned int percentage, unsigned int size, char suffix) +{ + struct progress_info *p, *progress = NULL; + uint64_t current_converted, current = 0; + const char *units = " kMGTP"; + unsigned long size_bytes; + char *update = NULL; + double total = 0; + unsigned int i; + int unit = 0; + + list_for_each_entry(&handler->progress, p, list) + if (p->procinfo == procinfo) + progress = p; + + if (!progress) { + pb_log("Registering new progress struct\n"); + progress = talloc_zero(handler, struct progress_info); + if (!progress) { + pb_log("Failed to allocate room for progress struct\n"); + return; + } + progress->procinfo = procinfo; + list_add(&handler->progress, &progress->list); + handler->n_progress++; + } + + size_bytes = size; + for (i = 0; i < strlen(units); i++) { + if (units[i] == suffix) + break; + } + + if (i >= strlen(units)) { + pb_log("Couldn't recognise suffix '%c'\n", suffix); + size_bytes = 0; + } else { + while (i--) + size_bytes <<= 10; + } + + progress->percentage = percentage; + progress->size = size_bytes; + + /* + * Aggregate the info we have and update status. If a progress struct + * has zero for both percentage and size we assume progress information + * is unavailable and fall back to a generic progress message. + */ + list_for_each_entry(&handler->progress, p, list) { + uint64_t c; + double t; + if (!p->percentage || !p->size) { + update = talloc_asprintf(handler, + _("%u downloads in progress..."), + handler->n_progress); + current = total = 0; + break; + } + + c = p->size; + t = (100 * c) / p->percentage; + + current += c; + total += t; + } + + if (total) { + current_converted = current; + while (current_converted >= 1000) { + current_converted >>= 10; + unit++; + } + update = talloc_asprintf(handler, + _("%u %s downloading: %.0f%% - %lu%cB"), + handler->n_progress, + ngettext("item", "items", handler->n_progress), + (current / total) * 100, current_converted, + units[unit]); + } + + if (!update) { + pb_log("%s: failed to allocate new status\n", __func__); + } else { + device_handler_status_info(handler, "%s\n", update); + talloc_free(update); + } +} + +void device_handler_status_download_remove(struct device_handler *handler, + struct process_info *procinfo) +{ + struct progress_info *p, *tmp; + + list_for_each_entry_safe(&handler->progress, p, tmp, list) + if (p->procinfo == procinfo) { + list_remove(&p->list); + talloc_free(p); + handler->n_progress--; + } +} + static void device_handler_boot_status_cb(void *arg, struct status *status) { device_handler_status(arg, status); @@ -788,8 +911,8 @@ struct discover_context *device_handler_discover_context_create( struct discover_context *ctx; ctx = talloc_zero(handler, struct discover_context); + ctx->handler = handler; ctx->device = device; - ctx->network = handler->network; list_init(&ctx->boot_options); return ctx; @@ -905,15 +1028,14 @@ int device_handler_discover(struct device_handler *handler, struct discover_context *ctx; int rc; - /* - * TRANSLATORS: this string will be passed the type and identifier - * of the device. For example, the first parameter could be "Disk", - * (which will be translated accordingly) and the second a Linux device - * identifier like 'sda1' (which will not be translated) - */ - device_handler_status_info(handler, _("Processing %s device %s"), - device_type_display_name(dev->device->type), - dev->device->id); + device_handler_status_dev_info(handler, dev, + /* + * TRANSLATORS: this string will be passed the type of the + * device (eg "disk" or "network"), which will be translated + * accordingly. + */ + _("Processing new %s device"), + device_type_display_name(dev->device->type)); process_boot_option_queue(handler); @@ -935,13 +1057,6 @@ int device_handler_discover(struct device_handler *handler, device_handler_discover_context_commit(handler, ctx); out: - /* - * TRANSLATORS: the format specifier in this string is a Linux - * device identifier, like 'sda1' - */ - device_handler_status_info(handler, _("Processing %s complete"), - dev->device->id); - talloc_unlink(handler, ctx); return 0; @@ -953,12 +1068,9 @@ int device_handler_dhcp(struct device_handler *handler, { struct discover_context *ctx; - /* - * TRANSLATORS: this format specifier will be the name of a network - * device, like 'eth0'. - */ - device_handler_status_info(handler, _("Processing dhcp event on %s"), - dev->device->id); + device_handler_status_dev_info(handler, dev, + _("Processing DHCP lease response (ip: %s)"), + event_get_param(event, "ip")); /* create our context */ ctx = device_handler_discover_context_create(handler, dev); @@ -969,13 +1081,6 @@ int device_handler_dhcp(struct device_handler *handler, device_handler_discover_context_commit(handler, ctx); - /* - * TRANSLATORS: this format specifier will be the name of a network - * device, like 'eth0'. - */ - device_handler_status_info(handler, _("Processing %s complete"), - dev->device->id); - talloc_unlink(handler, ctx); return 0;