diff --git a/src/builder/b-deletion.c b/src/builder/b-deletion.c
index 5671d08..a732c64 100644
--- a/src/builder/b-deletion.c
+++ b/src/builder/b-deletion.c
@@ -437,6 +437,77 @@ scan_jobs_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde)
return 0;
}
+int
+saib_deletion_free_kib(unsigned int needed_kib)
+{
+ struct sai_builder *b = &builder;
+ struct cleanup_ctx ctx;
+ char path[256];
+ unsigned int free_kib = saib_get_free_disk_kib(b->home);
+
+ if (free_kib >= needed_kib)
+ return 0;
+
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* find out the uuids of any active jobs */
+ lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1, b->sai_plat_owner.head) {
+ struct sai_plat *sp = lws_container_of(d, struct sai_plat, sai_plat_list);
+ lws_start_foreach_dll_safe(struct lws_dll2 *, d2, d3, sp->nspawn_owner.head) {
+ struct sai_nspawn *ns = lws_container_of(d2, struct sai_nspawn, list);
+ struct active_job_uuid *aj;
+
+ if (!ns->task) continue;
+
+ aj = lwsac_use_zero(&ctx.ac, sizeof(*aj), 64);
+ if (aj) {
+ lws_strncpy(aj->uuid, ns->inp_vn, sizeof(aj->uuid));
+ lws_dll2_add_tail(&aj->list, &ctx.active_owner);
+ }
+ } lws_end_foreach_dll_safe(d2, d3);
+ } lws_end_foreach_dll_safe(d, d1);
+
+ lws_snprintf(path, sizeof(path), "%s/jobs", b->home);
+ lws_dir(path, &ctx, scan_jobs_dir_cb);
+
+ if (ctx.inactive_count) {
+ int n, to_delete = 1;
+ struct inactive_job **sorted, *ij;
+
+ /* Assume each job frees roughly 100MB to reduce ping-ponging */
+ to_delete = (int)(needed_kib - free_kib) / (100 * 1024);
+ if (to_delete < 1) to_delete = 1;
+ if (to_delete > ctx.inactive_count) to_delete = ctx.inactive_count;
+
+ sorted = lwsac_use(&ctx.ac, sizeof(*sorted) * (unsigned int)ctx.inactive_count, 0);
+ if (sorted) {
+ n = 0;
+ ij = ctx.inactive_head;
+ while (ij) {
+ sorted[n++] = ij;
+ ij = ij->next;
+ }
+ qsort(sorted, (size_t)ctx.inactive_count, sizeof(*sorted), compare_age);
+
+ for (n = 0; n < to_delete; n++) {
+ lwsl_notice("%s: out of space (need %uMiB, free %uMiB): requesting removal of %s (age %llus)\n",
+ __func__, needed_kib / 1024, free_kib / 1024, sorted[n]->name, (unsigned long long)sorted[n]->age);
+
+#if defined(LWS_WITH_STUB)
+ if (builder.mgr_deletion) {
+ char json[256];
+ lws_snprintf(json, sizeof(json), "{\"delete\": \"%s\"}", sorted[n]->name);
+ lws_stub_request(builder.mgr_deletion, json, NULL, 0, NULL, NULL, NULL);
+ }
+#endif
+ }
+ }
+ }
+
+ lwsac_free(&ctx.ac);
+ return 0;
+}
+
void
sul_cleanup_jobs_cb(lws_sorted_usec_list_t *sul)
{
@@ -483,44 +554,7 @@ sul_cleanup_jobs_cb(lws_sorted_usec_list_t *sul)
lws_snprintf(path, sizeof(path), "%s/jobs", b->home);
lws_dir(path, &ctx, scan_jobs_dir_cb);
- /* dynamic cleanup */
- {
- unsigned int free_kib = saib_get_free_disk_kib(b->home);
- unsigned int target_free_kib = 3 * 1024 * 1024; /* 3GB target */
-
- if (free_kib < target_free_kib && ctx.inactive_count) {
- int n, to_delete = 1;
- struct inactive_job **sorted, *ij;
-
- if (to_delete > ctx.inactive_count) to_delete = ctx.inactive_count;
-
- sorted = lwsac_use(&ctx.ac, sizeof(*sorted) * (unsigned int)ctx.inactive_count, 0);
- if (sorted) {
- n = 0;
- ij = ctx.inactive_head;
- while (ij) {
- sorted[n++] = ij;
- ij = ij->next;
- }
-
- qsort(sorted, (size_t)ctx.inactive_count, sizeof(*sorted), compare_age);
-
- for (n = 0; n < to_delete; n++) {
- lwsl_notice("%s: dyn cleanup: requesting removal of %s (age %llus, free %uMiB, tgt %uMiB)\n",
- __func__, sorted[n]->name, (unsigned long long)sorted[n]->age,
- free_kib / 1024, target_free_kib / 1024);
-#if defined(LWS_WITH_STUB)
- if (builder.mgr_deletion) {
- char json[256];
- lws_snprintf(json, sizeof(json), "{\"delete\": \"%s\"}", sorted[n]->name);
- lws_stub_request(builder.mgr_deletion, json, NULL, 0, NULL, NULL, NULL);
- }
-#endif
- }
- }
- }
- }
lwsac_free(&ctx.ac);
@@ -546,7 +580,7 @@ callback_sai_deletion_stdwsi(struct lws *wsi, enum lws_callback_reasons reason,
#if defined(WIN32)
{
DWORD rb;
- if (!ReadFile((HANDLE)lws_get_socket_fd(wsi), buf, sizeof(buf), &rb, NULL)) {
+ if (!ReadFile((HANDLE)lws_get_socket_fd(wsi), buf, sizeof(buf) - 1, &rb, NULL)) {
return -1;
}
ilen = (int)rb;
diff --git a/src/builder/b-private.h b/src/builder/b-private.h
index 836d1cc..3b5928f 100644
--- a/src/builder/b-private.h
+++ b/src/builder/b-private.h
@@ -339,6 +339,8 @@ saib_deletion_init(const char *argv0);
extern void
suspender_destroy(void);
int
+saib_deletion_free_kib(unsigned int needed_kib);
+int
saib_reassess_idle_situation(void);
extern int interrupted;
diff --git a/src/builder/b-task.c b/src/builder/b-task.c
index 5ef375c..6048e0f 100644
--- a/src/builder/b-task.c
+++ b/src/builder/b-task.c
@@ -213,10 +213,18 @@ saib_can_accept_task(sai_task_t *task, sai_plat_t *sp)
return 1;
}
- if ((((builder.disk_total_kib * 7) / 8) - builder.disk_reserved_kib) < task->est_disk_kib) {
- lwsl_notice("%s: reject task %s: not enough disk: total %u, res %u, needed %u\n", __func__,
- task->uuid, (unsigned int)builder.disk_total_kib, (unsigned int)builder.disk_reserved_kib, (unsigned int)task->est_disk_kib);
- return 1;
+ {
+ unsigned int free_disk = saib_get_free_disk_kib(builder.home);
+ unsigned int needed_disk = task->est_disk_kib + (unsigned int)builder.disk_reserved_kib;
+
+ /* leave 12.5% of free space as a safety margin */
+ if (free_disk < needed_disk + (free_disk / 8)) {
+ lwsl_notice("%s: reject task %s: not enough disk: needed %u (task %u + res %u), actual free %u\n", __func__,
+ task->uuid, needed_disk, (unsigned int)task->est_disk_kib, (unsigned int)builder.disk_reserved_kib, free_disk);
+
+ saib_deletion_free_kib(needed_disk + (free_disk / 8));
+ return 1;
+ }
}
lws_start_foreach_dll(struct lws_dll2 *, p, sp->nspawn_owner.head) {