PostgreSQL Source Code  git master
copy_fetch.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include "datapagemap.h"
#include "fetch.h"
#include "file_ops.h"
#include "filemap.h"
#include "pg_rewind.h"
Include dependency graph for copy_fetch.c:

Go to the source code of this file.

Functions

static void recurse_dir (const char *datadir, const char *path, process_file_callback_t callback)
 
static void execute_pagemap (datapagemap_t *pagemap, const char *path)
 
void traverse_datadir (const char *datadir, process_file_callback_t callback)
 
static void rewind_copy_file_range (const char *path, off_t begin, off_t end, bool trunc)
 
void copy_executeFileMap (filemap_t *map)
 

Function Documentation

◆ copy_executeFileMap()

void copy_executeFileMap ( filemap_t map)

Definition at line 205 of file copy_fetch.c.

References file_entry_t::action, filemap_t::array, close_target_file(), create_target(), execute_pagemap(), FILE_ACTION_COPY, FILE_ACTION_COPY_TAIL, FILE_ACTION_CREATE, FILE_ACTION_NONE, FILE_ACTION_REMOVE, FILE_ACTION_TRUNCATE, i, filemap_t::narray, file_entry_t::newsize, file_entry_t::oldsize, file_entry_t::pagemap, file_entry_t::path, remove_target(), rewind_copy_file_range(), and truncate_target_file().

Referenced by executeFileMap().

206 {
207  file_entry_t *entry;
208  int i;
209 
210  for (i = 0; i < map->narray; i++)
211  {
212  entry = map->array[i];
213  execute_pagemap(&entry->pagemap, entry->path);
214 
215  switch (entry->action)
216  {
217  case FILE_ACTION_NONE:
218  /* ok, do nothing.. */
219  break;
220 
221  case FILE_ACTION_COPY:
222  rewind_copy_file_range(entry->path, 0, entry->newsize, true);
223  break;
224 
226  truncate_target_file(entry->path, entry->newsize);
227  break;
228 
230  rewind_copy_file_range(entry->path, entry->oldsize,
231  entry->newsize, false);
232  break;
233 
234  case FILE_ACTION_CREATE:
235  create_target(entry);
236  break;
237 
238  case FILE_ACTION_REMOVE:
239  remove_target(entry);
240  break;
241  }
242  }
243 
245 }
static void rewind_copy_file_range(const char *path, off_t begin, off_t end, bool trunc)
Definition: copy_fetch.c:156
file_entry_t ** array
Definition: filemap.h:79
size_t newsize
Definition: filemap.h:51
datapagemap_t pagemap
Definition: filemap.h:54
int narray
Definition: filemap.h:80
void truncate_target_file(const char *path, off_t newsize)
Definition: file_ops.c:191
static void execute_pagemap(datapagemap_t *pagemap, const char *path)
Definition: copy_fetch.c:248
file_action_t action
Definition: filemap.h:47
size_t oldsize
Definition: filemap.h:50
void remove_target(file_entry_t *entry)
Definition: file_ops.c:125
char * path
Definition: filemap.h:44
void close_target_file(void)
Definition: file_ops.c:70
int i
Definition: filemap.h:42
void create_target(file_entry_t *entry)
Definition: file_ops.c:146

◆ execute_pagemap()

static void execute_pagemap ( datapagemap_t pagemap,
const char *  path 
)
static

Definition at line 248 of file copy_fetch.c.

References datapagemap_iterate(), datapagemap_next(), pg_free(), and rewind_copy_file_range().

Referenced by copy_executeFileMap().

249 {
251  BlockNumber blkno;
252  off_t offset;
253 
254  iter = datapagemap_iterate(pagemap);
255  while (datapagemap_next(iter, &blkno))
256  {
257  offset = blkno * BLCKSZ;
258  rewind_copy_file_range(path, offset, offset + BLCKSZ, false);
259  /* Ok, this block has now been copied from new data dir to old */
260  }
261  pg_free(iter);
262 }
static void rewind_copy_file_range(const char *path, off_t begin, off_t end, bool trunc)
Definition: copy_fetch.c:156
uint32 BlockNumber
Definition: block.h:31
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition: datapagemap.c:88
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition: datapagemap.c:76
void pg_free(void *ptr)
Definition: fe_memutils.c:105

◆ recurse_dir()

static void recurse_dir ( const char *  datadir,
const char *  path,
process_file_callback_t  callback 
)
static

Definition at line 45 of file copy_fetch.c.

References callback(), closedir(), dirent::d_name, FILE_TYPE_DIRECTORY, FILE_TYPE_REGULAR, FILE_TYPE_SYMLINK, lstat, MAXPGPATH, opendir(), pg_fatal, pgwin32_is_junction(), readdir(), readlink, S_ISDIR, S_ISREG, snprintf, and stat.

Referenced by traverse_datadir().

47 {
48  DIR *xldir;
49  struct dirent *xlde;
50  char fullparentpath[MAXPGPATH];
51 
52  if (parentpath)
53  snprintf(fullparentpath, MAXPGPATH, "%s/%s", datadir, parentpath);
54  else
55  snprintf(fullparentpath, MAXPGPATH, "%s", datadir);
56 
57  xldir = opendir(fullparentpath);
58  if (xldir == NULL)
59  pg_fatal("could not open directory \"%s\": %m",
60  fullparentpath);
61 
62  while (errno = 0, (xlde = readdir(xldir)) != NULL)
63  {
64  struct stat fst;
65  char fullpath[MAXPGPATH * 2];
66  char path[MAXPGPATH * 2];
67 
68  if (strcmp(xlde->d_name, ".") == 0 ||
69  strcmp(xlde->d_name, "..") == 0)
70  continue;
71 
72  snprintf(fullpath, sizeof(fullpath), "%s/%s", fullparentpath, xlde->d_name);
73 
74  if (lstat(fullpath, &fst) < 0)
75  {
76  if (errno == ENOENT)
77  {
78  /*
79  * File doesn't exist anymore. This is ok, if the new master
80  * is running and the file was just removed. If it was a data
81  * file, there should be a WAL record of the removal. If it
82  * was something else, it couldn't have been anyway.
83  *
84  * TODO: But complain if we're processing the target dir!
85  */
86  }
87  else
88  pg_fatal("could not stat file \"%s\": %m",
89  fullpath);
90  }
91 
92  if (parentpath)
93  snprintf(path, sizeof(path), "%s/%s", parentpath, xlde->d_name);
94  else
95  snprintf(path, sizeof(path), "%s", xlde->d_name);
96 
97  if (S_ISREG(fst.st_mode))
98  callback(path, FILE_TYPE_REGULAR, fst.st_size, NULL);
99  else if (S_ISDIR(fst.st_mode))
100  {
101  callback(path, FILE_TYPE_DIRECTORY, 0, NULL);
102  /* recurse to handle subdirectories */
103  recurse_dir(datadir, path, callback);
104  }
105 #ifndef WIN32
106  else if (S_ISLNK(fst.st_mode))
107 #else
108  else if (pgwin32_is_junction(fullpath))
109 #endif
110  {
111 #if defined(HAVE_READLINK) || defined(WIN32)
112  char link_target[MAXPGPATH];
113  int len;
114 
115  len = readlink(fullpath, link_target, sizeof(link_target));
116  if (len < 0)
117  pg_fatal("could not read symbolic link \"%s\": %m",
118  fullpath);
119  if (len >= sizeof(link_target))
120  pg_fatal("symbolic link \"%s\" target is too long",
121  fullpath);
122  link_target[len] = '\0';
123 
124  callback(path, FILE_TYPE_SYMLINK, 0, link_target);
125 
126  /*
127  * If it's a symlink within pg_tblspc, we need to recurse into it,
128  * to process all the tablespaces. We also follow a symlink if
129  * it's for pg_wal. Symlinks elsewhere are ignored.
130  */
131  if ((parentpath && strcmp(parentpath, "pg_tblspc") == 0) ||
132  strcmp(path, "pg_wal") == 0)
133  recurse_dir(datadir, path, callback);
134 #else
135  pg_fatal("\"%s\" is a symbolic link, but symbolic links are not supported on this platform",
136  fullpath);
137 #endif /* HAVE_READLINK */
138  }
139  }
140 
141  if (errno)
142  pg_fatal("could not read directory \"%s\": %m",
143  fullparentpath);
144 
145  if (closedir(xldir))
146  pg_fatal("could not close directory \"%s\": %m",
147  fullparentpath);
148 }
static void recurse_dir(const char *datadir, const char *path, process_file_callback_t callback)
Definition: copy_fetch.c:45
int closedir(DIR *)
Definition: dirent.c:113
#define pg_fatal(...)
Definition: pg_rewind.h:43
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
DIR * opendir(const char *)
Definition: dirent.c:33
#define readlink(path, buf, size)
Definition: win32_port.h:222
char * datadir
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
struct dirent * readdir(DIR *)
Definition: dirent.c:77
#define S_ISDIR(m)
Definition: win32_port.h:296
#define lstat(path, sb)
Definition: win32_port.h:244
char d_name[MAX_PATH]
Definition: dirent.h:14
#define snprintf
Definition: port.h:192
bool pgwin32_is_junction(const char *path)

◆ rewind_copy_file_range()

static void rewind_copy_file_range ( const char *  path,
off_t  begin,
off_t  end,
bool  trunc 
)
static

Definition at line 156 of file copy_fetch.c.

References buf, close, PGAlignedBlock::data, datadir_source, MAXPGPATH, open_target_file(), PG_BINARY, pg_fatal, read, snprintf, and write_target_range().

Referenced by copy_executeFileMap(), and execute_pagemap().

157 {
159  char srcpath[MAXPGPATH];
160  int srcfd;
161 
162  snprintf(srcpath, sizeof(srcpath), "%s/%s", datadir_source, path);
163 
164  srcfd = open(srcpath, O_RDONLY | PG_BINARY, 0);
165  if (srcfd < 0)
166  pg_fatal("could not open source file \"%s\": %m",
167  srcpath);
168 
169  if (lseek(srcfd, begin, SEEK_SET) == -1)
170  pg_fatal("could not seek in source file: %m");
171 
172  open_target_file(path, trunc);
173 
174  while (end - begin > 0)
175  {
176  int readlen;
177  int len;
178 
179  if (end - begin > sizeof(buf))
180  len = sizeof(buf);
181  else
182  len = end - begin;
183 
184  readlen = read(srcfd, buf.data, len);
185 
186  if (readlen < 0)
187  pg_fatal("could not read file \"%s\": %m",
188  srcpath);
189  else if (readlen == 0)
190  pg_fatal("unexpected EOF while reading file \"%s\"", srcpath);
191 
192  write_target_range(buf.data, begin, readlen);
193  begin += readlen;
194  }
195 
196  if (close(srcfd) != 0)
197  pg_fatal("could not close file \"%s\": %m", srcpath);
198 }
void open_target_file(const char *path, bool trunc)
Definition: file_ops.c:42
void write_target_range(char *buf, off_t begin, size_t size)
Definition: file_ops.c:83
#define pg_fatal(...)
Definition: pg_rewind.h:43
#define PG_BINARY
Definition: c.h:1191
char data[BLCKSZ]
Definition: c.h:1060
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:68
char * datadir_source
Definition: pg_rewind.c:55
#define close(a)
Definition: win32.h:12
#define snprintf
Definition: port.h:192
#define read(a, b, c)
Definition: win32.h:13

◆ traverse_datadir()

void traverse_datadir ( const char *  datadir,
process_file_callback_t  callback 
)

Definition at line 33 of file copy_fetch.c.

References recurse_dir().

Referenced by fetchSourceFileList(), and main().

34 {
36 }
static void recurse_dir(const char *datadir, const char *path, process_file_callback_t callback)
Definition: copy_fetch.c:45
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
char * datadir