Commit f81e97d0 authored by Heikki Linnakangas's avatar Heikki Linnakangas

pg_rewind: Replace the hybrid list+array data structure with simplehash.

Now that simplehash can be used in frontend code, let's make use of it.

Reviewed-by: Kyotaro Horiguchi, Soumyadeep Chakraborty
Discussion: https://www.postgresql.org/message-id/0c5b3783-af52-3ee5-f8fa-6e794061f70d%40iki.fi
parent eb00f1d4
...@@ -207,9 +207,9 @@ copy_executeFileMap(filemap_t *map) ...@@ -207,9 +207,9 @@ copy_executeFileMap(filemap_t *map)
file_entry_t *entry; file_entry_t *entry;
int i; int i;
for (i = 0; i < map->narray; i++) for (i = 0; i < map->nentries; i++)
{ {
entry = map->array[i]; entry = map->entries[i];
execute_pagemap(&entry->target_pages_to_overwrite, entry->path); execute_pagemap(&entry->target_pages_to_overwrite, entry->path);
switch (entry->action) switch (entry->action)
......
...@@ -37,7 +37,7 @@ fetchSourceFileList(void) ...@@ -37,7 +37,7 @@ fetchSourceFileList(void)
* Fetch all relation data files that are marked in the given data page map. * Fetch all relation data files that are marked in the given data page map.
*/ */
void void
executeFileMap(void) execute_file_actions(filemap_t *filemap)
{ {
if (datadir_source) if (datadir_source)
copy_executeFileMap(filemap); copy_executeFileMap(filemap);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
*/ */
extern void fetchSourceFileList(void); extern void fetchSourceFileList(void);
extern char *fetchFile(const char *filename, size_t *filesize); extern char *fetchFile(const char *filename, size_t *filesize);
extern void executeFileMap(void); extern void execute_file_actions(filemap_t *filemap);
/* in libpq_fetch.c */ /* in libpq_fetch.c */
extern void libpqProcessFileList(void); extern void libpqProcessFileList(void);
......
This diff is collapsed.
...@@ -12,15 +12,6 @@ ...@@ -12,15 +12,6 @@
#include "storage/block.h" #include "storage/block.h"
#include "storage/relfilenode.h" #include "storage/relfilenode.h"
/*
* For every file found in the local or remote system, we have a file entry
* that contains information about the file on both systems. For relation
* files, there is also a page map that marks pages in the file that were
* changed in the target after the last common checkpoint. Each entry also
* contains an 'action' field, which says what we are going to do with the
* file.
*/
/* these enum values are sorted in the order we want actions to be processed */ /* these enum values are sorted in the order we want actions to be processed */
typedef enum typedef enum
{ {
...@@ -45,9 +36,21 @@ typedef enum ...@@ -45,9 +36,21 @@ typedef enum
FILE_TYPE_SYMLINK FILE_TYPE_SYMLINK
} file_type_t; } file_type_t;
/*
* For every file found in the local or remote system, we have a file entry
* that contains information about the file on both systems. For relation
* files, there is also a page map that marks pages in the file that were
* changed in the target after the last common checkpoint.
*
* When gathering information, these are kept in a hash table, private to
* filemap.c. decide_file_actions() fills in the 'action' field, sorts all
* the entries, and returns them in an array, ready for executing the actions.
*/
typedef struct file_entry_t typedef struct file_entry_t
{ {
char *path; uint32 status; /* hash status */
const char *path;
bool isrelfile; /* is it a relation data file? */ bool isrelfile; /* is it a relation data file? */
/* /*
...@@ -76,44 +79,25 @@ typedef struct file_entry_t ...@@ -76,44 +79,25 @@ typedef struct file_entry_t
* What will we do to the file? * What will we do to the file?
*/ */
file_action_t action; file_action_t action;
struct file_entry_t *next;
} file_entry_t; } file_entry_t;
/*
* This contains the final decisions on what to do with each file.
* 'entries' array contains an entry for each file, sorted in the order
* that their actions should executed.
*/
typedef struct filemap_t typedef struct filemap_t
{ {
/* /* Summary information, filled by calculate_totals() */
* New entries are accumulated to a linked list, in process_source_file
* and process_target_file.
*/
file_entry_t *first;
file_entry_t *last;
int nlist; /* number of entries currently in list */
/*
* After processing all the remote files, the entries in the linked list
* are moved to this array. After processing local files, too, all the
* local entries are added to the array by decide_file_actions(), and
* sorted in the final order. After decide_file_actions(), all the entries
* are in the array, and the linked list is empty.
*/
file_entry_t **array;
int narray; /* current length of array */
/*
* Summary information.
*/
uint64 total_size; /* total size of the source cluster */ uint64 total_size; /* total size of the source cluster */
uint64 fetch_size; /* number of bytes that needs to be copied */ uint64 fetch_size; /* number of bytes that needs to be copied */
} filemap_t;
extern filemap_t *filemap; int nentries; /* size of 'entries' array */
file_entry_t *entries[FLEXIBLE_ARRAY_MEMBER];
extern void filemap_create(void); } filemap_t;
extern void calculate_totals(void);
extern void print_filemap(void);
/* Functions for populating the filemap */ /* Functions for populating the filemap */
extern void filehash_init(void);
extern void process_source_file(const char *path, file_type_t type, extern void process_source_file(const char *path, file_type_t type,
size_t size, const char *link_target); size_t size, const char *link_target);
extern void process_target_file(const char *path, file_type_t type, extern void process_target_file(const char *path, file_type_t type,
...@@ -121,6 +105,9 @@ extern void process_target_file(const char *path, file_type_t type, ...@@ -121,6 +105,9 @@ extern void process_target_file(const char *path, file_type_t type,
extern void process_target_wal_block_change(ForkNumber forknum, extern void process_target_wal_block_change(ForkNumber forknum,
RelFileNode rnode, RelFileNode rnode,
BlockNumber blkno); BlockNumber blkno);
extern void decide_file_actions(void);
extern filemap_t *decide_file_actions(void);
extern void calculate_totals(filemap_t *filemap);
extern void print_filemap(filemap_t *filemap);
#endif /* FILEMAP_H */ #endif /* FILEMAP_H */
...@@ -460,9 +460,9 @@ libpq_executeFileMap(filemap_t *map) ...@@ -460,9 +460,9 @@ libpq_executeFileMap(filemap_t *map)
PQresultErrorMessage(res)); PQresultErrorMessage(res));
PQclear(res); PQclear(res);
for (i = 0; i < map->narray; i++) for (i = 0; i < map->nentries; i++)
{ {
entry = map->array[i]; entry = map->entries[i];
/* If this is a relation file, copy the modified blocks */ /* If this is a relation file, copy the modified blocks */
execute_pagemap(&entry->target_pages_to_overwrite, entry->path); execute_pagemap(&entry->target_pages_to_overwrite, entry->path);
......
...@@ -129,6 +129,7 @@ main(int argc, char **argv) ...@@ -129,6 +129,7 @@ main(int argc, char **argv)
TimeLineID endtli; TimeLineID endtli;
ControlFileData ControlFile_new; ControlFileData ControlFile_new;
bool writerecoveryconf = false; bool writerecoveryconf = false;
filemap_t *filemap;
pg_logging_init(argv[0]); pg_logging_init(argv[0]);
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_rewind")); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_rewind"));
...@@ -368,13 +369,16 @@ main(int argc, char **argv) ...@@ -368,13 +369,16 @@ main(int argc, char **argv)
(uint32) (chkptrec >> 32), (uint32) chkptrec, (uint32) (chkptrec >> 32), (uint32) chkptrec,
chkpttli); chkpttli);
/* Initialize the hash table to track the status of each file */
filehash_init();
/* /*
* Collect information about all files in the target and source systems. * Collect information about all files in the target and source systems.
*/ */
filemap_create();
if (showprogress) if (showprogress)
pg_log_info("reading source file list"); pg_log_info("reading source file list");
fetchSourceFileList(); fetchSourceFileList();
if (showprogress) if (showprogress)
pg_log_info("reading target file list"); pg_log_info("reading target file list");
traverse_datadir(datadir_target, &process_target_file); traverse_datadir(datadir_target, &process_target_file);
...@@ -395,13 +399,13 @@ main(int argc, char **argv) ...@@ -395,13 +399,13 @@ main(int argc, char **argv)
* We have collected all information we need from both systems. Decide * We have collected all information we need from both systems. Decide
* what to do with each file. * what to do with each file.
*/ */
decide_file_actions(); filemap = decide_file_actions();
if (showprogress) if (showprogress)
calculate_totals(); calculate_totals(filemap);
/* this is too verbose even for verbose mode */ /* this is too verbose even for verbose mode */
if (debug) if (debug)
print_filemap(); print_filemap(filemap);
/* /*
* Ok, we're ready to start copying things over. * Ok, we're ready to start copying things over.
...@@ -421,7 +425,7 @@ main(int argc, char **argv) ...@@ -421,7 +425,7 @@ main(int argc, char **argv)
* modified the target directory and there is no turning back! * modified the target directory and there is no turning back!
*/ */
executeFileMap(); execute_file_actions(filemap);
progress_report(true); progress_report(true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment