7a5eccf574d9785fbe862e6e5f1db2cbdfe44982 max Fri Jan 17 09:24:41 2014 -0800 not adding failover connections to the connection pool, as they aremanaged by their "parent". This lead to invalid pointers when failover was activated in the sqlCleanup step upon exit. Also fixing a debug message. diff --git src/hg/lib/jksql.c src/hg/lib/jksql.c index a540299..65a6ae5 100644 --- src/hg/lib/jksql.c +++ src/hg/lib/jksql.c @@ -822,42 +822,44 @@ } } static void sqlInitTracking(void) /* Initialize tracking and freeing of resources. */ { if (sqlOpenConnections == NULL) { sqlOpenConnections = newDlList(); atexit(sqlCleanupAll); } } static struct sqlConnection *sqlConnRemoteFillIn(struct sqlConnection *sc, char *host, unsigned int port, char *socket, char *user, char *password, - char *database, boolean abort) + char *database, boolean abort, boolean addAsOpen) /* Fill the sqlConnection object: Connect to database somewhere as somebody. * Database maybe NULL to just connect to the server. If abort is set display * error message and abort on error. This is the core function that connects to * a MySQL server. */ { MYSQL *conn; long deltaTime; sqlInitTracking(); sc->resultList = newDlList(); + +if (addAsOpen) sc->node = dlAddValTail(sqlOpenConnections, sc); long oldTime = monitorEnterTime; monitorEnterTime = 0; monitorEnter(); if ((sc->conn = conn = mysql_init(NULL)) == NULL) // no need for monitorLeave here errAbort("Couldn't connect to mySQL."); // Fix problem where client LOCAL setting is disabled by default for security mysql_options(conn, MYSQL_OPT_LOCAL_INFILE, NULL); if (mysql_real_connect( conn, host, /* host */ user, /* user name */ @@ -901,31 +903,31 @@ sc->hasTableCache=-1; // -1 => not determined sc->db=database; return sc; } static struct sqlConnection *sqlConnRemote(char *host, unsigned int port, char *socket, char *user, char *password, char *database, boolean abort) /* Connect to database somewhere as somebody. Database maybe NULL to just * connect to the server. If abort is set display error message and abort on * error. */ { struct sqlConnection *sc; AllocVar(sc); -return sqlConnRemoteFillIn(sc, host, port, socket, user, password, database, abort); +return sqlConnRemoteFillIn(sc, host, port, socket, user, password, database, abort, TRUE); } struct sqlConnection *sqlConnectRemote(char *host, char *user, char *password, char *database) /* Connect to database somewhere as somebody. Database maybe NULL to * just connect to the server. Abort on error. */ { return sqlConnRemote(host, 0, NULL, user, password, database, TRUE); } struct sqlConnection *sqlMayConnectRemote(char *host, char *user, char *password, char *database) /* Connect to database somewhere as somebody. Database maybe NULL to * just connect to the server. Return NULL can't connect */ { @@ -958,36 +960,37 @@ slowSc->profile = slow; // remember the profile slowSc->db = database; slowSc->hasTableCache = -1; sc->slowConn = slowSc; return sc; } struct sqlConnection *sqlMayConnect(char *database) /* Connect to database on default host as default user. * Return NULL (don't abort) on failure. */ { return sqlConnProfile(sqlProfileMustGet(NULL, database), database, FALSE); } static struct sqlConnection *sqlConnectIfUnconnected(struct sqlConnection *sc) -/* Take a yet unconnected sqlConnection object and connect it to the sql server */ +/* Take a yet unconnected failover sqlConnection object and connect it to the sql server. + * Don't add it to the list of open connections, as it is freed by it's non-failover parent */ { if (sc->conn!=NULL) return sc; struct sqlProfile *sp = sqlProfileMustGet(sc->profile->name, sc->db); -sqlConnRemoteFillIn(sc, sp->host, sp->port, sp->socket, sp->user, sp->password, sc->db, TRUE); +sqlConnRemoteFillIn(sc, sp->host, sp->port, sp->socket, sp->user, sp->password, sc->db, TRUE, FALSE); return sc; } struct sqlConnection *sqlConnect(char *database) /* Connect to database on default host as default user. */ { struct sqlProfile *defProf = sqlProfileMustGet(NULL, database); return sqlConnProfile(defProf, database, TRUE); } struct sqlConnection *sqlConnectProfile(char *profileName, char *database) /* Connect to profile or database using the specified profile. Can specify * profileName, database, or both. The profile is the prefix to the host, * user, and password variables in .hg.conf. For the default profile of "db", * the environment variables HGDB_HOST, HGDB_USER, and HGDB_PASSWORD can @@ -1077,31 +1080,31 @@ { sqlCheckError("Oops, multiple occurrences of NOSQLINJ tag in query: %s", query); query = replaceChars(query, "NOSQLINJ ", ""); fixedMultipleNOSQLINJ = TRUE; } assert(!sc->isFree); monitorEnter(); int mysqlError = mysql_real_query(sc->conn, query, strlen(query)); // if the query fails on the main connection, connect the slower/failover connection and try there if (mysqlError != 0 && sc->slowConn) { if (monitorFlags & JKSQL_TRACE) - monitorPrint(sc, "SQL_FAILOVER %s to %s\n", sc->profile->name, sc->slowConn->profile->name); + monitorPrint(sc, "SQL_FAILOVER", "%s -> %s", sc->profile->name, sc->slowConn->profile->name); sc = sc->slowConn; sc = sqlConnectIfUnconnected(sc); mysqlError = mysql_real_query(sc->conn, query, strlen(query)); } if (mysqlError != 0) { if (abort) { monitorLeave(); if (sameOk(cfgOption("noSqlInj.dumpStack"), "on")) dumpStack("DEBUG Can't start query"); // Extra debugging info. DEBUG REMOVE sqlAbort(sc, "Can't start query:\n%s\n", query); }