init.c revision 1.3 1 1.1 christos /* $NetBSD: init.c,v 1.3 2025/09/05 21:16:32 christos Exp $ */
2 1.1 christos
3 1.1 christos /* OpenLDAP WiredTiger backend */
4 1.1 christos /* $OpenLDAP$ */
5 1.1 christos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 christos *
7 1.3 christos * Copyright 2002-2024 The OpenLDAP Foundation.
8 1.1 christos * All rights reserved.
9 1.1 christos *
10 1.1 christos * Redistribution and use in source and binary forms, with or without
11 1.1 christos * modification, are permitted only as authorized by the OpenLDAP
12 1.1 christos * Public License.
13 1.1 christos *
14 1.1 christos * A copy of this license is available in the file LICENSE in the
15 1.1 christos * top-level directory of the distribution or, alternatively, at
16 1.1 christos * <http://www.OpenLDAP.org/license.html>.
17 1.1 christos */
18 1.1 christos /* ACKNOWLEDGEMENTS:
19 1.1 christos * This work was developed by HAMANO Tsukasa <hamano (at) osstech.co.jp>
20 1.1 christos * based on back-bdb for inclusion in OpenLDAP Software.
21 1.1 christos * WiredTiger is a product of MongoDB Inc.
22 1.1 christos */
23 1.1 christos
24 1.1 christos #include <sys/cdefs.h>
25 1.1 christos __RCSID("$NetBSD: init.c,v 1.3 2025/09/05 21:16:32 christos Exp $");
26 1.1 christos
27 1.1 christos #include "portable.h"
28 1.1 christos
29 1.1 christos #include <stdio.h>
30 1.1 christos #include <ac/string.h>
31 1.1 christos #include "back-wt.h"
32 1.1 christos #include "slap-config.h"
33 1.1 christos
34 1.1 christos static int
35 1.1 christos wt_db_init( BackendDB *be, ConfigReply *cr )
36 1.1 christos {
37 1.1 christos struct wt_info *wi;
38 1.1 christos
39 1.3 christos Debug( LDAP_DEBUG_TRACE, "wt_db_init: Initializing wt backend\n" );
40 1.1 christos
41 1.1 christos /* allocate backend-database-specific stuff */
42 1.3 christos wi = ch_calloc( 1, sizeof(struct wt_info) );
43 1.3 christos wi->wi_home = ch_strdup( SLAPD_DEFAULT_DB_DIR );
44 1.3 christos wi->wi_config = ch_calloc( 1, WT_CONFIG_MAX + 1);
45 1.3 christos if ( slapMode & SLAP_TOOL_READONLY ) {
46 1.3 christos strcpy(wi->wi_config, "readonly");
47 1.3 christos } else {
48 1.3 christos strcpy(wi->wi_config, "create");
49 1.3 christos }
50 1.1 christos wi->wi_lastid = 0;
51 1.1 christos wi->wi_search_stack_depth = DEFAULT_SEARCH_STACK_DEPTH;
52 1.1 christos wi->wi_search_stack = NULL;
53 1.3 christos wi->wi_flags = WT_USE_IDLCACHE;
54 1.1 christos
55 1.1 christos be->be_private = wi;
56 1.1 christos be->be_cf_ocs = be->bd_info->bi_cf_ocs;
57 1.1 christos
58 1.1 christos return LDAP_SUCCESS;
59 1.1 christos }
60 1.1 christos
61 1.1 christos static int
62 1.1 christos wt_db_open( BackendDB *be, ConfigReply *cr )
63 1.1 christos {
64 1.1 christos struct wt_info *wi = (struct wt_info *) be->be_private;
65 1.1 christos int rc;
66 1.1 christos struct stat st;
67 1.3 christos WT_SESSION *session = NULL;
68 1.3 christos WT_SESSION *cache_session = NULL;
69 1.1 christos
70 1.1 christos if ( be->be_suffix == NULL ) {
71 1.3 christos Debug( LDAP_DEBUG_ANY, "wt_db_open: need suffix.\n" );
72 1.1 christos return -1;
73 1.1 christos }
74 1.1 christos
75 1.1 christos Debug( LDAP_DEBUG_ARGS,
76 1.3 christos "wt_db_open: \"%s\", home=%s, config=%s\n",
77 1.3 christos be->be_suffix[0].bv_val, wi->wi_home, wi->wi_config );
78 1.1 christos
79 1.1 christos /* Check existence of home. Any error means trouble */
80 1.3 christos rc = stat( wi->wi_home, &st );
81 1.1 christos if( rc ) {
82 1.1 christos int saved_errno = errno;
83 1.1 christos Debug( LDAP_DEBUG_ANY,
84 1.3 christos "wt_db_open: database \"%s\": "
85 1.1 christos "cannot access database directory \"%s\" (%d).\n",
86 1.3 christos be->be_suffix[0].bv_val, wi->wi_home, saved_errno );
87 1.1 christos return -1;
88 1.1 christos }
89 1.1 christos
90 1.3 christos /* back-wt is always clean */
91 1.3 christos be->be_flags |= SLAP_DBFLAG_CLEAN;
92 1.3 christos
93 1.1 christos /* Open and create database */
94 1.3 christos rc = wiredtiger_open(wi->wi_home, NULL,
95 1.3 christos wi->wi_config, &wi->wi_conn);
96 1.1 christos if( rc ) {
97 1.1 christos int saved_errno = errno;
98 1.1 christos Debug( LDAP_DEBUG_ANY,
99 1.3 christos "wt_db_open: database \"%s\": "
100 1.1 christos "cannot open database \"%s\" (%d).\n",
101 1.3 christos be->be_suffix[0].bv_val, wi->wi_home, saved_errno );
102 1.1 christos return -1;
103 1.1 christos }
104 1.1 christos
105 1.3 christos rc = wi->wi_conn->open_session(wi->wi_conn, NULL, NULL, &session);
106 1.1 christos if( rc ) {
107 1.1 christos Debug( LDAP_DEBUG_ANY,
108 1.3 christos "wt_db_open: database \"%s\": "
109 1.1 christos "cannot open session: \"%s\"\n",
110 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
111 1.1 christos return -1;
112 1.1 christos }
113 1.1 christos
114 1.3 christos if ( slapMode & SLAP_TOOL_READONLY ) {
115 1.3 christos goto readonly;
116 1.3 christos }
117 1.3 christos
118 1.3 christos /* checking for obsolete table */
119 1.3 christos rc = session->verify(session, WT_INDEX_REVDN, NULL);
120 1.3 christos if ( !rc ) {
121 1.3 christos Debug( LDAP_DEBUG_ANY,
122 1.3 christos "wt_db_open: database \"%s\": "
123 1.3 christos "incompatible wiredtiger table, please restore from LDIF.\n",
124 1.3 christos be->be_suffix[0].bv_val );
125 1.3 christos return -1;
126 1.3 christos }
127 1.3 christos
128 1.3 christos /* create tables and indexes */
129 1.1 christos rc = session->create(session,
130 1.1 christos WT_TABLE_ID2ENTRY,
131 1.1 christos "key_format=Q,"
132 1.1 christos "value_format=Su,"
133 1.1 christos "columns=(id,dn,entry)");
134 1.1 christos if( rc ) {
135 1.1 christos Debug( LDAP_DEBUG_ANY,
136 1.3 christos "wt_db_open: database \"%s\": "
137 1.1 christos "cannot create entry table: \"%s\"\n",
138 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
139 1.1 christos return -1;
140 1.1 christos }
141 1.1 christos
142 1.1 christos rc = session->create(session,
143 1.1 christos WT_TABLE_DN2ID,
144 1.1 christos "key_format=S,"
145 1.3 christos "value_format=SQQ,"
146 1.3 christos "columns=(revdn,ndn,id,pid)");
147 1.1 christos if( rc ) {
148 1.1 christos Debug( LDAP_DEBUG_ANY,
149 1.3 christos "wt_db_open: database \"%s\": "
150 1.1 christos "cannot create entry table: \"%s\"\n",
151 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
152 1.1 christos return -1;
153 1.1 christos }
154 1.1 christos
155 1.1 christos /* not using dn2id index for id2entry table */
156 1.1 christos rc = session->create(session, WT_INDEX_DN, "columns=(dn)");
157 1.1 christos if( rc ) {
158 1.1 christos Debug( LDAP_DEBUG_ANY,
159 1.3 christos "wt_db_open: database \"%s\": "
160 1.1 christos "cannot create dn index: \"%s\"\n",
161 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
162 1.1 christos return -1;
163 1.1 christos }
164 1.1 christos
165 1.1 christos rc = session->create(session, WT_INDEX_PID, "columns=(pid)");
166 1.1 christos if( rc ) {
167 1.1 christos Debug( LDAP_DEBUG_ANY,
168 1.3 christos "wt_db_open: database \"%s\": "
169 1.1 christos "cannot create pid index: \"%s\"\n",
170 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
171 1.1 christos return -1;
172 1.1 christos }
173 1.1 christos
174 1.3 christos rc = session->create(session, WT_INDEX_NDN, "columns=(ndn)");
175 1.3 christos if( rc ) {
176 1.3 christos Debug( LDAP_DEBUG_ANY,
177 1.3 christos "wt_db_open: database \"%s\": "
178 1.3 christos "cannot create ndn index: \"%s\"\n",
179 1.3 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
180 1.3 christos return -1;
181 1.3 christos }
182 1.3 christos
183 1.3 christos /* open in-memory database for idlcache */
184 1.3 christos rc = wiredtiger_open(be->be_suffix[0].bv_val, NULL,
185 1.3 christos "in_memory=true", &wi->wi_cache);
186 1.3 christos if( rc ) {
187 1.3 christos Debug( LDAP_DEBUG_ANY,
188 1.3 christos "wt_db_open: database \"%s\": "
189 1.3 christos "cannot open database for cache (%s).\n",
190 1.3 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
191 1.3 christos return -1;
192 1.3 christos }
193 1.3 christos
194 1.3 christos rc = wi->wi_cache->open_session(wi->wi_cache, NULL, NULL, &cache_session);
195 1.3 christos if( rc ) {
196 1.3 christos Debug( LDAP_DEBUG_ANY,
197 1.3 christos "wt_db_open: database \"%s\": "
198 1.3 christos "cannot open session for cache: \"%s\"\n",
199 1.3 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
200 1.3 christos return -1;
201 1.3 christos }
202 1.3 christos
203 1.3 christos rc = cache_session->create(cache_session,
204 1.3 christos WT_TABLE_IDLCACHE,
205 1.3 christos "key_format=Sb,"
206 1.3 christos "value_format=u,"
207 1.3 christos "columns=(ndn,scope,idl)");
208 1.1 christos if( rc ) {
209 1.1 christos Debug( LDAP_DEBUG_ANY,
210 1.3 christos "wt_db_open: database \"%s\": "
211 1.3 christos "cannot create idlcache table: \"%s\"\n",
212 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc) );
213 1.1 christos return -1;
214 1.1 christos }
215 1.1 christos
216 1.3 christos readonly:
217 1.1 christos rc = wt_last_id( be, session, &wi->wi_lastid);
218 1.1 christos if (rc) {
219 1.1 christos snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
220 1.1 christos "last_id() failed: %s(%d).",
221 1.1 christos be->be_suffix[0].bv_val, wiredtiger_strerror(rc), rc );
222 1.3 christos Debug( LDAP_DEBUG_ANY, "wt_db_open: %s\n", cr->msg );
223 1.1 christos return rc;
224 1.1 christos }
225 1.1 christos
226 1.3 christos if (session) {
227 1.3 christos session->close(session, NULL);
228 1.3 christos }
229 1.3 christos if (cache_session) {
230 1.3 christos cache_session->close(cache_session, NULL);
231 1.3 christos }
232 1.3 christos
233 1.1 christos wi->wi_flags |= WT_IS_OPEN;
234 1.1 christos return LDAP_SUCCESS;
235 1.1 christos }
236 1.1 christos
237 1.1 christos static int
238 1.1 christos wt_db_close( BackendDB *be, ConfigReply *cr )
239 1.1 christos {
240 1.1 christos struct wt_info *wi = (struct wt_info *) be->be_private;
241 1.1 christos int rc;
242 1.1 christos
243 1.3 christos if ( wi->wi_cache ) {
244 1.3 christos rc = wi->wi_cache->close(wi->wi_cache, NULL);
245 1.3 christos if( rc ) {
246 1.3 christos Debug( LDAP_DEBUG_ANY,
247 1.3 christos "wt_db_close: cannot close cache database (%d).\n", rc );
248 1.3 christos return -1;
249 1.3 christos }
250 1.3 christos }
251 1.3 christos
252 1.3 christos if ( wi->wi_conn ) {
253 1.3 christos rc = wi->wi_conn->close(wi->wi_conn, NULL);
254 1.3 christos if( rc ) {
255 1.3 christos Debug( LDAP_DEBUG_ANY,
256 1.3 christos "wt_db_close: cannot close database (%d).\n", rc );
257 1.3 christos return -1;
258 1.3 christos }
259 1.3 christos wi->wi_flags &= ~WT_IS_OPEN;
260 1.1 christos }
261 1.1 christos
262 1.1 christos return LDAP_SUCCESS;
263 1.1 christos }
264 1.1 christos
265 1.1 christos static int
266 1.1 christos wt_db_destroy( Backend *be, ConfigReply *cr )
267 1.1 christos {
268 1.1 christos struct wt_info *wi = (struct wt_info *) be->be_private;
269 1.1 christos
270 1.3 christos if( wi->wi_home ) {
271 1.3 christos ch_free( wi->wi_home );
272 1.3 christos wi->wi_home = NULL;
273 1.3 christos }
274 1.3 christos
275 1.3 christos if( wi->wi_config ) {
276 1.3 christos ch_free( wi->wi_config );
277 1.3 christos wi->wi_config = NULL;
278 1.1 christos }
279 1.1 christos
280 1.1 christos wt_attr_index_destroy( wi );
281 1.1 christos ch_free( wi );
282 1.1 christos be->be_private = NULL;
283 1.1 christos
284 1.1 christos return LDAP_SUCCESS;
285 1.1 christos }
286 1.1 christos
287 1.1 christos int
288 1.1 christos wt_back_initialize( BackendInfo *bi )
289 1.1 christos {
290 1.3 christos static const char *controls[] = {
291 1.1 christos LDAP_CONTROL_ASSERT,
292 1.1 christos LDAP_CONTROL_MANAGEDSAIT,
293 1.1 christos LDAP_CONTROL_NOOP,
294 1.1 christos LDAP_CONTROL_PAGEDRESULTS,
295 1.1 christos LDAP_CONTROL_PRE_READ,
296 1.1 christos LDAP_CONTROL_POST_READ,
297 1.1 christos LDAP_CONTROL_SUBENTRIES,
298 1.1 christos LDAP_CONTROL_X_PERMISSIVE_MODIFY,
299 1.3 christos #ifdef LDAP_X_TXN
300 1.3 christos LDAP_CONTROL_X_TXN_SPEC,
301 1.3 christos #endif
302 1.1 christos NULL
303 1.1 christos };
304 1.1 christos
305 1.1 christos /* initialize the database system */
306 1.1 christos Debug( LDAP_DEBUG_TRACE,
307 1.3 christos "wt_back_initialize: initialize WiredTiger backend\n" );
308 1.1 christos
309 1.1 christos bi->bi_flags |=
310 1.1 christos SLAP_BFLAG_INCREMENT |
311 1.1 christos SLAP_BFLAG_SUBENTRIES |
312 1.1 christos SLAP_BFLAG_ALIASES |
313 1.1 christos SLAP_BFLAG_REFERRALS;
314 1.1 christos
315 1.3 christos bi->bi_controls = (char **)controls;
316 1.3 christos
317 1.3 christos /* version check */
318 1.1 christos Debug( LDAP_DEBUG_TRACE,
319 1.3 christos "wt_back_initialize: %s\n",
320 1.1 christos wiredtiger_version(NULL, NULL, NULL) );
321 1.1 christos
322 1.1 christos bi->bi_open = 0;
323 1.1 christos bi->bi_close = 0;
324 1.1 christos bi->bi_config = 0;
325 1.1 christos bi->bi_destroy = 0;
326 1.1 christos
327 1.1 christos bi->bi_db_init = wt_db_init;
328 1.1 christos bi->bi_db_config = config_generic_wrapper;
329 1.1 christos bi->bi_db_open = wt_db_open;
330 1.1 christos bi->bi_db_close = wt_db_close;
331 1.1 christos bi->bi_db_destroy = wt_db_destroy;
332 1.1 christos
333 1.1 christos bi->bi_op_add = wt_add;
334 1.1 christos bi->bi_op_bind = wt_bind;
335 1.1 christos bi->bi_op_unbind = 0;
336 1.1 christos bi->bi_op_search = wt_search;
337 1.1 christos bi->bi_op_compare = wt_compare;
338 1.1 christos bi->bi_op_modify = wt_modify;
339 1.3 christos bi->bi_op_modrdn = wt_modrdn;
340 1.1 christos bi->bi_op_delete = wt_delete;
341 1.1 christos bi->bi_op_abandon = 0;
342 1.1 christos
343 1.3 christos bi->bi_extended = wt_extended;
344 1.3 christos #ifdef LDAP_X_TXN
345 1.3 christos bi->bi_op_txn = 0;
346 1.3 christos #endif
347 1.1 christos
348 1.1 christos bi->bi_chk_referrals = 0;
349 1.1 christos bi->bi_operational = wt_operational;
350 1.1 christos
351 1.3 christos bi->bi_has_subordinates = wt_hasSubordinates;
352 1.1 christos bi->bi_entry_release_rw = wt_entry_release;
353 1.1 christos bi->bi_entry_get_rw = wt_entry_get;
354 1.1 christos
355 1.1 christos bi->bi_tool_entry_open = wt_tool_entry_open;
356 1.1 christos bi->bi_tool_entry_close = wt_tool_entry_close;
357 1.1 christos bi->bi_tool_entry_first = backend_tool_entry_first;
358 1.1 christos bi->bi_tool_entry_first_x = wt_tool_entry_first_x;
359 1.1 christos bi->bi_tool_entry_next = wt_tool_entry_next;
360 1.1 christos bi->bi_tool_entry_get = wt_tool_entry_get;
361 1.1 christos bi->bi_tool_entry_put = wt_tool_entry_put;
362 1.1 christos bi->bi_tool_entry_reindex = wt_tool_entry_reindex;
363 1.3 christos bi->bi_tool_sync = 0;
364 1.3 christos bi->bi_tool_dn2id_get = wt_tool_dn2id_get;
365 1.3 christos bi->bi_tool_entry_modify = wt_tool_entry_modify;
366 1.3 christos
367 1.3 christos #if LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= 5
368 1.3 christos bi->bi_tool_entry_delete = wt_tool_entry_delete;
369 1.3 christos #endif
370 1.1 christos
371 1.1 christos bi->bi_connection_init = 0;
372 1.1 christos bi->bi_connection_destroy = 0;
373 1.1 christos
374 1.1 christos return wt_back_init_cf( bi );
375 1.1 christos }
376 1.1 christos
377 1.1 christos #if SLAPD_WT == SLAPD_MOD_DYNAMIC
378 1.1 christos
379 1.1 christos /* conditionally define the init_module() function */
380 1.1 christos SLAP_BACKEND_INIT_MODULE( wt )
381 1.1 christos
382 1.1 christos #endif /* SLAPD_WT == SLAPD_MOD_DYNAMIC */
383 1.1 christos
384 1.1 christos /*
385 1.1 christos * Local variables:
386 1.1 christos * indent-tabs-mode: t
387 1.1 christos * tab-width: 4
388 1.1 christos * c-basic-offset: 4
389 1.1 christos * End:
390 1.1 christos */
391