summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-bdb/back-bdb.h
blob: ea68ebb052c0683c726c4a7f34cfab85232ccdaf (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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
/* back-bdb.h - bdb back-end header file */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
 * Copyright 2000-2021 The OpenLDAP Foundation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#ifndef _BACK_BDB_H_
#define _BACK_BDB_H_

#include <portable.h>
#include "slap.h"
#include <db.h>
#include "alock.h"

LDAP_BEGIN_DECL

#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)

#define DN_BASE_PREFIX		SLAP_INDEX_EQUALITY_PREFIX
#define DN_ONE_PREFIX	 	'%'
#define DN_SUBTREE_PREFIX 	'@'

#define DBTzero(t)			(memset((t), 0, sizeof(DBT)))
#define DBT2bv(t,bv)		((bv)->bv_val = (t)->data, \
								(bv)->bv_len = (t)->size)
#define bv2DBT(bv,t)		((t)->data = (bv)->bv_val, \
								(t)->size = (bv)->bv_len )

#define BDB_TXN_RETRIES		16

#define BDB_MAX_ADD_LOOP	30

#define BDB_SUFFIX		".bdb"
#define BDB_ID2ENTRY	0
#define BDB_DN2ID		1
#define BDB_NDB			2

/* The bdb on-disk entry format is pretty space-inefficient. Average
 * sized user entries are 3-4K each. You need at least two entries to
 * fit into a single database page, more is better. 64K is BDB's
 * upper bound. Smaller pages are better for concurrency.
 */
#ifndef BDB_ID2ENTRY_PAGESIZE
#define	BDB_ID2ENTRY_PAGESIZE	16384
#endif

#define DEFAULT_CACHE_SIZE     1000

/* The default search IDL stack cache depth */
#define DEFAULT_SEARCH_STACK_DEPTH	16

/* The minimum we can function with */
#define MINIMUM_SEARCH_STACK_DEPTH	8

typedef struct bdb_idl_cache_entry_s {
	struct berval kstr;
	ID      *idl;
	DB      *db;
	int		idl_flags;
	struct bdb_idl_cache_entry_s* idl_lru_prev;
	struct bdb_idl_cache_entry_s* idl_lru_next;
} bdb_idl_cache_entry_t;

/* BDB backend specific entry info */
typedef struct bdb_entry_info {
	struct bdb_entry_info *bei_parent;
	ID bei_id;

	/* we use the bei_id as a lockobj, but we need to make the size != 4
	 * to avoid conflicting with BDB's internal locks. So add a byte here
	 * that is always zero.
	 */
	short bei_lockpad;

	short bei_state;
#define	CACHE_ENTRY_DELETED	1
#define	CACHE_ENTRY_NO_KIDS	2
#define	CACHE_ENTRY_NOT_LINKED	4
#define CACHE_ENTRY_NO_GRANDKIDS	8
#define	CACHE_ENTRY_LOADING	0x10
#define	CACHE_ENTRY_WALKING	0x20
#define	CACHE_ENTRY_ONELEVEL	0x40
#define	CACHE_ENTRY_REFERENCED	0x80
#define	CACHE_ENTRY_NOT_CACHED	0x100
	int bei_finders;

	/*
	 * remaining fields require backend cache lock to access
	 */
	struct berval bei_nrdn;
#ifdef BDB_HIER
	struct berval bei_rdn;
	int	bei_modrdns;	/* track renames */
	int	bei_ckids;	/* number of kids cached */
	int	bei_dkids;	/* number of kids on-disk, plus 1 */
#endif
	Entry	*bei_e;
	Avlnode	*bei_kids;
#ifdef SLAP_ZONE_ALLOC
	struct bdb_info *bei_bdb;
	int bei_zseq;	
#endif
	ldap_pvt_thread_mutex_t	bei_kids_mutex;
	
	struct bdb_entry_info	*bei_lrunext;	/* for cache lru list */
	struct bdb_entry_info	*bei_lruprev;
} EntryInfo;
#undef BEI
#define BEI(e)	((EntryInfo *) ((e)->e_private))

/* for the in-core cache of entries */
typedef struct bdb_cache {
	EntryInfo	*c_eifree;	/* free list */
	Avlnode		*c_idtree;
	EntryInfo	*c_lruhead;	/* lru - add accessed entries here */
	EntryInfo	*c_lrutail;	/* lru - rem lru entries from here */
	EntryInfo	c_dntree;
	ID		c_maxsize;
	ID		c_cursize;
	ID		c_minfree;
	ID		c_eimax;
	ID		c_eiused;	/* EntryInfo's in use */
	ID		c_leaves;	/* EntryInfo leaf nodes */
	int		c_purging;
	DB_TXN	*c_txn;	/* used by lru cleaner */
	ldap_pvt_thread_rdwr_t c_rwlock;
	ldap_pvt_thread_mutex_t c_lru_mutex;
	ldap_pvt_thread_mutex_t c_count_mutex;
	ldap_pvt_thread_mutex_t c_eifree_mutex;
#ifdef SLAP_ZONE_ALLOC
	void *c_zctx;
#endif
} Cache;
 
#define CACHE_READ_LOCK                0
#define CACHE_WRITE_LOCK       1
 
#define BDB_INDICES		128

struct bdb_db_info {
	struct berval	bdi_name;
	DB			*bdi_db;
};

struct bdb_db_pgsize {
	struct bdb_db_pgsize *bdp_next;
	struct berval	bdp_name;
	int	bdp_size;
};

#ifdef LDAP_DEVEL
#define BDB_MONITOR_IDX
#endif /* LDAP_DEVEL */

typedef struct bdb_monitor_t {
	void		*bdm_cb;
	struct berval	bdm_ndn;
} bdb_monitor_t;

/* From ldap_rq.h */
struct re_s;

struct bdb_info {
	DB_ENV		*bi_dbenv;

	/* DB_ENV parameters */
	/* The DB_ENV can be tuned via DB_CONFIG */
	char		*bi_dbenv_home;
	u_int32_t	bi_dbenv_xflags; /* extra flags */
	int			bi_dbenv_mode;

	int			bi_ndatabases;
	int		bi_db_opflags;	/* db-specific flags */
	struct bdb_db_info **bi_databases;
	ldap_pvt_thread_mutex_t	bi_database_mutex;
	struct bdb_db_pgsize *bi_pagesizes;

	slap_mask_t	bi_defaultmask;
	Cache		bi_cache;
	struct bdb_attrinfo		**bi_attrs;
	int			bi_nattrs;
	void		*bi_search_stack;
	int		bi_search_stack_depth;
	int		bi_linear_index;

	int			bi_txn_cp;
	u_int32_t	bi_txn_cp_min;
	u_int32_t	bi_txn_cp_kbyte;
	struct re_s		*bi_txn_cp_task;
	struct re_s		*bi_index_task;

	u_int32_t		bi_lock_detect;
	long		bi_shm_key;

	ID			bi_lastid;
	ldap_pvt_thread_mutex_t	bi_lastid_mutex;
	ID	bi_idl_cache_max_size;
	ID		bi_idl_cache_size;
	Avlnode		*bi_idl_tree;
	bdb_idl_cache_entry_t	*bi_idl_lru_head;
	bdb_idl_cache_entry_t	*bi_idl_lru_tail;
	ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
	ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
	alock_info_t	bi_alock_info;
	char		*bi_db_config_path;
	BerVarray	bi_db_config;
	char		*bi_db_crypt_file;
	struct berval	bi_db_crypt_key;
	bdb_monitor_t	bi_monitor;

#ifdef BDB_MONITOR_IDX
	ldap_pvt_thread_mutex_t	bi_idx_mutex;
	Avlnode		*bi_idx;
#endif /* BDB_MONITOR_IDX */

	int		bi_flags;
#define	BDB_IS_OPEN		0x01
#define	BDB_HAS_CONFIG	0x02
#define	BDB_UPD_CONFIG	0x04
#define	BDB_DEL_INDEX	0x08
#define	BDB_RE_OPEN		0x10
#define BDB_CHKSUM		0x20
#ifdef BDB_HIER
	int		bi_modrdns;		/* number of modrdns completed */
	ldap_pvt_thread_mutex_t	bi_modrdns_mutex;
#endif
};

#define bi_id2entry	bi_databases[BDB_ID2ENTRY]
#define bi_dn2id	bi_databases[BDB_DN2ID]


struct bdb_lock_info {
	struct bdb_lock_info *bli_next;
	DB_LOCK	bli_lock;
	ID		bli_id;
	int		bli_flag;
};
#define	BLI_DONTFREE	1

struct bdb_op_info {
	OpExtra boi_oe;
	DB_TXN*		boi_txn;
	struct bdb_lock_info *boi_locks;	/* used when no txn */
	u_int32_t	boi_err;
	char		boi_acl_cache;
	char		boi_flag;
};
#define BOI_DONTFREE	1

#define	DB_OPEN(db, file, name, type, flags, mode) \
	((db)->open)(db, file, name, type, flags, mode)

#if DB_VERSION_MAJOR < 4
#define LOCK_DETECT(env,f,t,a)		lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l)		lock_get(env, i, f, o, m, l)
#define LOCK_PUT(env,l)			lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f)	txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f)		txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,gid)		txn_prepare((txn), (gid))
#define TXN_COMMIT(txn,f)			txn_commit((txn), (f))
#define	TXN_ABORT(txn)				txn_abort((txn))
#define TXN_ID(txn)					txn_id(txn)
#define XLOCK_ID(env, locker)		lock_id(env, locker)
#define XLOCK_ID_FREE(env, locker)	lock_id_free(env, locker)
#else
#define LOCK_DETECT(env,f,t,a)		(env)->lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l)		(env)->lock_get(env, i, f, o, m, l)
#define LOCK_PUT(env,l)			(env)->lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f)	(env)->txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f)		(env)->txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,g)			(txn)->prepare((txn), (g))
#define TXN_COMMIT(txn,f)			(txn)->commit((txn), (f))
#define TXN_ABORT(txn)				(txn)->abort((txn))
#define TXN_ID(txn)					(txn)->id(txn)
#define XLOCK_ID(env, locker)		(env)->lock_id(env, locker)
#define XLOCK_ID_FREE(env, locker)	(env)->lock_id_free(env, locker)

/* BDB 4.1.17 adds txn arg to db->open */
#if DB_VERSION_FULL >= 0x04010011
#undef DB_OPEN
#define	DB_OPEN(db, file, name, type, flags, mode) \
	((db)->open)(db, NULL, file, name, type, flags, mode)
#endif

/* #undef BDB_LOG_DEBUG */

#ifdef BDB_LOG_DEBUG

/* env->log_printf appeared in 4.4 */
#if DB_VERSION_FULL >= 0x04040000
#define	BDB_LOG_PRINTF(env,txn,fmt,...)	(env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
#else
extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
	const char *fmt,...);
#define	BDB_LOG_PRINTF(env,txn,fmt,...)	__db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
#endif

/* !BDB_LOG_DEBUG */
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
	(defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
#define BDB_LOG_PRINTF(a,b,c,...)
#else
#define BDB_LOG_PRINTF (void)	/* will evaluate and discard the arguments */

#endif /* BDB_LOG_DEBUG */

#endif

#ifndef DB_BUFFER_SMALL
#define DB_BUFFER_SMALL			ENOMEM
#endif

#define BDB_CSN_COMMIT	0
#define BDB_CSN_ABORT	1
#define BDB_CSN_RETRY	2

/* Copy an ID "src" to pointer "dst" in big-endian byte order */
#define BDB_ID2DISK( src, dst )	\
	do { int i0; ID tmp; unsigned char *_p;	\
		tmp = (src); _p = (unsigned char *)(dst);	\
		for ( i0=sizeof(ID)-1; i0>=0; i0-- ) {	\
			_p[i0] = tmp & 0xff; tmp >>= 8;	\
		} \
	} while(0)

/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
#define BDB_DISK2ID( src, dst ) \
	do { unsigned i0; ID tmp = 0; unsigned char *_p;	\
		_p = (unsigned char *)(src);	\
		for ( i0=0; i0<sizeof(ID); i0++ ) {	\
			tmp <<= 8; tmp |= *_p++;	\
		} *(dst) = tmp; \
	} while (0)

LDAP_END_DECL

/* for the cache of attribute information (which are indexed, etc.) */
typedef struct bdb_attrinfo {
	AttributeDescription *ai_desc; /* attribute description cn;lang-en */
	slap_mask_t ai_indexmask;	/* how the attr is indexed	*/
	slap_mask_t ai_newmask;	/* new settings to replace old mask */
#ifdef LDAP_COMP_MATCH
	ComponentReference* ai_cr; /*component indexing*/
#endif
} AttrInfo;

/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
#define	BDB_INDEX_DELETING	0x8000U	/* index is being modified */
#define	BDB_INDEX_UPDATE_OP	0x03	/* performing an index update */

/* For slapindex to record which attrs in an entry belong to which
 * index database 
 */
typedef struct AttrList {
	struct AttrList *next;
	Attribute *attr;
} AttrList;

typedef struct IndexRec {
	AttrInfo *ai;
	AttrList *attrs;
} IndexRec;

#include "proto-bdb.h"

#endif /* _BACK_BDB_H_ */