mirror of
https://github.com/phantomptr/ps5upload.git
synced 2026-10-19 02:20:02 -05:00
Merge #475 review fixes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
This commit is contained in:
commit
cf7f5884b1
2 files changed
+49
-16
No files matched your search
@@ -2532,6 +2532,32 @@ int ava1_test_ended_transfers(const char *jobs_dir) {
|
||||
rc = -8;
|
||||
}
|
||||
}
|
||||
if (!rc) {
|
||||
/* durable-by-log: every file swept (unswept_n 0) but not yet settled (its last Status{unswept=0}
|
||||
* and the segments' removal still to come): not evictable; once settled, it is */
|
||||
memset(id, 0x46, 16);
|
||||
if (!(j = ava1_job_find(id))) rc = -13;
|
||||
else {
|
||||
j->psegs = calloc(1, sizeof *j->psegs);
|
||||
if (j->psegs) j->psegs[0].fd = -1;
|
||||
j->npsegs = 1;
|
||||
ava1_job_put(j);
|
||||
conclude(0x46, 9000);
|
||||
if ((j = mk(0x74, SID)) != NULL) {
|
||||
ava1_job_put(j);
|
||||
rc = -14;
|
||||
} else if (!listed(0x46)) rc = -15;
|
||||
ava1_job_reap(ava1_mono_ms() + 11000u);
|
||||
if (!rc && !listed(0x46)) rc = -16; /* nor reaped */
|
||||
if (!rc && (j = ava1_job_find(id)) != NULL) {
|
||||
__atomic_store_n(&j->settled, 1, __ATOMIC_RELEASE);
|
||||
ava1_job_put(j);
|
||||
if (!(j = mk(0x74, SID))) rc = -17;
|
||||
else ava1_job_put(j);
|
||||
if (!rc && listed(0x46)) rc = -18;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!rc) {
|
||||
/* the reaper: an ended upload still attached goes 10 s after its end, not before; a running one stays */
|
||||
conclude(0x43, 0);
|
||||
|
||||
+23
-16
@@ -18,7 +18,7 @@ static struct {
|
||||
/* Ids that left the table but whose destroy may still be running (threads joined,
|
||||
* journal closed): a create of the same id must not touch the job's directory until
|
||||
* the destroy finished. Cleared when the job's last reference is dropped. */
|
||||
uint8_t retiring[AVA1_MAX_JOBS][16];
|
||||
uint8_t retiring[2 * AVA1_MAX_JOBS][16];
|
||||
unsigned retiring_n;
|
||||
} T = { .mu = PTHREAD_MUTEX_INITIALIZER };
|
||||
|
||||
@@ -27,9 +27,10 @@ static void retiring_add(const uint8_t id[16]) {
|
||||
unsigned i;
|
||||
for (i = 0; i < T.retiring_n; i++)
|
||||
if (memcmp(T.retiring[i], id, 16) == 0) return;
|
||||
/* Full: `create` refuses while the table is full (see there), so a new id cannot be
|
||||
* unlisted here — this branch is unreachable by construction. */
|
||||
if (T.retiring_n < AVA1_MAX_JOBS) memcpy(T.retiring[T.retiring_n++], id, 16);
|
||||
/* Full: unreachable by construction. `create` lists a job only while fewer than
|
||||
* AVA1_MAX_JOBS ids are retiring (an eviction included, see there), and at most
|
||||
* AVA1_MAX_JOBS jobs are listed, so at most 2 * AVA1_MAX_JOBS - 1 ids ever retire at once. */
|
||||
if (T.retiring_n < 2 * AVA1_MAX_JOBS) memcpy(T.retiring[T.retiring_n++], id, 16);
|
||||
}
|
||||
|
||||
/* Caller holds T.mu. */
|
||||
@@ -78,7 +79,10 @@ ava1_job_t *ava1_job_find(const uint8_t id[16]) {
|
||||
* and journal append are behind it) and `unswept_n` are read without j->mu, as in the reaper. */
|
||||
static int transfer_ended(const ava1_job_t *j) {
|
||||
return (j->kind == AVA1_JOB_UPLOAD || j->kind == AVA1_JOB_DOWNLOAD) && !j->c2c &&
|
||||
__atomic_load_n(&j->concluded_ms, __ATOMIC_ACQUIRE) && !__atomic_load_n(&j->unswept_n, __ATOMIC_RELAXED);
|
||||
__atomic_load_n(&j->concluded_ms, __ATOMIC_ACQUIRE) && !__atomic_load_n(&j->unswept_n, __ATOMIC_RELAXED) &&
|
||||
/* durable-by-log: settled too, or its last Status{unswept=0} (which the sender waits for) and
|
||||
* the pack segments' removal are still to come between unswept_n reaching 0 and `settled` */
|
||||
(!__atomic_load_n(&j->npsegs, __ATOMIC_RELAXED) || __atomic_load_n(&j->settled, __ATOMIC_ACQUIRE));
|
||||
}
|
||||
|
||||
/* Caller holds T.mu, and the table is full: the ended transfer nobody else holds (only the table's
|
||||
@@ -128,24 +132,27 @@ static ava1_job_t *create(const uint8_t id[16], const uint8_t owner[32], const u
|
||||
}
|
||||
if (!T.jobs[i] && slot == -1) slot = i;
|
||||
}
|
||||
if (slot == -1 && (i = evictable_locked()) >= 0) {
|
||||
evicted = T.jobs[i];
|
||||
unlist(evicted); /* its id stays retiring until the put below has destroyed it */
|
||||
slot = i;
|
||||
}
|
||||
if (slot >= 0)
|
||||
if (slot != -2)
|
||||
for (i = 0; i < (int)T.retiring_n; i++)
|
||||
if (memcmp(T.retiring[i], id, 16) == 0) {
|
||||
slot = -2; /* the previous job of this id is still being destroyed */
|
||||
break;
|
||||
}
|
||||
/* The retiring table is full: this job's own unlist could not be recorded, and the
|
||||
* reopen guard is only complete while every retiring id is listed — refuse rather
|
||||
* than let a create whose destroy would silently lose the guard through. */
|
||||
if (slot >= 0 && T.retiring_n >= AVA1_MAX_JOBS) slot = -2;
|
||||
/* Too many ids retiring: refuse rather than let a create through whose own unlist the
|
||||
* retiring list might not have room for (the reopen guard is only complete while every
|
||||
* retiring id is listed). An eviction adds one, so it needs room for that one as well: a
|
||||
* victim is only destroyed when the create it makes room for goes through. */
|
||||
if (slot != -2 && T.retiring_n + (slot == -1) >= AVA1_MAX_JOBS) slot = -2;
|
||||
if (slot == -1 && (i = evictable_locked()) >= 0) {
|
||||
evicted = T.jobs[i];
|
||||
unlist(evicted); /* its id stays retiring until its destroy below has run */
|
||||
slot = i;
|
||||
}
|
||||
if (slot >= 0) T.jobs[slot] = j;
|
||||
pthread_mutex_unlock(&T.mu);
|
||||
if (evicted) ava1_job_put(evicted); /* the table's reference, the last one: joins its idle threads */
|
||||
/* The table's reference, the last one: destroyed (its idle threads joined) on a thread of its
|
||||
* own, so the JobOpen waiting here is not held up by it. */
|
||||
if (evicted) ava1_job_put_nowait(evicted);
|
||||
if (slot < 0) {
|
||||
pthread_mutex_destroy(&j->mu);
|
||||
pthread_mutex_destroy(&j->jnl_mu);
|
||||
|
||||
Reference in new issue
Block a user