fd526976ba5971d4bae14235cf2f735751a5e548 angie Wed May 15 14:26:41 2019 -0700 Adding doReSaveSession to streamline loading and saving a session in one CGI request, for converting old session trash paths and customTrash tables to userdata and customData. refs #22440 diff --git src/hg/hgSession/hgSession.c src/hg/hgSession/hgSession.c index c07a0d5..1532a6a 100644 --- src/hg/hgSession/hgSession.c +++ src/hg/hgSession/hgSession.c @@ -745,44 +745,34 @@ } } if (tdb->visibility != tvHide) outIfNotPresent(cart, dy, tdb->track, tdb->visibility); } // Put a variable in the cart that says we put the default // visibilities in it. if (dy) dyStringPrintf(dy,"&%s=on", CART_HAS_DEFAULT_VISIBILITY); else printf("%s on", CART_HAS_DEFAULT_VISIBILITY); } #define INITIAL_USE_COUNT 0 -char *doNewSession(char *userName) -/* Save current settings in a new named session. - * Return a message confirming what we did. */ -{ -if (userName == NULL) - return "Unable to save session -- please log in and try again."; -struct dyString *dyMessage = dyStringNew(2048); -char *sessionName = trimSpaces(cartString(cart, hgsNewSessionName)); -char *encSessionName = cgiEncodeFull(sessionName); -boolean shareSession = cartBoolean(cart, hgsNewSessionShare); -char *encUserName = cgiEncodeFull(userName); -struct sqlConnection *conn = hConnectCentral(); - -if (sqlTableExists(conn, namedSessionTable)) +static int saveCartAsSession(struct sqlConnection *conn, char *encUserName, char *encSessionName, + boolean shareSession) +/* Save all settings in cart, either adding a new session or overwriting an existing session. + * Return useCount so that the caller can distinguish between adding and overWriting. */ { struct sqlResult *sr = NULL; struct dyString *dy = dyStringNew(16 * 1024); char **row; char *firstUse = "now()"; int useCount = INITIAL_USE_COUNT; char firstUseBuf[32]; /* If this session already existed, preserve its firstUse and useCount. */ sqlDyStringPrintf(dy, "SELECT firstUse, useCount FROM %s " "WHERE userName = '%s' AND sessionName = '%s';", namedSessionTable, encUserName, encSessionName); sr = sqlGetResult(conn, dy->string); if ((row = sqlNextRow(sr)) != NULL) { @@ -813,31 +803,49 @@ cartEncodeState(cart, encoded); // Now add all the default visibilities to output. outDefaultTracks(cart, encoded); sqlDyAppendEscaped(dy, encoded->string); dyStringFree(&encoded); dyStringAppend(dy, "', "); dyStringPrintf(dy, "%d, ", (shareSession ? 1 : 0)); dyStringPrintf(dy, "%s, now(), %d, '');", firstUse, useCount); sqlUpdate(conn, dy->string); dyStringFree(&dy); /* Prevent modification of custom track collections just saved to namedSessionDb: */ cartCopyCustomComposites(cart); +return useCount; +} +char *doNewSession(char *userName) +/* Save current settings in a new named session. + * Return a message confirming what we did. */ +{ +if (userName == NULL) + return "Unable to save session -- please log in and try again."; +struct dyString *dyMessage = dyStringNew(2048); +char *sessionName = trimSpaces(cartString(cart, hgsNewSessionName)); +char *encSessionName = cgiEncodeFull(sessionName); +boolean shareSession = cartBoolean(cart, hgsNewSessionShare); +char *encUserName = cgiEncodeFull(userName); +struct sqlConnection *conn = hConnectCentral(); + +if (sqlTableExists(conn, namedSessionTable)) + { + int useCount = saveCartAsSession(conn, encUserName, encSessionName, shareSession); if (useCount > INITIAL_USE_COUNT) dyStringPrintf(dyMessage, "Overwrote the contents of session <B>%s</B> " "(that %s be shared with other users). " "%s %s", htmlEncode(sessionName), (shareSession ? "may" : "may not"), getSessionLink(encUserName, encSessionName), getSessionEmailLink(encUserName, encSessionName)); else dyStringPrintf(dyMessage, "Added a new session <B>%s</B> that %s be shared with other users. " "%s %s", htmlEncode(sessionName), (shareSession ? "may" : "may not"), getSessionLink(encUserName, encSessionName), getSessionEmailLink(encUserName, encSessionName)); @@ -1522,30 +1530,80 @@ namedSessionTable, dyRa->string, encUserName, encSessionName); sqlUpdate(conn, dyQuery->string); dyStringPrintf(dyMessage, "Updated description of <B>%s</B>.\n", sessionName); } } if (isEmpty(dyMessage->string)) dyStringPrintf(dyMessage, "No changes to session <B>%s</B>.\n", sessionName); dyStringPrintf(dyMessage, "%s %s", getSessionLink(encUserName, encSessionName), getSessionEmailLink(encUserName, encSessionName)); if (shared) printShareMessage(dyMessage, encUserName, encSessionName, FALSE); return dyStringCannibalize(&dyMessage); } +static boolean isSessionShared(struct sqlConnection *conn, char *encUserName, char *encSessionName) +/* Return the value of 'shared' from the namedSessionDb row for user & session; + * errAbort if there is no such session. */ +{ +char query[2048]; +sqlSafef(query, sizeof(query), "select shared from %s where userName='%s' and sessionName = '%s';", + namedSessionTable, encUserName, encSessionName); +char buf[256]; +char *sharedStr = sqlQuickQuery(conn, query, buf, sizeof buf); +if (sharedStr == NULL) + errAbort("Unable to find session for userName='%s' and sessionName='%s'; no result from query '%s'", + encUserName, encSessionName, query); +return atoi(sharedStr); +} + +char *doReSaveSession(char *userName, char *actionVar) +/* Load a session (which may have old trash and customTrash references) and re-save it + * so that customTrash tables will be moved to customData* databases and trash paths + * will be replaced with userdata (hg.conf sessionDataDir) paths. + * NOTE: this is not intended to be reachable by the UI; it is for a script to update + * old sessions to use the new sessionData locations. */ +{ +if (userName == NULL) + return "Unable to re-save session -- please log in and try again."; +struct sqlConnection *conn = hConnectCentral(); +char *sessionName = cloneString(trimSpaces(cartString(cart, hgsNewSessionName))); +char *encUserName = cgiEncodeFull(userName); +char *encSessionName = cgiEncodeFull(sessionName); +boolean shareSession = isSessionShared(conn, encUserName, encSessionName); +cartLoadUserSession(conn, userName, sessionName, cart, NULL, actionVar); +// Don't cartCopyCustomComposites because we're not going to make any track collection changes +hubConnectLoadHubs(cart); +cartHideDefaultTracks(cart); +struct dyString *dyMessage = dyStringNew(1024); +dyStringPrintf(dyMessage, + "Re-saved settings from user <B>%s</B>'s session <B>%s</B> " + "that %s be shared with others. %s %s", + userName, htmlEncode(sessionName), (shareSession ? "may" : "may not"), + getSessionLink(userName, encSessionName), + getSessionEmailLink(encUserName, encSessionName)); +cartCheckForCustomTracks(cart, dyMessage); +int useCount = saveCartAsSession(conn, encUserName, encSessionName, shareSession); +if (useCount <= INITIAL_USE_COUNT) + errAbort("Expected useCount of at least %d after re-saving session for " + "userName='%s', sessionName='%s', but got %d", + INITIAL_USE_COUNT+1, encUserName, encSessionName, useCount); +hDisconnectCentral(&conn); +return dyStringCannibalize(&dyMessage); +} + // ====================================== void prepBackGroundCall(char **pBackgroundProgress, char *cleanPrefix) /* fix cart and save state */ { *pBackgroundProgress = cloneString(cgiUsualString("backgroundProgress", NULL)); cartRemove(cart, "backgroundExec"); cartRemove(cart, "backgroundProgress"); cartRemovePrefix(cart, cleanPrefix); cartSaveState(cart); // in case it crashes } void launchForeAndBackGround(char *operation) /* update cart, launch background and foreground */ { @@ -1718,30 +1776,35 @@ doMainPage(userName, message); } else if (cartVarExists(cart, hgsOldSessionName)) { char *message1 = doSessionChange(userName, cartString(cart, hgsOldSessionName)); char *message2 = doUpdateSessions(userName); char *message = message2; if (!startsWith("No changes to session", message1)) { size_t len = (sizeof message1[0]) * (strlen(message1) + strlen(message2) + 1); message = needMem(len); safef(message, len, "%s%s", message1, message2); } doMainPage(userName, message); } +else if (cartVarExists(cart, hgsDoReSaveSession)) + { + char *message = doReSaveSession(userName, hgsDoReSaveSession); + printf("\n%s\n\n", message); + } else { char *message = doUpdateSessions(userName); doMainPage(userName, message); } cleanHgSessionFromCart(cart); /* Save the cart state: */ cartCheckout(&cart); } int main(int argc, char *argv[]) /* Process command line. */ { long enteredMainTime = clock1000();