int hubPublicAdd(char *table, char *url) /* hubPublicAdd -- add url to hubPublic table */ { struct errCatch *errCatch = errCatchNew(); boolean gotWarning = FALSE; struct trackHub *tHub = NULL; int dbCount = 0; if (errCatchStart(errCatch)) tHub = trackHubOpen(url, "hub_1"); errCatchEnd(errCatch); if (errCatch->gotError) { gotWarning = TRUE; warn("%s", errCatch->message->string); } errCatchFree(&errCatch); if (gotWarning) return 1; struct hashEl *hel; struct hashCookie cookie = hashFirst(tHub->genomeHash); struct dyString *dy = newDyString(1024); while ((hel = hashNext(&cookie)) != NULL) { dbCount++; dyStringPrintf(dy, "%s,", trackHubSkipHubName(hel->name)); } printf("insert into %s (hubUrl,descriptionUrl,shortLabel,longLabel,registrationTime,dbCount,dbList) values (\"%s\",\"%s\", \"%s\", \"%s\", now(),%d, \"%s\");\n", table, url, tHub->descriptionUrl, tHub->shortLabel, tHub->longLabel, dbCount, dy->string); return 0; }
int hubSettingsCheckInit(struct trackHub *hub, struct trackHubCheckOptions *options, struct dyString *errors) { int retVal = 0; if (hub->version != NULL && options->version == NULL) options->version = hub->version; struct trackHubSettingSpec *hubLevel = NULL; int level = 0; if (hub->version != NULL) { AllocVar(hubLevel); if ((level = trackHubSettingLevel(hubLevel)) < 0) { dyStringPrintf(errors, "Unknown hub support level: %s. Defaulting to 'all'.\n", hub->level); retVal = 1; } else options->level = hub->level; } verbose(2, "Checking hub '%s'", hub->longLabel); if (options->level) verbose(2, " for compliance to level '%s' (use -settings to view)", options->level); verbose(2, "\n"); struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { /* make hash of settings for this version, saving in options */ struct trackHubSettingSpec *setting, *settings = trackHubSettingsForVersion(options->specHost, options->version); options->settings = newHash(0); options->suggest = NULL; for (setting = settings; setting != NULL; setting = setting->next) { hashAdd(options->settings, setting->name, setting); slNameAddHead(&options->suggest, setting->name); } /* TODO: ? also need to check settings not in this list (other tdb fields) */ // TODO: move extra file handling here (out of hubCheck) if (options->extra != NULL) { struct hashCookie cookie = hashFirst(options->extra); struct hashEl *hel; while ((hel = hashNext(&cookie)) != NULL) slNameAddHead(&options->suggest, hel->name); } slNameSort(&options->suggest); verbose(3, "Suggest list has %d settings\n", slCount(options->suggest)); } errCatchEnd(errCatch); if (errCatch->gotError) { retVal = 1; dyStringPrintf(errors, "%s", errCatch->message->string); } errCatchFree(&errCatch); return retVal; }
void cartJsonGetGroupedTrackDb(struct cartJson *cj, struct hash *paramHash) /* Translate trackDb list (only a subset of the fields) into JSON array of track group objects; * each group contains an array of track objects that may have subtracks. Send it in a wrapper * object that includes the database from which it was taken; it's possible that by the time * this reaches the client, the user might have switched to a new db. */ { struct jsonWrite *jw = cj->jw; struct trackDb *fullTrackList = NULL; struct grp *fullGroupList = NULL; struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { cartTrackDbInit(cj->cart, &fullTrackList, &fullGroupList, /* useAccessControl=*/TRUE); } errCatchEnd(errCatch); if (errCatch->gotError) { warn("%s", errCatch->message->string); jsonWriteObjectStart(jw, "groupedTrackDb"); jsonWriteString(jw, "db", cartString(cj->cart, "db")); jsonWriteListStart(jw, "groupedTrackDb"); jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); return; } errCatchFree(&errCatch); struct hash *groupedTrackRefList = hashTracksByGroup(fullTrackList); // If the optional param 'fields' is given, hash the field names that should be returned. char *fields = cartJsonOptionalParam(paramHash, "fields"); struct hash *fieldHash = hashFromCommaString(fields); char *excludeTypes = cartJsonOptionalParam(paramHash, "excludeTypes"); struct hash *excludeTypesHash = hashFromCommaString(excludeTypes); // Also check for optional parameter 'maxDepth': int maxDepth = -1; char *maxDepthStr = cartJsonOptionalParam(paramHash, "maxDepth"); if (isNotEmpty(maxDepthStr)) maxDepth = atoi(maxDepthStr); jsonWriteObjectStart(jw, "groupedTrackDb"); jsonWriteString(jw, "db", cartString(cj->cart, "db")); jsonWriteListStart(jw, "groupedTrackDb"); int nonEmptyGroupCount = 0; struct grp *grp; for (grp = fullGroupList; grp != NULL; grp = grp->next) { struct slRef *tdbRefList = hashFindVal(groupedTrackRefList, grp->name); if (writeGroupedTrack(jw, grp->name, grp->label, fieldHash, excludeTypesHash, maxDepth, tdbRefList)) { nonEmptyGroupCount++; } } if (nonEmptyGroupCount == 0) { // Catch-all for assembly hubs that don't declare groups for their tracks: add All Tracks struct slRef *allTracks = sortedAllTracks(fullTrackList); (void)writeGroupedTrack(jw, "allTracks", "All Tracks", fieldHash, excludeTypesHash, maxDepth, allTracks); } jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); }
int hubPublicCheck(char *table) /* hubPublicCheck - checks that the labels in hubPublic match what is in the hub labels. */ { struct sqlConnection *conn = hConnectCentral(); char query[512]; bool hasDescriptionUrl = sqlColumnExists(conn, table, "descriptionUrl"); if (hasDescriptionUrl) sqlSafef(query, sizeof(query), "select hubUrl, shortLabel,longLabel,dbList,descriptionUrl from %s", table); else sqlSafef(query, sizeof(query), "select hubUrl, shortLabel,longLabel,dbList from %s", table); struct sqlResult *sr = sqlGetResult(conn, query); char **row; int differences = 0; while ((row = sqlNextRow(sr)) != NULL) { char *url = row[0], *shortLabel = row[1], *longLabel = row[2], *dbList = row[3], *descriptionUrl = row[4]; struct errCatch *errCatch = errCatchNew(); boolean gotWarning = FALSE; struct trackHub *tHub = NULL; if (errCatchStart(errCatch)) tHub = trackHubOpen(url, "hub_1"); errCatchEnd(errCatch); if (errCatch->gotError) { gotWarning = TRUE; warn("%s", errCatch->message->string); } errCatchFree(&errCatch); if (gotWarning) { continue; } if (!sameString(shortLabel, tHub->shortLabel)) { differences++; printf("update %s set shortLabel=\"%s\" where hubUrl=\"%s\";\n",table, tHub->shortLabel, url); } if (!sameString(longLabel, tHub->longLabel)) { differences++; printf("update %s set longLabel=\"%s\" where hubUrl=\"%s\";\n",table, tHub->longLabel, url); } struct hashCookie cookie = hashFirst(tHub->genomeHash); struct dyString *dy = newDyString(1024); struct hashEl *hel; while ((hel = hashNext(&cookie)) != NULL) dyStringPrintf(dy, "%s,", trackHubSkipHubName(hel->name)); if (!sameString(dy->string, dbList)) { differences++; printf("update %s set dbList=\"%s\" where hubUrl=\"%s\";\n",table, dy->string, url); } if (hasDescriptionUrl && !isEmpty(tHub->descriptionUrl) && ((descriptionUrl == NULL) || !sameString(descriptionUrl, tHub->descriptionUrl))) { differences++; printf("update %s set descriptionUrl=\"%s\" where hubUrl=\"%s\";\n",table, tHub->descriptionUrl, url); } trackHubClose(&tHub); } return differences; }
void bamLoadItemsCore(struct track *tg, boolean isPaired) /* Load BAM data into tg->items item list, unless zoomed out so far * that the data would just end up in dense mode and be super-slow. */ { /* protect against temporary network error */ struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { struct hash *pairHash = isPaired ? hashNew(18) : NULL; int minAliQual = atoi(cartOrTdbString(cart, tg->tdb, BAM_MIN_ALI_QUAL, BAM_MIN_ALI_QUAL_DEFAULT)); char *colorMode = cartOrTdbString(cart, tg->tdb, BAM_COLOR_MODE, BAM_COLOR_MODE_DEFAULT); char *grayMode = cartOrTdbString(cart, tg->tdb, BAM_GRAY_MODE, BAM_GRAY_MODE_DEFAULT); char *userTag = cartOrTdbString(cart, tg->tdb, BAM_COLOR_TAG, BAM_COLOR_TAG_DEFAULT); int aliQualShadeMin = 0, aliQualShadeMax = 99, baseQualShadeMin = 0, baseQualShadeMax = 40; parseIntRangeSetting(tg->tdb, "aliQualRange", &aliQualShadeMin, &aliQualShadeMax); parseIntRangeSetting(tg->tdb, "baseQualRange", &baseQualShadeMin, &baseQualShadeMax); struct bamTrackData btd = {tg, pairHash, minAliQual, colorMode, grayMode, userTag, aliQualShadeMin, aliQualShadeMax, baseQualShadeMin, baseQualShadeMax}; char *fileName = trackDbSetting(tg->tdb, "bigDataUrl"); if (fileName == NULL) { if (tg->customPt) { errAbort("bamLoadItemsCore: can't find bigDataUrl for custom track %s", tg->track); } else { struct sqlConnection *conn = hAllocConnTrack(database, tg->tdb); fileName = bamFileNameFromTable(conn, tg->table, chromName); hFreeConn(&conn); } } char *fileName2 = hReplaceGbdb(fileName); char posForBam[512]; safef(posForBam, sizeof(posForBam), "%s:%d-%d", chromName, winStart, winEnd); char *cacheDir = cfgOption("cramRef"); char *refUrl = trackDbSetting(tg->tdb, "refUrl"); if (!isPaired) bamFetchPlus(fileName2, posForBam, addBam, &btd, NULL, refUrl, cacheDir); else { char *setting = trackDbSettingClosestToHomeOrDefault(tg->tdb, "pairSearchRange", "20000"); int pairSearchRange = atoi(setting); if (pairSearchRange > 0) safef(posForBam, sizeof(posForBam), "%s:%d-%d", chromName, max(0, winStart-pairSearchRange), winEnd+pairSearchRange); bamFetchPlus(fileName2, posForBam, addBamPaired, &btd, NULL, refUrl, cacheDir); struct hashEl *hel; struct hashCookie cookie = hashFirst(btd.pairHash); while ((hel = hashNext(&cookie)) != NULL) { struct linkedFeatures *lf = hel->val; if (lf->start < winEnd && lf->end > winStart) slAddHead(&(tg->items), lfsFromLf(lf)); } } freez(&fileName2); if (tg->visibility != tvDense) { slReverse(&(tg->items)); if (isPaired) slSort(&(tg->items), linkedFeaturesSeriesCmp); else if (sameString(colorMode, BAM_COLOR_MODE_STRAND)) slSort(&(tg->items), linkedFeaturesCmpOri); else if (sameString(colorMode, BAM_COLOR_MODE_GRAY) && sameString(grayMode, BAM_GRAY_MODE_ALI_QUAL)) slSort(&(tg->items), linkedFeaturesCmpScore); else slSort(&(tg->items), linkedFeaturesCmpStart); if (slCount(tg->items) > MAX_ITEMS_FOR_MAPBOX) { // flag drawItems to make a mapBox for the whole track tg->customInt = 1; tg->mapItem = dontMapItem; } } } errCatchEnd(errCatch); if (errCatch->gotError) { tg->networkErrMsg = cloneString(errCatch->message->string); tg->drawItems = bigDrawWarning; tg->totalHeight = bigWarnTotalHeight; } errCatchFree(&errCatch); }
void edwSubmit(char *submitUrl, char *email) /* edwSubmit - Submit URL with validated.txt to warehouse. */ { /* Parse out url a little into submitDir and submitFile */ char *lastSlash = strrchr(submitUrl, '/'); if (lastSlash == NULL) errAbort("%s is not a valid URL - it has no '/' in it.", submitUrl); char *submitFile = lastSlash+1; int submitDirSize = submitFile - submitUrl; char submitDir[submitDirSize+1]; memcpy(submitDir, submitUrl, submitDirSize); submitDir[submitDirSize] = 0; // Add trailing zero /* Make sure user has access. */ struct sqlConnection *conn = edwConnectReadWrite(); struct edwUser *user = edwMustGetUserFromEmail(conn, email); int userId = user->id; /* See if we are already running on same submission. If so council patience and quit. */ notOverlappingSelf(conn, submitUrl); /* Make a submit record. */ int submitId = makeNewEmptySubmitRecord(conn, submitUrl, userId); /* The next errCatch block will fill these in if all goes well. */ struct submitFileRow *sfrList = NULL, *oldList = NULL, *newList = NULL; int oldCount = 0; long long oldBytes = 0, newBytes = 0, byteCount = 0; /* Start catching errors from here and writing them in submitId. If we don't * throw we'll end up having a list of all files in the submit in sfrList. */ struct errCatch *errCatch = errCatchNew(); char query[1024]; if (errCatchStart(errCatch)) { /* Make sure they got a bit of space, enough for a reasonable submit file. * We do this here just because we can make error message more informative. */ long long diskFreeSpace = freeSpaceOnFileSystem(edwRootDir); if (diskFreeSpace < 4*1024*1024) errAbort("No space left in warehouse!"); /* Open remote submission file. This is most likely where we will fail. */ int hostId=0, submitDirId = 0; long long startUploadTime = edwNow(); int remoteFd = edwOpenAndRecordInDir(conn, submitDir, submitFile, submitUrl, &hostId, &submitDirId); /* Copy to local temp file. */ char tempSubmitFile[PATH_LEN]; fetchFdToTempFile(remoteFd, tempSubmitFile); mustCloseFd(&remoteFd); long long endUploadTime = edwNow(); /* Calculate MD5 sum, and see if we already have such a file. */ char *md5 = md5HexForFile(tempSubmitFile); int fileId = findFileGivenMd5AndSubmitDir(conn, md5, submitDirId); /* If we already have it, then delete temp file, otherwise put file in file table. */ char submitLocalPath[PATH_LEN]; if (fileId != 0) { remove(tempSubmitFile); char submitRelativePath[PATH_LEN]; sqlSafef(query, sizeof(query), "select edwFileName from edwFile where id=%d", fileId); sqlNeedQuickQuery(conn, query, submitRelativePath, sizeof(submitRelativePath)); safef(submitLocalPath, sizeof(submitLocalPath), "%s%s", edwRootDir, submitRelativePath); } else { /* Looks like it's the first time we've seen this submission file, so * save the file itself. We'll get to the records inside the file in a bit. */ fileId = makeNewEmptyFileRecord(conn, submitId, submitDirId, submitFile, 0); /* Get file/path names for submission file inside warehouse. */ char edwFile[PATH_LEN]; edwMakeFileNameAndPath(fileId, submitFile, edwFile, submitLocalPath); /* Move file to final resting place and get update time and size from local file system. */ mustRename(tempSubmitFile, submitLocalPath); time_t updateTime = fileModTime(submitLocalPath); off_t size = fileSize(submitLocalPath); /* Update file table which now should be complete including updateTime. */ sqlSafef(query, sizeof(query), "update edwFile set " " updateTime=%lld, size=%lld, md5='%s', edwFileName='%s'," " startUploadTime=%lld, endUploadTime=%lld" " where id=%u\n", (long long)updateTime, (long long)size, md5, edwFile, startUploadTime, endUploadTime, fileId); sqlUpdate(conn, query); } /* By now there is a submit file on the local file system. We parse it out. */ edwParseSubmitFile(conn, submitLocalPath, submitUrl, &sfrList); /* Save our progress so far to submit table. */ sqlSafef(query, sizeof(query), "update edwSubmit" " set submitFileId=%lld, submitDirId=%lld, fileCount=%d where id=%d", (long long)fileId, (long long)submitDirId, slCount(sfrList), submitId); sqlUpdate(conn, query); /* Weed out files we already have. */ struct submitFileRow *sfr, *sfrNext; for (sfr = sfrList; sfr != NULL; sfr = sfrNext) { sfrNext = sfr->next; struct edwFile *bf = sfr->file; long long fileId; if ((fileId = edwGotFile(conn, submitDir, bf->submitFileName, bf->md5, bf->size)) >= 0) { ++oldCount; oldBytes += bf->size; sfr->md5MatchFileId = fileId; slAddHead(&oldList, sfr); } else slAddHead(&newList, sfr); byteCount += bf->size; } sfrList = NULL; slReverse(&newList); slReverse(&oldList); /* Update database with oldFile count. */ sqlSafef(query, sizeof(query), "update edwSubmit set oldFiles=%d,oldBytes=%lld,byteCount=%lld where id=%u", oldCount, oldBytes, byteCount, submitId); sqlUpdate(conn, query); /* Deal with old files. This may throw an error. We do it before downloading new * files since we want to fail fast if we are going to fail. */ int updateCount = handleOldFileTags(conn, oldList, doUpdate); sqlSafef(query, sizeof(query), "update edwSubmit set metaChangeCount=%d where id=%u", updateCount, submitId); sqlUpdate(conn, query); } errCatchEnd(errCatch); if (errCatch->gotError) { handleSubmitError(conn, submitId, errCatch->message->string); /* The handleSubmitError will keep on throwing. */ } errCatchFree(&errCatch); /* Go through list attempting to load the files if we don't already have them. */ struct submitFileRow *sfr; for (sfr = newList; sfr != NULL; sfr = sfr->next) { if (edwSubmitShouldStop(conn, submitId)) break; struct edwFile *bf = sfr->file; int submitUrlSize = strlen(submitDir) + strlen(bf->submitFileName) + 1; char submitUrl[submitUrlSize]; safef(submitUrl, submitUrlSize, "%s%s", submitDir, bf->submitFileName); if (edwGotFile(conn, submitDir, bf->submitFileName, bf->md5, bf->size)<0) { /* We can't get a ID for this file. There's two possible reasons - * either somebody is in the middle of fetching it or nobody's started. * If somebody is in the middle of fetching it, assume they died * if they took more than an hour, and start up another fetch. * So here we fetch unless somebody else is fetching recently. */ if (edwGettingFile(conn, submitDir, bf->submitFileName) < 0) { verbose(1, "Fetching %s\n", bf->submitFileName); getSubmittedFile(conn, bf, submitDir, submitUrl, submitId); newBytes += bf->size; sqlSafef(query, sizeof(query), "update edwSubmit set newFiles=newFiles+1,newBytes=%lld where id=%d", newBytes, submitId); sqlUpdate(conn, query); } } else { verbose(2, "Already got %s\n", bf->submitFileName); sqlSafef(query, sizeof(query), "update edwSubmit set oldFiles=oldFiles+1 where id=%d", submitId); sqlUpdate(conn, query); } if (sfr->replacesFile != 0) { /* What happens when the replacement doesn't validate? */ verbose(2, "Replacing %s with %s\n", sfr->replaces, bf->submitFileName); sqlSafef(query, sizeof(query), "update edwFile set replacedBy=%u, deprecated='%s' where id=%u", bf->id, sfr->replaceReason, sfr->replacesFile); sqlUpdate(conn, query); } } /* If we made it here, update submit endUploadTime */ sqlSafef(query, sizeof(query), "update edwSubmit set endUploadTime=%lld where id=%d", edwNow(), submitId); sqlUpdate(conn, query); /* Get a real submission record and then set things up so mail user when all done. */ struct edwSubmit *submit = edwSubmitFromId(conn, submitId); sqlDisconnect(&conn); // We'll be waiting a while so free connection waitForValidationAndSendEmail(submit, email); }
int edwFileFetch(struct sqlConnection *conn, struct edwFile *ef, int fd, char *submitFileName, unsigned submitId, unsigned submitDirId, unsigned hostId) /* Fetch file and if successful update a bunch of the fields in ef with the result. * Returns fileId. */ { ef->id = makeNewEmptyFileRecord(conn, submitId, submitDirId, ef->submitFileName, ef->size); /* Update edwSubmit with file in transit info */ char query[256]; sqlSafef(query, sizeof(query), "update edwSubmit set fileIdInTransit=%lld where id=%u", (long long)ef->id, submitId); sqlUpdate(conn, query); sqlSafef(query, sizeof(query), "select paraFetchStreams from edwHost where id=%u", hostId); int paraFetchStreams = sqlQuickNum(conn, query); struct paraFetchInterruptContext interruptContext = {.conn=conn, .submitId=submitId}; /* Wrap getting the file, the actual data transfer, with an error catcher that * will remove partly uploaded files. Perhaps some day we'll attempt to rescue * ones that are just truncated by downloading the rest, but not now. */ struct errCatch *errCatch = errCatchNew(); char tempName[PATH_LEN] = ""; char edwFile[PATH_LEN] = "", edwPath[PATH_LEN]; if (errCatchStart(errCatch)) { /* Now make temp file name and open temp file in an atomic operation */ char *tempDir = edwTempDir(); safef(tempName, PATH_LEN, "%sedwSubmitXXXXXX", tempDir); int localFd = mustMkstemp(tempName); /* Update file name in database with temp file name so web app can track us. */ char query[PATH_LEN+128]; sqlSafef(query, sizeof(query), "update edwFile set edwFileName='%s' where id=%lld", tempName + strlen(edwRootDir), (long long)ef->id); sqlUpdate(conn, query); /* Do actual upload tracking how long it takes. */ ef->startUploadTime = edwNow(); mustCloseFd(&localFd); if (!parallelFetchInterruptable(submitFileName, tempName, paraFetchStreams, 4, FALSE, FALSE, paraFetchInterruptFunction, &interruptContext)) { if (interruptContext.isInterrupted) errAbort("Submission stopped by user."); else errAbort("parallel fetch of %s failed", submitFileName); } ef->endUploadTime = edwNow(); /* Rename file both in file system and (via ef) database. */ edwMakeFileNameAndPath(ef->id, submitFileName, edwFile, edwPath); mustRename(tempName, edwPath); if (endsWith(edwPath, ".gz") && !encode3IsGzipped(edwPath)) errAbort("%s has .gz suffix, but is not gzipped", submitFileName); ef->edwFileName = cloneString(edwFile); } errCatchEnd(errCatch); if (errCatch->gotError) { /* Attempt to remove any partial file. */ if (tempName[0] != 0) { verbose(1, "Removing partial %s\n", tempName); parallelFetchRemovePartial(tempName); remove(tempName); } handleSubmitError(conn, submitId, errCatch->message->string); // Throws further assert(FALSE); // We never get here } errCatchFree(&errCatch); /* Now we got the file. We'll go ahead and save the file name and stuff. */ sqlSafef(query, sizeof(query), "update edwFile set" " edwFileName='%s', startUploadTime=%lld, endUploadTime=%lld" " where id = %d" , ef->edwFileName, ef->startUploadTime, ef->endUploadTime, ef->id); sqlUpdate(conn, query); /* Wrap the validations in an error catcher that will save error to file table in database */ errCatch = errCatchNew(); boolean success = FALSE; if (errCatchStart(errCatch)) { /* Check MD5 sum here. */ unsigned char md5bin[16]; md5ForFile(edwPath, md5bin); char md5[33]; hexBinaryString(md5bin, sizeof(md5bin), md5, sizeof(md5)); if (!sameWord(md5, ef->md5)) errAbort("%s has md5 mismatch: %s != %s. File may be corrupted in upload, or file may have " "been changed since validateManifest was run. Please check that md5 of file " "before upload is really %s. If it is then try submitting again, otherwise " "rerun validateManifest and then try submitting again. \n", ef->submitFileName, ef->md5, md5, ef->md5); /* Finish updating a bunch more of edwFile record. Note there is a requirement in * the validFile section that ef->updateTime be updated last. A nonzero ef->updateTime * is used as a sign of record complete. */ struct dyString *dy = dyStringNew(0); /* Includes tag so query may be long */ sqlDyStringPrintf(dy, "update edwFile set md5='%s',size=%lld,updateTime=%lld", md5, ef->size, ef->updateTime); dyStringAppend(dy, ", tags='"); dyStringAppend(dy, ef->tags); dyStringPrintf(dy, "' where id=%d", ef->id); sqlUpdate(conn, dy->string); dyStringFree(&dy); /* Update edwSubmit so file no longer shown as in transit */ sqlSafef(query, sizeof(query), "update edwSubmit set fileIdInTransit=0 where id=%u", submitId); sqlUpdate(conn, query); success = TRUE; } errCatchEnd(errCatch); if (errCatch->gotError) { handleFileError(conn, submitId, ef->id, errCatch->message->string); } return ef->id; }
void autoUpgradeTableAddSessionKey(struct sqlConnection *conn, char *tableName) /* Try to upgrade the table by adding sessionKey field * in a safe way handling success failures and retries * with multiple CGIs running. */ { boolean testAgain = checkAutoUpgradeTableResultTimeIsOld(tableName); if (testAgain) { // Get the advisory lock for this table // This prevents multiple CGI processes from trying to upgrade simultaneously char lockName[256]; safef(lockName, sizeof lockName, "AUTO_UPGRADE_%s", tableName); sqlGetLock(conn, lockName); // Make sure that the table has not been already upgraded by some earlier process. // We do not want to upgrade more than once. if (sqlFieldIndex(conn, tableName, "sessionKey") == -1) { char result[4096]; // Put a catch around the table upgrade attempt, // both to allow us to continue if it fails, // and to catch the error message and save it in the results file struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { char query[256]; sqlSafef(query, sizeof query, "alter table %s add column sessionKey varchar(255) NOT NULL default ''", tableName); sqlUpdate(conn, query); } errCatchEnd(errCatch); if (errCatch->gotError) { safef(result, sizeof result, "AUTOUPGRADE FAILED\n%s", errCatch->message->string); } else { safef(result, sizeof result, "OK\n"); } errCatchFree(&errCatch); writeAutoUpgradeTableResult(tableName, result); } // Release the advisory lock for this table sqlReleaseLock(conn, lockName); } else { // in the interests of speed, just use the old result char *oldResult = readAutoUpgradeTableResult(tableName); if (oldResult) { if (startsWith("AUTOUPGRADE FAILED", oldResult)) { // cannot do this here since it is too early and the warn handler does not work right // it ends up writing html and javascript before the cookie and response header have even been finished. // warn("%s", oldResult); // instead, save the error message for access later from select places like hgGateway if (!dyUpgradeError) dyUpgradeError = dyStringNew(256); else dyStringPrintf(dyUpgradeError,"\n"); dyStringPrintf(dyUpgradeError,"%s", oldResult); } } } }