PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
copydir.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef enum FileCopyMethod FileCopyMethod
 

Enumerations

enum  FileCopyMethod { FILE_COPY_METHOD_COPY , FILE_COPY_METHOD_CLONE }
 

Functions

void copydir (const char *fromdir, const char *todir, bool recurse)
 
void copy_file (const char *fromfile, const char *tofile)
 

Variables

PGDLLIMPORT int file_copy_method
 

Typedef Documentation

◆ FileCopyMethod

Enumeration Type Documentation

◆ FileCopyMethod

Enumerator
FILE_COPY_METHOD_COPY 
FILE_COPY_METHOD_CLONE 

Definition at line 16 of file copydir.h.

17{
FileCopyMethod
Definition: copydir.h:17
@ FILE_COPY_METHOD_COPY
Definition: copydir.h:18
@ FILE_COPY_METHOD_CLONE
Definition: copydir.h:19

Function Documentation

◆ copy_file()

void copy_file ( const char *  fromfile,
const char *  tofile 
)

Definition at line 133 of file copydir.c.

134{
135 char *buffer;
136 int srcfd;
137 int dstfd;
138 int nbytes;
139 off_t offset;
140 off_t flush_offset;
141
142 /* Size of copy buffer (read and write requests) */
143#define COPY_BUF_SIZE (8 * BLCKSZ)
144
145 /*
146 * Size of data flush requests. It seems beneficial on most platforms to
147 * do this every 1MB or so. But macOS, at least with early releases of
148 * APFS, is really unfriendly to small mmap/msync requests, so there do it
149 * only every 32MB.
150 */
151#if defined(__darwin__)
152#define FLUSH_DISTANCE (32 * 1024 * 1024)
153#else
154#define FLUSH_DISTANCE (1024 * 1024)
155#endif
156
157 /* Use palloc to ensure we get a maxaligned buffer */
158 buffer = palloc(COPY_BUF_SIZE);
159
160 /*
161 * Open the files
162 */
163 srcfd = OpenTransientFile(fromfile, O_RDONLY | PG_BINARY);
164 if (srcfd < 0)
167 errmsg("could not open file \"%s\": %m", fromfile)));
168
169 dstfd = OpenTransientFile(tofile, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
170 if (dstfd < 0)
173 errmsg("could not create file \"%s\": %m", tofile)));
174
175 /*
176 * Do the data copying.
177 */
178 flush_offset = 0;
179 for (offset = 0;; offset += nbytes)
180 {
181 /* If we got a cancel signal during the copy of the file, quit */
183
184 /*
185 * We fsync the files later, but during the copy, flush them every so
186 * often to avoid spamming the cache and hopefully get the kernel to
187 * start writing them out before the fsync comes.
188 */
189 if (offset - flush_offset >= FLUSH_DISTANCE)
190 {
191 pg_flush_data(dstfd, flush_offset, offset - flush_offset);
192 flush_offset = offset;
193 }
194
195 pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_READ);
196 nbytes = read(srcfd, buffer, COPY_BUF_SIZE);
198 if (nbytes < 0)
201 errmsg("could not read file \"%s\": %m", fromfile)));
202 if (nbytes == 0)
203 break;
204 errno = 0;
205 pgstat_report_wait_start(WAIT_EVENT_COPY_FILE_WRITE);
206 if ((int) write(dstfd, buffer, nbytes) != nbytes)
207 {
208 /* if write didn't set errno, assume problem is no disk space */
209 if (errno == 0)
210 errno = ENOSPC;
213 errmsg("could not write to file \"%s\": %m", tofile)));
214 }
216 }
217
218 if (offset > flush_offset)
219 pg_flush_data(dstfd, flush_offset, offset - flush_offset);
220
221 if (CloseTransientFile(dstfd) != 0)
224 errmsg("could not close file \"%s\": %m", tofile)));
225
226 if (CloseTransientFile(srcfd) != 0)
229 errmsg("could not close file \"%s\": %m", fromfile)));
230
231 pfree(buffer);
232}
#define PG_BINARY
Definition: c.h:1244
#define FLUSH_DISTANCE
#define COPY_BUF_SIZE
int errcode_for_file_access(void)
Definition: elog.c:877
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void pg_flush_data(int fd, off_t offset, off_t nbytes)
Definition: fd.c:525
int CloseTransientFile(int fd)
Definition: fd.c:2871
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2694
static int dstfd
Definition: file_ops.c:31
#define write(a, b, c)
Definition: win32.h:14
#define read(a, b, c)
Definition: win32.h:13
void pfree(void *pointer)
Definition: mcxt.c:2147
void * palloc(Size size)
Definition: mcxt.c:1940
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101

References CHECK_FOR_INTERRUPTS, CloseTransientFile(), COPY_BUF_SIZE, dstfd, ereport, errcode_for_file_access(), errmsg(), ERROR, FLUSH_DISTANCE, OpenTransientFile(), palloc(), pfree(), PG_BINARY, pg_flush_data(), pgstat_report_wait_end(), pgstat_report_wait_start(), read, and write.

Referenced by basic_archive_file(), copydir(), process_directory_recursively(), reconstruct_from_incremental_file(), and ResetUnloggedRelationsInDbspaceDir().

◆ copydir()

void copydir ( const char *  fromdir,
const char *  todir,
bool  recurse 
)

Definition at line 48 of file copydir.c.

49{
50 DIR *xldir;
51 struct dirent *xlde;
52 char fromfile[MAXPGPATH * 2];
53 char tofile[MAXPGPATH * 2];
54
55 if (MakePGDirectory(todir) != 0)
58 errmsg("could not create directory \"%s\": %m", todir)));
59
60 xldir = AllocateDir(fromdir);
61
62 while ((xlde = ReadDir(xldir, fromdir)) != NULL)
63 {
64 PGFileType xlde_type;
65
66 /* If we got a cancel signal during the copy of the directory, quit */
68
69 if (strcmp(xlde->d_name, ".") == 0 ||
70 strcmp(xlde->d_name, "..") == 0)
71 continue;
72
73 snprintf(fromfile, sizeof(fromfile), "%s/%s", fromdir, xlde->d_name);
74 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
75
76 xlde_type = get_dirent_type(fromfile, xlde, false, ERROR);
77
78 if (xlde_type == PGFILETYPE_DIR)
79 {
80 /* recurse to handle subdirectories */
81 if (recurse)
82 copydir(fromfile, tofile, true);
83 }
84 else if (xlde_type == PGFILETYPE_REG)
85 {
87 clone_file(fromfile, tofile);
88 else
89 copy_file(fromfile, tofile);
90 }
91 }
92 FreeDir(xldir);
93
94 /*
95 * Be paranoid here and fsync all files to ensure the copy is really done.
96 * But if fsync is disabled, we're done.
97 */
98 if (!enableFsync)
99 return;
100
101 xldir = AllocateDir(todir);
102
103 while ((xlde = ReadDir(xldir, todir)) != NULL)
104 {
105 if (strcmp(xlde->d_name, ".") == 0 ||
106 strcmp(xlde->d_name, "..") == 0)
107 continue;
108
109 snprintf(tofile, sizeof(tofile), "%s/%s", todir, xlde->d_name);
110
111 /*
112 * We don't need to sync subdirectories here since the recursive
113 * copydir will do it before it returns
114 */
115 if (get_dirent_type(tofile, xlde, false, ERROR) == PGFILETYPE_REG)
116 fsync_fname(tofile, false);
117 }
118 FreeDir(xldir);
119
120 /*
121 * It's important to fsync the destination directory itself as individual
122 * file fsyncs don't guarantee that the directory entry for the file is
123 * synced. Recent versions of ext4 have made the window much wider but
124 * it's been true for ext3 and other filesystems in the past.
125 */
126 fsync_fname(todir, true);
127}
int file_copy_method
Definition: copydir.c:34
static void clone_file(const char *fromfile, const char *tofile)
Definition: copydir.c:238
void copy_file(const char *fromfile, const char *tofile)
Definition: copydir.c:133
void copydir(const char *fromdir, const char *todir, bool recurse)
Definition: copydir.c:48
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3978
int FreeDir(DIR *dir)
Definition: fd.c:3025
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:756
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2907
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2973
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:547
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_REG
Definition: file_utils.h:22
bool enableFsync
Definition: globals.c:130
#define MAXPGPATH
#define snprintf
Definition: port.h:239
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References AllocateDir(), CHECK_FOR_INTERRUPTS, clone_file(), copy_file(), copydir(), dirent::d_name, enableFsync, ereport, errcode_for_file_access(), errmsg(), ERROR, file_copy_method, FILE_COPY_METHOD_CLONE, FreeDir(), fsync_fname(), get_dirent_type(), MakePGDirectory(), MAXPGPATH, PGFILETYPE_DIR, PGFILETYPE_REG, ReadDir(), and snprintf.

Referenced by copydir(), CreateDatabaseUsingFileCopy(), dbase_redo(), and movedb().

Variable Documentation

◆ file_copy_method

PGDLLIMPORT int file_copy_method
extern

Definition at line 34 of file copydir.c.

Referenced by copydir().