1 /*-------------------------------------------------------------------------
2  *
3  * filemap.h
4  *
5  * Copyright (c) 2013-2021, PostgreSQL Global Development Group
6  *-------------------------------------------------------------------------
7  */
8 #ifndef FILEMAP_H
9 #define FILEMAP_H
10 
11 #include "datapagemap.h"
12 #include "storage/block.h"
13 #include "storage/relfilenode.h"
14 
15 /* these enum values are sorted in the order we want actions to be processed */
16 typedef enum
17 {
18 	FILE_ACTION_UNDECIDED = 0,	/* not decided yet */
19 
20 	FILE_ACTION_CREATE,			/* create local directory or symbolic link */
21 	FILE_ACTION_COPY,			/* copy whole file, overwriting if exists */
22 	FILE_ACTION_COPY_TAIL,		/* copy tail from 'source_size' to
23 								 * 'target_size' */
24 	FILE_ACTION_NONE,			/* no action (we might still copy modified
25 								 * blocks based on the parsed WAL) */
26 	FILE_ACTION_TRUNCATE,		/* truncate local file to 'newsize' bytes */
27 	FILE_ACTION_REMOVE			/* remove local file / directory / symlink */
28 } file_action_t;
29 
30 typedef enum
31 {
32 	FILE_TYPE_UNDEFINED = 0,
33 
34 	FILE_TYPE_REGULAR,
35 	FILE_TYPE_DIRECTORY,
36 	FILE_TYPE_SYMLINK
37 } file_type_t;
38 
39 /*
40  * For every file found in the local or remote system, we have a file entry
41  * that contains information about the file on both systems.  For relation
42  * files, there is also a page map that marks pages in the file that were
43  * changed in the target after the last common checkpoint.
44  *
45  * When gathering information, these are kept in a hash table, private to
46  * filemap.c.  decide_file_actions() fills in the 'action' field, sorts all
47  * the entries, and returns them in an array, ready for executing the actions.
48  */
49 typedef struct file_entry_t
50 {
51 	uint32		status;			/* hash status */
52 
53 	const char *path;
54 	bool		isrelfile;		/* is it a relation data file? */
55 
56 	/*
57 	 * Status of the file in the target.
58 	 */
59 	bool		target_exists;
60 	file_type_t target_type;
61 	size_t		target_size;	/* for a regular file */
62 	char	   *target_link_target; /* for a symlink */
63 
64 	/*
65 	 * Pages that were modified in the target and need to be replaced from the
66 	 * source.
67 	 */
68 	datapagemap_t target_pages_to_overwrite;
69 
70 	/*
71 	 * Status of the file in the source.
72 	 */
73 	bool		source_exists;
74 	file_type_t source_type;
75 	size_t		source_size;
76 	char	   *source_link_target; /* for a symlink */
77 
78 	/*
79 	 * What will we do to the file?
80 	 */
81 	file_action_t action;
82 } file_entry_t;
83 
84 /*
85  * This contains the final decisions on what to do with each file.
86  * 'entries' array contains an entry for each file, sorted in the order
87  * that their actions should executed.
88  */
89 typedef struct filemap_t
90 {
91 	/* Summary information, filled by calculate_totals() */
92 	uint64		total_size;		/* total size of the source cluster */
93 	uint64		fetch_size;		/* number of bytes that needs to be copied */
94 
95 	int			nentries;		/* size of 'entries' array */
96 	file_entry_t *entries[FLEXIBLE_ARRAY_MEMBER];
97 } filemap_t;
98 
99 /* Functions for populating the filemap */
100 extern void filehash_init(void);
101 extern void process_source_file(const char *path, file_type_t type,
102 								size_t size, const char *link_target);
103 extern void process_target_file(const char *path, file_type_t type,
104 								size_t size, const char *link_target);
105 extern void process_target_wal_block_change(ForkNumber forknum,
106 											RelFileNode rnode,
107 											BlockNumber blkno);
108 
109 extern filemap_t *decide_file_actions(void);
110 extern void calculate_totals(filemap_t *filemap);
111 extern void print_filemap(filemap_t *filemap);
112 
113 #endif							/* FILEMAP_H */
114