aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_rewind/libpq_fetch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_rewind/libpq_fetch.c')
-rw-r--r--src/bin/pg_rewind/libpq_fetch.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/src/bin/pg_rewind/libpq_fetch.c b/src/bin/pg_rewind/libpq_fetch.c
index fdb4198154e..e90907bd380 100644
--- a/src/bin/pg_rewind/libpq_fetch.c
+++ b/src/bin/pg_rewind/libpq_fetch.c
@@ -195,7 +195,7 @@ libpqProcessFileList(void)
for (i = 0; i < PQntuples(res); i++)
{
char *path = PQgetvalue(res, i, 0);
- int filesize = atoi(PQgetvalue(res, i, 1));
+ int64 filesize = atol(PQgetvalue(res, i, 1));
bool isdir = (strcmp(PQgetvalue(res, i, 2), "t") == 0);
char *link_target = PQgetvalue(res, i, 3);
file_type_t type;
@@ -221,13 +221,35 @@ libpqProcessFileList(void)
PQclear(res);
}
+/*
+ * Converts an int64 from network byte order to native format.
+ */
+static int64
+pg_recvint64(int64 value)
+{
+ union
+ {
+ int64 i64;
+ uint32 i32[2];
+ } swap;
+ int64 result;
+
+ swap.i64 = value;
+
+ result = (uint32) ntohl(swap.i32[0]);
+ result <<= 32;
+ result |= (uint32) ntohl(swap.i32[1]);
+
+ return result;
+}
+
/*----
* Runs a query, which returns pieces of files from the remote source data
* directory, and overwrites the corresponding parts of target files with
* the received parts. The result set is expected to be of format:
*
* path text -- path in the data directory, e.g "base/1/123"
- * begin int4 -- offset within the file
+ * begin int8 -- offset within the file
* chunk bytea -- file content
*----
*/
@@ -248,7 +270,7 @@ receiveFileChunks(const char *sql)
{
char *filename;
int filenamelen;
- int chunkoff;
+ int64 chunkoff;
int chunksize;
char *chunk;
@@ -271,7 +293,7 @@ receiveFileChunks(const char *sql)
pg_fatal("unexpected result set size while fetching remote files\n");
if (PQftype(res, 0) != TEXTOID ||
- PQftype(res, 1) != INT4OID ||
+ PQftype(res, 1) != INT8OID ||
PQftype(res, 2) != BYTEAOID)
{
pg_fatal("unexpected data types in result set while fetching remote files: %u %u %u\n",
@@ -291,12 +313,12 @@ receiveFileChunks(const char *sql)
pg_fatal("unexpected null values in result while fetching remote files\n");
}
- if (PQgetlength(res, 0, 1) != sizeof(int32))
+ if (PQgetlength(res, 0, 1) != sizeof(int64))
pg_fatal("unexpected result length while fetching remote files\n");
/* Read result set to local variables */
- memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int32));
- chunkoff = ntohl(chunkoff);
+ memcpy(&chunkoff, PQgetvalue(res, 0, 1), sizeof(int64));
+ chunkoff = pg_recvint64(chunkoff);
chunksize = PQgetlength(res, 0, 2);
filenamelen = PQgetlength(res, 0, 0);
@@ -321,7 +343,7 @@ receiveFileChunks(const char *sql)
continue;
}
- pg_log(PG_DEBUG, "received chunk for file \"%s\", offset %d, size %d\n",
+ pg_log(PG_DEBUG, "received chunk for file \"%s\", offset " INT64_FORMAT ", size %d\n",
filename, chunkoff, chunksize);
open_target_file(filename, false);
@@ -381,7 +403,7 @@ libpqGetFile(const char *filename, size_t *filesize)
* function to actually fetch the data.
*/
static void
-fetch_file_range(const char *path, unsigned int begin, unsigned int end)
+fetch_file_range(const char *path, uint64 begin, uint64 end)
{
char linebuf[MAXPGPATH + 23];
@@ -390,12 +412,13 @@ fetch_file_range(const char *path, unsigned int begin, unsigned int end)
{
unsigned int len;
+ /* Fine as long as CHUNKSIZE is not bigger than UINT32_MAX */
if (end - begin > CHUNKSIZE)
len = CHUNKSIZE;
else
- len = end - begin;
+ len = (unsigned int) (end - begin);
- snprintf(linebuf, sizeof(linebuf), "%s\t%u\t%u\n", path, begin, len);
+ snprintf(linebuf, sizeof(linebuf), "%s\t" UINT64_FORMAT "\t%u\n", path, begin, len);
if (PQputCopyData(conn, linebuf, strlen(linebuf)) != 1)
pg_fatal("could not send COPY data: %s",
@@ -420,7 +443,7 @@ libpq_executeFileMap(filemap_t *map)
* First create a temporary table, and load it with the blocks that we
* need to fetch.
*/
- sql = "CREATE TEMPORARY TABLE fetchchunks(path text, begin int4, len int4);";
+ sql = "CREATE TEMPORARY TABLE fetchchunks(path text, begin int8, len int4);";
res = PQexec(conn, sql);
if (PQresultStatus(res) != PGRES_COMMAND_OK)