]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-merge.c
Do not return pointers into BerElement we do not own
[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 static int
39 merge_func (
40         Backend *be,
41         Connection      *conn,
42         Operation       *op,
43         Entry   *stored_entry,
44         AttributeName   *attrs,
45         int             attrsonly,
46         LDAPControl **ctrls
47 ); 
48
49 void
50 add_func (
51         Connection      *conn,
52         Operation       *op,
53         ber_int_t       err,
54         const char      *matched,
55         const char      *text,
56         BerVarray       refs,
57         LDAPControl     **ctrls,
58         int             nentries
59 ); 
60
61 static Attribute* 
62 add_attribute(const char* attr_name, 
63         Entry* e,
64         BerVarray value_array
65 ); 
66
67 static int
68 get_size_func (
69         Backend         *be,
70         Connection      *conn,
71         Operation       *op,
72         Entry           *entry,
73         AttributeName   *attrs,
74         int             attrsonly,
75         LDAPControl     **ctrls
76 ); 
77
78
79 /* Two empty callback functions to avoid sending results */
80 void callback_null_response(
81         Connection      *conn,
82         Operation       *o,
83         ber_tag_t       tag,
84         ber_int_t       msgid,
85         ber_int_t       err,
86         const char      *matched,
87         const char      *text,
88         BerVarray       ref,
89         const char      *resoid,
90         struct berval   *resdata,
91         struct berval   *sasldata,
92         LDAPControl     **c     )
93 {
94 }
95
96 void callback_null_sresult(
97         Connection      *conn,
98         Operation       *o,
99         ber_int_t       err,
100         const char      *matched,
101         const char      *text,
102         BerVarray       refs,
103         LDAPControl     **c,
104         int nentries    )
105 {
106 }
107
108 struct entry_info {
109         int                     size_init; 
110         int                     size_final; 
111         int                     added; 
112         Entry*                  entry; 
113         struct berval*          uuid; 
114         struct timeval          tv;     /* time */ 
115         enum type_of_result     err; 
116         Backend*                glue_be; 
117 }; 
118
119 int 
120 get_entry_size(
121         Entry* e, 
122         int size_init, 
123         struct exception* result )
124 {
125         Attribute       *a;
126         struct berval   bv;
127         int             i; 
128         int             tmplen;
129         int             size=0;
130
131         if ( result )
132                 result->type = SUCCESS; 
133
134         if ( e->e_dn != NULL ) {
135                 tmplen = strlen( e->e_dn );
136                 size = LDIF_SIZE_NEEDED( 2, tmplen );
137         }
138
139         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
140                 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
141                         bv = a->a_vals[i];
142                         tmplen = a->a_desc->ad_cname.bv_len;
143                         size += LDIF_SIZE_NEEDED( tmplen, bv.bv_len);
144                 }
145         }
146         if ((size < size_init) && result) {
147                 result->type = SIZE_ERR; 
148         }
149         return size;
150 }
151
152
153 int
154 merge_entry (
155         Backend*                be,
156         Connection*             conn, 
157         Entry*                  e, 
158         struct berval*          query_uuid, 
159         struct exception*       result  )
160 {
161         struct entry_info info; 
162         struct berval normdn; 
163         struct berval prettydn; 
164
165         Operation op = {0};
166         slap_callback cb = {callback_null_response, 
167                 add_func, merge_func, NULL}; 
168
169         Filter* filter = str2filter("(queryid=*)");           
170
171         dnPrettyNormal(0, &(e->e_name), &prettydn, &normdn); 
172
173         free(e->e_name.bv_val); 
174         e->e_name = prettydn; 
175         e->e_nname = normdn; 
176
177         info.entry = e; 
178         info.uuid = query_uuid; 
179         info.size_init = 0; 
180         info.size_final = 0; 
181         info.added = 0; 
182         info.glue_be = be; 
183         info.err = SUCCESS; 
184         cb.sc_private = &info;
185
186         op.o_tag = LDAP_REQ_SEARCH;
187         op.o_protocol = LDAP_VERSION3;
188         op.o_ndn = conn->c_ndn;
189         op.o_callback = &cb;
190         op.o_caching_on = 1;
191         op.o_time = slap_get_time();
192         op.o_do_not_cache = 1;
193
194         be->be_search( be, conn, &op, NULL, &(e->e_nname),
195                 LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
196                 filter, NULL, NULL, 0 );
197         result->type = info.err; 
198         if ( result->type == SUCCESS )
199                 result->rc = info.added; 
200         else 
201                 result->rc = 0; 
202         return ( info.size_final - info.size_init );
203 }
204
205 static int
206 merge_func (
207         Backend         *be_glue,
208         Connection      *conn,
209         Operation       *op,
210         Entry           *e,
211         AttributeName   *attrs,
212         int             attrsonly,
213         LDAPControl     **ctrls
214 )
215
216         Backend* be; 
217         char            *new_attr_name;
218         Attribute               *a_new, *a;
219         int             i=0;
220         int             rc=0;
221     
222         int             count; 
223         struct timeval      time;       /* time */ 
224         long            timediff; /* time */ 
225         slap_callback   *tmp = op->o_callback;  
226         struct entry_info*      info = tmp->sc_private; 
227         Filter* filter = str2filter("(queryid=*)");           
228         Entry* entry = info->entry; 
229         struct berval* uuid = info->uuid; 
230         Modifications *modhead = NULL; 
231         Modifications *mod; 
232         Modifications **modtail = &modhead; 
233         AttributeDescription* a_new_desc;
234         const char      *text = NULL; 
235
236         info->err = SUCCESS; 
237
238         be = select_backend(&entry->e_nname, 0, 0); 
239      
240         info->size_init = get_entry_size(e, 0, 0);  
241         a_new = entry->e_attrs;
242
243         while (a_new != NULL) {
244                 a_new_desc = a_new->a_desc; 
245                 mod = (Modifications *) malloc( sizeof(Modifications) );
246                 mod->sml_op = LDAP_MOD_REPLACE;
247                 ber_dupbv(&(mod->sml_type), &(a_new_desc->ad_cname)); 
248
249                 for (count=0; a_new->a_vals[count].bv_val; count++) 
250                         ;
251                 mod->sml_bvalues = (struct berval*) malloc(
252                                 (count+1) * sizeof( struct berval) );
253
254                 for (i=0; i < count; i++) {
255                         ber_dupbv(mod->sml_bvalues+i, a_new->a_vals+i); 
256                 }
257
258                 mod->sml_bvalues[count].bv_val = 0; 
259                 mod->sml_bvalues[count].bv_len = 0; 
260
261                 mod->sml_desc = NULL;
262                 slap_bv2ad(&mod->sml_type, &mod->sml_desc, &text); 
263                 mod->sml_next =NULL;
264                 *modtail = mod;
265                 modtail = &mod->sml_next;
266                 a_new = a_new->a_next; 
267         } 
268
269         /* add query UUID to queryid attribute */
270         mod = (Modifications *) ch_malloc( sizeof(Modifications) );
271         mod->sml_op = LDAP_MOD_ADD;
272         mod->sml_desc = slap_schema.si_ad_queryid; 
273         ber_dupbv(&(mod->sml_type), &(mod->sml_desc->ad_cname)); 
274         mod->sml_bvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) );
275         ber_dupbv( mod->sml_bvalues, uuid );
276         mod->sml_bvalues[1].bv_val = NULL;
277         mod->sml_bvalues[1].bv_len = 0;
278         *modtail = mod;
279         mod->sml_next = NULL; 
280
281         if (be->be_modify(be, conn, op, &(entry->e_name),
282                                 &(entry->e_nname), modhead) != 0 ) {
283                 info->err = MERGE_ERR;
284                 return 0; 
285         }
286         op->o_callback->sc_sendentry = get_size_func; 
287         op->o_callback->sc_sresult = NULL; 
288     
289         if (be->be_search( be, conn, op, NULL, &(entry->e_nname),
290                         LDAP_SCOPE_BASE, LDAP_DEREF_NEVER, 1, 0,
291                         filter, NULL, NULL, 0 ) != 0) {
292                 info->err = GET_SIZE_ERR;
293         }
294         return 0; 
295 }
296
297 void
298 add_func (
299         Connection      *conn,
300         Operation       *op,
301         ber_int_t       err,
302         const char      *matched,
303         const char      *text,
304         BerVarray       refs,
305         LDAPControl **ctrls,
306         int             nentries
307 )
308 {
309         slap_callback   *tmp = op->o_callback;  
310         struct entry_info   *info = tmp->sc_private; 
311         Entry* entry = info->entry; 
312         struct berval* uuid = info->uuid; 
313         Backend* be; 
314         BerVarray               value_array; 
315         Entry           *e; 
316         Attribute               *a; 
317
318         struct timeval      time;       /* time */ 
319         long            timediff; /* time */ 
320
321         /* 
322          * new entry, construct an entry with 
323          * the projected attributes 
324          */
325         if (nentries) 
326                 return; 
327         
328         be = select_backend(&entry->e_nname, 0, 0); 
329         e = (Entry*)malloc(sizeof(Entry)); 
330
331         ber_dupbv(&e->e_name,&entry->e_name); 
332         ber_dupbv(&e->e_nname,&entry->e_nname); 
333
334         e->e_private = 0;
335         e->e_attrs = 0; 
336         e->e_bv.bv_val = 0; 
337
338         /* add queryid attribute */     
339         value_array = (struct berval *)malloc(2 * sizeof( struct berval) );
340         ber_dupbv(value_array, uuid);
341         value_array[1].bv_val = NULL;
342         value_array[1].bv_len = 0;
343
344         a = add_attribute("queryid", e, value_array); 
345
346         /* append the attribute list from the fetched entry */
347         a->a_next = entry->e_attrs;
348         entry->e_attrs = NULL;
349
350         info->size_final = get_entry_size(e, 0, NULL); 
351         if ( be->be_add( be, conn, op, e ) == 0 ) {
352                 info->added = 1; 
353                 be_entry_release_w( be, conn, op, e );
354         } else {
355                 info->err = MERGE_ERR; 
356         }
357 }
358  
359
360 static Attribute* 
361 add_attribute(const char* attr_name, 
362         Entry* e, 
363         BerVarray value_array) 
364 {
365         Attribute* new_attr, *last_attr; 
366         const char* text; 
367
368         if (e->e_attrs == NULL) 
369                 last_attr = NULL; 
370         else 
371                 for (last_attr = e->e_attrs; last_attr->a_next;
372                                 last_attr = last_attr->a_next)
373                         ; 
374
375         new_attr = (Attribute*)malloc(sizeof(Attribute));               
376         if (last_attr) 
377                 last_attr->a_next = new_attr;
378         else 
379                 e->e_attrs = new_attr; 
380
381         new_attr->a_next = NULL; 
382         new_attr->a_desc = NULL;
383         new_attr->a_vals = value_array; 
384         slap_str2ad(attr_name, &(new_attr->a_desc), &text);   
385
386         return new_attr; 
387 }
388
389 static int
390 get_size_func (
391         Backend         *be,
392         Connection      *conn,
393         Operation       *op,
394         Entry           *entry,
395         AttributeName   *attrs,
396         int             attrsonly,
397         LDAPControl     **ctrls
398 )
399 {
400         slap_callback           *tmp = op->o_callback;  
401         struct entry_info       *info = tmp->sc_private; 
402         struct exception        result; 
403
404         result.type = info->err;  
405         info->size_final = get_entry_size(entry, info->size_init, &result); 
406         return 0; 
407 }  
408 #endif /* LDAP_CACHING */