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 "logging.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 206 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().

207 {
208  file_entry_t *entry;
209  int i;
210 
211  for (i = 0; i < map->narray; i++)
212  {
213  entry = map->array[i];
214  execute_pagemap(&entry->pagemap, entry->path);
215 
216  switch (entry->action)
217  {
218  case FILE_ACTION_NONE:
219  /* ok, do nothing.. */
220  break;
221 
222  case FILE_ACTION_COPY:
223  rewind_copy_file_range(entry->path, 0, entry->newsize, true);
224  break;
225 
227  truncate_target_file(entry->path, entry->newsize);
228  break;
229 
231  rewind_copy_file_range(entry->path, entry->oldsize,
232  entry->newsize, false);
233  break;
234 
235  case FILE_ACTION_CREATE:
236  create_target(entry);
237  break;
238 
239  case FILE_ACTION_REMOVE:
240  remove_target(entry);
241  break;
242  }
243  }
244 
246 }
static void rewind_copy_file_range(const char *path, off_t begin, off_t end, bool trunc)
Definition: copy_fetch.c:157
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:192
static void execute_pagemap(datapagemap_t *pagemap, const char *path)
Definition: copy_fetch.c:249
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:126
char * path
Definition: filemap.h:44
void close_target_file(void)
Definition: file_ops.c:71
int i
Definition: filemap.h:42
void create_target(file_entry_t *entry)
Definition: file_ops.c:147

◆ execute_pagemap()

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

Definition at line 249 of file copy_fetch.c.

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

Referenced by copy_executeFileMap().

250 {
252  BlockNumber blkno;
253  off_t offset;
254 
255  iter = datapagemap_iterate(pagemap);
256  while (datapagemap_next(iter, &blkno))
257  {
258  offset = blkno * BLCKSZ;
259  rewind_copy_file_range(path, offset, offset + BLCKSZ, false);
260  /* Ok, this block has now been copied from new data dir to old */
261  }
262  pg_free(iter);
263 }
static void rewind_copy_file_range(const char *path, off_t begin, off_t end, bool trunc)
Definition: copy_fetch.c:157
uint32 BlockNumber
Definition: block.h:31
bool datapagemap_next(datapagemap_iterator_t *iter, BlockNumber *blkno)
Definition: datapagemap.c:87
datapagemap_iterator_t * datapagemap_iterate(datapagemap_t *map)
Definition: datapagemap.c:75
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 46 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(), stat, and strerror().

Referenced by traverse_datadir().

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

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

Referenced by copy_executeFileMap(), and execute_pagemap().

158 {
159  char buf[BLCKSZ];
160  char srcpath[MAXPGPATH];
161  int srcfd;
162 
163  snprintf(srcpath, sizeof(srcpath), "%s/%s", datadir_source, path);
164 
165  srcfd = open(srcpath, O_RDONLY | PG_BINARY, 0);
166  if (srcfd < 0)
167  pg_fatal("could not open source file \"%s\": %s\n",
168  srcpath, strerror(errno));
169 
170  if (lseek(srcfd, begin, SEEK_SET) == -1)
171  pg_fatal("could not seek in source file: %s\n", strerror(errno));
172 
173  open_target_file(path, trunc);
174 
175  while (end - begin > 0)
176  {
177  int readlen;
178  int len;
179 
180  if (end - begin > sizeof(buf))
181  len = sizeof(buf);
182  else
183  len = end - begin;
184 
185  readlen = read(srcfd, buf, len);
186 
187  if (readlen < 0)
188  pg_fatal("could not read file \"%s\": %s\n",
189  srcpath, strerror(errno));
190  else if (readlen == 0)
191  pg_fatal("unexpected EOF while reading file \"%s\"\n", srcpath);
192 
193  write_target_range(buf, begin, readlen);
194  begin += readlen;
195  }
196 
197  if (close(srcfd) != 0)
198  pg_fatal("could not close file \"%s\": %s\n", srcpath, strerror(errno));
199 }
void open_target_file(const char *path, bool trunc)
Definition: file_ops.c:43
void write_target_range(char *buf, off_t begin, size_t size)
Definition: file_ops.c:84
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
void pg_fatal(const char *fmt,...)
Definition: logging.c:83
#define PG_BINARY
Definition: c.h:1080
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:67
char * datadir_source
Definition: pg_rewind.c:52
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

◆ traverse_datadir()

void traverse_datadir ( const char *  datadir,
process_file_callback_t  callback 
)

Definition at line 34 of file copy_fetch.c.

References recurse_dir().

Referenced by fetchSourceFileList(), and main().

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