summaryrefslogtreecommitdiff
path: root/db/rep/rep_region.c
blob: 10a001b4bb62ae14309ea6ab62b1884f2edeea24 (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
212
213
214
215
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2001-2003
 *	Sleepycat Software.  All rights reserved.
 */
#include "db_config.h"

#ifndef lint
static const char revid[] = "$Id: rep_region.c,v 1.42 2003/09/04 18:06:49 bostic Exp $";
#endif /* not lint */

#ifndef NO_SYSTEM_INCLUDES
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif

#include <string.h>
#endif

#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/log.h"
#include "dbinc/db_am.h"

/*
 * __rep_region_init --
 *	Initialize the shared memory state for the replication system.
 *
 * PUBLIC: int __rep_region_init __P((DB_ENV *));
 */
int
__rep_region_init(dbenv)
	DB_ENV *dbenv;
{
	REGENV *renv;
	REGINFO *infop;
	DB_MUTEX *db_mutexp;
	DB_REP *db_rep;
	REP *rep;
	int ret;

	db_rep = dbenv->rep_handle;
	infop = dbenv->reginfo;
	renv = infop->primary;
	ret = 0;

	MUTEX_LOCK(dbenv, &renv->mutex);
	if (renv->rep_off == INVALID_ROFF) {
		/* Must create the region. */
		if ((ret = __db_shalloc(infop->addr,
		    sizeof(REP), MUTEX_ALIGN, &rep)) != 0)
			goto err;
		memset(rep, 0, sizeof(*rep));
		rep->tally_off = INVALID_ROFF;
		rep->v2tally_off = INVALID_ROFF;
		renv->rep_off = R_OFFSET(infop, rep);

		if ((ret = __db_mutex_setup(dbenv, infop, &rep->mutex,
		    MUTEX_NO_RECORD)) != 0)
			goto err;

		/*
		 * We must create a place for the db_mutex separately;
		 * mutexes have to be aligned to MUTEX_ALIGN, and the only way
		 * to guarantee that is to make sure they're at the beginning
		 * of a shalloc'ed chunk.
		 */
		if ((ret = __db_shalloc(infop->addr, sizeof(DB_MUTEX),
		    MUTEX_ALIGN, &db_mutexp)) != 0)
			goto err;
		rep->db_mutex_off = R_OFFSET(infop, db_mutexp);

		/*
		 * Because we have no way to prevent deadlocks and cannot log
		 * changes made to it, we single-thread access to the client
		 * bookkeeping database.  This is suboptimal, but it only gets
		 * accessed when messages arrive out-of-order, so it should
		 * stay small and not be used in a high-performance app.
		 */
		if ((ret = __db_mutex_setup(dbenv, infop, db_mutexp,
		    MUTEX_NO_RECORD)) != 0)
			goto err;

		/* We have the region; fill in the values. */
		rep->eid = DB_EID_INVALID;
		rep->master_id = DB_EID_INVALID;
		rep->gen = 0;
		rep->egen = rep->gen + 1;

		/*
		 * Set default values for the min and max log records that we
		 * wait before requesting a missing log record.
		 */
		rep->request_gap = DB_REP_REQUEST_GAP;
		rep->max_gap = DB_REP_MAX_GAP;
		F_SET(rep, REP_F_NOARCHIVE);
		(void)time(&rep->timestamp);
	} else
		rep = R_ADDR(infop, renv->rep_off);
	MUTEX_UNLOCK(dbenv, &renv->mutex);

	db_rep->rep_mutexp = &rep->mutex;
	db_rep->db_mutexp = R_ADDR(infop, rep->db_mutex_off);
	db_rep->region = rep;

	return (0);

err:	MUTEX_UNLOCK(dbenv, &renv->mutex);
	return (ret);
}

/*
 * __rep_region_destroy --
 *	Destroy any system resources allocated in the replication region.
 *
 * PUBLIC: int __rep_region_destroy __P((DB_ENV *));
 */
int
__rep_region_destroy(dbenv)
	DB_ENV *dbenv;
{
	DB_REP *db_rep;
	int ret, t_ret;

	ret = t_ret = 0;
	db_rep = dbenv->rep_handle;

	if (db_rep != NULL) {
		if (db_rep->rep_mutexp != NULL)
			ret = __db_mutex_destroy(db_rep->rep_mutexp);
		if (db_rep->db_mutexp != NULL)
			t_ret = __db_mutex_destroy(db_rep->db_mutexp);
	}

	return (ret == 0 ? t_ret : ret);
}

/*
 * __rep_dbenv_refresh --
 *	Replication-specific refresh of the DB_ENV structure.
 *
 * PUBLIC: void __rep_dbenv_refresh __P((DB_ENV *));
 */
void
__rep_dbenv_refresh(dbenv)
	DB_ENV *dbenv;
{
	if (REP_ON(dbenv))
		((DB_REP *)dbenv->rep_handle)->region = NULL;
	return;
}

/*
 * __rep_dbenv_close --
 *	Replication-specific destruction of the DB_ENV structure.
 *
 * PUBLIC: int __rep_dbenv_close __P((DB_ENV *));
 */
int
__rep_dbenv_close(dbenv)
	DB_ENV *dbenv;
{
	if (REP_ON(dbenv)) {
		__os_free(dbenv, dbenv->rep_handle);
		dbenv->rep_handle = NULL;
		dbenv->rep_send = NULL;
	}

	return (0);
}

/*
 * __rep_preclose --
 *	If we are a client, shut down our client database and, if we're
 * actually closing the environment, close all databases we've opened
 * while applying messages.
 *
 * PUBLIC: int __rep_preclose __P((DB_ENV *, int));
 */
int
__rep_preclose(dbenv, do_closefiles)
	DB_ENV *dbenv;
	int do_closefiles;
{
	DB *dbp;
	DB_REP *db_rep;
	int ret, t_ret;

	ret = t_ret = 0;

	/* If replication is not initialized, we have nothing to do. */
	if (!REP_ON(dbenv))
		return (0);

	db_rep = dbenv->rep_handle;
	if ((dbp = db_rep->rep_db) != NULL) {
		MUTEX_LOCK(dbenv, db_rep->db_mutexp);
		ret = __db_close(dbp, NULL, DB_NOSYNC);
		db_rep->rep_db = NULL;
		MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);
	}

	if (do_closefiles)
		t_ret = __dbreg_close_files(dbenv);

	return (ret == 0 ? t_ret : ret);
}