f518e03d8f56af784ec14536a7bdc0daed9a38fd chmalee Wed Sep 16 11:11:32 2026 -0700 Send each file's genome with a hubtools upload so hubSpace rows get a db, and stop the server rewriting a user-uploaded hub.txt, no redmine Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> diff --git src/hg/lib/userdata.c src/hg/lib/userdata.c index 0bc28371523..4617b662ff6 100644 --- src/hg/lib/userdata.c +++ src/hg/lib/userdata.c @@ -620,47 +620,57 @@ sleep1000(HUB_LOCK_POLL_MS); waitedMs += HUB_LOCK_POLL_MS; } dyStringFree(&lockPath); return fd; } void unlockHubDir(int fd) /* Release an exclusive hub lock acquired by lockHubDir. Closing the fd * releases the flock automatically on Linux. */ { if (fd >= 0) close(fd); } -void upgradeExistingHubToAssembly(struct hubSpace *rowForFile, char *userDataDir) -/* When a 2bit lands in a hub, add the assembly stanza to hub.txt (if the - * backend owns it) and flip every row for this hub to hubType='assemblyHub'. - * No-op unless rowForFile is a 2bit. */ +void upgradeExistingHubToAssembly(struct hubSpace *rowForFile, char *userDataDir, + boolean backendOwnsHubTxt) +/* When a 2bit arrives into a hub, mark every hubSpace row for this hub as + * hubType='assemblyHub'. When backendOwnsHubTxt, first add the assembly stanza to + * the synthesized hub.txt, which is itself a no-op if that file does not exist. + * Pass FALSE for a hub.txt the user uploaded, whose contents are theirs to write. + * The whole function is a no-op unless rowForFile is a 2bit. */ { if (!sameOk(rowForFile->fileType, "2bit")) return; char *hubDir = hubPathFromParentDir(rowForFile->parentDir, userDataDir); struct dyString *hubFileDy = dyStringCreate("%s%shub.txt", hubDir, endsWith(hubDir, "/") ? "" : "/"); char *hubFile = dyStringCannibalize(&hubFileDy); +// rewrite hub.txt before any row is touched. upgradeHubTxtForAssembly aborts on a +// failed write and the caller's errCatch does not roll back mysql, so flipping the +// rows first would leave a hub marked assemblyHub whose hub.txt has no twoBitPath +if (backendOwnsHubTxt) upgradeHubTxtForAssembly(hubFile, rowForFile->db, rowForFile->location); setAssemblyHubTypeForDir(rowForFile->userName, hubDir); +if (backendOwnsHubTxt) + { // hub.txt just changed on disk, so the row's size and md5 are out of date refreshHubTextRow(rowForFile->userName, hubFile); + } freeMem(hubFile); } char *writeHubText(char *path, char *userName, char *db, char *twoBitFileName) /* Create a hub.txt file, optionally creating the directory holding it. * If twoBitFileName is non-NULL, write an assembly hub stanza referencing it * (with stub organism / scientificName / description / defaultPos derived from * the 2bit). For convenience, return the file name of the created hub, which * can be freed. */ { // an empty path would put the hub.txt at the root of the filesystem if (isEmpty(path)) errAbort("no directory given for the hub, cannot create hub.txt"); int oldUmask = 00;