summaryrefslogtreecommitdiffstats
path: root/src/pmdk/src/libpmempool/replica.h
blob: 06fa5b3f200a409c8dd9772bf8df9a0203f80383 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright 2016-2020, Intel Corporation */

/*
 * replica.h -- module for synchronizing and transforming poolset
 */
#ifndef REPLICA_H
#define REPLICA_H

#include "libpmempool.h"
#include "pool.h"
#include "badblocks.h"

#ifdef __cplusplus
extern "C" {
#endif

#define UNDEF_REPLICA UINT_MAX
#define UNDEF_PART UINT_MAX

/*
 * A part marked as broken does not exist or is damaged so that
 * it cannot be opened and has to be recreated.
 */
#define IS_BROKEN		(1U << 0)

/*
 * A replica marked as inconsistent exists but has inconsistent metadata
 * (e.g. inconsistent parts or replicas linkage)
 */
#define IS_INCONSISTENT		(1U << 1)

/*
 * A part or replica marked in this way has bad blocks inside.
 */
#define HAS_BAD_BLOCKS		(1U << 2)

/*
 * A part marked in this way has bad blocks in the header
 */
#define HAS_CORRUPTED_HEADER	(1U << 3)

/*
 * A flag which can be passed to sync_replica() to indicate that the function is
 * called by pmempool_transform
 */
#define IS_TRANSFORMED		(1U << 10)

/*
 * Number of lanes utilized when working with remote replicas
 */
#define REMOTE_NLANES	1

/*
 * Helping structures for storing part's health status
 */
struct part_health_status {
	unsigned flags;
	struct badblocks bbs;		/* structure with bad blocks */
	char *recovery_file_name;	/* name of bad block recovery file */
	int recovery_file_exists;	/* bad block recovery file exists */
};

/*
 * Helping structures for storing replica and poolset's health status
 */
struct replica_health_status {
	unsigned nparts;
	unsigned nhdrs;
	/* a flag for the replica */
	unsigned flags;
	/* effective size of a pool, valid only for healthy replica */
	size_t pool_size;
	/* flags for each part */
	struct part_health_status part[];
};

struct poolset_health_status {
	unsigned nreplicas;
	/* a flag for the poolset */
	unsigned flags;
	/* health statuses for each replica */
	struct replica_health_status *replica[];
};

/* get index of the (r)th replica health status */
static inline unsigned
REP_HEALTHidx(struct poolset_health_status *set, unsigned r)
{
	ASSERTne(set->nreplicas, 0);
	return (set->nreplicas + r) % set->nreplicas;
}

/* get index of the (r + 1)th replica health status */
static inline unsigned
REPN_HEALTHidx(struct poolset_health_status *set, unsigned r)
{
	ASSERTne(set->nreplicas, 0);
	return (set->nreplicas + r + 1) % set->nreplicas;
}

/* get (p)th part health status */
static inline unsigned
PART_HEALTHidx(struct replica_health_status *rep, unsigned p)
{
	ASSERTne(rep->nparts, 0);
	return (rep->nparts + p) % rep->nparts;
}

/* get (r)th replica health status */
static inline struct replica_health_status *
REP_HEALTH(struct poolset_health_status *set, unsigned r)
{
	return set->replica[REP_HEALTHidx(set, r)];
}

/* get (p)th part health status */
static inline unsigned
PART_HEALTH(struct replica_health_status *rep, unsigned p)
{
	return rep->part[PART_HEALTHidx(rep, p)].flags;
}

uint64_t replica_get_part_offset(struct pool_set *set,
		unsigned repn, unsigned partn);

void replica_align_badblock_offset_length(size_t *offset, size_t *length,
		struct pool_set *set_in, unsigned repn, unsigned partn);

size_t replica_get_part_data_len(struct pool_set *set_in, unsigned repn,
		unsigned partn);
uint64_t replica_get_part_data_offset(struct pool_set *set_in, unsigned repn,
		unsigned part);

/*
 * is_dry_run -- (internal) check whether only verification mode is enabled
 */
static inline bool
is_dry_run(unsigned flags)
{
	/*
	 * PMEMPOOL_SYNC_DRY_RUN and PMEMPOOL_TRANSFORM_DRY_RUN
	 * have to have the same value in order to use this common function.
	 */
	ASSERT_COMPILE_ERROR_ON(PMEMPOOL_SYNC_DRY_RUN !=
				PMEMPOOL_TRANSFORM_DRY_RUN);

	return flags & PMEMPOOL_SYNC_DRY_RUN;
}

/*
 * fix_bad_blocks -- (internal) fix bad blocks - it causes reading or creating
 *                              bad blocks recovery files
 *                              (depending on if they exist or not)
 */
static inline bool
fix_bad_blocks(unsigned flags)
{
	return flags & PMEMPOOL_SYNC_FIX_BAD_BLOCKS;
}

int replica_remove_all_recovery_files(struct poolset_health_status *set_hs);
int replica_remove_part(struct pool_set *set, unsigned repn, unsigned partn,
		int fix_bad_blocks);
int replica_create_poolset_health_status(struct pool_set *set,
		struct poolset_health_status **set_hsp);
void replica_free_poolset_health_status(struct poolset_health_status *set_s);
int replica_check_poolset_health(struct pool_set *set,
		struct poolset_health_status **set_hs,
		int called_from_sync, unsigned flags);
int replica_is_part_broken(unsigned repn, unsigned partn,
		struct poolset_health_status *set_hs);
int replica_has_bad_blocks(unsigned repn, struct poolset_health_status *set_hs);
int replica_part_has_bad_blocks(struct part_health_status *phs);
int replica_part_has_corrupted_header(unsigned repn, unsigned partn,
				struct poolset_health_status *set_hs);
unsigned replica_find_unbroken_part(unsigned repn,
		struct poolset_health_status *set_hs);
int replica_is_replica_broken(unsigned repn,
		struct poolset_health_status *set_hs);
int replica_is_replica_consistent(unsigned repn,
		struct poolset_health_status *set_hs);
int replica_is_replica_healthy(unsigned repn,
		struct poolset_health_status *set_hs);

unsigned replica_find_healthy_replica(
		struct poolset_health_status *set_hs);
unsigned replica_find_replica_healthy_header(
		struct poolset_health_status *set_hs);

int replica_is_poolset_healthy(struct poolset_health_status *set_hs);
int replica_is_poolset_transformed(unsigned flags);
ssize_t replica_get_pool_size(struct pool_set *set, unsigned repn);
int replica_check_part_sizes(struct pool_set *set, size_t min_size);
int replica_check_part_dirs(struct pool_set *set);
int replica_check_local_part_dir(struct pool_set *set, unsigned repn,
		unsigned partn);

int replica_open_replica_part_files(struct pool_set *set, unsigned repn);
int replica_open_poolset_part_files(struct pool_set *set);

int replica_sync(struct pool_set *set_in, struct poolset_health_status *set_hs,
		unsigned flags);
int replica_transform(struct pool_set *set_in, struct pool_set *set_out,
		unsigned flags);

#ifdef __cplusplus
}
#endif

#endif