From f14521f8cb567c98814d392ba7ec196b4a7df77c Mon Sep 17 00:00:00 2001 From: Oleksandr Shulgin Date: Wed, 3 Jun 2015 14:10:20 +0200 Subject: [PATCH] Add libpq_support.c and win32_support.c Move libpq-specific code for streaming replication support into a separate file. Also provide gettimeofday() on Win32, implementation copied from Postgres core. --- psycopg/libpq_support.c | 111 ++++++++++++++++++++++++++++++++++++++++ psycopg/libpq_support.h | 40 +++++++++++++++ psycopg/pqpath.c | 83 ++---------------------------- psycopg/win32_support.c | 61 ++++++++++++++++++++++ psycopg/win32_support.h | 36 +++++++++++++ setup.py | 2 + 6 files changed, 254 insertions(+), 79 deletions(-) create mode 100644 psycopg/libpq_support.c create mode 100644 psycopg/libpq_support.h create mode 100644 psycopg/win32_support.c create mode 100644 psycopg/win32_support.h diff --git a/psycopg/libpq_support.c b/psycopg/libpq_support.c new file mode 100644 index 00000000..95a3ebc6 --- /dev/null +++ b/psycopg/libpq_support.c @@ -0,0 +1,111 @@ +/* libpq_support.c - functions not provided by libpq, but which are + * required for advanced communication with the server, such as + * streaming replication + * + * Copyright (C) 2003-2015 Federico Di Gregorio + * + * This file is part of psycopg. + * + * psycopg2 is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link this program with the OpenSSL library (or with + * modified versions of OpenSSL that use the same license as OpenSSL), + * and distribute linked combinations including the two. + * + * You must obey the GNU Lesser General Public License in all respects for + * all of the code used other than OpenSSL. + * + * psycopg2 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ + +#define PSYCOPG_MODULE +#include "psycopg/psycopg.h" + +#include "psycopg/libpq_support.h" + +/* htonl(), ntohl() */ +#ifdef _WIN32 +#include +/* gettimeofday() */ +#include "psycopg/win32_support.h" +#else +#include +#endif + +/* support routines taken from pg_basebackup/streamutil.c */ + +/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */ +#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */ +#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */ + +#define SECS_PER_DAY 86400 +#define USECS_PER_SEC 1000000LL + +/* + * Frontend version of GetCurrentTimestamp(), since we are not linked with + * backend code. The protocol always uses integer timestamps, regardless of + * server setting. + */ +pg_int64 +feGetCurrentTimestamp(void) +{ + pg_int64 result; + struct timeval tp; + + gettimeofday(&tp, NULL); + + result = (pg_int64) tp.tv_sec - + ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); + + result = (result * USECS_PER_SEC) + tp.tv_usec; + + return result; +} + +/* + * Converts an int64 to network byte order. + */ +void +fe_sendint64(pg_int64 i, char *buf) +{ + uint32 n32; + + /* High order half first, since we're doing MSB-first */ + n32 = (uint32) (i >> 32); + n32 = htonl(n32); + memcpy(&buf[0], &n32, 4); + + /* Now the low order half */ + n32 = (uint32) i; + n32 = htonl(n32); + memcpy(&buf[4], &n32, 4); +} + +/* + * Converts an int64 from network byte order to native format. + */ +pg_int64 +fe_recvint64(char *buf) +{ + pg_int64 result; + uint32 h32; + uint32 l32; + + memcpy(&h32, buf, 4); + memcpy(&l32, buf + 4, 4); + h32 = ntohl(h32); + l32 = ntohl(l32); + + result = h32; + result <<= 32; + result |= l32; + + return result; +} diff --git a/psycopg/libpq_support.h b/psycopg/libpq_support.h new file mode 100644 index 00000000..007f5e18 --- /dev/null +++ b/psycopg/libpq_support.h @@ -0,0 +1,40 @@ +/* libpq_support.h - definitions for libpq_support.c + * + * Copyright (C) 2003-2015 Federico Di Gregorio + * + * This file is part of psycopg. + * + * psycopg2 is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link this program with the OpenSSL library (or with + * modified versions of OpenSSL that use the same license as OpenSSL), + * and distribute linked combinations including the two. + * + * You must obey the GNU Lesser General Public License in all respects for + * all of the code used other than OpenSSL. + * + * psycopg2 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ +#ifndef PSYCOPG_LIBPQ_SUPPORT_H +#define PSYCOPG_LIBPQ_SUPPORT_H 1 + +#include "psycopg/config.h" + +/* type and constant definitions from internal postgres includes */ +typedef unsigned int uint32; +typedef unsigned PG_INT64_TYPE XLogRecPtr; + +#define InvalidXLogRecPtr ((XLogRecPtr) 0) + +HIDDEN pg_int64 feGetCurrentTimestamp(void); +HIDDEN void fe_sendint64(pg_int64 i, char *buf); +HIDDEN pg_int64 fe_recvint64(char *buf); + +#endif /* !defined(PSYCOPG_LIBPQ_SUPPORT_H) */ diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c index 9e4424a8..4fb4771e 100644 --- a/psycopg/pqpath.c +++ b/psycopg/pqpath.c @@ -40,13 +40,14 @@ #include "psycopg/pgtypes.h" #include "psycopg/error.h" +#include "psycopg/libpq_support.h" #include "libpq-fe.h" -/* htonl, ntohl */ #ifdef _WIN32 +/* select() */ #include -#else -#include +/* gettimeofday() */ +#include "win32_support.h" #endif extern HIDDEN PyObject *psyco_DescriptionType; @@ -1520,82 +1521,6 @@ exit: return ret; } -/* support routines taken from pg_basebackup/streamutil.c */ -/* type and constant definitions from internal postgres includes */ -typedef unsigned int uint32; -typedef unsigned PG_INT64_TYPE XLogRecPtr; - -#define InvalidXLogRecPtr ((XLogRecPtr) 0) - -/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */ -#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */ -#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */ - -#define SECS_PER_DAY 86400 -#define USECS_PER_SEC 1000000LL - -/* - * Frontend version of GetCurrentTimestamp(), since we are not linked with - * backend code. The protocol always uses integer timestamps, regardless of - * server setting. - */ -static pg_int64 -feGetCurrentTimestamp(void) -{ - pg_int64 result; - struct timeval tp; - - gettimeofday(&tp, NULL); - - result = (pg_int64) tp.tv_sec - - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY); - - result = (result * USECS_PER_SEC) + tp.tv_usec; - - return result; -} - -/* - * Converts an int64 to network byte order. - */ -static void -fe_sendint64(pg_int64 i, char *buf) -{ - uint32 n32; - - /* High order half first, since we're doing MSB-first */ - n32 = (uint32) (i >> 32); - n32 = htonl(n32); - memcpy(&buf[0], &n32, 4); - - /* Now the low order half */ - n32 = (uint32) i; - n32 = htonl(n32); - memcpy(&buf[4], &n32, 4); -} - -/* - * Converts an int64 from network byte order to native format. - */ -static pg_int64 -fe_recvint64(char *buf) -{ - pg_int64 result; - uint32 h32; - uint32 l32; - - memcpy(&h32, buf, 4); - memcpy(&l32, buf + 4, 4); - h32 = ntohl(h32); - l32 = ntohl(l32); - - result = h32; - result <<= 32; - result |= l32; - - return result; -} - static int sendFeedback(PGconn *conn, XLogRecPtr written_lsn, XLogRecPtr fsync_lsn, int replyRequested) diff --git a/psycopg/win32_support.c b/psycopg/win32_support.c new file mode 100644 index 00000000..8a760b9f --- /dev/null +++ b/psycopg/win32_support.c @@ -0,0 +1,61 @@ +/* win32_support.c - emulate some functions missing on Win32 + * + * Copyright (C) 2003-2015 Federico Di Gregorio + * + * This file is part of psycopg. + * + * psycopg2 is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link this program with the OpenSSL library (or with + * modified versions of OpenSSL that use the same license as OpenSSL), + * and distribute linked combinations including the two. + * + * You must obey the GNU Lesser General Public License in all respects for + * all of the code used other than OpenSSL. + * + * psycopg2 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ + +#define PSYCOPG_MODULE +#include "psycopg/psycopg.h" + +#include "psycopg/win32_support.h" + +#ifdef _WIN32 +/* millisecond-precision port of gettimeofday for Win32, taken from + src/port/gettimeofday.c in PostgreSQL core */ + +/* FILETIME of Jan 1 1970 00:00:00. */ +static const unsigned __int64 epoch = 116444736000000000ULL; + +/* + * timezone information is stored outside the kernel so tzp isn't used anymore. + * + * Note: this function is not for Win32 high precision timing purpose. See + * elapsed_time(). + */ +int +gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + FILETIME file_time; + SYSTEMTIME system_time; + ULARGE_INTEGER ularge; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + ularge.LowPart = file_time.dwLowDateTime; + ularge.HighPart = file_time.dwHighDateTime; + + tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + + return 0; +} +#endif /* _WIN32 */ diff --git a/psycopg/win32_support.h b/psycopg/win32_support.h new file mode 100644 index 00000000..c6577317 --- /dev/null +++ b/psycopg/win32_support.h @@ -0,0 +1,36 @@ +/* win32_support.h - definitions for win32_support.c + * + * Copyright (C) 2003-2015 Federico Di Gregorio + * + * This file is part of psycopg. + * + * psycopg2 is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link this program with the OpenSSL library (or with + * modified versions of OpenSSL that use the same license as OpenSSL), + * and distribute linked combinations including the two. + * + * You must obey the GNU Lesser General Public License in all respects for + * all of the code used other than OpenSSL. + * + * psycopg2 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + */ +#ifndef PSYCOPG_WIN32_SUPPORT_H +#define PSYCOPG_WIN32_SUPPORT_H 1 + +#include "psycopg/config.h" + +#include + +#ifdef _WIN32 +HIDDEN int gettimeofday(struct timeval * tp, struct timezone * tzp); +#endif + +#endif /* !defined(PSYCOPG_WIN32_SUPPORT_H) */ diff --git a/setup.py b/setup.py index fc4f1711..1f87520e 100644 --- a/setup.py +++ b/setup.py @@ -462,6 +462,7 @@ data_files = [] sources = [ 'psycopgmodule.c', 'green.c', 'pqpath.c', 'utils.c', 'bytes_format.c', + 'libpq_support.c', 'win32_support.c', 'connection_int.c', 'connection_type.c', 'cursor_int.c', 'cursor_type.c', @@ -481,6 +482,7 @@ depends = [ 'config.h', 'pgtypes.h', 'psycopg.h', 'python.h', 'connection.h', 'cursor.h', 'diagnostics.h', 'error.h', 'green.h', 'lobject.h', 'notify.h', 'pqpath.h', 'xid.h', + 'libpq_support.h', 'win32_support.h', 'adapter_asis.h', 'adapter_binary.h', 'adapter_datetime.h', 'adapter_list.h', 'adapter_pboolean.h', 'adapter_pdecimal.h',