PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
walmethods.c File Reference
#include "postgres_fe.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "common/file_perm.h"
#include "common/file_utils.h"
#include "common/logging.h"
#include "pgtar.h"
#include "walmethods.h"
Include dependency graph for walmethods.c:

Go to the source code of this file.

Data Structures

struct  DirectoryMethodData
 
struct  DirectoryMethodFile
 
struct  TarMethodFile
 
struct  TarMethodData
 

Macros

#define ZLIB_OUT_SIZE   4096
 
#define LZ4_IN_SIZE   4096
 
#define clear_error(wwmethod)    ((wwmethod)->lasterrstring = NULL, (wwmethod)->lasterrno = 0)
 

Typedefs

typedef struct DirectoryMethodData DirectoryMethodData
 
typedef struct DirectoryMethodFile DirectoryMethodFile
 
typedef struct TarMethodFile TarMethodFile
 
typedef struct TarMethodData TarMethodData
 

Functions

static Walfiledir_open_for_write (WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
 
static int dir_close (Walfile *f, WalCloseMethod method)
 
static bool dir_existsfile (WalWriteMethod *wwmethod, const char *pathname)
 
static ssize_t dir_get_file_size (WalWriteMethod *wwmethod, const char *pathname)
 
static char * dir_get_file_name (WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)
 
static ssize_t dir_write (Walfile *f, const void *buf, size_t count)
 
static int dir_sync (Walfile *f)
 
static bool dir_finish (WalWriteMethod *wwmethod)
 
static void dir_free (WalWriteMethod *wwmethod)
 
WalWriteMethodCreateWalDirectoryMethod (const char *basedir, pg_compress_algorithm compression_algorithm, int compression_level, bool sync)
 
static Walfiletar_open_for_write (WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
 
static int tar_close (Walfile *f, WalCloseMethod method)
 
static bool tar_existsfile (WalWriteMethod *wwmethod, const char *pathname)
 
static ssize_t tar_get_file_size (WalWriteMethod *wwmethod, const char *pathname)
 
static char * tar_get_file_name (WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)
 
static ssize_t tar_write (Walfile *f, const void *buf, size_t count)
 
static int tar_sync (Walfile *f)
 
static bool tar_finish (WalWriteMethod *wwmethod)
 
static void tar_free (WalWriteMethod *wwmethod)
 
static bool tar_write_padding_data (TarMethodFile *f, size_t bytes)
 
WalWriteMethodCreateWalTarMethod (const char *tarbase, pg_compress_algorithm compression_algorithm, int compression_level, bool sync)
 
const char * GetLastWalMethodError (WalWriteMethod *wwmethod)
 

Variables

static const WalWriteMethodOps WalDirectoryMethodOps
 
static const WalWriteMethodOps WalTarMethodOps
 

Macro Definition Documentation

◆ clear_error

#define clear_error (   wwmethod)     ((wwmethod)->lasterrstring = NULL, (wwmethod)->lasterrno = 0)

Definition at line 98 of file walmethods.c.

◆ LZ4_IN_SIZE

#define LZ4_IN_SIZE   4096

Definition at line 36 of file walmethods.c.

◆ ZLIB_OUT_SIZE

#define ZLIB_OUT_SIZE   4096

Definition at line 33 of file walmethods.c.

Typedef Documentation

◆ DirectoryMethodData

◆ DirectoryMethodFile

◆ TarMethodData

typedef struct TarMethodData TarMethodData

◆ TarMethodFile

typedef struct TarMethodFile TarMethodFile

Function Documentation

◆ CreateWalDirectoryMethod()

WalWriteMethod * CreateWalDirectoryMethod ( const char *  basedir,
pg_compress_algorithm  compression_algorithm,
int  compression_level,
bool  sync 
)

Definition at line 640 of file walmethods.c.

643{
644 DirectoryMethodData *wwmethod;
645
646 wwmethod = pg_malloc0(sizeof(DirectoryMethodData));
647 *((const WalWriteMethodOps **) &wwmethod->base.ops) =
650 wwmethod->base.compression_level = compression_level;
651 wwmethod->base.sync = sync;
652 clear_error(&wwmethod->base);
653 wwmethod->basedir = pg_strdup(basedir);
654
655 return &wwmethod->base;
656}
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
static char * basedir
static pg_compress_algorithm compression_algorithm
Definition: pg_receivewal.c:55
WalWriteMethod base
Definition: walmethods.c:75
int compression_level
Definition: walmethods.h:107
const WalWriteMethodOps * ops
Definition: walmethods.h:105
pg_compress_algorithm compression_algorithm
Definition: walmethods.h:106
#define clear_error(wwmethod)
Definition: walmethods.c:98
static const WalWriteMethodOps WalDirectoryMethodOps
Definition: walmethods.c:58

References DirectoryMethodData::base, basedir, DirectoryMethodData::basedir, clear_error, compression_algorithm, WalWriteMethod::compression_algorithm, WalWriteMethod::compression_level, WalWriteMethod::ops, pg_malloc0(), pg_strdup(), WalWriteMethod::sync, and WalDirectoryMethodOps.

Referenced by LogStreamerMain(), and StreamLog().

◆ CreateWalTarMethod()

WalWriteMethod * CreateWalTarMethod ( const char *  tarbase,
pg_compress_algorithm  compression_algorithm,
int  compression_level,
bool  sync 
)

Definition at line 1355 of file walmethods.c.

1358{
1359 TarMethodData *wwmethod;
1360 const char *suffix = (compression_algorithm == PG_COMPRESSION_GZIP) ?
1361 ".tar.gz" : ".tar";
1362
1363 wwmethod = pg_malloc0(sizeof(TarMethodData));
1364 *((const WalWriteMethodOps **) &wwmethod->base.ops) =
1367 wwmethod->base.compression_level = compression_level;
1368 wwmethod->base.sync = sync;
1369 clear_error(&wwmethod->base);
1370
1371 wwmethod->tarfilename = pg_malloc0(strlen(tarbase) + strlen(suffix) + 1);
1372 sprintf(wwmethod->tarfilename, "%s%s", tarbase, suffix);
1373 wwmethod->fd = -1;
1374#ifdef HAVE_LIBZ
1376 wwmethod->zlibOut = (char *) pg_malloc(ZLIB_OUT_SIZE + 1);
1377#endif
1378
1379 return &wwmethod->base;
1380}
@ PG_COMPRESSION_GZIP
Definition: compression.h:24
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
#define sprintf
Definition: port.h:240
WalWriteMethod base
Definition: walmethods.c:701
char * tarfilename
Definition: walmethods.c:702
static const WalWriteMethodOps WalTarMethodOps
Definition: walmethods.c:679
#define ZLIB_OUT_SIZE
Definition: walmethods.c:33

References TarMethodData::base, clear_error, compression_algorithm, WalWriteMethod::compression_algorithm, WalWriteMethod::compression_level, TarMethodData::fd, WalWriteMethod::ops, PG_COMPRESSION_GZIP, pg_malloc(), pg_malloc0(), sprintf, WalWriteMethod::sync, TarMethodData::tarfilename, WalTarMethodOps, and ZLIB_OUT_SIZE.

Referenced by LogStreamerMain().

◆ dir_close()

static int dir_close ( Walfile f,
WalCloseMethod  method 
)
static

Definition at line 385 of file walmethods.c.

386{
387 int r;
390 char tmppath[MAXPGPATH];
391 char tmppath2[MAXPGPATH];
392
393 Assert(f != NULL);
395
396#ifdef HAVE_LIBZ
398 {
399 errno = 0; /* in case gzclose() doesn't set it */
400 r = gzclose(df->gzfp);
401 }
402 else
403#endif
404#ifdef USE_LZ4
406 {
407 size_t compressed;
408
409 compressed = LZ4F_compressEnd(df->ctx,
410 df->lz4buf, df->lz4bufsize,
411 NULL);
412
413 if (LZ4F_isError(compressed))
414 {
415 f->wwmethod->lasterrstring = LZ4F_getErrorName(compressed);
416 return -1;
417 }
418
419 errno = 0;
420 if (write(df->fd, df->lz4buf, compressed) != compressed)
421 {
422 /* If write didn't set errno, assume problem is no disk space */
423 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
424 return -1;
425 }
426
427 r = close(df->fd);
428 }
429 else
430#endif
431 r = close(df->fd);
432
433 if (r == 0)
434 {
435 /* Build path to the current version of the file */
436 if (method == CLOSE_NORMAL && df->temp_suffix)
437 {
438 char *filename;
439 char *filename2;
440
441 /*
442 * If we have a temp prefix, normal operation is to rename the
443 * file.
444 */
446 df->temp_suffix);
447 snprintf(tmppath, sizeof(tmppath), "%s/%s",
448 dir_data->basedir, filename);
450
451 /* permanent name, so no need for the prefix */
452 filename2 = dir_get_file_name(f->wwmethod, df->base.pathname, NULL);
453 snprintf(tmppath2, sizeof(tmppath2), "%s/%s",
454 dir_data->basedir, filename2);
455 pg_free(filename2);
456 if (f->wwmethod->sync)
457 r = durable_rename(tmppath, tmppath2);
458 else
459 {
460 if (rename(tmppath, tmppath2) != 0)
461 {
462 pg_log_error("could not rename file \"%s\" to \"%s\": %m",
463 tmppath, tmppath2);
464 r = -1;
465 }
466 }
467 }
468 else if (method == CLOSE_UNLINK)
469 {
470 char *filename;
471
472 /* Unlink the file once it's closed */
474 df->temp_suffix);
475 snprintf(tmppath, sizeof(tmppath), "%s/%s",
476 dir_data->basedir, filename);
478 r = unlink(tmppath);
479 }
480 else
481 {
482 /*
483 * Else either CLOSE_NORMAL and no temp suffix, or
484 * CLOSE_NO_RENAME. In this case, fsync the file and containing
485 * directory if sync mode is requested.
486 */
487 if (f->wwmethod->sync)
488 {
489 r = fsync_fname(df->fullpath, false);
490 if (r == 0)
492 }
493 }
494 }
495
496 if (r != 0)
497 f->wwmethod->lasterrno = errno;
498
499#ifdef USE_LZ4
500 pg_free(df->lz4buf);
501 /* supports free on NULL */
502 LZ4F_freeCompressionContext(df->ctx);
503#endif
504
505 pg_free(df->base.pathname);
506 pg_free(df->fullpath);
507 pg_free(df->temp_suffix);
508 pg_free(df);
509
510 return r;
511}
#define Assert(condition)
Definition: c.h:812
@ PG_COMPRESSION_LZ4
Definition: compression.h:25
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:781
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:755
static int fsync_parent_path(const char *fname, int elevel)
Definition: fd.c:3896
void pg_free(void *ptr)
Definition: fe_memutils.c:105
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
#define pg_log_error(...)
Definition: logging.h:106
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:119
#define snprintf
Definition: port.h:238
const char * lasterrstring
Definition: walmethods.h:109
WalWriteMethod * wwmethod
Definition: walmethods.h:19
char * pathname
Definition: walmethods.h:21
static char * dir_get_file_name(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)
Definition: walmethods.c:102
@ CLOSE_UNLINK
Definition: walmethods.h:34
@ CLOSE_NORMAL
Definition: walmethods.h:33

References Assert, DirectoryMethodFile::base, DirectoryMethodData::basedir, clear_error, close, CLOSE_NORMAL, CLOSE_UNLINK, WalWriteMethod::compression_algorithm, dir_get_file_name(), durable_rename(), DirectoryMethodFile::fd, filename, fsync_fname(), fsync_parent_path(), DirectoryMethodFile::fullpath, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, MAXPGPATH, Walfile::pathname, PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, pg_free(), pg_log_error, snprintf, WalWriteMethod::sync, DirectoryMethodFile::temp_suffix, write, and Walfile::wwmethod.

◆ dir_existsfile()

static bool dir_existsfile ( WalWriteMethod wwmethod,
const char *  pathname 
)
static

Definition at line 584 of file walmethods.c.

585{
586 DirectoryMethodData *dir_data = (DirectoryMethodData *) wwmethod;
587 char tmppath[MAXPGPATH];
588 int fd;
589
590 clear_error(wwmethod);
591
592 snprintf(tmppath, sizeof(tmppath), "%s/%s",
593 dir_data->basedir, pathname);
594
595 fd = open(tmppath, O_RDONLY | PG_BINARY, 0);
596 if (fd < 0)
597
598 /*
599 * Skip setting dir_data->lasterrno here because we are only checking
600 * for existence.
601 */
602 return false;
603 close(fd);
604 return true;
605}
#define PG_BINARY
Definition: c.h:1227
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References DirectoryMethodData::basedir, clear_error, close, fd(), MAXPGPATH, PG_BINARY, and snprintf.

◆ dir_finish()

static bool dir_finish ( WalWriteMethod wwmethod)
static

Definition at line 608 of file walmethods.c.

609{
610 clear_error(wwmethod);
611
612 if (wwmethod->sync)
613 {
614 DirectoryMethodData *dir_data = (DirectoryMethodData *) wwmethod;
615
616 /*
617 * Files are fsynced when they are closed, but we need to fsync the
618 * directory entry here as well.
619 */
620 if (fsync_fname(dir_data->basedir, true) != 0)
621 {
622 wwmethod->lasterrno = errno;
623 return false;
624 }
625 }
626 return true;
627}

References DirectoryMethodData::basedir, clear_error, fsync_fname(), WalWriteMethod::lasterrno, and WalWriteMethod::sync.

◆ dir_free()

static void dir_free ( WalWriteMethod wwmethod)
static

Definition at line 630 of file walmethods.c.

631{
632 DirectoryMethodData *dir_data = (DirectoryMethodData *) wwmethod;
633
634 pg_free(dir_data->basedir);
635 pg_free(wwmethod);
636}

References DirectoryMethodData::basedir, and pg_free().

◆ dir_get_file_name()

static char * dir_get_file_name ( WalWriteMethod wwmethod,
const char *  pathname,
const char *  temp_suffix 
)
static

Definition at line 102 of file walmethods.c.

104{
105 char *filename = pg_malloc0(MAXPGPATH * sizeof(char));
106
107 snprintf(filename, MAXPGPATH, "%s%s%s",
108 pathname,
109 wwmethod->compression_algorithm == PG_COMPRESSION_GZIP ? ".gz" :
110 wwmethod->compression_algorithm == PG_COMPRESSION_LZ4 ? ".lz4" : "",
111 temp_suffix ? temp_suffix : "");
112
113 return filename;
114}

References WalWriteMethod::compression_algorithm, filename, MAXPGPATH, PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, pg_malloc0(), and snprintf.

Referenced by dir_close(), and dir_open_for_write().

◆ dir_get_file_size()

static ssize_t dir_get_file_size ( WalWriteMethod wwmethod,
const char *  pathname 
)
static

Definition at line 565 of file walmethods.c.

566{
567 DirectoryMethodData *dir_data = (DirectoryMethodData *) wwmethod;
568 struct stat statbuf;
569 char tmppath[MAXPGPATH];
570
571 snprintf(tmppath, sizeof(tmppath), "%s/%s",
572 dir_data->basedir, pathname);
573
574 if (stat(tmppath, &statbuf) != 0)
575 {
576 wwmethod->lasterrno = errno;
577 return -1;
578 }
579
580 return statbuf.st_size;
581}
#define stat
Definition: win32_port.h:284

References DirectoryMethodData::basedir, WalWriteMethod::lasterrno, MAXPGPATH, snprintf, stat::st_size, and stat.

◆ dir_open_for_write()

static Walfile * dir_open_for_write ( WalWriteMethod wwmethod,
const char *  pathname,
const char *  temp_suffix,
size_t  pad_to_size 
)
static

Definition at line 117 of file walmethods.c.

119{
120 DirectoryMethodData *dir_data = (DirectoryMethodData *) wwmethod;
121 char tmppath[MAXPGPATH];
122 char *filename;
123 int fd;
125#ifdef HAVE_LIBZ
126 gzFile gzfp = NULL;
127#endif
128#ifdef USE_LZ4
129 LZ4F_compressionContext_t ctx = NULL;
130 size_t lz4bufsize = 0;
131 void *lz4buf = NULL;
132#endif
133
134 clear_error(wwmethod);
135
136 filename = dir_get_file_name(wwmethod, pathname, temp_suffix);
137 snprintf(tmppath, sizeof(tmppath), "%s/%s",
138 dir_data->basedir, filename);
140
141 /*
142 * Open a file for non-compressed as well as compressed files. Tracking
143 * the file descriptor is important for dir_sync() method as gzflush()
144 * does not do any system calls to fsync() to make changes permanent on
145 * disk.
146 */
147 fd = open(tmppath, O_WRONLY | O_CREAT | PG_BINARY, pg_file_create_mode);
148 if (fd < 0)
149 {
150 wwmethod->lasterrno = errno;
151 return NULL;
152 }
153
154#ifdef HAVE_LIBZ
156 {
157 gzfp = gzdopen(fd, "wb");
158 if (gzfp == NULL)
159 {
160 wwmethod->lasterrno = errno;
161 close(fd);
162 return NULL;
163 }
164
165 if (gzsetparams(gzfp, wwmethod->compression_level,
166 Z_DEFAULT_STRATEGY) != Z_OK)
167 {
168 wwmethod->lasterrno = errno;
169 gzclose(gzfp);
170 return NULL;
171 }
172 }
173#endif
174#ifdef USE_LZ4
176 {
177 size_t ctx_out;
178 size_t header_size;
179 LZ4F_preferences_t prefs;
180
181 ctx_out = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
182 if (LZ4F_isError(ctx_out))
183 {
184 wwmethod->lasterrstring = LZ4F_getErrorName(ctx_out);
185 close(fd);
186 return NULL;
187 }
188
189 lz4bufsize = LZ4F_compressBound(LZ4_IN_SIZE, NULL);
190 lz4buf = pg_malloc0(lz4bufsize);
191
192 /* assign the compression level, default is 0 */
193 memset(&prefs, 0, sizeof(prefs));
194 prefs.compressionLevel = wwmethod->compression_level;
195
196 /* add the header */
197 header_size = LZ4F_compressBegin(ctx, lz4buf, lz4bufsize, &prefs);
198 if (LZ4F_isError(header_size))
199 {
200 wwmethod->lasterrstring = LZ4F_getErrorName(header_size);
201 (void) LZ4F_freeCompressionContext(ctx);
202 pg_free(lz4buf);
203 close(fd);
204 return NULL;
205 }
206
207 errno = 0;
208 if (write(fd, lz4buf, header_size) != header_size)
209 {
210 /* If write didn't set errno, assume problem is no disk space */
211 wwmethod->lasterrno = errno ? errno : ENOSPC;
212 (void) LZ4F_freeCompressionContext(ctx);
213 pg_free(lz4buf);
214 close(fd);
215 return NULL;
216 }
217 }
218#endif
219
220 /* Do pre-padding on non-compressed files */
221 if (pad_to_size && wwmethod->compression_algorithm == PG_COMPRESSION_NONE)
222 {
223 ssize_t rc;
224
225 rc = pg_pwrite_zeros(fd, pad_to_size, 0);
226
227 if (rc < 0)
228 {
229 wwmethod->lasterrno = errno;
230 close(fd);
231 return NULL;
232 }
233
234 /*
235 * pg_pwrite() (called via pg_pwrite_zeros()) may have moved the file
236 * position, so reset it (see win32pwrite.c).
237 */
238 if (lseek(fd, 0, SEEK_SET) != 0)
239 {
240 wwmethod->lasterrno = errno;
241 close(fd);
242 return NULL;
243 }
244 }
245
246 /*
247 * fsync WAL file and containing directory, to ensure the file is
248 * persistently created and zeroed (if padded). That's particularly
249 * important when using synchronous mode, where the file is modified and
250 * fsynced in-place, without a directory fsync.
251 */
252 if (wwmethod->sync)
253 {
254 if (fsync_fname(tmppath, false) != 0 ||
255 fsync_parent_path(tmppath) != 0)
256 {
257 wwmethod->lasterrno = errno;
258#ifdef HAVE_LIBZ
260 gzclose(gzfp);
261 else
262#endif
263#ifdef USE_LZ4
265 {
266 (void) LZ4F_compressEnd(ctx, lz4buf, lz4bufsize, NULL);
267 (void) LZ4F_freeCompressionContext(ctx);
268 pg_free(lz4buf);
269 close(fd);
270 }
271 else
272#endif
273 close(fd);
274 return NULL;
275 }
276 }
277
278 f = pg_malloc0(sizeof(DirectoryMethodFile));
279#ifdef HAVE_LIBZ
281 f->gzfp = gzfp;
282#endif
283#ifdef USE_LZ4
285 {
286 f->ctx = ctx;
287 f->lz4buf = lz4buf;
288 f->lz4bufsize = lz4bufsize;
289 }
290#endif
291
292 f->base.wwmethod = wwmethod;
293 f->base.currpos = 0;
294 f->base.pathname = pg_strdup(pathname);
295 f->fd = fd;
296 f->fullpath = pg_strdup(tmppath);
297 if (temp_suffix)
298 f->temp_suffix = pg_strdup(temp_suffix);
299
300 return &f->base;
301}
@ PG_COMPRESSION_NONE
Definition: compression.h:23
int pg_file_create_mode
Definition: file_perm.c:19
ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset)
Definition: file_utils.c:688
off_t currpos
Definition: walmethods.h:20
#define LZ4_IN_SIZE
Definition: walmethods.c:36

References DirectoryMethodFile::base, DirectoryMethodData::basedir, clear_error, close, WalWriteMethod::compression_algorithm, WalWriteMethod::compression_level, Walfile::currpos, dir_get_file_name(), DirectoryMethodFile::fd, fd(), filename, fsync_fname(), fsync_parent_path(), DirectoryMethodFile::fullpath, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, LZ4_IN_SIZE, MAXPGPATH, Walfile::pathname, PG_BINARY, PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, PG_COMPRESSION_NONE, pg_file_create_mode, pg_free(), pg_malloc0(), pg_pwrite_zeros(), pg_strdup(), snprintf, WalWriteMethod::sync, DirectoryMethodFile::temp_suffix, write, and Walfile::wwmethod.

◆ dir_sync()

static int dir_sync ( Walfile f)
static

Definition at line 514 of file walmethods.c.

515{
516 int r;
517
518 Assert(f != NULL);
520
521 if (!f->wwmethod->sync)
522 return 0;
523
524#ifdef HAVE_LIBZ
526 {
527 if (gzflush(((DirectoryMethodFile *) f)->gzfp, Z_SYNC_FLUSH) != Z_OK)
528 {
529 f->wwmethod->lasterrno = errno;
530 return -1;
531 }
532 }
533#endif
534#ifdef USE_LZ4
536 {
538 size_t compressed;
539
540 /* Flush any internal buffers */
541 compressed = LZ4F_flush(df->ctx, df->lz4buf, df->lz4bufsize, NULL);
542 if (LZ4F_isError(compressed))
543 {
544 f->wwmethod->lasterrstring = LZ4F_getErrorName(compressed);
545 return -1;
546 }
547
548 errno = 0;
549 if (write(df->fd, df->lz4buf, compressed) != compressed)
550 {
551 /* If write didn't set errno, assume problem is no disk space */
552 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
553 return -1;
554 }
555 }
556#endif
557
558 r = fsync(((DirectoryMethodFile *) f)->fd);
559 if (r < 0)
560 f->wwmethod->lasterrno = errno;
561 return r;
562}
#define fsync(fd)
Definition: win32_port.h:85

References Assert, clear_error, WalWriteMethod::compression_algorithm, DirectoryMethodFile::fd, fd(), fsync, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, WalWriteMethod::sync, write, and Walfile::wwmethod.

◆ dir_write()

static ssize_t dir_write ( Walfile f,
const void *  buf,
size_t  count 
)
static

Definition at line 304 of file walmethods.c.

305{
306 ssize_t r;
308
309 Assert(f != NULL);
311
312#ifdef HAVE_LIBZ
314 {
315 errno = 0;
316 r = (ssize_t) gzwrite(df->gzfp, buf, count);
317 if (r != count)
318 {
319 /* If write didn't set errno, assume problem is no disk space */
320 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
321 }
322 }
323 else
324#endif
325#ifdef USE_LZ4
327 {
328 size_t chunk;
329 size_t remaining;
330 const void *inbuf = buf;
331
332 remaining = count;
333 while (remaining > 0)
334 {
335 size_t compressed;
336
339 else
341
342 remaining -= chunk;
343 compressed = LZ4F_compressUpdate(df->ctx,
344 df->lz4buf, df->lz4bufsize,
345 inbuf, chunk,
346 NULL);
347
348 if (LZ4F_isError(compressed))
349 {
350 f->wwmethod->lasterrstring = LZ4F_getErrorName(compressed);
351 return -1;
352 }
353
354 errno = 0;
355 if (write(df->fd, df->lz4buf, compressed) != compressed)
356 {
357 /* If write didn't set errno, assume problem is no disk space */
358 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
359 return -1;
360 }
361
362 inbuf = ((char *) inbuf) + chunk;
363 }
364
365 /* Our caller keeps track of the uncompressed size. */
366 r = (ssize_t) count;
367 }
368 else
369#endif
370 {
371 errno = 0;
372 r = write(df->fd, buf, count);
373 if (r != count)
374 {
375 /* If write didn't set errno, assume problem is no disk space */
376 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
377 }
378 }
379 if (r > 0)
380 df->base.currpos += r;
381 return r;
382}
uint64 chunk
int remaining
Definition: informix.c:692
static char * buf
Definition: pg_test_fsync.c:72

References Assert, DirectoryMethodFile::base, buf, chunk, clear_error, WalWriteMethod::compression_algorithm, Walfile::currpos, DirectoryMethodFile::fd, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, LZ4_IN_SIZE, PG_COMPRESSION_GZIP, PG_COMPRESSION_LZ4, remaining, write, and Walfile::wwmethod.

◆ GetLastWalMethodError()

const char * GetLastWalMethodError ( WalWriteMethod wwmethod)

◆ tar_close()

static int tar_close ( Walfile f,
WalCloseMethod  method 
)
static

Definition at line 1042 of file walmethods.c.

1043{
1044 ssize_t filesize;
1045 int padding;
1046 TarMethodData *tar_data = (TarMethodData *) f->wwmethod;
1047 TarMethodFile *tf = (TarMethodFile *) f;
1048
1049 Assert(f != NULL);
1051
1052 if (method == CLOSE_UNLINK)
1053 {
1055 {
1056 f->wwmethod->lasterrstring = _("unlink not supported with compression");
1057 return -1;
1058 }
1059
1060 /*
1061 * Unlink the file that we just wrote to the tar. We do this by
1062 * truncating it to the start of the header. This is safe as we only
1063 * allow writing of the very last file.
1064 */
1065 if (ftruncate(tar_data->fd, tf->ofs_start) != 0)
1066 {
1067 f->wwmethod->lasterrno = errno;
1068 return -1;
1069 }
1070
1071 pg_free(tf->base.pathname);
1072 pg_free(tf);
1073 tar_data->currentfile = NULL;
1074
1075 return 0;
1076 }
1077
1078 /*
1079 * Pad the file itself with zeroes if necessary. Note that this is
1080 * different from the tar format padding -- this is the padding we asked
1081 * for when the file was opened.
1082 */
1083 if (tf->pad_to_size)
1084 {
1086 {
1087 /*
1088 * A compressed tarfile is padded on close since we cannot know
1089 * the size of the compressed output until the end.
1090 */
1091 size_t sizeleft = tf->pad_to_size - tf->base.currpos;
1092
1093 if (sizeleft)
1094 {
1095 if (!tar_write_padding_data(tf, sizeleft))
1096 return -1;
1097 }
1098 }
1099 else
1100 {
1101 /*
1102 * An uncompressed tarfile was padded on creation, so just adjust
1103 * the current position as if we seeked to the end.
1104 */
1105 tf->base.currpos = tf->pad_to_size;
1106 }
1107 }
1108
1109 /*
1110 * Get the size of the file, and pad out to a multiple of the tar block
1111 * size.
1112 */
1113 filesize = f->currpos;
1114 padding = tarPaddingBytesRequired(filesize);
1115 if (padding)
1116 {
1117 char zerobuf[TAR_BLOCK_SIZE] = {0};
1118
1119 if (tar_write(f, zerobuf, padding) != padding)
1120 return -1;
1121 }
1122
1123
1124#ifdef HAVE_LIBZ
1126 {
1127 /* Flush the current buffer */
1128 if (!tar_write_compressed_data(tar_data, NULL, 0, true))
1129 return -1;
1130 }
1131#endif
1132
1133 /*
1134 * Now go back and update the header with the correct filesize and
1135 * possibly also renaming the file. We overwrite the entire current header
1136 * when done, including the checksum.
1137 */
1138 print_tar_number(&(tf->header[TAR_OFFSET_SIZE]), 12, filesize);
1139
1140 if (method == CLOSE_NORMAL)
1141
1142 /*
1143 * We overwrite it with what it was before if we have no tempname,
1144 * since we're going to write the buffer anyway.
1145 */
1146 strlcpy(&(tf->header[TAR_OFFSET_NAME]), tf->base.pathname, 100);
1147
1148 print_tar_number(&(tf->header[TAR_OFFSET_CHECKSUM]), 8,
1149 tarChecksum(((TarMethodFile *) f)->header));
1150 if (lseek(tar_data->fd, tf->ofs_start, SEEK_SET) != ((TarMethodFile *) f)->ofs_start)
1151 {
1152 f->wwmethod->lasterrno = errno;
1153 return -1;
1154 }
1155 if (f->wwmethod->compression_algorithm == PG_COMPRESSION_NONE)
1156 {
1157 errno = 0;
1158 if (write(tar_data->fd, tf->header, TAR_BLOCK_SIZE) != TAR_BLOCK_SIZE)
1159 {
1160 /* If write didn't set errno, assume problem is no disk space */
1161 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
1162 return -1;
1163 }
1164 }
1165#ifdef HAVE_LIBZ
1166 else if (f->wwmethod->compression_algorithm == PG_COMPRESSION_GZIP)
1167 {
1168 /* Turn off compression */
1169 if (deflateParams(tar_data->zp, 0, Z_DEFAULT_STRATEGY) != Z_OK)
1170 {
1171 f->wwmethod->lasterrstring = _("could not change compression parameters");
1172 return -1;
1173 }
1174
1175 /* Overwrite the header, assuming the size will be the same */
1176 if (!tar_write_compressed_data(tar_data, tar_data->currentfile->header,
1177 TAR_BLOCK_SIZE, true))
1178 return -1;
1179
1180 /* Turn compression back on */
1181 if (deflateParams(tar_data->zp, f->wwmethod->compression_level,
1182 Z_DEFAULT_STRATEGY) != Z_OK)
1183 {
1184 f->wwmethod->lasterrstring = _("could not change compression parameters");
1185 return -1;
1186 }
1187 }
1188#endif
1189 else
1190 {
1191 /* not reachable */
1192 Assert(false);
1193 }
1194
1195 /* Move file pointer back down to end, so we can write the next file */
1196 if (lseek(tar_data->fd, 0, SEEK_END) < 0)
1197 {
1198 f->wwmethod->lasterrno = errno;
1199 return -1;
1200 }
1201
1202 /* Always fsync on close, so the padding gets fsynced */
1203 if (tar_sync(f) < 0)
1204 {
1205 /* XXX this seems pretty bogus; why is only this case fatal? */
1206 pg_fatal("could not fsync file \"%s\": %s",
1207 tf->base.pathname, GetLastWalMethodError(f->wwmethod));
1208 }
1209
1210 /* Clean up and done */
1211 pg_free(tf->base.pathname);
1212 pg_free(tf);
1213 tar_data->currentfile = NULL;
1214
1215 return 0;
1216}
#define _(x)
Definition: elog.c:90
#define pg_fatal(...)
static size_t tarPaddingBytesRequired(size_t len)
Definition: pgtar.h:79
int tarChecksum(char *header)
Definition: tar.c:90
@ TAR_OFFSET_NAME
Definition: pgtar.h:39
@ TAR_OFFSET_SIZE
Definition: pgtar.h:43
@ TAR_OFFSET_CHECKSUM
Definition: pgtar.h:45
#define TAR_BLOCK_SIZE
Definition: pgtar.h:17
void print_tar_number(char *s, int len, uint64 val)
Definition: tar.c:22
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
TarMethodFile * currentfile
Definition: walmethods.c:704
size_t pad_to_size
Definition: walmethods.c:696
char header[TAR_BLOCK_SIZE]
Definition: walmethods.c:695
static ssize_t tar_write(Walfile *f, const void *buf, size_t count)
Definition: walmethods.c:765
static int tar_sync(Walfile *f)
Definition: walmethods.c:1017
const char * GetLastWalMethodError(WalWriteMethod *wwmethod)
Definition: walmethods.c:1383
static bool tar_write_padding_data(TarMethodFile *f, size_t bytes)
Definition: walmethods.c:805
#define ftruncate(a, b)
Definition: win32_port.h:82

References _, Assert, clear_error, CLOSE_NORMAL, CLOSE_UNLINK, WalWriteMethod::compression_algorithm, WalWriteMethod::compression_level, TarMethodData::currentfile, Walfile::currpos, TarMethodData::fd, ftruncate, GetLastWalMethodError(), TarMethodFile::header, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, TarMethodFile::pad_to_size, PG_COMPRESSION_GZIP, PG_COMPRESSION_NONE, pg_fatal, pg_free(), print_tar_number(), strlcpy(), TAR_BLOCK_SIZE, TAR_OFFSET_CHECKSUM, TAR_OFFSET_NAME, TAR_OFFSET_SIZE, tar_sync(), tar_write(), tar_write_padding_data(), tarChecksum(), tarPaddingBytesRequired(), write, and Walfile::wwmethod.

Referenced by tar_finish().

◆ tar_existsfile()

static bool tar_existsfile ( WalWriteMethod wwmethod,
const char *  pathname 
)
static

Definition at line 1219 of file walmethods.c.

1220{
1221 clear_error(wwmethod);
1222 /* We only deal with new tarfiles, so nothing externally created exists */
1223 return false;
1224}

References clear_error.

◆ tar_finish()

static bool tar_finish ( WalWriteMethod wwmethod)
static

Definition at line 1227 of file walmethods.c.

1228{
1229 TarMethodData *tar_data = (TarMethodData *) wwmethod;
1230 char zerobuf[1024] = {0};
1231
1232 clear_error(wwmethod);
1233
1234 if (tar_data->currentfile)
1235 {
1236 if (tar_close(&tar_data->currentfile->base, CLOSE_NORMAL) != 0)
1237 return false;
1238 }
1239
1240 /* A tarfile always ends with two empty blocks */
1242 {
1243 errno = 0;
1244 if (write(tar_data->fd, zerobuf, sizeof(zerobuf)) != sizeof(zerobuf))
1245 {
1246 /* If write didn't set errno, assume problem is no disk space */
1247 wwmethod->lasterrno = errno ? errno : ENOSPC;
1248 return false;
1249 }
1250 }
1251#ifdef HAVE_LIBZ
1252 else if (wwmethod->compression_algorithm == PG_COMPRESSION_GZIP)
1253 {
1254 if (!tar_write_compressed_data(tar_data, zerobuf, sizeof(zerobuf),
1255 false))
1256 return false;
1257
1258 /* Also flush all data to make sure the gzip stream is finished */
1259 tar_data->zp->next_in = NULL;
1260 tar_data->zp->avail_in = 0;
1261 while (true)
1262 {
1263 int r;
1264
1265 r = deflate(tar_data->zp, Z_FINISH);
1266
1267 if (r == Z_STREAM_ERROR)
1268 {
1269 wwmethod->lasterrstring = _("could not compress data");
1270 return false;
1271 }
1272 if (tar_data->zp->avail_out < ZLIB_OUT_SIZE)
1273 {
1274 size_t len = ZLIB_OUT_SIZE - tar_data->zp->avail_out;
1275
1276 errno = 0;
1277 if (write(tar_data->fd, tar_data->zlibOut, len) != len)
1278 {
1279 /*
1280 * If write didn't set errno, assume problem is no disk
1281 * space.
1282 */
1283 wwmethod->lasterrno = errno ? errno : ENOSPC;
1284 return false;
1285 }
1286 }
1287 if (r == Z_STREAM_END)
1288 break;
1289 }
1290
1291 if (deflateEnd(tar_data->zp) != Z_OK)
1292 {
1293 wwmethod->lasterrstring = _("could not close compression stream");
1294 return false;
1295 }
1296 }
1297#endif
1298 else
1299 {
1300 /* not reachable */
1301 Assert(false);
1302 }
1303
1304 /* sync the empty blocks as well, since they're after the last file */
1305 if (wwmethod->sync)
1306 {
1307 if (fsync(tar_data->fd) != 0)
1308 {
1309 wwmethod->lasterrno = errno;
1310 return false;
1311 }
1312 }
1313
1314 if (close(tar_data->fd) != 0)
1315 {
1316 wwmethod->lasterrno = errno;
1317 return false;
1318 }
1319
1320 tar_data->fd = -1;
1321
1322 if (wwmethod->sync)
1323 {
1324 if (fsync_fname(tar_data->tarfilename, false) != 0 ||
1325 fsync_parent_path(tar_data->tarfilename) != 0)
1326 {
1327 wwmethod->lasterrno = errno;
1328 return false;
1329 }
1330 }
1331
1332 return true;
1333}
const void size_t len
Walfile base
Definition: walmethods.c:693
static int tar_close(Walfile *f, WalCloseMethod method)
Definition: walmethods.c:1042

References _, Assert, TarMethodFile::base, clear_error, close, CLOSE_NORMAL, WalWriteMethod::compression_algorithm, TarMethodData::currentfile, TarMethodData::fd, fsync, fsync_fname(), fsync_parent_path(), WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, len, PG_COMPRESSION_GZIP, PG_COMPRESSION_NONE, WalWriteMethod::sync, tar_close(), TarMethodData::tarfilename, write, and ZLIB_OUT_SIZE.

◆ tar_free()

static void tar_free ( WalWriteMethod wwmethod)
static

Definition at line 1336 of file walmethods.c.

1337{
1338 TarMethodData *tar_data = (TarMethodData *) wwmethod;
1339
1340 pg_free(tar_data->tarfilename);
1341#ifdef HAVE_LIBZ
1343 pg_free(tar_data->zlibOut);
1344#endif
1345 pg_free(wwmethod);
1346}

References WalWriteMethod::compression_algorithm, PG_COMPRESSION_GZIP, pg_free(), and TarMethodData::tarfilename.

◆ tar_get_file_name()

static char * tar_get_file_name ( WalWriteMethod wwmethod,
const char *  pathname,
const char *  temp_suffix 
)
static

Definition at line 825 of file walmethods.c.

827{
828 char *filename = pg_malloc0(MAXPGPATH * sizeof(char));
829
830 snprintf(filename, MAXPGPATH, "%s%s",
831 pathname, temp_suffix ? temp_suffix : "");
832
833 return filename;
834}

References filename, MAXPGPATH, pg_malloc0(), and snprintf.

Referenced by tar_open_for_write().

◆ tar_get_file_size()

static ssize_t tar_get_file_size ( WalWriteMethod wwmethod,
const char *  pathname 
)
static

Definition at line 1007 of file walmethods.c.

1008{
1009 clear_error(wwmethod);
1010
1011 /* Currently not used, so not supported */
1012 wwmethod->lasterrno = ENOSYS;
1013 return -1;
1014}

References clear_error, and WalWriteMethod::lasterrno.

◆ tar_open_for_write()

static Walfile * tar_open_for_write ( WalWriteMethod wwmethod,
const char *  pathname,
const char *  temp_suffix,
size_t  pad_to_size 
)
static

Definition at line 837 of file walmethods.c.

839{
840 TarMethodData *tar_data = (TarMethodData *) wwmethod;
841 char *tmppath;
842
843 clear_error(wwmethod);
844
845 if (tar_data->fd < 0)
846 {
847 /*
848 * We open the tar file only when we first try to write to it.
849 */
850 tar_data->fd = open(tar_data->tarfilename,
851 O_WRONLY | O_CREAT | PG_BINARY,
853 if (tar_data->fd < 0)
854 {
855 wwmethod->lasterrno = errno;
856 return NULL;
857 }
858
859#ifdef HAVE_LIBZ
861 {
862 tar_data->zp = (z_streamp) pg_malloc(sizeof(z_stream));
863 tar_data->zp->zalloc = Z_NULL;
864 tar_data->zp->zfree = Z_NULL;
865 tar_data->zp->opaque = Z_NULL;
866 tar_data->zp->next_out = tar_data->zlibOut;
867 tar_data->zp->avail_out = ZLIB_OUT_SIZE;
868
869 /*
870 * Initialize deflation library. Adding the magic value 16 to the
871 * default 15 for the windowBits parameter makes the output be
872 * gzip instead of zlib.
873 */
874 if (deflateInit2(tar_data->zp, wwmethod->compression_level,
875 Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK)
876 {
877 pg_free(tar_data->zp);
878 tar_data->zp = NULL;
879 wwmethod->lasterrstring =
880 _("could not initialize compression library");
881 return NULL;
882 }
883 }
884#endif
885
886 /* There's no tar header itself, the file starts with regular files */
887 }
888
889 if (tar_data->currentfile != NULL)
890 {
891 wwmethod->lasterrstring =
892 _("implementation error: tar files can't have more than one open file");
893 return NULL;
894 }
895
896 tar_data->currentfile = pg_malloc0(sizeof(TarMethodFile));
897 tar_data->currentfile->base.wwmethod = wwmethod;
898
899 tmppath = tar_get_file_name(wwmethod, pathname, temp_suffix);
900
901 /* Create a header with size set to 0 - we will fill out the size on close */
902 if (tarCreateHeader(tar_data->currentfile->header, tmppath, NULL, 0, S_IRUSR | S_IWUSR, 0, 0, time(NULL)) != TAR_OK)
903 {
904 pg_free(tar_data->currentfile);
905 pg_free(tmppath);
906 tar_data->currentfile = NULL;
907 wwmethod->lasterrstring = _("could not create tar header");
908 return NULL;
909 }
910
911 pg_free(tmppath);
912
913#ifdef HAVE_LIBZ
915 {
916 /* Flush existing data */
917 if (!tar_write_compressed_data(tar_data, NULL, 0, true))
918 return NULL;
919
920 /* Turn off compression for header */
921 if (deflateParams(tar_data->zp, 0, Z_DEFAULT_STRATEGY) != Z_OK)
922 {
923 wwmethod->lasterrstring =
924 _("could not change compression parameters");
925 return NULL;
926 }
927 }
928#endif
929
930 tar_data->currentfile->ofs_start = lseek(tar_data->fd, 0, SEEK_CUR);
931 if (tar_data->currentfile->ofs_start == -1)
932 {
933 wwmethod->lasterrno = errno;
934 pg_free(tar_data->currentfile);
935 tar_data->currentfile = NULL;
936 return NULL;
937 }
938 tar_data->currentfile->base.currpos = 0;
939
941 {
942 errno = 0;
943 if (write(tar_data->fd, tar_data->currentfile->header,
945 {
946 /* If write didn't set errno, assume problem is no disk space */
947 wwmethod->lasterrno = errno ? errno : ENOSPC;
948 pg_free(tar_data->currentfile);
949 tar_data->currentfile = NULL;
950 return NULL;
951 }
952 }
953#ifdef HAVE_LIBZ
954 else if (wwmethod->compression_algorithm == PG_COMPRESSION_GZIP)
955 {
956 /* Write header through the zlib APIs but with no compression */
957 if (!tar_write_compressed_data(tar_data, tar_data->currentfile->header,
958 TAR_BLOCK_SIZE, true))
959 return NULL;
960
961 /* Re-enable compression for the rest of the file */
962 if (deflateParams(tar_data->zp, wwmethod->compression_level,
963 Z_DEFAULT_STRATEGY) != Z_OK)
964 {
965 wwmethod->lasterrstring = _("could not change compression parameters");
966 return NULL;
967 }
968 }
969#endif
970 else
971 {
972 /* not reachable */
973 Assert(false);
974 }
975
976 tar_data->currentfile->base.pathname = pg_strdup(pathname);
977
978 /*
979 * Uncompressed files are padded on creation, but for compression we can't
980 * do that
981 */
982 if (pad_to_size)
983 {
984 tar_data->currentfile->pad_to_size = pad_to_size;
986 {
987 /* Uncompressed, so pad now */
988 if (!tar_write_padding_data(tar_data->currentfile, pad_to_size))
989 return NULL;
990 /* Seek back to start */
991 if (lseek(tar_data->fd,
993 SEEK_SET) != tar_data->currentfile->ofs_start + TAR_BLOCK_SIZE)
994 {
995 wwmethod->lasterrno = errno;
996 return NULL;
997 }
998
999 tar_data->currentfile->base.currpos = 0;
1000 }
1001 }
1002
1003 return &tar_data->currentfile->base;
1004}
enum tarError tarCreateHeader(char *h, const char *filename, const char *linktarget, pgoff_t size, mode_t mode, uid_t uid, gid_t gid, time_t mtime)
Definition: tar.c:114
@ TAR_OK
Definition: pgtar.h:21
off_t ofs_start
Definition: walmethods.c:694
static char * tar_get_file_name(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)
Definition: walmethods.c:825
#define S_IRUSR
Definition: win32_port.h:289
#define S_IWUSR
Definition: win32_port.h:292

References _, Assert, TarMethodFile::base, clear_error, WalWriteMethod::compression_algorithm, WalWriteMethod::compression_level, TarMethodData::currentfile, Walfile::currpos, TarMethodData::fd, TarMethodFile::header, WalWriteMethod::lasterrno, WalWriteMethod::lasterrstring, TarMethodFile::ofs_start, TarMethodFile::pad_to_size, Walfile::pathname, PG_BINARY, PG_COMPRESSION_GZIP, PG_COMPRESSION_NONE, pg_file_create_mode, pg_free(), pg_malloc(), pg_malloc0(), pg_strdup(), S_IRUSR, S_IWUSR, TAR_BLOCK_SIZE, tar_get_file_name(), TAR_OK, tar_write_padding_data(), tarCreateHeader(), TarMethodData::tarfilename, write, Walfile::wwmethod, and ZLIB_OUT_SIZE.

◆ tar_sync()

static int tar_sync ( Walfile f)
static

Definition at line 1017 of file walmethods.c.

1018{
1019 TarMethodData *tar_data = (TarMethodData *) f->wwmethod;
1020 int r;
1021
1022 Assert(f != NULL);
1024
1025 if (!f->wwmethod->sync)
1026 return 0;
1027
1028 /*
1029 * Always sync the whole tarfile, because that's all we can do. This makes
1030 * no sense on compressed files, so just ignore those.
1031 */
1033 return 0;
1034
1035 r = fsync(tar_data->fd);
1036 if (r < 0)
1037 f->wwmethod->lasterrno = errno;
1038 return r;
1039}

References Assert, clear_error, WalWriteMethod::compression_algorithm, TarMethodData::fd, fsync, WalWriteMethod::lasterrno, PG_COMPRESSION_NONE, WalWriteMethod::sync, and Walfile::wwmethod.

Referenced by tar_close().

◆ tar_write()

static ssize_t tar_write ( Walfile f,
const void *  buf,
size_t  count 
)
static

Definition at line 765 of file walmethods.c.

766{
767 TarMethodData *tar_data = (TarMethodData *) f->wwmethod;
768 ssize_t r;
769
770 Assert(f != NULL);
772
773 /* Tarfile will always be positioned at the end */
775 {
776 errno = 0;
777 r = write(tar_data->fd, buf, count);
778 if (r != count)
779 {
780 /* If write didn't set errno, assume problem is no disk space */
781 f->wwmethod->lasterrno = errno ? errno : ENOSPC;
782 return -1;
783 }
784 f->currpos += r;
785 return r;
786 }
787#ifdef HAVE_LIBZ
789 {
790 if (!tar_write_compressed_data(tar_data, buf, count, false))
791 return -1;
792 f->currpos += count;
793 return count;
794 }
795#endif
796 else
797 {
798 /* Can't happen - compression enabled with no method set */
799 f->wwmethod->lasterrno = ENOSYS;
800 return -1;
801 }
802}

References Assert, buf, clear_error, WalWriteMethod::compression_algorithm, Walfile::currpos, TarMethodData::fd, WalWriteMethod::lasterrno, PG_COMPRESSION_GZIP, PG_COMPRESSION_NONE, write, and Walfile::wwmethod.

Referenced by tar_close(), and tar_write_padding_data().

◆ tar_write_padding_data()

static bool tar_write_padding_data ( TarMethodFile f,
size_t  bytes 
)
static

Definition at line 805 of file walmethods.c.

806{
807 PGAlignedXLogBlock zerobuf;
808 size_t bytesleft = bytes;
809
810 memset(zerobuf.data, 0, XLOG_BLCKSZ);
811 while (bytesleft)
812 {
813 size_t bytestowrite = Min(bytesleft, XLOG_BLCKSZ);
814 ssize_t r = tar_write(&f->base, zerobuf.data, bytestowrite);
815
816 if (r < 0)
817 return false;
818 bytesleft -= r;
819 }
820
821 return true;
822}
#define Min(x, y)
Definition: c.h:958
char data[XLOG_BLCKSZ]
Definition: c.h:1102

References TarMethodFile::base, PGAlignedXLogBlock::data, Min, and tar_write().

Referenced by tar_close(), and tar_open_for_write().

Variable Documentation

◆ WalDirectoryMethodOps

const WalWriteMethodOps WalDirectoryMethodOps
static
Initial value:
= {
.open_for_write = dir_open_for_write,
.close = dir_close,
.existsfile = dir_existsfile,
.get_file_size = dir_get_file_size,
.get_file_name = dir_get_file_name,
.write = dir_write,
.sync = dir_sync,
.finish = dir_finish,
.free = dir_free
}
static Walfile * dir_open_for_write(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.c:117
static bool dir_finish(WalWriteMethod *wwmethod)
Definition: walmethods.c:608
static void dir_free(WalWriteMethod *wwmethod)
Definition: walmethods.c:630
static int dir_sync(Walfile *f)
Definition: walmethods.c:514
static int dir_close(Walfile *f, WalCloseMethod method)
Definition: walmethods.c:385
static ssize_t dir_get_file_size(WalWriteMethod *wwmethod, const char *pathname)
Definition: walmethods.c:565
static bool dir_existsfile(WalWriteMethod *wwmethod, const char *pathname)
Definition: walmethods.c:584
static ssize_t dir_write(Walfile *f, const void *buf, size_t count)
Definition: walmethods.c:304

Definition at line 58 of file walmethods.c.

Referenced by CreateWalDirectoryMethod().

◆ WalTarMethodOps

const WalWriteMethodOps WalTarMethodOps
static
Initial value:
= {
.open_for_write = tar_open_for_write,
.close = tar_close,
.existsfile = tar_existsfile,
.get_file_size = tar_get_file_size,
.get_file_name = tar_get_file_name,
.write = tar_write,
.sync = tar_sync,
.finish = tar_finish,
.free = tar_free
}
static Walfile * tar_open_for_write(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
Definition: walmethods.c:837
static void tar_free(WalWriteMethod *wwmethod)
Definition: walmethods.c:1336
static bool tar_finish(WalWriteMethod *wwmethod)
Definition: walmethods.c:1227
static bool tar_existsfile(WalWriteMethod *wwmethod, const char *pathname)
Definition: walmethods.c:1219
static ssize_t tar_get_file_size(WalWriteMethod *wwmethod, const char *pathname)
Definition: walmethods.c:1007

Definition at line 679 of file walmethods.c.

Referenced by CreateWalTarMethod().