[prev in list] [next in list] [prev in thread] [next in thread]
List: postgresql-general
Subject: [HACKERS] hackers mail broken?
From: Bradley McLean <brad () bradm ! net>
Date: 2002-03-29 13:38:12
[Download RAW message or body]
Original titles:
Patch to add real cancel to ODBC driver
Patch to add real can--cel to ODBC driver
Bruce, sorry to bother you, would you forward this onto the list?
I can't post for reasons I can't fathom.
-----
Patch against 7,2 submitted for comment.
It's a little messy; I had some trouble trying to reconcile the code
style of libpq which I copied from, and odbc.
Suggestions on what parts look ugly, and or where to send this
(is there a separate ODBC place?) are welcome.
This seems to work just fine; Now, when our users submit a 2 hour
query with four million row sorts by accident, then cancel it 30 seconds
later, it doesn't bog down the server ...
regards,
-Brad
["odbccancel.patch" (text/plain)]
diff -cr postgresql-7.2/src/interfaces/odbc/connection.c \
postgresql-7.2-brad/src/interfaces/odbc/connection.c
*** postgresql-7.2/src/interfaces/odbc/connection.c Sun Dec 30 18:09:42 2001
--- postgresql-7.2-brad/src/interfaces/odbc/connection.c Wed Mar 27 10:04:45 2002
***************
*** 19,24 ****
--- 19,27 ----
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+ #ifndef WIN32
+ #include <errno.h>
+ #endif
#include "environ.h"
#include "socket.h"
***************
*** 828,835 ****
}
break;
case 'K': /* Secret key (6.4 protocol) */
! (void) SOCK_get_int(sock, 4); /* pid */
! (void) SOCK_get_int(sock, 4); /* key */
break;
case 'Z': /* Backend is ready for new query (6.4) */
--- 831,839 ----
}
break;
case 'K': /* Secret key (6.4 protocol) */
! self->be_pid = SOCK_get_int(sock, 4); /* pid */
! self->be_key = SOCK_get_int(sock, 4); /* key */
! qlog("conn=%u, Backend pid=%u\n",self,self->be_pid);
break;
case 'Z': /* Backend is ready for new query (6.4) */
***************
*** 1837,1839 ****
--- 1841,1903 ----
value = BLCKSZ;
return value;
}
+
+ int
+ CC_send_cancel_request(const ConnectionClass *conn)
+ {
+ #ifdef WIN32
+ int save_errno = (WSAGetLastError());
+ #else
+ int save_errno = errno;
+ #endif
+ int tmpsock = -1;
+ struct
+ {
+ uint32 packetlen;
+ CancelRequestPacket cp;
+ } crp;
+
+ /* Check we have an open connection */
+ if (!conn)
+ return FALSE;
+
+ if (conn->sock == NULL )
+ {
+ return FALSE;
+ }
+
+ /*
+ * We need to open a temporary connection to the postmaster. Use the
+ * information saved by connectDB to do this with only kernel calls.
+ */
+ if ((tmpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ return FALSE;
+ }
+ if (connect(tmpsock, (struct sockaddr *)&(conn->sock->sadr),
+ sizeof(conn->sock->sadr)) < 0)
+ {
+ return FALSE;
+ }
+
+ /*
+ * We needn't set nonblocking I/O or NODELAY options here.
+ */
+ crp.packetlen = htonl((uint32) sizeof(crp));
+ crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
+ crp.cp.backendPID = htonl(conn->be_pid);
+ crp.cp.cancelAuthCode = htonl(conn->be_key);
+
+ if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
+ {
+ return FALSE;
+ }
+
+ /* Sent it, done */
+ closesocket(tmpsock);
+ #ifdef WIN32
+ WSASetLastError(save_errno);
+ #else
+ errno = save_errno;
+ #endif
+ }
diff -cr postgresql-7.2/src/interfaces/odbc/connection.h \
postgresql-7.2-brad/src/interfaces/odbc/connection.h
*** postgresql-7.2/src/interfaces/odbc/connection.h Mon Nov 5 12:46:38 2001
--- postgresql-7.2-brad/src/interfaces/odbc/connection.h Tue Mar 26 14:45:35 2002
***************
*** 125,130 ****
--- 125,146 ----
char tty[PATH_SIZE];
} StartupPacket6_2;
+ /* Transferred from pqcomm.h: */
+
+
+ typedef ProtocolVersion MsgType;
+
+ #define PG_PROTOCOL(m,n) (((m) << 16) | (n))
+ #define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678)
+
+ typedef struct CancelRequestPacket
+ {
+ /* Note that each field is stored in network byte order! */
+ MsgType cancelRequestCode; /* code to identify a \
cancel request */ + unsigned int backendPID; /* PID of \
client's backend */ + unsigned int cancelAuthCode; /* secret key to \
authorize cancel */ + } CancelRequestPacket;
+
/* Structure to hold all the connection attributes for a specific
connection (used for both registry and file, DSN and DRIVER)
***************
*** 266,271 ****
--- 282,289 ----
Int2 pg_version_major;
Int2 pg_version_minor;
char ms_jet;
+ int be_pid; /* pid returned by backend */
+ int be_key; /* auth code needed to send cancel */
#ifdef MULTIBYTE
char *client_encoding;
char *server_encoding;
diff -cr postgresql-7.2/src/interfaces/odbc/execute.c \
postgresql-7.2-brad/src/interfaces/odbc/execute.c
*** postgresql-7.2/src/interfaces/odbc/execute.c Thu Oct 25 01:50:14 2001
--- postgresql-7.2-brad/src/interfaces/odbc/execute.c Wed Mar 27 11:20:26 2002
***************
*** 510,515 ****
--- 510,519 ----
if (stmt->data_at_exec < 0)
{
/*
+ * Tell the Backend that we're cancelling this request
+ */
+ CC_send_cancel_request(SC_get_conn(stmt));
+ /*
* MAJOR HACK for Windows to reset the driver manager's cursor
* state: Because of what seems like a bug in the Odbc driver
* manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as
***************
*** 517,523 ****
* force method calls the driver manager's function on behalf of
* the application.
*/
-
#ifdef WIN32
if (ci->drivers.cancel_as_freestmt)
{
--- 521,526 ----
diff -cr postgresql-7.2/src/interfaces/odbc/socket.c \
postgresql-7.2-brad/src/interfaces/odbc/socket.c
*** postgresql-7.2/src/interfaces/odbc/socket.c Sun Oct 28 01:26:14 2001
--- postgresql-7.2-brad/src/interfaces/odbc/socket.c Tue Mar 26 21:40:59 2002
***************
*** 107,113 ****
SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
{
struct hostent *host;
- struct sockaddr_in sadr;
unsigned long iaddr;
if (self->socket != -1)
--- 107,112 ----
***************
*** 117,123 ****
return 0;
}
! memset((char *) &sadr, 0, sizeof(sadr));
/*
* If it is a valid IP address, use it. Otherwise use hostname lookup.
--- 116,122 ----
return 0;
}
! memset((char *) &(self->sadr), 0, sizeof(self->sadr));
/*
* If it is a valid IP address, use it. Otherwise use hostname lookup.
***************
*** 132,144 ****
self->errormsg = "Could not resolve hostname.";
return 0;
}
! memcpy(&(sadr.sin_addr), host->h_addr, host->h_length);
}
else
! memcpy(&(sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
! sadr.sin_family = AF_INET;
! sadr.sin_port = htons(port);
self->socket = socket(AF_INET, SOCK_STREAM, 0);
if (self->socket == -1)
--- 131,143 ----
self->errormsg = "Could not resolve hostname.";
return 0;
}
! memcpy(&(self->sadr.sin_addr), host->h_addr, host->h_length);
}
else
! memcpy(&(self->sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
! self->sadr.sin_family = AF_INET;
! self->sadr.sin_port = htons(port);
self->socket = socket(AF_INET, SOCK_STREAM, 0);
if (self->socket == -1)
***************
*** 148,155 ****
return 0;
}
! if (connect(self->socket, (struct sockaddr *) & (sadr),
! sizeof(sadr)) < 0)
{
self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket.";
--- 147,154 ----
return 0;
}
! if (connect(self->socket, (struct sockaddr *) & (self->sadr),
! sizeof(self->sadr)) < 0)
{
self->errornumber = SOCKET_COULD_NOT_CONNECT;
self->errormsg = "Could not connect to remote socket.";
diff -cr postgresql-7.2/src/interfaces/odbc/socket.h \
postgresql-7.2-brad/src/interfaces/odbc/socket.h
*** postgresql-7.2/src/interfaces/odbc/socket.h Sun Oct 28 01:26:15 2001
--- postgresql-7.2-brad/src/interfaces/odbc/socket.h Tue Mar 26 21:35:41 2002
***************
*** 64,70 ****
char reverse; /* used to handle Postgres 6.2 protocol
* (reverse byte order) */
!
};
#define SOCK_get_char(self) (SOCK_get_next_byte(self))
--- 64,70 ----
char reverse; /* used to handle Postgres 6.2 protocol
* (reverse byte order) */
! struct sockaddr_in sadr; /* Used for handling connections for cancel */
};
#define SOCK_get_char(self) (SOCK_get_next_byte(self))
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic