1/*	$NetBSD: back-bdb.h,v 1.1.1.3 2010/12/12 15:22:53 adam Exp $	*/
2
3/* back-bdb.h - bdb back-end header file */
4/* OpenLDAP: pkg/ldap/servers/slapd/back-bdb/back-bdb.h,v 1.141.2.24 2010/04/13 20:23:23 kurt Exp */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2000-2010 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18
19#ifndef _BACK_BDB_H_
20#define _BACK_BDB_H_
21
22#include <portable.h>
23#include "slap.h"
24#include <db.h>
25#include "alock.h"
26
27LDAP_BEGIN_DECL
28
29#define DB_VERSION_FULL ((DB_VERSION_MAJOR << 24) | (DB_VERSION_MINOR << 16) | DB_VERSION_PATCH)
30
31#define DN_BASE_PREFIX		SLAP_INDEX_EQUALITY_PREFIX
32#define DN_ONE_PREFIX	 	'%'
33#define DN_SUBTREE_PREFIX 	'@'
34
35#define DBTzero(t)			(memset((t), 0, sizeof(DBT)))
36#define DBT2bv(t,bv)		((bv)->bv_val = (t)->data, \
37								(bv)->bv_len = (t)->size)
38#define bv2DBT(bv,t)		((t)->data = (bv)->bv_val, \
39								(t)->size = (bv)->bv_len )
40
41#define BDB_TXN_RETRIES		16
42
43#define BDB_MAX_ADD_LOOP	30
44
45#define BDB_SUFFIX		".bdb"
46#define BDB_ID2ENTRY	0
47#define BDB_DN2ID		1
48#define BDB_NDB			2
49
50/* The bdb on-disk entry format is pretty space-inefficient. Average
51 * sized user entries are 3-4K each. You need at least two entries to
52 * fit into a single database page, more is better. 64K is BDB's
53 * upper bound. Smaller pages are better for concurrency.
54 */
55#ifndef BDB_ID2ENTRY_PAGESIZE
56#define	BDB_ID2ENTRY_PAGESIZE	16384
57#endif
58
59#define DEFAULT_CACHE_SIZE     1000
60
61/* The default search IDL stack cache depth */
62#define DEFAULT_SEARCH_STACK_DEPTH	16
63
64/* The minimum we can function with */
65#define MINIMUM_SEARCH_STACK_DEPTH	8
66
67typedef struct bdb_idl_cache_entry_s {
68	struct berval kstr;
69	ID      *idl;
70	DB      *db;
71	int		idl_flags;
72	struct bdb_idl_cache_entry_s* idl_lru_prev;
73	struct bdb_idl_cache_entry_s* idl_lru_next;
74} bdb_idl_cache_entry_t;
75
76/* BDB backend specific entry info */
77typedef struct bdb_entry_info {
78	struct bdb_entry_info *bei_parent;
79	ID bei_id;
80
81	/* we use the bei_id as a lockobj, but we need to make the size != 4
82	 * to avoid conflicting with BDB's internal locks. So add a byte here
83	 * that is always zero.
84	 */
85	short bei_lockpad;
86
87	short bei_state;
88#define	CACHE_ENTRY_DELETED	1
89#define	CACHE_ENTRY_NO_KIDS	2
90#define	CACHE_ENTRY_NOT_LINKED	4
91#define CACHE_ENTRY_NO_GRANDKIDS	8
92#define	CACHE_ENTRY_LOADING	0x10
93#define	CACHE_ENTRY_WALKING	0x20
94#define	CACHE_ENTRY_ONELEVEL	0x40
95#define	CACHE_ENTRY_REFERENCED	0x80
96#define	CACHE_ENTRY_NOT_CACHED	0x100
97	int bei_finders;
98
99	/*
100	 * remaining fields require backend cache lock to access
101	 */
102	struct berval bei_nrdn;
103#ifdef BDB_HIER
104	struct berval bei_rdn;
105	int	bei_modrdns;	/* track renames */
106	int	bei_ckids;	/* number of kids cached */
107	int	bei_dkids;	/* number of kids on-disk, plus 1 */
108#endif
109	Entry	*bei_e;
110	Avlnode	*bei_kids;
111#ifdef SLAP_ZONE_ALLOC
112	struct bdb_info *bei_bdb;
113	int bei_zseq;
114#endif
115	ldap_pvt_thread_mutex_t	bei_kids_mutex;
116
117	struct bdb_entry_info	*bei_lrunext;	/* for cache lru list */
118	struct bdb_entry_info	*bei_lruprev;
119} EntryInfo;
120#undef BEI
121#define BEI(e)	((EntryInfo *) ((e)->e_private))
122
123/* for the in-core cache of entries */
124typedef struct bdb_cache {
125	EntryInfo	*c_eifree;	/* free list */
126	Avlnode		*c_idtree;
127	EntryInfo	*c_lruhead;	/* lru - add accessed entries here */
128	EntryInfo	*c_lrutail;	/* lru - rem lru entries from here */
129	EntryInfo	c_dntree;
130	ID		c_maxsize;
131	ID		c_cursize;
132	ID		c_minfree;
133	ID		c_eimax;
134	ID		c_eiused;	/* EntryInfo's in use */
135	ID		c_leaves;	/* EntryInfo leaf nodes */
136	int		c_purging;
137	DB_TXN	*c_txn;	/* used by lru cleaner */
138	ldap_pvt_thread_rdwr_t c_rwlock;
139	ldap_pvt_thread_mutex_t c_lru_mutex;
140	ldap_pvt_thread_mutex_t c_count_mutex;
141	ldap_pvt_thread_mutex_t c_eifree_mutex;
142#ifdef SLAP_ZONE_ALLOC
143	void *c_zctx;
144#endif
145} Cache;
146
147#define CACHE_READ_LOCK                0
148#define CACHE_WRITE_LOCK       1
149
150#define BDB_INDICES		128
151
152struct bdb_db_info {
153	struct berval	bdi_name;
154	DB			*bdi_db;
155};
156
157struct bdb_db_pgsize {
158	struct bdb_db_pgsize *bdp_next;
159	struct berval	bdp_name;
160	int	bdp_size;
161};
162
163#ifdef LDAP_DEVEL
164#define BDB_MONITOR_IDX
165#endif /* LDAP_DEVEL */
166
167typedef struct bdb_monitor_t {
168	void		*bdm_cb;
169	struct berval	bdm_ndn;
170} bdb_monitor_t;
171
172/* From ldap_rq.h */
173struct re_s;
174
175struct bdb_info {
176	DB_ENV		*bi_dbenv;
177
178	/* DB_ENV parameters */
179	/* The DB_ENV can be tuned via DB_CONFIG */
180	char		*bi_dbenv_home;
181	u_int32_t	bi_dbenv_xflags; /* extra flags */
182	int			bi_dbenv_mode;
183
184	int			bi_ndatabases;
185	int		bi_db_opflags;	/* db-specific flags */
186	struct bdb_db_info **bi_databases;
187	ldap_pvt_thread_mutex_t	bi_database_mutex;
188	struct bdb_db_pgsize *bi_pagesizes;
189
190	slap_mask_t	bi_defaultmask;
191	Cache		bi_cache;
192	struct bdb_attrinfo		**bi_attrs;
193	int			bi_nattrs;
194	void		*bi_search_stack;
195	int		bi_search_stack_depth;
196	int		bi_linear_index;
197
198	int			bi_txn_cp;
199	u_int32_t	bi_txn_cp_min;
200	u_int32_t	bi_txn_cp_kbyte;
201	struct re_s		*bi_txn_cp_task;
202	struct re_s		*bi_index_task;
203
204	u_int32_t		bi_lock_detect;
205	long		bi_shm_key;
206
207	ID			bi_lastid;
208	ldap_pvt_thread_mutex_t	bi_lastid_mutex;
209	ID	bi_idl_cache_max_size;
210	ID		bi_idl_cache_size;
211	Avlnode		*bi_idl_tree;
212	bdb_idl_cache_entry_t	*bi_idl_lru_head;
213	bdb_idl_cache_entry_t	*bi_idl_lru_tail;
214	ldap_pvt_thread_rdwr_t bi_idl_tree_rwlock;
215	ldap_pvt_thread_mutex_t bi_idl_tree_lrulock;
216	alock_info_t	bi_alock_info;
217	char		*bi_db_config_path;
218	BerVarray	bi_db_config;
219	char		*bi_db_crypt_file;
220	struct berval	bi_db_crypt_key;
221	bdb_monitor_t	bi_monitor;
222
223#ifdef BDB_MONITOR_IDX
224	ldap_pvt_thread_mutex_t	bi_idx_mutex;
225	Avlnode		*bi_idx;
226#endif /* BDB_MONITOR_IDX */
227
228	int		bi_flags;
229#define	BDB_IS_OPEN		0x01
230#define	BDB_HAS_CONFIG	0x02
231#define	BDB_UPD_CONFIG	0x04
232#define	BDB_DEL_INDEX	0x08
233#define	BDB_RE_OPEN		0x10
234#define BDB_CHKSUM		0x20
235#ifdef BDB_HIER
236	int		bi_modrdns;		/* number of modrdns completed */
237	ldap_pvt_thread_mutex_t	bi_modrdns_mutex;
238#endif
239};
240
241#define bi_id2entry	bi_databases[BDB_ID2ENTRY]
242#define bi_dn2id	bi_databases[BDB_DN2ID]
243
244
245struct bdb_lock_info {
246	struct bdb_lock_info *bli_next;
247	DB_LOCK	bli_lock;
248	ID		bli_id;
249	int		bli_flag;
250};
251#define	BLI_DONTFREE	1
252
253struct bdb_op_info {
254	OpExtra boi_oe;
255	DB_TXN*		boi_txn;
256	struct bdb_lock_info *boi_locks;	/* used when no txn */
257	u_int32_t	boi_err;
258	char		boi_acl_cache;
259	char		boi_flag;
260};
261#define BOI_DONTFREE	1
262
263#define	DB_OPEN(db, file, name, type, flags, mode) \
264	((db)->open)(db, file, name, type, flags, mode)
265
266#if DB_VERSION_MAJOR < 4
267#define LOCK_DETECT(env,f,t,a)		lock_detect(env, f, t, a)
268#define LOCK_GET(env,i,f,o,m,l)		lock_get(env, i, f, o, m, l)
269#define LOCK_PUT(env,l)			lock_put(env, l)
270#define TXN_CHECKPOINT(env,k,m,f)	txn_checkpoint(env, k, m, f)
271#define TXN_BEGIN(env,p,t,f)		txn_begin((env), p, t, f)
272#define TXN_PREPARE(txn,gid)		txn_prepare((txn), (gid))
273#define TXN_COMMIT(txn,f)			txn_commit((txn), (f))
274#define	TXN_ABORT(txn)				txn_abort((txn))
275#define TXN_ID(txn)					txn_id(txn)
276#define XLOCK_ID(env, locker)		lock_id(env, locker)
277#define XLOCK_ID_FREE(env, locker)	lock_id_free(env, locker)
278#else
279#define LOCK_DETECT(env,f,t,a)		(env)->lock_detect(env, f, t, a)
280#define LOCK_GET(env,i,f,o,m,l)		(env)->lock_get(env, i, f, o, m, l)
281#define LOCK_PUT(env,l)			(env)->lock_put(env, l)
282#define TXN_CHECKPOINT(env,k,m,f)	(env)->txn_checkpoint(env, k, m, f)
283#define TXN_BEGIN(env,p,t,f)		(env)->txn_begin((env), p, t, f)
284#define TXN_PREPARE(txn,g)			(txn)->prepare((txn), (g))
285#define TXN_COMMIT(txn,f)			(txn)->commit((txn), (f))
286#define TXN_ABORT(txn)				(txn)->abort((txn))
287#define TXN_ID(txn)					(txn)->id(txn)
288#define XLOCK_ID(env, locker)		(env)->lock_id(env, locker)
289#define XLOCK_ID_FREE(env, locker)	(env)->lock_id_free(env, locker)
290
291/* BDB 4.1.17 adds txn arg to db->open */
292#if DB_VERSION_FULL >= 0x04010011
293#undef DB_OPEN
294#define	DB_OPEN(db, file, name, type, flags, mode) \
295	((db)->open)(db, NULL, file, name, type, flags, mode)
296#endif
297
298/* #undef BDB_LOG_DEBUG */
299
300#ifdef BDB_LOG_DEBUG
301
302/* env->log_printf appeared in 4.4 */
303#if DB_VERSION_FULL >= 0x04040000
304#define	BDB_LOG_PRINTF(env,txn,fmt,...)	(env)->log_printf((env),(txn),(fmt),__VA_ARGS__)
305#else
306extern int __db_logmsg(const DB_ENV *env, DB_TXN *txn, const char *op, u_int32_t flags,
307	const char *fmt,...);
308#define	BDB_LOG_PRINTF(env,txn,fmt,...)	__db_logmsg((env),(txn),"DIAGNOSTIC",0,(fmt),__VA_ARGS__)
309#endif
310
311/* !BDB_LOG_DEBUG */
312#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
313	(defined(__GNUC__) && __GNUC__ >= 3 && !defined(__STRICT_ANSI__))
314#define BDB_LOG_PRINTF(a,b,c,...)
315#else
316#define BDB_LOG_PRINTF (void)	/* will evaluate and discard the arguments */
317
318#endif /* BDB_LOG_DEBUG */
319
320#endif
321
322#ifndef DB_BUFFER_SMALL
323#define DB_BUFFER_SMALL			ENOMEM
324#endif
325
326#define BDB_CSN_COMMIT	0
327#define BDB_CSN_ABORT	1
328#define BDB_CSN_RETRY	2
329
330/* Copy an ID "src" to pointer "dst" in big-endian byte order */
331#define BDB_ID2DISK( src, dst )	\
332	do { int i0; ID tmp; unsigned char *_p;	\
333		tmp = (src); _p = (unsigned char *)(dst);	\
334		for ( i0=sizeof(ID)-1; i0>=0; i0-- ) {	\
335			_p[i0] = tmp & 0xff; tmp >>= 8;	\
336		} \
337	} while(0)
338
339/* Copy a pointer "src" to a pointer "dst" from big-endian to native order */
340#define BDB_DISK2ID( src, dst ) \
341	do { unsigned i0; ID tmp = 0; unsigned char *_p;	\
342		_p = (unsigned char *)(src);	\
343		for ( i0=0; i0<sizeof(ID); i0++ ) {	\
344			tmp <<= 8; tmp |= *_p++;	\
345		} *(dst) = tmp; \
346	} while (0)
347
348LDAP_END_DECL
349
350/* for the cache of attribute information (which are indexed, etc.) */
351typedef struct bdb_attrinfo {
352	AttributeDescription *ai_desc; /* attribute description cn;lang-en */
353	slap_mask_t ai_indexmask;	/* how the attr is indexed	*/
354	slap_mask_t ai_newmask;	/* new settings to replace old mask */
355#ifdef LDAP_COMP_MATCH
356	ComponentReference* ai_cr; /*component indexing*/
357#endif
358} AttrInfo;
359
360/* These flags must not clash with SLAP_INDEX flags or ops in slap.h! */
361#define	BDB_INDEX_DELETING	0x8000U	/* index is being modified */
362#define	BDB_INDEX_UPDATE_OP	0x03	/* performing an index update */
363
364/* For slapindex to record which attrs in an entry belong to which
365 * index database
366 */
367typedef struct AttrList {
368	struct AttrList *next;
369	Attribute *attr;
370} AttrList;
371
372typedef struct IndexRec {
373	AttrInfo *ai;
374	AttrList *attrs;
375} IndexRec;
376
377#include "proto-bdb.h"
378
379#endif /* _BACK_BDB_H_ */
380