[mapserver-commits] r7539 - branches/branch-5-0/mapserver
svn at osgeo.org
svn at osgeo.org
Sun Apr 27 16:03:19 EDT 2008
Author: pramsey
Date: 2008-04-27 16:03:19 -0400 (Sun, 27 Apr 2008)
New Revision: 7539
Modified:
branches/branch-5-0/mapserver/HISTORY.TXT
branches/branch-5-0/mapserver/mappostgis.c
Log:
Fixed overlapping transaction behavior, which causes fcgi failures. (#2497) Patch from David Fuhry.
Modified: branches/branch-5-0/mapserver/HISTORY.TXT
===================================================================
--- branches/branch-5-0/mapserver/HISTORY.TXT 2008-04-27 07:14:40 UTC (rev 7538)
+++ branches/branch-5-0/mapserver/HISTORY.TXT 2008-04-27 20:03:19 UTC (rev 7539)
@@ -13,6 +13,9 @@
Current Version (future 5.0.3, svn branch-5-0)
----------------------------------------------
+- mappostgis.c: Fixed overlapping transactions causing core
+ dump in fcgi (#2497)
+
- mapagg.cpp: Fixed rendering of non filled vector symbols (#2585)
- Fixed handling of encrypted connection strings in postgis driver (#2563)
Modified: branches/branch-5-0/mapserver/mappostgis.c
===================================================================
--- branches/branch-5-0/mapserver/mappostgis.c 2008-04-27 07:14:40 UTC (rev 7538)
+++ branches/branch-5-0/mapserver/mappostgis.c 2008-04-27 20:03:19 UTC (rev 7539)
@@ -165,6 +165,78 @@
PQfinish((PGconn*) conn_handle);
}
+/* takes a connection and ensures that it is in a valid transactional state */
+/* performing PQreset(), ROLLBACK, and/or BEGIN on it as necessary */
+int msPOSTGISSanitizeConnection(PGconn *conn)
+{
+ int conn_bad = 0;
+
+ if (PQstatus(conn) == CONNECTION_BAD)
+ {
+ msDebug("Warning: resetting bad database connection due to PQstatus(conn) == CONNECTION_BAD in msPOSTGISSanitizeConnection()\n");
+ conn_bad = 1;
+ }
+ else if (PQtransactionStatus(conn) == PQTRANS_UNKNOWN)
+ {
+ msDebug("Warning: resetting bad database connection due to PQtransactionStatus(conn) == PQTRANS_UNKNOWN in msPOSTGISSanitizeConnection()\n");
+ conn_bad = 1;
+ }
+
+ // if connection is in bad, PQreset() it
+ if (conn_bad)
+ {
+ PQreset(conn);
+ if (PQstatus(conn) == CONNECTION_BAD)
+ {
+ msSetError(MS_QUERYERR, "Database connection status is CONNECTION_BAD even after attempt to PQreset() it: %s", "msPOSTGISSanitizeConnection()", PQerrorMessage(conn));
+ return MS_FAILURE;
+ }
+ else if (PQtransactionStatus(conn) == PQTRANS_UNKNOWN)
+ {
+ msSetError(MS_QUERYERR, "Database connection transaction status is PQTRANS_UNKNOWN even after attempt to PQreset() it: %s", "msPOSTGISSanitizeConnection()", PQerrorMessage(conn));
+ return MS_FAILURE;
+ }
+ }
+
+ if (PQtransactionStatus(conn) == PQTRANS_ACTIVE) // no connection should have an active async call
+ {
+ msSetError(MS_QUERYERR, "Refusing to sanitize a database connection with a pending asynchronous query (transaction status of PQTRANS_ACTIVE).", "msPOSTGISSanitizeConnection()");
+ return MS_FAILURE;
+ }
+
+ if (PQtransactionStatus(conn) == PQTRANS_INERROR) // idle, in a failed transaction block
+ {
+ PGresult *rb_res = PQexec(conn, "ROLLBACK");
+ if (!rb_res || PQresultStatus(rb_res) != PGRES_COMMAND_OK) {
+ msSetError(MS_QUERYERR, "Error executing POSTGIS ROLLBACK statement: %s", "msPOSTGISSanitizeConnection()", PQerrorMessage(conn));
+
+ if(rb_res) {
+ PQclear(rb_res);
+ }
+
+ return MS_FAILURE;
+ }
+ PQclear(rb_res);
+ }
+
+ if (PQtransactionStatus(conn) == PQTRANS_IDLE) // idle, but not in a transaction block
+ {
+ PGresult *beg_res = PQexec(conn, "BEGIN");
+ if (!beg_res || PQresultStatus(beg_res) != PGRES_COMMAND_OK) {
+ msSetError(MS_QUERYERR, "Error executing POSTGIS BEGIN statement: %s", "msPOSTGISSanitizeConnection()", PQerrorMessage(conn));
+
+ if(beg_res) {
+ PQclear(beg_res);
+ }
+
+ return MS_FAILURE;
+ }
+ PQclear(beg_res);
+ }
+
+ return MS_SUCCESS;
+}
+
/*static int gBYTE_ORDER = 0;*/
/* open up a connection to the postgresql database using the connection string in layer->connection */
@@ -248,6 +320,12 @@
return MS_FAILURE;
}
+ /* start a transaction, since it's required by all subsequent (DECLARE CURSOR) queries */
+ if (msPOSTGISSanitizeConnection(layerinfo->conn) != MS_SUCCESS)
+ {
+ return MS_FAILURE;
+ }
+
msConnPoolRegister(layer, layerinfo->conn, msPOSTGISCloseConnection);
PQsetNoticeProcessor(layerinfo->conn, postresql_NOTICE_HANDLER, (void *) layer);
@@ -345,10 +423,6 @@
size_t length;
char *pos_from, *pos_ftab, *pos_space, *pos_paren;
- char *tmp2 = 0;
- char *error_message = 0;
- char *postgresql_error;
-
layerinfo = getPostGISLayerInfo(layer);
/* Set the urid name */
@@ -484,28 +558,6 @@
free(f_table_name);
free(columns_wanted);
- /* start transaction required by cursor */
-
- result = PQexec(layerinfo->conn, "BEGIN");
- if(!result || PQresultStatus(result) != PGRES_COMMAND_OK) {
- msSetError(MS_QUERYERR, "Error executing POSTGIS BEGIN statement.", "prepare_database()");
-
- if(result) {
- PQclear(result);
- }
- if(layerinfo->query_result) {
- PQclear(layerinfo->query_result);
- }
- layerinfo->query_result = NULL;
- PQreset(layerinfo->conn);
-
- free(query_string_0_6);
-
- return MS_FAILURE; /* totally screwed */
- }
-
- PQclear(result);
-
/* set enable_seqscan=off not required (already done) */
if(layer->debug) {
@@ -513,65 +565,25 @@
}
result = PQexec(layerinfo->conn, query_string_0_6);
- if(result && PQresultStatus(result) == PGRES_COMMAND_OK)
+ if(!result || PQresultStatus(result) != PGRES_COMMAND_OK)
{
- *sql_results = result;
-
- *query_string = (char *) malloc(strlen(query_string_0_6) + 1);
- strcpy(*query_string, query_string_0_6);
-
+ msSetError(MS_QUERYERR, "Error declaring cursor: %s\nWith query string: %s\n", "prepare_database()", PQerrorMessage(layerinfo->conn), query_string_0_6);
free(query_string_0_6);
-
- return MS_SUCCESS;
- }
-
- /* Save PostgreSQL Error Message */
- postgresql_error = PQerrorMessage(layerinfo->conn);
- error_message = (char *) malloc(strlen(postgresql_error) + 1);
- strcpy(error_message, postgresql_error);
-
- /* okay, that command didnt work. Its probably a 0.5 database */
- /* We have to everything again, after performing a rollback. */
-
- if(result) {
- PQclear(result);
- }
- result = PQexec(layerinfo->conn, "rollback" );
- if(result) {
- PQclear(result);
- }
- result = PQexec(layerinfo->conn, "begin" );
-
- if(!result || PQresultStatus(result) != PGRES_COMMAND_OK)
- {
- msSetError(MS_QUERYERR, "Couldnt recover from a bad query: \n'%s'\n", "prepare_database()", query_string_0_6);
-
- if(result) {
- PQclear(result);
+ if (result)
+ {
+ PQclear(result);
}
- layerinfo->query_result = NULL;
- PQreset(layerinfo->conn);
-
- free(error_message);
- free(query_string_0_6);
-
- return MS_FAILURE; /* totally screwed */
+ return MS_FAILURE;
}
+
+ *sql_results = result;
- PQclear(result);
- layerinfo->query_result = NULL;
- PQreset(layerinfo->conn);
+ *query_string = (char *) malloc(strlen(query_string_0_6) + 1);
+ strcpy(*query_string, query_string_0_6);
- /* TODO Rename tmp2 to something meaningful */
- tmp2 = (char *) malloc(149 + strlen(query_string_0_6) + strlen(error_message) + 1);
- sprintf(tmp2, "Error executing POSTGIS DECLARE (the actual query) statement: '%s' \n\nPostgresql reports the error as '%s'\n\nMore Help:\n\n", query_string_0_6, error_message);
- msSetError(MS_QUERYERR, DATA_ERROR_MESSAGE, "prepare_database()", tmp2, "check your .map file");
-
- free(tmp2);
- free(error_message);
free(query_string_0_6);
- return MS_FAILURE; /* totally screwed */
+ return MS_SUCCESS;
}
@@ -641,7 +653,7 @@
PQclear(layerinfo->query_result);
}
layerinfo->query_result = NULL;
- PQreset(layerinfo->conn);
+ msPOSTGISSanitizeConnection(layerinfo->conn);
return MS_FAILURE;
}
@@ -1200,21 +1212,6 @@
free(geom_column_name);
free(table_name);
- query_result = PQexec(layerinfo->conn, "BEGIN");
- if(!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK) {
- msSetError(MS_QUERYERR, "Error executing POSTGIS BEGIN statement.", "msPOSTGISLayerGetShape()");
-
- if(query_result) {
- PQclear(query_result);
- }
- PQreset(layerinfo->conn);
-
- free(query_str);
-
- return MS_FAILURE;
- }
- PQclear(query_result);
-
query_result = PQexec(layerinfo->conn, query_str);
if(!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK) {
@@ -1223,7 +1220,7 @@
if(query_result) {
PQclear(query_result);
}
- PQreset(layerinfo->conn);
+ msPOSTGISSanitizeConnection(layerinfo->conn);
free(query_str);
@@ -1239,7 +1236,7 @@
if(query_result) {
PQclear(query_result);
}
- PQreset(layerinfo->conn);
+ msPOSTGISSanitizeConnection(layerinfo->conn);
free(query_str);
@@ -1310,21 +1307,22 @@
PQclear(query_result);
query_result = PQexec(layerinfo->conn, "CLOSE mycursor2");
- if(query_result) {
- PQclear(query_result);
- }
- query_result = PQexec(layerinfo->conn, "ROLLBACK");
- if(!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK) {
- msSetError(MS_QUERYERR, "Error executing POSTGIS BEGIN statement.", "msPOSTGISLayerGetShape()");
-
- if(query_result) {
+ if(!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK)
+ {
+ msFreeShape(shape);
+ if (query_result)
+ {
PQclear(query_result);
}
- PQreset(layerinfo->conn);
- msFreeShape(shape);
+ if (msPOSTGISSanitizeConnection(layerinfo->conn) != MS_SUCCESS)
+ {
+ return MS_FAILURE;
+ }
+ msSetError(MS_QUERYERR, "Error executing POSTGIS CLOSE statement on query (which returned one or more tuples).", "msPOSTGISLayerGetShape()");
+
return MS_FAILURE;
}
@@ -1338,19 +1336,21 @@
PQclear(query_result);
query_result = PQexec(layerinfo->conn, "CLOSE mycursor2");
- if(query_result) {
- PQclear(query_result);
- }
- query_result = PQexec(layerinfo->conn, "ROLLBACK");
- if(!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK) {
- msSetError(MS_QUERYERR, "Error executing POSTGIS BEGIN statement.", "msPOSTGISLayerGetShape()");
+ if (!query_result || PQresultStatus(query_result) != PGRES_COMMAND_OK)
+ {
+ if (query_result)
+ {
+ PQclear(query_result);
+ }
- if(query_result) {
- PQclear(query_result);
+ if (msPOSTGISSanitizeConnection(layerinfo->conn) != MS_SUCCESS)
+ {
+ return MS_FAILURE;
}
- PQreset(layerinfo->conn);
+ msSetError(MS_QUERYERR, "Error executing POSTGIS CLOSE statement on query (which returned zero tuples).", "msPOSTGISLayerGetShape()");
+
return MS_FAILURE;
}
More information about the mapserver-commits
mailing list