summaryrefslogtreecommitdiff
path: root/lib/ldb/ldb_key_value/ldb_kv.h
blob: e627644ba3499663078b1a8ff0ab8a789f3e779e (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
#include "replace.h"
#include "system/filesys.h"
#include "system/time.h"
#include "tdb.h"
#include "ldb_module.h"

#ifndef __LDB_KV_H__
#define __LDB_KV_H__
struct ldb_kv_private;
typedef int (*ldb_kv_traverse_fn)(struct ldb_kv_private *ldb_kv,
				  struct ldb_val key,
				  struct ldb_val data,
				  void *ctx);

struct kv_db_ops {
	uint32_t options;

	int (*store)(struct ldb_kv_private *ldb_kv,
		     struct ldb_val key,
		     struct ldb_val data,
		     int flags);
	int (*delete)(struct ldb_kv_private *ldb_kv, struct ldb_val key);
	int (*iterate)(struct ldb_kv_private *ldb_kv,
		       ldb_kv_traverse_fn fn,
		       void *ctx);
	int (*update_in_iterate)(struct ldb_kv_private *ldb_kv,
				 struct ldb_val key,
				 struct ldb_val key2,
				 struct ldb_val data,
				 void *ctx);
	int (*fetch_and_parse)(struct ldb_kv_private *ldb_kv,
			       struct ldb_val key,
			       int (*parser)(struct ldb_val key,
					     struct ldb_val data,
					     void *private_data),
			       void *ctx);
	int (*iterate_range)(struct ldb_kv_private *ldb_kv,
			     struct ldb_val start_key,
			     struct ldb_val end_key,
			     ldb_kv_traverse_fn fn,
			     void *ctx);
	int (*lock_read)(struct ldb_module *);
	int (*unlock_read)(struct ldb_module *);
	int (*begin_write)(struct ldb_kv_private *);
	int (*prepare_write)(struct ldb_kv_private *);
	int (*abort_write)(struct ldb_kv_private *);
	int (*finish_write)(struct ldb_kv_private *);
	int (*error)(struct ldb_kv_private *ldb_kv);
	const char *(*errorstr)(struct ldb_kv_private *ldb_kv);
	const char *(*name)(struct ldb_kv_private *ldb_kv);
	bool (*has_changed)(struct ldb_kv_private *ldb_kv);
	bool (*transaction_active)(struct ldb_kv_private *ldb_kv);
	size_t (*get_size)(struct ldb_kv_private *ldb_kv);
	int (*begin_nested_write)(struct ldb_kv_private *);
	int (*finish_nested_write)(struct ldb_kv_private *);
	int (*abort_nested_write)(struct ldb_kv_private *);
};

/* this private structure is used by the key value backends in the
   ldb_context */
struct ldb_kv_private {
	const struct kv_db_ops *kv_ops;
	struct ldb_module *module;
	TDB_CONTEXT *tdb;
	struct lmdb_private *lmdb_private;
	unsigned int connect_flags;

	unsigned long long sequence_number;
	uint32_t pack_format_version;
	uint32_t target_pack_format_version;
	uint32_t pack_format_override;

	/* the low level tdb seqnum - used to avoid loading BASEINFO when
	   possible */
	int tdb_seqnum;

	struct ldb_kv_cache {
		struct ldb_message *indexlist;
		bool one_level_indexes;
		bool attribute_indexes;
		const char *GUID_index_attribute;
		const char *GUID_index_dn_component;
	} *cache;


	bool check_base;
	bool disallow_dn_filter;
	/*
	 * To improve the performance of batch operations we maintain a cache
	 * of index records, these entries get written to disk in the
	 * prepare_commit phase.
	 */
	struct ldb_kv_idxptr *idxptr;
	/*
	 * To ensure that the indexes in idxptr are consistent we cache any
	 * index updates during an operation, i.e. ldb_kv_add, ldb_kv_delete ...
	 * Once the changes to the data record have been commited to disk
	 * the contents of this cache are copied to idxptr
	 */
	struct ldb_kv_idxptr *nested_idx_ptr;
	/*
	 * If batch mode is set the sub transactions and index caching
	 * wrapping individual operations is disabled.
	 * This is to improve the performance of large batch operations
	 * i.e. domain joins.
	 */
	bool batch_mode;
	/*
	 * Has an operation failed, if true and we're in batch_mode
	 * the transaction commit will fail.
	 */
	bool operation_failed;

	bool prepared_commit;
	int read_lock_count;

	bool warn_unindexed;
	bool warn_reindex;

	bool read_only;

	bool reindex_failed;

	const struct ldb_schema_syntax *GUID_index_syntax;

	/*
	 * Maximum index key length.  If non zero keys longer than this length
	 * will be truncated for non unique indexes. Keys for unique indexes
	 * greater than this length will be rejected.
	 */
	unsigned max_key_length;

	/*
	 * To allow testing that ensures the DB does not fall back
	 * to a full scan
	 */
	bool disable_full_db_scan;

	/*
	 * The PID that opened this database so we don't work in a
	 * fork()ed child.
	 */
	pid_t pid;

	/*
	 * The size to be used for the index transaction cache
	 */
	size_t index_transaction_cache_size;
};

struct ldb_kv_context {
	struct ldb_module *module;
	struct ldb_request *req;

	bool request_terminated;
	struct ldb_kv_req_spy *spy;

	/* search stuff */
	const struct ldb_parse_tree *tree;
	struct ldb_dn *base;
	enum ldb_scope scope;
	const char * const *attrs;
	struct tevent_timer *timeout_event;

	/* error handling */
	int error;
};

struct ldb_kv_reindex_context {
	int error;
	uint32_t count;
};

struct ldb_kv_repack_context {
	int error;
	uint32_t count;
	bool normal_record_seen;
};


/* special record types */
#define LDB_KV_INDEX      "@INDEX"
#define LDB_KV_INDEXLIST  "@INDEXLIST"
#define LDB_KV_IDX        "@IDX"
#define LDB_KV_IDXVERSION "@IDXVERSION"
#define LDB_KV_IDXATTR    "@IDXATTR"
#define LDB_KV_IDXONE     "@IDXONE"
#define LDB_KV_IDXDN     "@IDXDN"
#define LDB_KV_IDXGUID    "@IDXGUID"
#define LDB_KV_IDX_DN_GUID "@IDX_DN_GUID"

/*
 * This will be used to indicate when a new, yet to be developed
 * sub-database version of the indicies are in use, to ensure we do
 * not load future databases unintentionally.
 */

#define LDB_KV_IDX_LMDB_SUBDB "@IDX_LMDB_SUBDB"

#define LDB_KV_BASEINFO   "@BASEINFO"
#define LDB_KV_OPTIONS    "@OPTIONS"
#define LDB_KV_ATTRIBUTES "@ATTRIBUTES"

/* special attribute types */
#define LDB_KV_SEQUENCE_NUMBER "sequenceNumber"
#define LDB_KV_CHECK_BASE "checkBaseOnSearch"
#define LDB_KV_DISALLOW_DN_FILTER "disallowDNFilter"
#define LDB_KV_MOD_TIMESTAMP "whenChanged"
#define LDB_KV_OBJECTCLASS "objectClass"

/* DB keys */
#define LDB_KV_GUID_KEY_PREFIX "GUID="
#define LDB_KV_GUID_SIZE 16
#define LDB_KV_GUID_KEY_SIZE (LDB_KV_GUID_SIZE + sizeof(LDB_KV_GUID_KEY_PREFIX) - 1)

/* LDB KV options */
/*
 * This allows pointers to be referenced after the callback to any variant of
 * iterate or fetch_and_parse -- as long as an overall read lock is held.
 */
#define LDB_KV_OPTION_STABLE_READ_LOCK 0x00000001

/*
 * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_cache.c
 */

int ldb_kv_cache_reload(struct ldb_module *module);
int ldb_kv_cache_load(struct ldb_module *module);
int ldb_kv_increase_sequence_number(struct ldb_module *module);
int ldb_kv_check_at_attributes_values(const struct ldb_val *value);

/*
 * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_index.c
 */

/*
 * The default size of the in memory TDB used to cache index records
 * The value chosen gives a prime modulo for the hash table and keeps the
 * tdb memory overhead under 4 kB
 */
#define DEFAULT_INDEX_CACHE_SIZE 491

struct ldb_parse_tree;

int ldb_kv_search_indexed(struct ldb_kv_context *ctx, uint32_t *);
int ldb_kv_index_add_new(struct ldb_module *module,
			 struct ldb_kv_private *ldb_kv,
			 const struct ldb_message *msg);
int ldb_kv_index_delete(struct ldb_module *module,
			const struct ldb_message *msg);
int ldb_kv_index_del_element(struct ldb_module *module,
			     struct ldb_kv_private *ldb_kv,
			     const struct ldb_message *msg,
			     struct ldb_message_element *el);
int ldb_kv_index_add_element(struct ldb_module *module,
			     struct ldb_kv_private *ldb_kv,
			     const struct ldb_message *msg,
			     struct ldb_message_element *el);
int ldb_kv_index_del_value(struct ldb_module *module,
			   struct ldb_kv_private *ldb_kv,
			   const struct ldb_message *msg,
			   struct ldb_message_element *el,
			   unsigned int v_idx);
int ldb_kv_reindex(struct ldb_module *module);
int ldb_kv_repack(struct ldb_module *module);
int ldb_kv_index_transaction_start(
	struct ldb_module *module,
	size_t cache_size);
int ldb_kv_index_transaction_commit(struct ldb_module *module);
int ldb_kv_index_transaction_cancel(struct ldb_module *module);
int ldb_kv_key_dn_from_idx(struct ldb_module *module,
			   struct ldb_kv_private *ldb_kv,
			   TALLOC_CTX *mem_ctx,
			   struct ldb_dn *dn,
			  struct ldb_val *key);

/*
 * The following definitions come from lib/ldb/ldb_key_value/ldb_kv_search.c
 */
int ldb_kv_search_dn1(struct ldb_module *module,
		      struct ldb_dn *dn,
		      struct ldb_message *msg,
		      unsigned int unpack_flags);
int ldb_kv_search_base(struct ldb_module *module,
		       TALLOC_CTX *mem_ctx,
		       struct ldb_dn *dn,
		       struct ldb_dn **ret_dn);
int ldb_kv_search_key(struct ldb_module *module,
		      struct ldb_kv_private *ldb_kv,
		      const struct ldb_val ldb_key,
		      struct ldb_message *msg,
		      unsigned int unpack_flags);
int ldb_kv_filter_attrs(struct ldb_context *ldb,
			const struct ldb_message *msg,
			const char *const *attrs,
			struct ldb_message *filtered_msg);
int ldb_kv_search(struct ldb_kv_context *ctx);

/*
 * The following definitions come from lib/ldb/ldb_key_value/ldb_kv.c  */
/*
 * Determine if this key could hold a normal record.  We allow the new
 * GUID index, the old DN index and a possible future ID= but not
 * DN=@.
 */
bool ldb_kv_key_is_normal_record(struct ldb_val key);
struct ldb_val ldb_kv_key_dn(TALLOC_CTX *mem_ctx,
			     struct ldb_dn *dn);
struct ldb_val ldb_kv_key_msg(struct ldb_module *module,
			     TALLOC_CTX *mem_ctx,
			      const struct ldb_message *msg);
int ldb_kv_guid_to_key(const struct ldb_val *GUID_val,
		       struct ldb_val *key);
int ldb_kv_idx_to_key(struct ldb_module *module,
		      struct ldb_kv_private *ldb_kv,
		      TALLOC_CTX *mem_ctx,
		      const struct ldb_val *idx_val,
		      struct ldb_val *key);
int ldb_kv_store(struct ldb_module *module,
		 const struct ldb_message *msg,
		 int flgs);
int ldb_kv_modify_internal(struct ldb_module *module,
			   const struct ldb_message *msg,
			   struct ldb_request *req);
int ldb_kv_delete_noindex(struct ldb_module *module,
			  const struct ldb_message *msg);
int ldb_kv_init_store(struct ldb_kv_private *ldb_kv,
		      const char *name,
		      struct ldb_context *ldb,
		      const char *options[],
		      struct ldb_module **_module);
int ldb_kv_index_sub_transaction_start(struct ldb_kv_private *ldb_kv);
int ldb_kv_index_sub_transaction_cancel(struct ldb_kv_private *ldb_kv);
int ldb_kv_index_sub_transaction_commit(struct ldb_kv_private *ldb_kv);
#endif /* __LDB_KV_H__ */