mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Fix multiple bugs and infelicities in pg_rewind.
Bugs all spotted by Coverity, including wrong realloc() size request and memory leaks. Cosmetic improvements by me. The usage of the global variable "filemap" here is still pretty awful, but at least I got rid of the gratuitous aliasing in several routines (which was helping to annoy Coverity, as well as being a bug risk).
This commit is contained in:
parent
e4cbfd673d
commit
c67f366fa9
@ -30,12 +30,12 @@ static char *datasegpath(RelFileNode rnode, ForkNumber forknum,
|
|||||||
BlockNumber segno);
|
BlockNumber segno);
|
||||||
static int path_cmp(const void *a, const void *b);
|
static int path_cmp(const void *a, const void *b);
|
||||||
static int final_filemap_cmp(const void *a, const void *b);
|
static int final_filemap_cmp(const void *a, const void *b);
|
||||||
static void filemap_list_to_array(void);
|
static void filemap_list_to_array(filemap_t *map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new file map.
|
* Create a new file map (stored in the global pointer "filemap").
|
||||||
*/
|
*/
|
||||||
filemap_t *
|
void
|
||||||
filemap_create(void)
|
filemap_create(void)
|
||||||
{
|
{
|
||||||
filemap_t *map;
|
filemap_t *map;
|
||||||
@ -48,8 +48,6 @@ filemap_create(void)
|
|||||||
|
|
||||||
Assert(filemap == NULL);
|
Assert(filemap == NULL);
|
||||||
filemap = map;
|
filemap = map;
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -271,7 +269,10 @@ process_local_file(const char *path, file_type_t type, size_t oldsize,
|
|||||||
pg_fatal("remote file list is empty\n");
|
pg_fatal("remote file list is empty\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
filemap_list_to_array();
|
filemap_list_to_array(map);
|
||||||
|
|
||||||
|
Assert(map->array != NULL);
|
||||||
|
|
||||||
qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
|
qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,8 +285,8 @@ process_local_file(const char *path, file_type_t type, size_t oldsize,
|
|||||||
|
|
||||||
key.path = (char *) path;
|
key.path = (char *) path;
|
||||||
key_ptr = &key;
|
key_ptr = &key;
|
||||||
exists = bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
|
exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
|
||||||
path_cmp) != NULL;
|
path_cmp) != NULL);
|
||||||
|
|
||||||
/* Remove any file or folder that doesn't exist in the remote system. */
|
/* Remove any file or folder that doesn't exist in the remote system. */
|
||||||
if (!exists)
|
if (!exists)
|
||||||
@ -335,7 +336,7 @@ process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
|
|||||||
filemap_t *map = filemap;
|
filemap_t *map = filemap;
|
||||||
file_entry_t **e;
|
file_entry_t **e;
|
||||||
|
|
||||||
Assert(filemap->array);
|
Assert(map->array);
|
||||||
|
|
||||||
segno = blkno / RELSEG_SIZE;
|
segno = blkno / RELSEG_SIZE;
|
||||||
blkno_inseg = blkno % RELSEG_SIZE;
|
blkno_inseg = blkno % RELSEG_SIZE;
|
||||||
@ -395,38 +396,40 @@ process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the linked list of entries in filemap->first/last to the array,
|
* Convert the linked list of entries in map->first/last to the array,
|
||||||
* filemap->array.
|
* map->array.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
filemap_list_to_array(void)
|
filemap_list_to_array(filemap_t *map)
|
||||||
{
|
{
|
||||||
int narray;
|
int narray;
|
||||||
file_entry_t *entry,
|
file_entry_t *entry,
|
||||||
*next;
|
*next;
|
||||||
|
|
||||||
filemap->array =
|
map->array = (file_entry_t **)
|
||||||
pg_realloc(filemap->array,
|
pg_realloc(map->array,
|
||||||
(filemap->nlist + filemap->narray) * sizeof(file_entry_t));
|
(map->nlist + map->narray) * sizeof(file_entry_t *));
|
||||||
|
|
||||||
narray = filemap->narray;
|
narray = map->narray;
|
||||||
for (entry = filemap->first; entry != NULL; entry = next)
|
for (entry = map->first; entry != NULL; entry = next)
|
||||||
{
|
{
|
||||||
filemap->array[narray++] = entry;
|
map->array[narray++] = entry;
|
||||||
next = entry->next;
|
next = entry->next;
|
||||||
entry->next = NULL;
|
entry->next = NULL;
|
||||||
}
|
}
|
||||||
Assert(narray == filemap->nlist + filemap->narray);
|
Assert(narray == map->nlist + map->narray);
|
||||||
filemap->narray = narray;
|
map->narray = narray;
|
||||||
filemap->nlist = 0;
|
map->nlist = 0;
|
||||||
filemap->first = filemap->last = NULL;
|
map->first = map->last = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
filemap_finalize(void)
|
filemap_finalize(void)
|
||||||
{
|
{
|
||||||
filemap_list_to_array();
|
filemap_t *map = filemap;
|
||||||
qsort(filemap->array, filemap->narray, sizeof(file_entry_t *),
|
|
||||||
|
filemap_list_to_array(map);
|
||||||
|
qsort(map->array, map->narray, sizeof(file_entry_t *),
|
||||||
final_filemap_cmp);
|
final_filemap_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,9 +469,9 @@ calculate_totals(void)
|
|||||||
map->total_size = 0;
|
map->total_size = 0;
|
||||||
map->fetch_size = 0;
|
map->fetch_size = 0;
|
||||||
|
|
||||||
for (i = 0; i < filemap->narray; i++)
|
for (i = 0; i < map->narray; i++)
|
||||||
{
|
{
|
||||||
entry = filemap->array[i];
|
entry = map->array[i];
|
||||||
|
|
||||||
if (entry->type != FILE_TYPE_REGULAR)
|
if (entry->type != FILE_TYPE_REGULAR)
|
||||||
continue;
|
continue;
|
||||||
@ -501,12 +504,13 @@ calculate_totals(void)
|
|||||||
void
|
void
|
||||||
print_filemap(void)
|
print_filemap(void)
|
||||||
{
|
{
|
||||||
|
filemap_t *map = filemap;
|
||||||
file_entry_t *entry;
|
file_entry_t *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < filemap->narray; i++)
|
for (i = 0; i < map->narray; i++)
|
||||||
{
|
{
|
||||||
entry = filemap->array[i];
|
entry = map->array[i];
|
||||||
if (entry->action != FILE_ACTION_NONE ||
|
if (entry->action != FILE_ACTION_NONE ||
|
||||||
entry->pagemap.bitmapsize > 0)
|
entry->pagemap.bitmapsize > 0)
|
||||||
{
|
{
|
||||||
|
@ -29,8 +29,7 @@ typedef enum
|
|||||||
FILE_ACTION_NONE, /* no action (we might still copy modified blocks
|
FILE_ACTION_NONE, /* no action (we might still copy modified blocks
|
||||||
* based on the parsed WAL) */
|
* based on the parsed WAL) */
|
||||||
FILE_ACTION_TRUNCATE, /* truncate local file to 'newsize' bytes */
|
FILE_ACTION_TRUNCATE, /* truncate local file to 'newsize' bytes */
|
||||||
FILE_ACTION_REMOVE, /* remove local file / directory / symlink */
|
FILE_ACTION_REMOVE /* remove local file / directory / symlink */
|
||||||
|
|
||||||
} file_action_t;
|
} file_action_t;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -40,7 +39,7 @@ typedef enum
|
|||||||
FILE_TYPE_SYMLINK
|
FILE_TYPE_SYMLINK
|
||||||
} file_type_t;
|
} file_type_t;
|
||||||
|
|
||||||
struct file_entry_t
|
typedef struct file_entry_t
|
||||||
{
|
{
|
||||||
char *path;
|
char *path;
|
||||||
file_type_t type;
|
file_type_t type;
|
||||||
@ -58,11 +57,9 @@ struct file_entry_t
|
|||||||
char *link_target;
|
char *link_target;
|
||||||
|
|
||||||
struct file_entry_t *next;
|
struct file_entry_t *next;
|
||||||
};
|
} file_entry_t;
|
||||||
|
|
||||||
typedef struct file_entry_t file_entry_t;
|
typedef struct filemap_t
|
||||||
|
|
||||||
struct filemap_t
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* New entries are accumulated to a linked list, in process_remote_file
|
* New entries are accumulated to a linked list, in process_remote_file
|
||||||
@ -70,7 +67,7 @@ struct filemap_t
|
|||||||
*/
|
*/
|
||||||
file_entry_t *first;
|
file_entry_t *first;
|
||||||
file_entry_t *last;
|
file_entry_t *last;
|
||||||
int nlist;
|
int nlist; /* number of entries currently in list */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After processing all the remote files, the entries in the linked list
|
* After processing all the remote files, the entries in the linked list
|
||||||
@ -80,7 +77,7 @@ struct filemap_t
|
|||||||
* the array, and the linked list is empty.
|
* the array, and the linked list is empty.
|
||||||
*/
|
*/
|
||||||
file_entry_t **array;
|
file_entry_t **array;
|
||||||
int narray;
|
int narray; /* current length of array */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Summary information. total_size is the total size of the source cluster,
|
* Summary information. total_size is the total size of the source cluster,
|
||||||
@ -88,14 +85,11 @@ struct filemap_t
|
|||||||
*/
|
*/
|
||||||
uint64 total_size;
|
uint64 total_size;
|
||||||
uint64 fetch_size;
|
uint64 fetch_size;
|
||||||
};
|
} filemap_t;
|
||||||
|
|
||||||
typedef struct filemap_t filemap_t;
|
extern filemap_t *filemap;
|
||||||
|
|
||||||
extern filemap_t * filemap;
|
|
||||||
|
|
||||||
extern filemap_t *filemap_create(void);
|
|
||||||
|
|
||||||
|
extern void filemap_create(void);
|
||||||
extern void calculate_totals(void);
|
extern void calculate_totals(void);
|
||||||
extern void print_filemap(void);
|
extern void print_filemap(void);
|
||||||
|
|
||||||
|
@ -285,6 +285,10 @@ receiveFileChunks(const char *sql)
|
|||||||
open_target_file(filename, false);
|
open_target_file(filename, false);
|
||||||
|
|
||||||
write_target_range(chunk, chunkoff, chunksize);
|
write_target_range(chunk, chunkoff, chunksize);
|
||||||
|
|
||||||
|
pg_free(filename);
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Build the filemap, by comparing the remote and local data directories.
|
* Build the filemap, by comparing the remote and local data directories.
|
||||||
*/
|
*/
|
||||||
(void) filemap_create();
|
filemap_create();
|
||||||
pg_log(PG_PROGRESS, "reading source file list\n");
|
pg_log(PG_PROGRESS, "reading source file list\n");
|
||||||
fetchRemoteFileList();
|
fetchRemoteFileList();
|
||||||
pg_log(PG_PROGRESS, "reading target file list\n");
|
pg_log(PG_PROGRESS, "reading target file list\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user