Skip to content

Commit 3fd2a79

Browse files
committed
Provide pg_pread() and pg_pwrite() for random I/O.
Forward to POSIX pread() and pwrite(), or emulate them if unavailable. The emulation is not perfect as the file position is changed, so we'll put pg_ prefixes on the names to minimize the risk of confusion in future patches that might inadvertently try to mix pread() and read() on the same file descriptor. Author: Thomas Munro Reviewed-by: Tom Lane, Jesper Pedersen Discussion: https://postgr.es/m/CAEepm=02rapCpPR3ZGF2vW=SBHSdFYO_bz_f-wwWJonmA3APgw@mail.gmail.com
1 parent b43df56 commit 3fd2a79

File tree

8 files changed

+168
-0
lines changed

8 files changed

+168
-0
lines changed

configure

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15539,6 +15539,32 @@ esac
1553915539

1554015540
fi
1554115541

15542+
ac_fn_c_check_func "$LINENO" "pread" "ac_cv_func_pread"
15543+
if test "x$ac_cv_func_pread" = xyes; then :
15544+
$as_echo "#define HAVE_PREAD 1" >>confdefs.h
15545+
15546+
else
15547+
case " $LIBOBJS " in
15548+
*" pread.$ac_objext "* ) ;;
15549+
*) LIBOBJS="$LIBOBJS pread.$ac_objext"
15550+
;;
15551+
esac
15552+
15553+
fi
15554+
15555+
ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite"
15556+
if test "x$ac_cv_func_pwrite" = xyes; then :
15557+
$as_echo "#define HAVE_PWRITE 1" >>confdefs.h
15558+
15559+
else
15560+
case " $LIBOBJS " in
15561+
*" pwrite.$ac_objext "* ) ;;
15562+
*) LIBOBJS="$LIBOBJS pwrite.$ac_objext"
15563+
;;
15564+
esac
15565+
15566+
fi
15567+
1554215568
ac_fn_c_check_func "$LINENO" "random" "ac_cv_func_random"
1554315569
if test "x$ac_cv_func_random" = xyes; then :
1554415570
$as_echo "#define HAVE_RANDOM 1" >>confdefs.h

configure.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,8 @@ AC_REPLACE_FUNCS(m4_normalize([
16981698
getrusage
16991699
inet_aton
17001700
mkdtemp
1701+
pread
1702+
pwrite
17011703
random
17021704
rint
17031705
srandom

src/include/pg_config.h.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@
438438
/* Define to 1 if you have the `ppoll' function. */
439439
#undef HAVE_PPOLL
440440

441+
/* Define to 1 if you have the `pread' function. */
442+
#undef HAVE_PREAD
443+
441444
/* Define to 1 if you have the `pstat' function. */
442445
#undef HAVE_PSTAT
443446

@@ -453,6 +456,9 @@
453456
/* Have PTHREAD_PRIO_INHERIT. */
454457
#undef HAVE_PTHREAD_PRIO_INHERIT
455458

459+
/* Define to 1 if you have the `pwrite' function. */
460+
#undef HAVE_PWRITE
461+
456462
/* Define to 1 if you have the `random' function. */
457463
#undef HAVE_RANDOM
458464

src/include/pg_config.h.win32

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,18 @@
322322
/* Define to 1 if you have the `ppoll' function. */
323323
/* #undef HAVE_PPOLL */
324324

325+
/* Define to 1 if you have the `pread' function. */
326+
/* #undef HAVE_PREAD */
327+
325328
/* Define to 1 if you have the `pstat' function. */
326329
/* #undef HAVE_PSTAT */
327330

328331
/* Define to 1 if the PS_STRINGS thing exists. */
329332
/* #undef HAVE_PS_STRINGS */
330333

334+
/* Define to 1 if you have the `pwrite' function. */
335+
/* #undef HAVE_PWRITE */
336+
331337
/* Define to 1 if you have the `random' function. */
332338
/* #undef HAVE_RANDOM */
333339

src/include/port.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,23 @@ extern double rint(double x);
392392
extern int inet_aton(const char *cp, struct in_addr *addr);
393393
#endif
394394

395+
/*
396+
* Windows and older Unix don't have pread(2) and pwrite(2). We have
397+
* replacement functions, but they have slightly different semantics so we'll
398+
* use a name with a pg_ prefix to avoid confusion.
399+
*/
400+
#ifdef HAVE_PREAD
401+
#define pg_pread pread
402+
#else
403+
extern ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset);
404+
#endif
405+
406+
#ifdef HAVE_PWRITE
407+
#define pg_pwrite pwrite
408+
#else
409+
extern ssize_t pg_pwrite(int fd, const void *buf, size_t nbyte, off_t offset);
410+
#endif
411+
395412
#if !HAVE_DECL_STRLCAT
396413
extern size_t strlcat(char *dst, const char *src, size_t siz);
397414
#endif

src/port/pread.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pread.c
4+
* Implementation of pread(2) for platforms that lack one.
5+
*
6+
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* src/port/pread.c
10+
*
11+
* Note that this implementation changes the current file position, unlike
12+
* the POSIX function, so we use the name pg_pread().
13+
*
14+
*-------------------------------------------------------------------------
15+
*/
16+
17+
18+
#include "postgres.h"
19+
20+
#ifdef WIN32
21+
#include <windows.h>
22+
#else
23+
#include <unistd.h>
24+
#endif
25+
26+
ssize_t
27+
pg_pread(int fd, void *buf, size_t size, off_t offset)
28+
{
29+
#ifdef WIN32
30+
OVERLAPPED overlapped = {0};
31+
HANDLE handle;
32+
DWORD result;
33+
34+
handle = (HANDLE) _get_osfhandle(fd);
35+
if (handle == INVALID_HANDLE_VALUE)
36+
{
37+
errno = EBADF;
38+
return -1;
39+
}
40+
41+
overlapped.Offset = offset;
42+
if (!ReadFile(handle, buf, size, &result, &overlapped))
43+
{
44+
_dosmaperr(GetLastError());
45+
return -1;
46+
}
47+
48+
return result;
49+
#else
50+
if (lseek(fd, offset, SEEK_SET) < 0)
51+
return -1;
52+
53+
return read(fd, buf, size);
54+
#endif
55+
}

src/port/pwrite.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pwrite.c
4+
* Implementation of pwrite(2) for platforms that lack one.
5+
*
6+
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* src/port/pwrite.c
10+
*
11+
* Note that this implementation changes the current file position, unlike
12+
* the POSIX function, so we use the name pg_write().
13+
*
14+
*-------------------------------------------------------------------------
15+
*/
16+
17+
18+
#include "postgres.h"
19+
20+
#ifdef WIN32
21+
#include <windows.h>
22+
#else
23+
#include <unistd.h>
24+
#endif
25+
26+
ssize_t
27+
pg_pwrite(int fd, const void *buf, size_t size, off_t offset)
28+
{
29+
#ifdef WIN32
30+
OVERLAPPED overlapped = {0};
31+
HANDLE handle;
32+
DWORD result;
33+
34+
handle = (HANDLE) _get_osfhandle(fd);
35+
if (handle == INVALID_HANDLE_VALUE)
36+
{
37+
errno = EBADF;
38+
return -1;
39+
}
40+
41+
overlapped.Offset = offset;
42+
if (!WriteFile(handle, buf, size, &result, &overlapped))
43+
{
44+
_dosmaperr(GetLastError());
45+
return -1;
46+
}
47+
48+
return result;
49+
#else
50+
if (lseek(fd, offset, SEEK_SET) < 0)
51+
return -1;
52+
53+
return write(fd, buf, size);
54+
#endif
55+
}

src/tools/msvc/Mkvcbuild.pm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ sub mkvcbuild
9797
srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
9898
erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
9999
dirent.c dlopen.c getopt.c getopt_long.c
100+
pread.c pwrite.c
100101
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
101102
pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
102103
sprompt.c strerror.c tar.c thread.c

0 commit comments

Comments
 (0)