/***********************************************************************************************************************************
Archive Common
***********************************************************************************************************************************/
#ifndef COMMAND_ARCHIVE_COMMON_H
#define COMMAND_ARCHIVE_COMMON_H

#include <sys/types.h>

#include "common/type/stringId.h"

/***********************************************************************************************************************************
Archive mode enum

Used for functions that are common to both archive-push and archive-get so they can tailor their behavior to the command being run.
***********************************************************************************************************************************/
typedef enum
{
    archiveModeGet = STRID5("get", 0x50a70),
    archiveModePush = STRID5("push", 0x44eb00),
} ArchiveMode;

#include "common/compress/helper.h"
#include "common/type/stringList.h"
#include "storage/storage.h"

/***********************************************************************************************************************************
Status file extension constants
***********************************************************************************************************************************/
#define STATUS_EXT_ERROR                                            ".error"
#define STATUS_EXT_ERROR_SIZE                                       (sizeof(STATUS_EXT_ERROR) - 1)

#define STATUS_EXT_OK                                               ".ok"
#define STATUS_EXT_OK_SIZE                                          (sizeof(STATUS_EXT_OK) - 1)

/***********************************************************************************************************************************
WAL segment constants
***********************************************************************************************************************************/
// Extension for partial segments
#define WAL_SEGMENT_PARTIAL_EXT                                     ".partial"

// Match when the first 24 characters match a WAL segment
#define WAL_SEGMENT_PREFIX_REGEXP                                   "^[0-F]{24}"

// Match on a WAL segment without checksum appended
#define WAL_SEGMENT_REGEXP                                          WAL_SEGMENT_PREFIX_REGEXP "$"
STRING_DECLARE(WAL_SEGMENT_REGEXP_STR);

// Match on a WAL segment with partial allowed
#define WAL_SEGMENT_PARTIAL_REGEXP                                  WAL_SEGMENT_PREFIX_REGEXP "(\\.partial){0,1}$"
STRING_DECLARE(WAL_SEGMENT_PARTIAL_REGEXP_STR);

// Defines the size of standard WAL segment name -- hopefully this won't change
#define WAL_SEGMENT_NAME_SIZE                                       ((unsigned int)24)

// WAL segment directory/file
#define WAL_SEGMENT_DIR_REGEXP                                      "^[0-F]{16}$"
STRING_DECLARE(WAL_SEGMENT_DIR_REGEXP_STR);
#define WAL_SEGMENT_FILE_REGEXP                                     "^[0-F]{24}-[0-f]{40}" COMPRESS_TYPE_REGEXP "{0,1}$"
STRING_DECLARE(WAL_SEGMENT_FILE_REGEXP_STR);

// Timeline history file
#define WAL_TIMELINE_HISTORY_REGEXP                                 "^[0-F]{8}.history$"
STRING_DECLARE(WAL_TIMELINE_HISTORY_REGEXP_STR);

/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Remove errors for an archive file. This should be done before forking the async process to prevent a race condition where an old
// error may be reported rather than waiting for the async process to succeed or fail.
FN_EXTERN void archiveAsyncErrorClear(ArchiveMode archiveMode, const String *archiveFile);

// Check for ok/error status files in the spool in/out directory. throwOnError determines whether an error will be thrown when an
// error file is found. warnOnOk determines whether a warning will be output when found in an ok file.
FN_EXTERN bool archiveAsyncStatus(ArchiveMode archiveMode, const String *walSegment, bool throwOnError, bool warnOnOk);

// Write an ok status file
FN_EXTERN void archiveAsyncStatusOkWrite(ArchiveMode archiveMode, const String *walSegment, const String *warning);

// Write an error status file
FN_EXTERN void archiveAsyncStatusErrorWrite(ArchiveMode archiveMode, const String *walSegment, int code, const String *message);

// Execute the async process. This function will only return in the calling process and the implementation is platform dependent.
FN_EXTERN void archiveAsyncExec(ArchiveMode archiveMode, const StringList *commandExec);

// Comparator function for sorting archive ids by the database history id (the number after the dash) e.g. 9.6-1, 10-2
FN_EXTERN int archiveIdComparator(const void *item1, const void *item2);

// Is the segment partial?
FN_EXTERN bool walIsPartial(const String *walSegment);

// Is the file a segment or some other file (e.g. .history, .backup, etc)
FN_EXTERN bool walIsSegment(const String *walSegment);

// Generates the location of the wal directory using a relative wal path and the supplied pg path
FN_EXTERN String *walPath(const String *walFile, const String *pgPath, const String *command);

// Get the next WAL segment given a WAL segment and WAL segment size
FN_EXTERN String *walSegmentNext(const String *walSegment, size_t walSegmentSize, unsigned int pgVersion);

// Build a list of WAL segments based on a beginning WAL and number of WAL in the range (inclusive)
FN_EXTERN StringList *walSegmentRange(
    const String *walSegmentBegin, size_t walSegmentSize, unsigned int pgVersion, unsigned int range);

#endif
