]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-merge.c
now LDAP_CACHING can be enabled again; not sure it works, though
[openldap] / servers / slapd / back-meta / cache-merge.c
1 /* Copyright (c) 2003 by International Business Machines, Inc.
2  *
3  * International Business Machines, Inc. (hereinafter called IBM) grants
4  * permission under its copyrights to use, copy, modify, and distribute this
5  * Software with or without fee, provided that the above copyright notice and
6  * all paragraphs of this notice appear in all copies, and that the name of IBM
7  * not be used in connection with the marketing of any product incorporating
8  * the Software or modifications thereof, without specific, written prior
9  * permission.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
12  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
13  * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
14  * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
15  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
16  * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
17  */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/socket.h>
24 #include <ac/string.h>
25 #include <ac/time.h>
26
27 #include "slap.h"
28 #include "ldif.h"
29 #include "../back-ldap/back-ldap.h"
30 #include "back-meta.h"
31 #include "ldap_pvt.h"
32 #undef ldap_debug       /* silence a warning in ldap-int.h */
33 #include "ldap_log.h"
34 #include "../../../libraries/libldap/ldap-int.h"
35 #include <sys/time.h>
36
37 #ifdef LDAP_CACHING
38
39 static struct berval bv_queryid_any = BER_BVC( "(queryid=*)" );
40
41 static int
42 merge_func (
43         Operation       *op,
44         SlapReply       *rs
45 ); 
46
47 void
48 add_func (
49         Operation       *op,
50         SlapReply       *rs
51 ); 
52
53 static Attribute* 
54 add_attribute(AttributeDescription *ad,
55         Entry* e,
56         BerVarray value_array
57 ); 
58
59 static int
60 get_size_func (
61         Operation       *op,
62         SlapReply       *rs
63 ); 
64
65 struct entry_info {
66         int                     size_init; 
67         int                     size_final; 
68         int                     added; 
69         Entry*                  entry; 
70         struct berval*          uuid; 
71         struct timeval          tv;     /* time */ 
72         enum type_of_result     err; 
73         Backend*                glue_be; 
74 }; 
75
76 int 
77 get_entry_size(
78         Entry* e, 
79         int size_init, 
80         struct exception* result )
81 {
82         Attribute       *a;
83         struct berval   bv;
84         int             i; 
85         int             tmplen;
86         int             size=0;
87
88         if ( result )
89                 result->type = SUCCESS; 
90
91         if ( e->e_dn != NULL ) {
92                 tmplen = strlen( e->e_dn );
93                 size = LDIF_SIZE_NEEDED( 2, tmplen );
94         }
95
96         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
97                 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
98                         bv = a->a_vals[i];
99                         tmplen = a->a_desc->ad_cname.bv_len;
100                         size += LDIF_SIZE_NEEDED( tmplen, bv.bv_len);
101                 }
102         }
103         if ((size < size_init) && result) {
104                 result->type = SIZE_ERR; 
105         }
106         return size;
107 }
108
109 /* quick hack: call the right callback */
110 static int
111 add_merge_func( Operation *op, SlapReply *rs )
112 {
113         switch ( rs->sr_type ) {
114         case REP_SEARCH:
115                 add_func( op, rs );
116                 break;
117
118         case REP_RESULT:
119                 merge_func( op, rs );
120                 break;
121         }
122         return 0;
123 }
124
125 int
126 merge_entry(
127         Operation               *op,
128         SlapReply               *rs,
129         struct berval*          query_uuid, 
130         struct exception*       result )
131 {
132         struct entry_info info;
133         struct berval normdn;
134         struct berval prettydn;
135
136         Operation op_tmp = *op;
137         slap_callback cb = { add_merge_func, NULL };
138
139         Filter* filter = str2filter( bv_queryid_any.bv_val );
140
141         dnPrettyNormal(0, &rs->sr_entry->e_name, &prettydn, &normdn,
142                         op->o_tmpmemctx);
143
144         free(rs->sr_entry->e_name.bv_val);
145         rs->sr_entry->e_name = prettydn;
146         if (rs->sr_entry->e_nname.bv_val) free(rs->sr_entry->e_nname.bv_val);
147         rs->sr_entry->e_nname = normdn;
148
149         info.entry = rs->sr_entry;
150         info.uuid = query_uuid;
151         info.size_init = 0;
152         info.size_final = 0;
153         info.added = 0;
154         info.glue_be = op->o_bd;
155         info.err = SUCCESS;
156         cb.sc_private = &info;
157
158         op_tmp.o_tag = LDAP_REQ_SEARCH;
159         op_tmp.o_protocol = LDAP_VERSION3;
160         op_tmp.o_callback = &cb;
161         op_tmp.o_caching_on = 1;
162         op_tmp.o_time = slap_get_time();
163         op_tmp.o_do_not_cache = 1;
164
165         op_tmp.o_req_dn = rs->sr_entry->e_name;
166         op_tmp.o_req_ndn = rs->sr_entry->e_nname;
167         op_tmp.ors_scope = LDAP_SCOPE_BASE;
168         op_tmp.ors_deref = LDAP_DEREF_NEVER;
169         op_tmp.ors_slimit = 1;
170         op_tmp.ors_tlimit = 0;
171         op_tmp.ors_filter = filter;
172         op_tmp.ors_filterstr = bv_queryid_any;
173         op_tmp.ors_attrs = NULL;
174         op_tmp.ors_attrsonly = 0;
175
176         op->o_bd->be_search( &op_tmp, rs );
177         result->type = info.err; 
178         if ( result->type == SUCCESS )
179                 result->rc = info.added; 
180         else 
181                 result->rc = 0; 
182         return ( info.size_final - info.size_init );
183 }
184
185 static int
186 merge_func (
187         Operation       *op,
188         SlapReply       *rs
189 )
190 {
191         Backend                 *be;
192         char                    *new_attr_name;
193         Attribute               *a_new, *a;
194         int                     i = 0;
195         int                     rc = 0;
196     
197         int                     count;
198         struct timeval          time;   /* time */
199         long                    timediff; /* time */
200         struct entry_info       *info = op->o_callback->sc_private;
201         Filter                  *filter = str2filter( bv_queryid_any.bv_val );
202         Entry                   *entry = info->entry;
203         struct berval           *uuid = info->uuid;
204         Modifications           *modhead = NULL;
205         Modifications           *mod;
206         Modifications           **modtail = &modhead;
207         AttributeDescription    *a_new_desc;
208         const char              *text = NULL;
209         Operation               op_tmp = *op;
210
211         info->err = SUCCESS; 
212
213         be = select_backend(&entry->e_nname, 0, 0); 
214      
215         info->size_init = get_entry_size(rs->sr_entry, 0, 0);  
216         a_new = entry->e_attrs;
217
218         while (a_new != NULL) {
219                 a_new_desc = a_new->a_desc; 
220                 mod = (Modifications *) malloc( sizeof(Modifications) );
221                 mod->sml_op = LDAP_MOD_REPLACE;
222                 ber_dupbv(&mod->sml_type, &a_new_desc->ad_cname); 
223
224                 for (count = 0; a_new->a_vals[count].bv_val; count++) 
225                         ;
226                 mod->sml_bvalues = (struct berval*) malloc(
227                                 (count+1) * sizeof( struct berval) );
228
229                 for (i=0; i < count; i++) {
230                         ber_dupbv(mod->sml_bvalues+i, a_new->a_vals+i); 
231                 }
232
233                 mod->sml_bvalues[count].bv_val = 0; 
234                 mod->sml_bvalues[count].bv_len = 0; 
235
236                 mod->sml_desc = NULL;
237                 slap_bv2ad(&mod->sml_type, &mod->sml_desc, &text); 
238                 mod->sml_next =NULL;
239                 *modtail = mod;
240                 modtail = &mod->sml_next;
241                 a_new = a_new->a_next; 
242         } 
243
244         /* add query UUID to queryid attribute */
245         mod = (Modifications *) ch_malloc( sizeof(Modifications) );
246         mod->sml_op = LDAP_MOD_ADD;
247         mod->sml_desc = slap_schema.si_ad_queryid; 
248         ber_dupbv(&mod->sml_type, &mod->sml_desc->ad_cname); 
249         mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
250         ber_dupbv( mod->sml_bvalues, uuid );
251         mod->sml_bvalues[1].bv_val = NULL;
252         mod->sml_bvalues[1].bv_len = 0;
253         *modtail = mod;
254         mod->sml_next = NULL; 
255
256         /* Apply changes */
257         op_tmp.o_req_dn = entry->e_name;
258         op_tmp.o_req_ndn = entry->e_nname;
259         op_tmp.orm_modlist = modhead;
260
261         if (be->be_modify(op, rs ) != 0 ) {
262                 /* FIXME: cleanup ? */
263                 info->err = MERGE_ERR;
264                 return 0; 
265         }
266
267         /* compute the size of the entry */
268         op_tmp.o_callback->sc_response = get_size_func; 
269
270         op_tmp.ors_scope = LDAP_SCOPE_BASE;
271         op_tmp.ors_deref = LDAP_DEREF_NEVER;
272         op_tmp.ors_slimit = 1;
273         op_tmp.ors_tlimit = 0;
274         op_tmp.ors_filter = filter;
275         op_tmp.ors_filterstr = bv_queryid_any;
276         op_tmp.ors_attrs = NULL;
277         op_tmp.ors_attrsonly = 0;
278     
279         if (be->be_search( &op_tmp, rs ) != 0) {
280                 info->err = GET_SIZE_ERR;
281         }
282
283         return 0; 
284 }
285
286 void
287 add_func (
288         Operation       *op,
289         SlapReply       *rs
290 )
291 {
292         struct entry_info       *info = op->o_callback->sc_private; 
293         Entry                   *entry = info->entry; 
294         struct berval           *uuid = info->uuid; 
295         Backend                 *be; 
296         BerVarray               value_array; 
297         Entry                   *e; 
298         Attribute               *a; 
299
300         struct timeval          time;   /* time */ 
301         long                    timediff; /* time */ 
302
303         Operation               op_tmp = *op;
304
305         /* 
306          * new entry, construct an entry with 
307          * the projected attributes 
308          */
309         if (rs->sr_nentries) 
310                 return; 
311         
312         be = select_backend(&entry->e_nname, 0, 0); 
313         e = (Entry*)malloc(sizeof(Entry)); 
314
315         ber_dupbv(&e->e_name,&entry->e_name); 
316         ber_dupbv(&e->e_nname,&entry->e_nname); 
317
318         e->e_private = 0;
319         e->e_attrs = 0; 
320         e->e_bv.bv_val = 0; 
321
322         /* add queryid attribute */     
323         value_array = (struct berval *)malloc(2 * sizeof( struct berval) );
324         ber_dupbv(value_array, uuid);
325         value_array[1].bv_val = NULL;
326         value_array[1].bv_len = 0;
327
328         a = add_attribute(slap_schema.si_ad_queryid, 
329                         e, value_array); 
330
331         /* append the attribute list from the fetched entry */
332         a->a_next = entry->e_attrs;
333         entry->e_attrs = NULL;
334
335         info->size_final = get_entry_size(e, 0, NULL); 
336
337         op_tmp.o_bd = be;
338         op_tmp.ora_e = e;
339         
340         if ( be->be_add( &op_tmp, rs ) == 0 ) {
341                 info->added = 1; 
342                 be_entry_release_w( &op_tmp, e );
343         } else {
344                 info->err = MERGE_ERR; 
345         }
346 }
347  
348
349 static Attribute* 
350 add_attribute(AttributeDescription *ad,
351         Entry* e, 
352         BerVarray value_array) 
353 {
354         Attribute* new_attr, *last_attr; 
355         const char* text; 
356
357         if (e->e_attrs == NULL) 
358                 last_attr = NULL; 
359         else 
360                 for (last_attr = e->e_attrs; last_attr->a_next;
361                                 last_attr = last_attr->a_next)
362                         ; 
363
364         new_attr = (Attribute*)malloc(sizeof(Attribute));               
365         if (last_attr) 
366                 last_attr->a_next = new_attr;
367         else 
368                 e->e_attrs = new_attr; 
369
370         new_attr->a_next = NULL; 
371         new_attr->a_desc = NULL;
372         new_attr->a_vals = value_array; 
373         new_attr->a_desc = ad;
374
375         return new_attr; 
376 }
377
378 static int
379 get_size_func (
380         Operation       *op,
381         SlapReply       *rs
382 )
383 {
384         struct entry_info       *info = op->o_callback->sc_private; 
385         struct exception        result; 
386
387         if ( rs->sr_type == REP_SEARCH ) {
388                 result.type = info->err;  
389                 info->size_final = get_entry_size(rs->sr_entry,
390                                 info->size_init, &result); 
391         }
392
393         return 0; 
394 }
395
396 #endif /* LDAP_CACHING */