2dffcd60f62e3fb25bbe8b009b4235bb3b9eb44f galt Sun Mar 9 14:54:38 2014 -0700 Adding better handling of auto-upgrade for the situation where simultaneous CGIs would try to all upgrade at once. It uses an advisory lock to make sure only one process is trying to upgrade at a time, and it checks again that the field does not exist already before adding the new sessionkey field, it writes the result of success or failure with the error message to a TRASH file so that other CGIs may access it. To prevent them all from repeatedly trying to do the same upgrade with every CGI execution, it checks the time-stamp on the AUTOUPGRADE trash file, and if it is older than 3 minutes, then it will try again to see if the admins have given it the permissions needed - which will then re-write the trash file with the results and its time will be updated. If an error occurs during sql upgrade, it traps the error instead of errAborting and the message is saved to be included in the trash file, and the system proceeds for now without the new sessionKey field. diff --git src/hg/hgGateway/hgGateway.c src/hg/hgGateway/hgGateway.c index 0a2bcc9..33e029d 100644 --- src/hg/hgGateway/hgGateway.c +++ src/hg/hgGateway/hgGateway.c @@ -1,356 +1,364 @@ /* hgGateway - Human Genome Browser Gateway. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "cheapcgi.h" #include "htmshell.h" #include "obscure.h" #include "web.h" #include "cart.h" #include "hdb.h" #include "dbDb.h" #include "hgFind.h" #include "hCommon.h" #include "hui.h" #include "customTrack.h" #include "hubConnect.h" #include "hgConfig.h" #include "jsHelper.h" #include "hPrint.h" #include "suggest.h" #include "search.h" #include "geoMirror.h" #include "trackHub.h" struct cart *cart = NULL; struct hash *oldVars = NULL; char *clade = NULL; char *organism = NULL; char *db = NULL; +// TODO REMOVE AFTER AUTOUPGRADE COMPLETE: (added 2014-03-09) +extern struct dyString *dyUpgradeError; + void hgGateway() /* hgGateway - Human Genome Browser Gateway. */ { char *defaultPosition = hDefaultPos(db); char *position = cloneString(cartUsualString(cart, "position", defaultPosition)); boolean gotClade = hGotClade(); char *survey = cfgOptionEnv("HGDB_SURVEY", "survey"); char *surveyLabel = cfgOptionEnv("HGDB_SURVEY_LABEL", "surveyLabel"); boolean supportsSuggest = FALSE; if (!trackHubDatabase(db)) supportsSuggest = assemblySupportsGeneSuggest(db); /* JavaScript to copy input data on the change genome button to a hidden form This was done in order to be able to flexibly arrange the UI HTML */ char *onChangeDB = "onchange=\"document.orgForm.db.value = document.mainForm.db.options[document.mainForm.db.selectedIndex].value; document.orgForm.submit();\""; char *onChangeOrg = "onchange=\"document.orgForm.org.value = document.mainForm.org.options[document.mainForm.org.selectedIndex].value; document.orgForm.db.value = 0; document.orgForm.submit();\""; char *onChangeClade = "onchange=\"document.orgForm.clade.value = document.mainForm.clade.options[document.mainForm.clade.selectedIndex].value; document.orgForm.org.value = 0; document.orgForm.db.value = 0; document.orgForm.submit();\""; /* If we are changing databases via explicit cgi request, then remove custom track data which will be irrelevant in this new database . If databases were changed then use the new default position too. */ if (sameString(position, "genome") || sameString(position, "hgBatch")) position = defaultPosition; jsIncludeFile("jquery.js", NULL); webIncludeResourceFile("jquery-ui.css"); jsIncludeFile("jquery-ui.js", NULL); jsIncludeFile("ajax.js", NULL); jsIncludeFile("autocomplete.js", NULL); jsIncludeFile("hgGateway.js", NULL); jsIncludeFile("utils.js", NULL); jsIncludeFile("jquery.watermarkinput.js", NULL); puts("
" "The UCSC Genome Browser was created by the \n" "Genome Bioinformatics Group of UC Santa Cruz.\n" "
" "Software Copyright (c) The Regents of the University of California.\n" "All rights reserved.\n" "
\n"); puts("
\n" "
" "\n" "\n"); puts("
\n"); cgiMakeHiddenVar(hgHubConnectCgiDestUrl, "../cgi-bin/hgTracks"); puts(""); if (gotClade) puts(""); puts("\n" "\n" "\n" "\n" "\n" "\n"); if (gotClade) { puts("\n"); } puts("\n"); puts("\n"); puts("\n"); cartSetString(cart, "position", position); cartSetString(cart, "db", db); cartSetString(cart, "org", organism); if (gotClade) cartSetString(cart, "clade", clade); freez(&defaultPosition); position = NULL; puts("\n" "
groupgenomeassemblypositionsearch term  
\n"); printCladeListHtml(organism, onChangeClade); puts("\n"); if (gotClade) printGenomeListForCladeHtml(db, onChangeOrg); else printGenomeListHtml(db, onChangeOrg); puts("\n"); printAssemblyListHtml(db, onChangeDB); puts("\n"); hPrintf("%s", addCommasToPos(db, position)); hPrintf("\n", addCommasToPos(db, position)); puts("\n"); hPrintf("\n"); if(supportsSuggest) hPrintf("\n", assemblyGeneSuggestTrack(db)); printf(""); hButton("Submit", "submit"); /* This is a clear submit button that browsers will use by default when enter is pressed in position box. FIXME: This should be done with js onchange event! */ printf(""); cartSaveSession(cart); /* Put up hgsid= as hidden variable. */ puts("
\n" "

\n" "Click here to reset " "the browser user interface settings to their defaults."); #define SURVEY 1 #ifdef SURVEY if (survey && differentWord(survey, "off")) printf("   " "%s", survey, surveyLabel ? surveyLabel : "Take survey"); #endif puts("
\n" "
\n" "
\n"); puts(""); puts(""); if (isSearchTracksSupported(db,cart)) { puts(""); } // custom track button. disable hgCustom button on GSID server, until // necessary additional work is authorized. puts(""); if (hubConnectTableExists()) { puts(""); } // configure button puts(""); puts("
"); cgiMakeButtonWithMsg(TRACK_SEARCH, TRACK_SEARCH_BUTTON,TRACK_SEARCH_HINT); puts(""); /* disable CT for CGB servers for the time being */ if (!hIsGsidServer() && !hIsCgbServer()) { boolean hasCustomTracks = customTracksExist(cart, NULL); printf("\n", hgCustomName(),hasCustomTracks ? CT_MANAGE_BUTTON_LABEL:CT_ADD_BUTTON_LABEL, hasCustomTracks ? "Manage your custom tracks" : "Add your own custom tracks" ); } puts(""); printf("\n", "../cgi-bin/hgHubConnect", "track hubs", "Import tracks"); puts(""); cgiMakeButtonWithMsg("hgTracksConfigPage", "configure tracks and display", "Configure track selections and browser display"); puts("
"); puts("
\n" "
\n" ); puts("
"); if(!cartVarExists(cart, "pix")) // put a hidden input for pix on page so default value can be filled in on the client side hPrintf("\n"); puts("
"); if (hIsPreviewHost()) { puts("

" "WARNING: This is our preview site. It is a weekly mirror of our internal development server for public access. " "Data and tools here are under construction, have not been quality reviewed, and are subject to change " "at any time. We provide this site for early access, with the warning that it is less available " "and stable than our public site. For high-quality reviewed annotations on our production server, visit " " http://genome.ucsc.edu." "


"); } else if (hIsPrivateHost()) { puts("

WARNING: This is our development and test site. It usually works, but it is filled with tracks in various " "stages of construction, and others of little interest to people outside of our local group. " "It is usually slow because we are building databases on it. The documentation is poor. " "More data than usual is flat out wrong. Maybe you want to go to " "genome.ucsc.edu instead."); } if (hIsGsidServer()) { webNewSection("%s", "Sequence View\n"); printf("%s","Sequence View is a customized version of the UCSC Genome Browser, which is " "specifically tailored to provide functions needed for the GSID HIV Data Browser.\n"); } hgPositionsHelpHtml(organism, db); puts("

"); cartSaveSession(cart); /* Put up hgsid= as hidden variable. */ if (gotClade) printf("\n", clade); else printf("\n", "mammal"); printf("\n", organism); printf("\n", db); puts("

"); } void doMiddle(struct cart *theCart) /* Set up pretty web display and save cart in global. */ { char *scientificName = NULL; cart = theCart; getDbGenomeClade(cart, &db, &organism, &clade, oldVars); if (! hDbIsActive(db)) { db = hDefaultDb(); organism = hGenome(db); clade = hClade(organism); } scientificName = hScientificName(db); if (hIsGsidServer()) cartWebStart(theCart, db, "GSID %s Sequence View (UCSC Genome Browser) Gateway \n", organism); else { char buffer[128]; /* tell html routines *not* to escape htmlOut strings*/ htmlNoEscape(); buffer[0] = 0; if ((scientificName != NULL) && (*scientificName != 0)) { if (sameString(clade,"ancestor")) safef(buffer, sizeof(buffer), "(%s Ancestor) ", scientificName); else safef(buffer, sizeof(buffer), "(%s) ", scientificName); } cartWebStart(theCart, db, "%s %s%s Gateway\n", trackHubSkipHubName(organism), buffer, hBrowserName()); htmlDoEscape(); } hgGateway(); + +// TODO REMOVE AFTER AUTOUPGRADE COMPLETE: (added 2014-03-09) +if (dyUpgradeError) + warn(dyUpgradeError->string); + cartWebEnd(); } static void checkForGeoMirrorRedirect() { // Implement Geo/IP based redirection // // NOTE that we want to redirect people as quickly as possible, so for efficiency purposes, this code is designed to be // called from main BEFORE the cart is loaded (so we only use CGI parameters and/or cookies). char *thisNodeStr = geoMirrorNode(); if (thisNodeStr) { char *redirectCookie = findCookieData("redirect"); char *redirect = cgiOptionalString("redirect"); //fprintf(stderr, "GALT redirectCookie=%s redirect=%s\n", //redirectCookie, redirect); fflush(stderr); // DEBUG REMOVE if (redirect == NULL && redirectCookie == NULL) { int thisNode = sqlUnsigned(thisNodeStr); struct sqlConnection *centralConn = hConnectCentral(); char *ipStr = cgiRemoteAddr(); int node = defaultNode(centralConn, ipStr); // get location of redirect node if (thisNode != node) { char *geoSuffix = cfgOptionDefault("browser.geoSuffix",""); char query[1056]; sqlSafef(query, sizeof query, "select domain from gbNode%s where node = %d", geoSuffix, node); char *newDomain = sqlQuickString(centralConn, query); //fprintf(stderr, "GALT newDomain=%s\n", newDomain); fflush(stderr); // DEBUG REMOVE char *oldDomain = cgiServerName(); char *port = cgiServerPort(); char *uri = cgiRequestUri(); char *sep = strchr(uri, '?') ? "&" : "?"; int newUriSize = strlen(uri) + 1024; char *newUri = needMem(newUriSize); safef(newUri, newUriSize, "http%s://%s:%s%s%sredirect=auto&source=%s", cgiServerHttpsIsOn() ? "s" : "", newDomain, port, uri, sep, oldDomain); struct dyString *dy = dyStringNew(256); dyStringPrintf(dy, "HTTP/1.1 302 found: \n" "Content-Type: text/html; charset=iso-8859-1\n" "Connection: close\n" "Location: %s\n" "\n" "Redirecting to closer site\n" "%s\n" , newUri , newUri, newUri); //fprintf(stderr, "GALT redirect response:\n%s", dy->string); fflush(stderr); // DEBUG REMOVE puts(dyStringContents(dy)); exit(0); } hDisconnectCentral(¢ralConn); } } } char *excludeVars[] = {NULL}; int main(int argc, char *argv[]) /* Process command line. */ { long enteredMainTime = clock1000(); oldVars = hashNew(10); cgiSpoof(&argc, argv); setUdcCacheDir(); if(cgiIsOnWeb()) checkForGeoMirrorRedirect(); cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars); cgiExitTime("hgGateway", enteredMainTime); return 0; }