PostgreSQL Source Code  git master
file.c File Reference
#include "postgres_fe.h"
#include "access/visibilitymap.h"
#include "common/file_perm.h"
#include "pg_upgrade.h"
#include "storage/bufpage.h"
#include "storage/checksum.h"
#include "storage/checksum_impl.h"
#include <sys/stat.h>
#include <fcntl.h>
Include dependency graph for file.c:

Go to the source code of this file.

Macros

#define COPY_BUF_SIZE   (50 * BLCKSZ)
 

Functions

void copyFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void linkFile (const char *src, const char *dst, const char *schemaName, const char *relName)
 
void rewriteVisibilityMap (const char *fromfile, const char *tofile, const char *schemaName, const char *relName)
 
void check_hard_link (void)
 

Macro Definition Documentation

◆ COPY_BUF_SIZE

#define COPY_BUF_SIZE   (50 * BLCKSZ)

Referenced by copyFile().

Function Documentation

◆ check_hard_link()

void check_hard_link ( void  )

Definition at line 283 of file file.c.

References _dosmaperr(), MAXPGPATH, new_cluster, old_cluster, pg_fatal(), pg_link_file, ClusterInfo::pgdata, snprintf(), and strerror().

Referenced by check_new_cluster().

284 {
285  char existing_file[MAXPGPATH];
286  char new_link_file[MAXPGPATH];
287 
288  snprintf(existing_file, sizeof(existing_file), "%s/PG_VERSION", old_cluster.pgdata);
289  snprintf(new_link_file, sizeof(new_link_file), "%s/PG_VERSION.linktest", new_cluster.pgdata);
290  unlink(new_link_file); /* might fail */
291 
292  if (pg_link_file(existing_file, new_link_file) < 0)
293  pg_fatal("could not create hard link between old and new data directories: %s\n"
294  "In link mode the old and new data directories must be on the same file system.\n",
295  strerror(errno));
296 
297  unlink(new_link_file);
298 }
#define pg_link_file
Definition: pg_upgrade.h:74
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
ClusterInfo new_cluster
Definition: pg_upgrade.c:57
#define MAXPGPATH
ClusterInfo old_cluster
Definition: pg_upgrade.c:57
char * pgdata
Definition: pg_upgrade.h:266
const char * strerror(int errnum)
Definition: strerror.c:19

◆ copyFile()

void copyFile ( const char *  src,
const char *  dst,
const char *  schemaName,
const char *  relName 
)

Definition at line 35 of file file.c.

References _dosmaperr(), buffer, close, COPY_BUF_SIZE, PG_BINARY, pg_fatal(), pg_file_create_mode, pg_free(), pg_malloc(), read, strerror(), and write.

Referenced by transfer_relfile().

37 {
38 #ifndef WIN32
39  int src_fd;
40  int dest_fd;
41  char *buffer;
42 
43  if ((src_fd = open(src, O_RDONLY | PG_BINARY, 0)) < 0)
44  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %s\n",
45  schemaName, relName, src, strerror(errno));
46 
47  if ((dest_fd = open(dst, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
48  pg_file_create_mode)) < 0)
49  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s\n",
50  schemaName, relName, dst, strerror(errno));
51 
52  /* copy in fairly large chunks for best efficiency */
53 #define COPY_BUF_SIZE (50 * BLCKSZ)
54 
55  buffer = (char *) pg_malloc(COPY_BUF_SIZE);
56 
57  /* perform data copying i.e read src source, write to destination */
58  while (true)
59  {
60  ssize_t nbytes = read(src_fd, buffer, COPY_BUF_SIZE);
61 
62  if (nbytes < 0)
63  pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %s\n",
64  schemaName, relName, src, strerror(errno));
65 
66  if (nbytes == 0)
67  break;
68 
69  errno = 0;
70  if (write(dest_fd, buffer, nbytes) != nbytes)
71  {
72  /* if write didn't set errno, assume problem is no disk space */
73  if (errno == 0)
74  errno = ENOSPC;
75  pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %s\n",
76  schemaName, relName, dst, strerror(errno));
77  }
78  }
79 
80  pg_free(buffer);
81  close(src_fd);
82  close(dest_fd);
83 
84 #else /* WIN32 */
85 
86  if (CopyFile(src, dst, true) == 0)
87  {
88  _dosmaperr(GetLastError());
89  pg_fatal("error while copying relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
90  schemaName, relName, src, dst, strerror(errno));
91  }
92 
93 #endif /* WIN32 */
94 }
int pg_file_create_mode
Definition: file_perm.c:20
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define write(a, b, c)
Definition: win32.h:14
void _dosmaperr(unsigned long)
Definition: win32error.c:171
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
#define PG_BINARY
Definition: c.h:1080
#define COPY_BUF_SIZE
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
void pg_free(void *ptr)
Definition: fe_memutils.c:105
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13

◆ linkFile()

void linkFile ( const char *  src,
const char *  dst,
const char *  schemaName,
const char *  relName 
)

Definition at line 104 of file file.c.

References pg_fatal(), pg_link_file, and strerror().

Referenced by transfer_relfile().

106 {
107  if (pg_link_file(src, dst) < 0)
108  pg_fatal("error while creating link for relation \"%s.%s\" (\"%s\" to \"%s\"): %s\n",
109  schemaName, relName, src, dst, strerror(errno));
110 }
#define pg_link_file
Definition: pg_upgrade.h:74
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
const char * strerror(int errnum)
Definition: strerror.c:19

◆ rewriteVisibilityMap()

void rewriteVisibilityMap ( const char *  fromfile,
const char *  tofile,
const char *  schemaName,
const char *  relName 
)

Definition at line 130 of file file.c.

References BITS_PER_BYTE, BITS_PER_HEAPBLOCK, buffer, byte, close, ClusterInfo::controldata, ControlData::data_checksum_version, i, new_cluster, PG_BINARY, pg_checksum_page(), pg_fatal(), pg_file_create_mode, pg_free(), pg_malloc(), read, SizeOfPageHeaderData, stat, strerror(), VISIBILITYMAP_ALL_VISIBLE, and write.

Referenced by transfer_relfile().

132 {
133  int src_fd;
134  int dst_fd;
135  char *buffer;
136  char *new_vmbuf;
137  ssize_t totalBytesRead = 0;
138  ssize_t src_filesize;
139  int rewriteVmBytesPerPage;
140  BlockNumber new_blkno = 0;
141  struct stat statbuf;
142 
143  /* Compute number of old-format bytes per new page */
144  rewriteVmBytesPerPage = (BLCKSZ - SizeOfPageHeaderData) / 2;
145 
146  if ((src_fd = open(fromfile, O_RDONLY | PG_BINARY, 0)) < 0)
147  pg_fatal("error while copying relation \"%s.%s\": could not open file \"%s\": %s\n",
148  schemaName, relName, fromfile, strerror(errno));
149 
150  if (fstat(src_fd, &statbuf) != 0)
151  pg_fatal("error while copying relation \"%s.%s\": could not stat file \"%s\": %s\n",
152  schemaName, relName, fromfile, strerror(errno));
153 
154  if ((dst_fd = open(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY,
155  pg_file_create_mode)) < 0)
156  pg_fatal("error while copying relation \"%s.%s\": could not create file \"%s\": %s\n",
157  schemaName, relName, tofile, strerror(errno));
158 
159  /* Save old file size */
160  src_filesize = statbuf.st_size;
161 
162  /*
163  * Malloc the work buffers, rather than making them local arrays, to
164  * ensure adequate alignment.
165  */
166  buffer = (char *) pg_malloc(BLCKSZ);
167  new_vmbuf = (char *) pg_malloc(BLCKSZ);
168 
169  /*
170  * Turn each visibility map page into 2 pages one by one. Each new page
171  * has the same page header as the old one. If the last section of the
172  * last page is empty, we skip it, mostly to avoid turning one-page
173  * visibility maps for small relations into two pages needlessly.
174  */
175  while (totalBytesRead < src_filesize)
176  {
177  ssize_t bytesRead;
178  char *old_cur;
179  char *old_break;
180  char *old_blkend;
181  PageHeaderData pageheader;
182  bool old_lastblk;
183 
184  if ((bytesRead = read(src_fd, buffer, BLCKSZ)) != BLCKSZ)
185  {
186  if (bytesRead < 0)
187  pg_fatal("error while copying relation \"%s.%s\": could not read file \"%s\": %s\n",
188  schemaName, relName, fromfile, strerror(errno));
189  else
190  pg_fatal("error while copying relation \"%s.%s\": partial page found in file \"%s\"\n",
191  schemaName, relName, fromfile);
192  }
193 
194  totalBytesRead += BLCKSZ;
195  old_lastblk = (totalBytesRead == src_filesize);
196 
197  /* Save the page header data */
198  memcpy(&pageheader, buffer, SizeOfPageHeaderData);
199 
200  /*
201  * These old_* variables point to old visibility map page. old_cur
202  * points to current position on old page. old_blkend points to end of
203  * old block. old_break is the end+1 position on the old page for the
204  * data that will be transferred to the current new page.
205  */
206  old_cur = buffer + SizeOfPageHeaderData;
207  old_blkend = buffer + bytesRead;
208  old_break = old_cur + rewriteVmBytesPerPage;
209 
210  while (old_break <= old_blkend)
211  {
212  char *new_cur;
213  bool empty = true;
214  bool old_lastpart;
215 
216  /* First, copy old page header to new page */
217  memcpy(new_vmbuf, &pageheader, SizeOfPageHeaderData);
218 
219  /* Rewriting the last part of the last old page? */
220  old_lastpart = old_lastblk && (old_break == old_blkend);
221 
222  new_cur = new_vmbuf + SizeOfPageHeaderData;
223 
224  /* Process old page bytes one by one, and turn it into new page. */
225  while (old_cur < old_break)
226  {
227  uint8 byte = *(uint8 *) old_cur;
228  uint16 new_vmbits = 0;
229  int i;
230 
231  /* Generate new format bits while keeping old information */
232  for (i = 0; i < BITS_PER_BYTE; i++)
233  {
234  if (byte & (1 << i))
235  {
236  empty = false;
237  new_vmbits |=
239  }
240  }
241 
242  /* Copy new visibility map bytes to new-format page */
243  new_cur[0] = (char) (new_vmbits & 0xFF);
244  new_cur[1] = (char) (new_vmbits >> 8);
245 
246  old_cur++;
247  new_cur += BITS_PER_HEAPBLOCK;
248  }
249 
250  /* If the last part of the last page is empty, skip writing it */
251  if (old_lastpart && empty)
252  break;
253 
254  /* Set new checksum for visibility map page, if enabled */
256  ((PageHeader) new_vmbuf)->pd_checksum =
257  pg_checksum_page(new_vmbuf, new_blkno);
258 
259  errno = 0;
260  if (write(dst_fd, new_vmbuf, BLCKSZ) != BLCKSZ)
261  {
262  /* if write didn't set errno, assume problem is no disk space */
263  if (errno == 0)
264  errno = ENOSPC;
265  pg_fatal("error while copying relation \"%s.%s\": could not write file \"%s\": %s\n",
266  schemaName, relName, tofile, strerror(errno));
267  }
268 
269  /* Advance for next new page */
270  old_break += rewriteVmBytesPerPage;
271  new_blkno++;
272  }
273  }
274 
275  /* Clean up */
276  pg_free(buffer);
277  pg_free(new_vmbuf);
278  close(dst_fd);
279  close(src_fd);
280 }
int pg_file_create_mode
Definition: file_perm.c:20
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
ControlData controldata
Definition: pg_upgrade.h:264
#define BITS_PER_BYTE
#define write(a, b, c)
Definition: win32.h:14
unsigned char uint8
Definition: c.h:323
uint32 BlockNumber
Definition: block.h:31
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PG_BINARY
Definition: c.h:1080
ClusterInfo new_cluster
Definition: pg_upgrade.c:57
unsigned short uint16
Definition: c.h:324
bool data_checksum_version
Definition: pg_upgrade.h:229
#define BITS_PER_HEAPBLOCK
Definition: visibilitymap.h:23
#define byte(x, n)
Definition: rijndael.c:68
#define stat(a, b)
Definition: win32_port.h:266
PageHeaderData * PageHeader
Definition: bufpage.h:162
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define VISIBILITYMAP_ALL_VISIBLE
Definition: visibilitymap.h:26
int i
const char * strerror(int errnum)
Definition: strerror.c:19
#define close(a)
Definition: win32.h:12
uint16 pg_checksum_page(char *page, BlockNumber blkno)
#define read(a, b, c)
Definition: win32.h:13