33 #define ZLIB_OUT_SIZE 4096
36 #define LZ4_IN_SIZE 4096
45 const char *temp_suffix,
50 const char *pathname);
52 const char *pathname,
const char *temp_suffix);
92 LZ4F_compressionContext_t ctx;
98 #define clear_error(wwmethod) \
99 ((wwmethod)->lasterrstring = NULL, (wwmethod)->lasterrno = 0)
103 const char *pathname,
const char *temp_suffix)
111 temp_suffix ? temp_suffix :
"");
118 const char *temp_suffix,
size_t pad_to_size)
129 LZ4F_compressionContext_t ctx = NULL;
130 size_t lz4bufsize = 0;
137 snprintf(tmppath,
sizeof(tmppath),
"%s/%s",
157 gzfp = gzdopen(
fd,
"wb");
166 Z_DEFAULT_STRATEGY) != Z_OK)
179 LZ4F_preferences_t prefs;
181 ctx_out = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
182 if (LZ4F_isError(ctx_out))
189 lz4bufsize = LZ4F_compressBound(
LZ4_IN_SIZE, NULL);
193 memset(&prefs, 0,
sizeof(prefs));
197 header_size = LZ4F_compressBegin(ctx, lz4buf, lz4bufsize, &prefs);
198 if (LZ4F_isError(header_size))
201 (void) LZ4F_freeCompressionContext(ctx);
208 if (
write(
fd, lz4buf, header_size) != header_size)
211 wwmethod->
lasterrno = errno ? errno : ENOSPC;
212 (void) LZ4F_freeCompressionContext(ctx);
238 if (lseek(
fd, 0, SEEK_SET) != 0)
266 (void) LZ4F_compressEnd(ctx, lz4buf, lz4bufsize, NULL);
267 (void) LZ4F_freeCompressionContext(ctx);
288 f->lz4bufsize = lz4bufsize;
316 r = (ssize_t) gzwrite(df->gzfp,
buf, count);
330 const void *inbuf =
buf;
343 compressed = LZ4F_compressUpdate(df->ctx,
344 df->lz4buf, df->lz4bufsize,
348 if (LZ4F_isError(compressed))
355 if (
write(df->
fd, df->lz4buf, compressed) != compressed)
362 inbuf = ((
char *) inbuf) +
chunk;
400 r = gzclose(df->gzfp);
409 compressed = LZ4F_compressEnd(df->ctx,
410 df->lz4buf, df->lz4bufsize,
413 if (LZ4F_isError(compressed))
420 if (
write(df->
fd, df->lz4buf, compressed) != compressed)
447 snprintf(tmppath,
sizeof(tmppath),
"%s/%s",
453 snprintf(tmppath2,
sizeof(tmppath2),
"%s/%s",
460 if (rename(tmppath, tmppath2) != 0)
462 pg_log_error(
"could not rename file \"%s\" to \"%s\": %m",
475 snprintf(tmppath,
sizeof(tmppath),
"%s/%s",
502 LZ4F_freeCompressionContext(df->ctx);
529 f->wwmethod->lasterrno = errno;
541 compressed = LZ4F_flush(df->ctx, df->lz4buf, df->lz4bufsize, NULL);
542 if (LZ4F_isError(compressed))
549 if (
write(df->
fd, df->lz4buf, compressed) != compressed)
571 snprintf(tmppath,
sizeof(tmppath),
"%s/%s",
574 if (
stat(tmppath, &statbuf) != 0)
592 snprintf(tmppath,
sizeof(tmppath),
"%s/%s",
642 int compression_level,
bool sync)
655 return &wwmethod->
base;
665 const char *pathname,
666 const char *temp_suffix,
671 const char *pathname);
673 const char *pathname,
const char *temp_suffix);
713 tar_write_compressed_data(
TarMethodData *tar_data,
const void *
buf,
size_t count,
716 tar_data->zp->next_in =
buf;
717 tar_data->zp->avail_in = count;
719 while (tar_data->zp->avail_in || flush)
723 r = deflate(tar_data->zp, flush ? Z_FINISH : Z_NO_FLUSH);
724 if (r == Z_STREAM_ERROR)
742 tar_data->zp->next_out = tar_data->zlibOut;
746 if (r == Z_STREAM_END)
753 if (deflateReset(tar_data->zp) != Z_OK)
790 if (!tar_write_compressed_data(tar_data,
buf, count,
false))
808 size_t bytesleft = bytes;
810 memset(zerobuf.
data, 0, XLOG_BLCKSZ);
813 size_t bytestowrite =
Min(bytesleft, XLOG_BLCKSZ);
826 const char *temp_suffix)
831 pathname, temp_suffix ? temp_suffix :
"");
838 const char *temp_suffix,
size_t pad_to_size)
845 if (tar_data->
fd < 0)
853 if (tar_data->
fd < 0)
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;
875 Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK)
880 _(
"could not initialize compression library");
892 _(
"implementation error: tar files can't have more than one open file");
917 if (!tar_write_compressed_data(tar_data, NULL, 0,
true))
921 if (deflateParams(tar_data->zp, 0, Z_DEFAULT_STRATEGY) != Z_OK)
924 _(
"could not change compression parameters");
947 wwmethod->
lasterrno = errno ? errno : ENOSPC;
963 Z_DEFAULT_STRATEGY) != Z_OK)
965 wwmethod->
lasterrstring =
_(
"could not change compression parameters");
991 if (lseek(tar_data->
fd,
1083 if (tf->pad_to_size)
1091 size_t sizeleft = tf->
pad_to_size - tf->base.currpos;
1105 tf->base.currpos = tf->pad_to_size;
1119 if (
tar_write(f, zerobuf, padding) != padding)
1128 if (!tar_write_compressed_data(tar_data, NULL, 0,
true))
1150 if (lseek(tar_data->
fd, tf->ofs_start, SEEK_SET) != ((
TarMethodFile *) f)->ofs_start)
1169 if (deflateParams(tar_data->zp, 0, Z_DEFAULT_STRATEGY) != Z_OK)
1182 Z_DEFAULT_STRATEGY) != Z_OK)
1196 if (lseek(tar_data->
fd, 0, SEEK_END) < 0)
1206 pg_fatal(
"could not fsync file \"%s\": %s",
1230 char zerobuf[1024] = {0};
1244 if (
write(tar_data->
fd, zerobuf,
sizeof(zerobuf)) !=
sizeof(zerobuf))
1247 wwmethod->
lasterrno = errno ? errno : ENOSPC;
1254 if (!tar_write_compressed_data(tar_data, zerobuf,
sizeof(zerobuf),
1259 tar_data->zp->next_in = NULL;
1260 tar_data->zp->avail_in = 0;
1265 r = deflate(tar_data->zp, Z_FINISH);
1267 if (r == Z_STREAM_ERROR)
1283 wwmethod->
lasterrno = errno ? errno : ENOSPC;
1287 if (r == Z_STREAM_END)
1291 if (deflateEnd(tar_data->zp) != Z_OK)
1293 wwmethod->
lasterrstring =
_(
"could not close compression stream");
1357 int compression_level,
bool sync)
1379 return &wwmethod->
base;
#define Assert(condition)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
void fsync_fname(const char *fname, bool isdir)
static int fsync_parent_path(const char *fname, int elevel)
void * pg_malloc0(size_t size)
char * pg_strdup(const char *in)
void * pg_malloc(size_t size)
ssize_t pg_pwrite_zeros(int fd, size_t size, off_t offset)
#define pg_log_error(...)
static pg_compress_algorithm compression_algorithm
static size_t tarPaddingBytesRequired(size_t len)
int tarChecksum(char *header)
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)
void print_tar_number(char *s, int len, uint64 val)
size_t strlcpy(char *dst, const char *src, size_t siz)
static int fd(const char *x, int i)
TarMethodFile * currentfile
char header[TAR_BLOCK_SIZE]
Walfile *(* open_for_write)(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
const char * lasterrstring
const WalWriteMethodOps * ops
pg_compress_algorithm compression_algorithm
WalWriteMethod * wwmethod
static char * dir_get_file_name(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)
static Walfile * dir_open_for_write(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
WalWriteMethod * CreateWalDirectoryMethod(const char *basedir, pg_compress_algorithm compression_algorithm, int compression_level, bool sync)
struct DirectoryMethodData DirectoryMethodData
static Walfile * tar_open_for_write(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix, size_t pad_to_size)
static ssize_t tar_write(Walfile *f, const void *buf, size_t count)
static void tar_free(WalWriteMethod *wwmethod)
static const WalWriteMethodOps WalTarMethodOps
struct TarMethodData TarMethodData
WalWriteMethod * CreateWalTarMethod(const char *tarbase, pg_compress_algorithm compression_algorithm, int compression_level, bool sync)
static bool dir_finish(WalWriteMethod *wwmethod)
#define clear_error(wwmethod)
static const WalWriteMethodOps WalDirectoryMethodOps
const char * GetLastWalMethodError(WalWriteMethod *wwmethod)
struct DirectoryMethodFile DirectoryMethodFile
static void dir_free(WalWriteMethod *wwmethod)
static int dir_sync(Walfile *f)
static int tar_sync(Walfile *f)
static bool tar_finish(WalWriteMethod *wwmethod)
static int dir_close(Walfile *f, WalCloseMethod method)
static ssize_t dir_get_file_size(WalWriteMethod *wwmethod, const char *pathname)
static bool tar_existsfile(WalWriteMethod *wwmethod, const char *pathname)
static ssize_t tar_get_file_size(WalWriteMethod *wwmethod, const char *pathname)
struct TarMethodFile TarMethodFile
static bool dir_existsfile(WalWriteMethod *wwmethod, const char *pathname)
static int tar_close(Walfile *f, WalCloseMethod method)
static ssize_t dir_write(Walfile *f, const void *buf, size_t count)
static bool tar_write_padding_data(TarMethodFile *f, size_t bytes)
static char * tar_get_file_name(WalWriteMethod *wwmethod, const char *pathname, const char *temp_suffix)