*
* appender.h: File appender used by Backup/Restore manager.
*
* Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
* Portions Copyright (c) 2009-2013, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
* Portions Copyright (c) 2015-2018, Postgres Professional
*
*-------------------------------------------------------------------------
*/
#ifndef FILE_APPEND_H
#define FILE_APPEND_H
#include "../../pg_probackup.h"
#include "buffer.h"
typedef struct FileAppenderSegHeader
{
FILE_APPEND_SEG_TYPE type;
uint32 size;
uint32 permission;
off_t filesize;
pg_crc32 crc;
int external_dir_num;
device_type_t file_type;
} FileAppenderSegHeader;
typedef struct ParallelFileAppenderSegHeader
{
FILE_APPEND_SEG_TYPE type;
uint32 size;
uint32 permission;
off_t filesize;
pg_crc32 crc;
int external_dir_num;
device_type_t file_type;
short threadId;
} ParallelFileAppenderSegHeader;
#define SEG_HEADER_DEFAULT_VERSION 0
#define SEG_HEADER_PARALLEL_VERSION 1
#define SEG_HEADER_VERSION_MAX 2
#define SEG_HEADER_VERSION_OFFSET 16
#define SEG_HEADER_VERSION_MASK (0xFFFF0000)
#define SEG_HEADER_TYPE_MASK (0xFFFF)
inline uint32 getSegHeaderSize(uint32 version)
{
switch (version) {
case SEG_HEADER_DEFAULT_VERSION:
return sizeof(FileAppenderSegHeader);
case SEG_HEADER_PARALLEL_VERSION:
return sizeof(ParallelFileAppenderSegHeader);
default:
break;
}
Assert(false);
return -1;
}
inline uint32 getSegHeaderVersion(void *header)
{
uint32 version = (uint32)((*(uint32*)header) >> SEG_HEADER_VERSION_OFFSET);
Assert(version < SEG_HEADER_VERSION_MAX);
return version;
}
inline NO_VERSION_SEG_TYPE GetSegHeaderType(void* header)
{
NO_VERSION_SEG_TYPE type = (NO_VERSION_SEG_TYPE)(((FileAppenderSegHeader *)header)->type & SEG_HEADER_TYPE_MASK);
Assert(type < FILE_APPEND_TYPE_MAX);
return type;
}
inline void setSegHeaderVersion(void* header, uint32 version)
{
Assert(version < SEG_HEADER_VERSION_MAX);
((FileAppenderSegHeader *)header)->type = (FILE_APPEND_SEG_TYPE)((((FileAppenderSegHeader *)header)->type &
SEG_HEADER_TYPE_MASK) + (version << SEG_HEADER_VERSION_OFFSET));
}
inline void SetSegHeaderType(void* header, NO_VERSION_SEG_TYPE type)
{
Assert(type < FILE_APPEND_TYPE_MAX);
((FileAppenderSegHeader *)header)->type =
(FILE_APPEND_SEG_TYPE)((((FileAppenderSegHeader *)header)->type & SEG_HEADER_VERSION_MASK) + type);
}
#define MAX_BACKUP_THREAD 11
typedef struct FileAppenderSegDescriptor
{
char* header;
char* payload;
int header_offset;
int payload_offset;
FILE* outputFile[MAX_BACKUP_THREAD];
pgFile* inputFile[MAX_BACKUP_THREAD];
pg_crc32 crc[MAX_BACKUP_THREAD];
uint32 version;
} FileAppenderSegDescriptor;
#define READ_BUFFER_BLOCK_COUNT 2
#define APPEND_FILENAME_END_SIZE 10
#define APPEND_FILENAME_END_DIGIT 6
constexpr int APPEND_FILE_MAX_SIZE = 1073741824;
#define APPEND_FILE_HEADER_SIZE (sizeof(FileAppenderSegHeader))
#define PARALLEL_APPEND_FILE_HEADER_SIZE (sizeof(ParallelFileAppenderSegHeader))
#define SEG_HEADER_MAX_SIZE (PARALLEL_APPEND_FILE_HEADER_SIZE)
extern void initFileAppender(FileAppender* appender, FILE_APPEND_SEG_TYPE type, uint32 minFileNo, uint32 maxFileNo);
extern void initSegDescriptor(FileAppenderSegDescriptor** segDesc);
extern void getSegDescriptor(FileAppenderSegDescriptor* desc, char** buffOffset, size_t* remainBuffLen,
BufferCxt* cxt, uint32 headerVersion, size_t segHdrLen);
extern void parseSegDescriptor(FileAppenderSegDescriptor* segDesc, char** buffOffset, size_t* remainBuffLen, char* tempBuffer,
BufferCxt* cxt, pgBackup* dest_backup,
bool isValidate = false, validate_files_arg* arg = NULL);
extern void destorySegDescriptor(FileAppenderSegDescriptor** descriptor);
extern void closeFileAppender(FileAppender* retAppender);
extern void destoryFileAppender(FileAppender** retAppender);
extern char* getAppendFileName(const char* baseFileName, uint32 fileNo);
extern void constructHeader(FileAppenderSegHeader* header, FILE_APPEND_SEG_TYPE type,
uint32 size, off_t filesize, pgFile* file);
extern void constructParallelHeader(ParallelFileAppenderSegHeader* header, FILE_APPEND_SEG_TYPE type,
uint32 size, off_t filesize, pgFile* file, short readerIndexId = 0);
extern void WriteHeader(ParallelFileAppenderSegHeader* header, FileAppender* appender);
extern size_t writeToCompFile(const char* data, size_t len, void* file);
extern void WriteDataBlock(ParallelFileAppenderSegHeader* header, const char* payload,
size_t payloadSize, FileAppender* appender);
#endif