]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
ee3be9ccd00901540df984ca532b1e7db7862b03
[openldap] / servers / slapd / backover.c
1 /* backover.c - backend overlay routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 /*
9  * Functions to overlay other modules over a backend.
10  *
11  *  -- Howard Chu
12  */
13
14 #include "portable.h"
15
16 #include <stdio.h>
17
18 #include <ac/string.h>
19 #include <ac/socket.h>
20
21 #define SLAPD_TOOLS
22 #include "slap.h"
23
24 static slap_overinst *overlays;
25
26 enum db_which { db_open = 0, db_close, db_destroy };
27
28 static int
29 over_db_func(
30         BackendDB *be,
31         enum db_which which
32 )
33 {
34         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
35         slap_overinst *on = oi->oi_list;
36         BackendDB bd;
37         BI_db_open **func;
38         int rc = 0;
39
40         func = &oi->oi_bd.bd_info->bi_db_open;
41         if ( func[which] ) {
42                 rc = func[which]( &oi->oi_bd );
43                 if ( rc ) return rc;
44         }
45
46         bd = *be;
47         for (; on; on=on->on_next) {
48                 bd.bd_info = &on->on_bi;
49                 func = &on->on_bi.bi_db_open;
50                 if (func[which]) {
51                         rc = func[which]( &bd );
52                         if ( rc ) break;
53                 }
54         }
55         return rc;
56 }
57
58 static int
59 over_db_config(
60         BackendDB *be,
61         const char *fname,
62         int lineno,
63         int argc,
64         char **argv
65 )
66 {
67         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
68         slap_overinst *on = oi->oi_list;
69         BackendDB bd;
70         int rc = 0;
71
72         if ( oi->oi_bd.bd_info->bi_db_config ) {
73                 rc = oi->oi_bd.bd_info->bi_db_config( &oi->oi_bd, fname, lineno,
74                         argc, argv );
75                 if ( rc ) return rc;
76         }
77
78         bd = *be;
79         for (; on; on=on->on_next) {
80                 bd.bd_info = &on->on_bi;
81                 if (on->on_bi.bi_db_config) {
82                         rc = on->on_bi.bi_db_config( &bd, fname, lineno,
83                                 argc, argv );
84                         if ( rc ) break;
85                 }
86         }
87         return rc;
88 }
89
90 static int
91 over_db_open(
92         BackendDB *be
93 )
94 {
95         return over_db_func( be, db_open );
96 }
97
98 static int
99 over_db_close(
100         BackendDB *be
101 )
102 {
103         return over_db_func( be, db_close );
104 }
105
106 static int
107 over_db_destroy(
108         BackendDB *be
109 )
110 {
111         slap_overinfo *oi = (slap_overinfo *) be->bd_info;
112         slap_overinst *on = oi->oi_list, *next;
113         int rc;
114
115         rc = over_db_func( be, db_destroy );
116
117         for (next = on->on_next; on; on=next) {
118                 next = on->on_next;
119                 free( on );
120         }
121         free( oi );
122         return rc;
123 }
124
125 static int
126 over_back_response ( Operation *op, SlapReply *rs )
127 {
128         slap_overinfo *oi = (slap_overinfo *) op->o_bd->bd_info;
129         slap_overinst *on = oi->oi_list;
130         int rc = SLAP_CB_CONTINUE;
131         BackendDB *be = op->o_bd, db = *op->o_bd;
132         slap_callback *sc = op->o_callback->sc_private;
133         slap_callback *s0 = op->o_callback;
134
135         op->o_bd = &db;
136         op->o_callback = sc;
137         for (; on; on=on->on_next ) {
138                 if ( on->on_response ) {
139                         db.bd_info = (BackendInfo *)on;
140                         rc = on->on_response( op, rs );
141                         if ( rc != SLAP_CB_CONTINUE ) break;
142                 }
143         }
144         if ( sc && (rc == SLAP_CB_CONTINUE) ) {
145                 rc = sc->sc_response( op, rs );
146         }
147         op->o_bd = be;
148         op->o_callback = s0;
149         return rc;
150 }
151
152 enum op_which { op_bind = 0, op_unbind, op_search, op_compare,
153         op_modify, op_modrdn, op_add, op_delete, op_abandon,
154         op_cancel, op_extended };
155
156 static int
157 over_op_func(
158         Operation *op,
159         SlapReply *rs,
160         enum op_which which
161 )
162 {
163         slap_overinfo *oi = (slap_overinfo *) op->o_bd->bd_info;
164         slap_overinst *on = oi->oi_list;
165         BI_op_bind **func;
166         BackendDB *be = op->o_bd, db = *op->o_bd;
167         slap_callback cb = {over_back_response, NULL};
168         int rc = SLAP_CB_CONTINUE;
169
170         op->o_bd = &db;
171         cb.sc_private = op->o_callback;
172         op->o_callback = &cb;
173
174         for (; on; on=on->on_next ) {
175                 func = &on->on_bi.bi_op_bind;
176                 if ( func[which] ) {
177                         db.bd_info = (BackendInfo *)on;
178                         rc = func[which]( op, rs );
179                         if ( rc != SLAP_CB_CONTINUE ) break;
180                 }
181         }
182
183         func = &oi->oi_bd.bd_info->bi_op_bind;
184         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
185                 rc = func[which]( op, rs );
186         }
187         /* should not fall thru this far without anything happening... */
188         if ( rc == SLAP_CB_CONTINUE ) {
189                 rc = LDAP_UNWILLING_TO_PERFORM;
190         }
191         op->o_bd = be;
192         op->o_callback = cb.sc_private;
193         return rc;
194 }
195
196 static int
197 over_op_bind( Operation *op, SlapReply *rs )
198 {
199         return over_op_func( op, rs, op_bind );
200 }
201
202 static int
203 over_op_unbind( Operation *op, SlapReply *rs )
204 {
205         return over_op_func( op, rs, op_unbind );
206 }
207
208 static int
209 over_op_search( Operation *op, SlapReply *rs )
210 {
211         return over_op_func( op, rs, op_search );
212 }
213
214 static int
215 over_op_compare( Operation *op, SlapReply *rs )
216 {
217         return over_op_func( op, rs, op_compare );
218 }
219
220 static int
221 over_op_modify( Operation *op, SlapReply *rs )
222 {
223         return over_op_func( op, rs, op_modify );
224 }
225
226 static int
227 over_op_modrdn( Operation *op, SlapReply *rs )
228 {
229         return over_op_func( op, rs, op_modrdn );
230 }
231
232 static int
233 over_op_add( Operation *op, SlapReply *rs )
234 {
235         return over_op_func( op, rs, op_add );
236 }
237
238 static int
239 over_op_delete( Operation *op, SlapReply *rs )
240 {
241         return over_op_func( op, rs, op_delete );
242 }
243
244 static int
245 over_op_abandon( Operation *op, SlapReply *rs )
246 {
247         return over_op_func( op, rs, op_abandon );
248 }
249
250 static int
251 over_op_cancel( Operation *op, SlapReply *rs )
252 {
253         return over_op_func( op, rs, op_cancel );
254 }
255
256 static int
257 over_op_extended( Operation *op, SlapReply *rs )
258 {
259         return over_op_func( op, rs, op_extended );
260 }
261
262 int
263 overlay_register(
264         slap_overinst *on
265 )
266 {
267         on->on_next = overlays;
268         overlays = on;
269         return 0;
270 }
271
272 static const char overtype[] = "over";
273
274 /* add an overlay to a particular backend. */
275 int
276 overlay_config( BackendDB *be, const char *ov )
277 {
278         slap_overinst *on, *on2, *prev;
279         slap_overinfo *oi;
280         BackendInfo *bi;
281
282         for ( on = overlays; on; on=on->on_next ) {
283                 if (!strcmp( ov, on->on_bi.bi_type ) )
284                         break;
285         }
286         if (!on) {
287                 Debug( LDAP_DEBUG_ANY, "overlay %s not found\n", ov, 0, 0 );
288                 return 1;
289         }
290
291         /* If this is the first overlay on this backend, set up the
292          * overlay info structure
293          */
294         if ( be->bd_info->bi_type != overtype ) {
295                 oi = ch_malloc( sizeof(slap_overinfo) );
296                 oi->oi_bd = *be;
297                 oi->oi_bi = *be->bd_info;
298                 oi->oi_list = NULL;
299                 bi = (BackendInfo *)oi;
300
301                 bi->bi_type = (char *)overtype;
302
303                 bi->bi_db_config = over_db_config;
304                 bi->bi_db_open = over_db_open;
305                 bi->bi_db_close = over_db_close;
306                 bi->bi_db_destroy = over_db_destroy;
307
308                 bi->bi_op_bind = over_op_bind;
309                 bi->bi_op_unbind = over_op_unbind;
310                 bi->bi_op_search = over_op_search;
311                 bi->bi_op_compare = over_op_compare;
312                 bi->bi_op_modify = over_op_modify;
313                 bi->bi_op_modrdn = over_op_modrdn;
314                 bi->bi_op_add = over_op_add;
315                 bi->bi_op_delete = over_op_delete;
316                 bi->bi_op_abandon = over_op_abandon;
317                 bi->bi_op_cancel = over_op_cancel;
318                 bi->bi_extended = over_op_extended;
319
320                 be->bd_info = bi;
321         }
322
323         /* Walk to the end of the list of overlays, add the new
324          * one onto the end
325          */
326         oi = (slap_overinfo *) be->bd_info;
327         for ( prev=NULL, on2 = oi->oi_list; on2; prev=on2, on2=on2->on_next );
328         on2 = ch_calloc( 1, sizeof(slap_overinst) );
329         if ( !prev ) {
330                 oi->oi_list = on2;
331         } else {
332                 prev->on_next = on2;
333         }
334         *on2 = *on;
335         on2->on_next = NULL;
336         on2->on_info = oi;
337
338         /* Any initialization needed? */
339         if ( on->on_bi.bi_db_init ) {
340                 be->bd_info = (BackendInfo *)on2;
341                 on2->on_bi.bi_db_init( be );
342                 be->bd_info = (BackendInfo *)oi;
343         }
344
345         return 0;
346 }
347