]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-merge.c
Fix prev commit, return generated passwd
[openldap] / servers / slapd / back-meta / cache-merge.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2003 The OpenLDAP Foundation.
5  * Portions Copyright 2003 IBM Corporation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS:
17  * This work was initially developed by the Apurva Kumar for inclusion
18  * in OpenLDAP Software.
19  */
20
21 #include "portable.h"
22
23 #include <stdio.h>
24
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/time.h>
28
29 #include "slap.h"
30 #include "ldif.h"
31 #include "../back-ldap/back-ldap.h"
32 #include "back-meta.h"
33 #include "ldap_pvt.h"
34 #undef ldap_debug       /* silence a warning in ldap-int.h */
35 #include "ldap_log.h"
36 #include "../../../libraries/libldap/ldap-int.h"
37 #include <sys/time.h>
38
39 static struct berval bv_queryid_any = BER_BVC( "(queryid=*)" );
40
41 static Attribute* 
42 add_attribute(AttributeDescription *ad,
43         Entry* e,
44         BerVarray value_array
45 ); 
46
47 static int
48 null_response (
49         Operation       *op,
50         SlapReply       *rs
51 ); 
52
53 static int 
54 normalize_values( Attribute* attr );    
55
56 struct entry_info {
57         int                     size_init; 
58         int                     size_final; 
59         int                     added; 
60         Entry*                  entry; 
61         struct berval*          uuid; 
62         struct timeval          tv;     /* time */ 
63         enum type_of_result     err; 
64         Backend*                glue_be; 
65 }; 
66
67
68 int 
69 get_entry_size(
70         Entry* e, 
71         int size_init, 
72         struct exception* result )
73 {
74         Attribute       *a;
75         struct berval   bv;
76         int             i; 
77         int             tmplen;
78         int             size=0;
79
80         if ( result )
81                 result->type = SUCCESS; 
82
83         if ( e->e_dn != NULL ) {
84                 tmplen = strlen( e->e_dn );
85                 size = LDIF_SIZE_NEEDED( 2, tmplen );
86         }
87
88         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
89                 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
90                         bv = a->a_vals[i];
91                         tmplen = a->a_desc->ad_cname.bv_len;
92                         size += LDIF_SIZE_NEEDED( tmplen, bv.bv_len);
93                 }
94         }
95         if ((size < size_init) && result) {
96                 result->type = SIZE_ERR; 
97         }
98         return size;
99 }
100
101 int
102 merge_entry(
103         Operation               *op,
104         SlapReply               *rs,
105         struct berval*          query_uuid, 
106         struct exception*       result )
107 {
108         struct entry_info info;
109         int             rc;
110         Modifications* modlist = NULL;
111         const char*     text = NULL;
112         BerVarray               value_array; 
113         Attribute               *uuid_attr, *attr;
114         Entry                   *e;
115         char                    textbuf[SLAP_TEXT_BUFLEN];
116         size_t                  textlen = sizeof(textbuf);
117
118         SlapReply sreply = {REP_RESULT};
119
120         Operation op_tmp = *op;
121         slap_callback cb;
122
123         sreply.sr_entry = NULL; 
124         sreply.sr_nentries = 0; 
125
126         e = ( Entry * ) ch_calloc( 1, sizeof( Entry )); 
127
128         dnPrettyNormal(0, &rs->sr_entry->e_name, &op_tmp.o_req_dn, &op_tmp.o_req_ndn, op->o_tmpmemctx);
129         ber_dupbv( &e->e_name, &op_tmp.o_req_dn );
130         ber_dupbv( &e->e_nname, &op_tmp.o_req_ndn );
131         sl_free( op_tmp.o_req_ndn.bv_val, op->o_tmpmemctx );
132         sl_free( op_tmp.o_req_dn.bv_val, op->o_tmpmemctx );
133         op_tmp.o_req_dn = e->e_name;
134         op_tmp.o_req_ndn = e->e_nname;
135
136         e->e_private = NULL;
137         e->e_attrs = NULL; 
138         e->e_bv.bv_val = NULL; 
139
140         /* add queryid attribute */     
141         value_array = (struct berval *)malloc(2 * sizeof( struct berval) );
142         ber_dupbv(value_array, query_uuid);
143         value_array[1].bv_val = NULL;
144         value_array[1].bv_len = 0;
145
146         uuid_attr = add_attribute(slap_schema.si_ad_queryid, e, value_array); 
147
148         /* append the attribute list from the fetched entry */
149         uuid_attr->a_next = rs->sr_entry->e_attrs;
150         rs->sr_entry->e_attrs = NULL;
151
152         for ( attr = e->e_attrs; attr; attr = attr->a_next ) {
153                 if ( normalize_values( attr ) ) {
154                         info.err = MERGE_ERR; 
155                         result->rc = info.err;
156                         return 0;
157                 }
158         }
159
160         info.entry = e;
161         info.uuid = query_uuid;
162         info.size_init = get_entry_size( rs->sr_entry, 0, 0 );
163         info.size_final = 0;
164         info.added = 0;
165         info.glue_be = op->o_bd;
166         info.err = SUCCESS;
167         cb.sc_private = &info;
168         cb.sc_response = null_response;
169
170         op_tmp.o_tag = LDAP_REQ_ADD;
171         op_tmp.o_protocol = LDAP_VERSION3;
172         op_tmp.o_callback = &cb;
173         op_tmp.o_time = slap_get_time();
174         op_tmp.o_do_not_cache = 1;
175
176         op_tmp.ora_e = e;
177         rc = op->o_bd->be_add( &op_tmp, &sreply );
178
179         if ( rc != LDAP_SUCCESS ) {
180                 if ( rc == LDAP_ALREADY_EXISTS ) {
181                         slap_entry2mods( e, &modlist, &text, textbuf, textlen );
182                         op_tmp.o_tag = LDAP_REQ_MODIFY;
183                         op_tmp.orm_modlist = modlist;
184                         op_tmp.o_req_dn = e->e_name;
185                         op_tmp.o_req_ndn = e->e_nname;
186                         rc = op->o_bd->be_modify( &op_tmp, &sreply );
187                         result->rc = info.added;
188                 } else if ( rc == LDAP_REFERRAL ||
189                                         rc == LDAP_NO_SUCH_OBJECT ) {
190                         syncrepl_add_glue( &op_tmp, e );
191                         result->rc = info.added;
192                 } else {
193                         result->rc = 0;
194                 }
195                 if ( modlist != NULL ) slap_mods_free( modlist );
196         } else {
197                 info.size_init = 0;
198                 result->rc = info.added;
199                 be_entry_release_w( &op_tmp, e );
200         }
201
202         if ( result->rc )
203                 info.size_final = get_entry_size( e, info.size_init, result );
204         else
205                 info.size_final = info.size_init;
206
207         return ( info.size_final - info.size_init );
208 }
209
210 static Attribute* 
211 add_attribute(AttributeDescription *ad,
212         Entry* e, 
213         BerVarray value_array) 
214 {
215         Attribute* new_attr, *last_attr; 
216         const char* text; 
217
218         if (e->e_attrs == NULL) 
219                 last_attr = NULL; 
220         else 
221                 for (last_attr = e->e_attrs; last_attr->a_next;
222                                 last_attr = last_attr->a_next)
223                         ; 
224
225         new_attr = (Attribute*)malloc(sizeof(Attribute));               
226         if (last_attr) 
227                 last_attr->a_next = new_attr;
228         else 
229                 e->e_attrs = new_attr; 
230
231         new_attr->a_next = NULL; 
232         new_attr->a_desc = NULL;
233         new_attr->a_vals = value_array; 
234         new_attr->a_desc = ad;
235
236         return new_attr; 
237 }
238
239 static int
240 null_response (
241         Operation       *op,
242         SlapReply       *rs )
243 {
244         return 0;
245 }
246
247 static int 
248 normalize_values( Attribute* attr ) 
249 {
250         int nvals, rc, i; 
251  
252         if (attr->a_vals == NULL) {
253                 attr->a_nvals = NULL; 
254                 return 0; 
255         } 
256
257         for ( nvals = 0; attr->a_vals[nvals].bv_val; nvals++ ) 
258                 ; 
259
260         attr->a_nvals = (struct berval*)ch_malloc((nvals+1)*sizeof(struct berval));
261
262         if ( attr->a_desc->ad_type->sat_equality &&
263                                 attr->a_desc->ad_type->sat_equality->smr_normalize )
264         {
265                 for ( i = 0; i < nvals; i++ ) {
266                         rc = attr->a_desc->ad_type->sat_equality->smr_normalize(
267                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
268                                 attr->a_desc->ad_type->sat_syntax,
269                                 attr->a_desc->ad_type->sat_equality,
270                                 &attr->a_vals[i], &attr->a_nvals[i], NULL );
271                         if ( rc ) {
272 #ifdef NEW_LOGGING
273                                 LDAP_LOG( OPERATION, DETAIL1,
274                                         "Error in normalizing attribute %s value %d (%d)\n",
275                                         attr->a_desc->ad_cname.bv_val, i, rc );
276 #else
277                                 Debug( LDAP_DEBUG_ANY,
278                                         "Error in normalizing attribute %s value %d (%d)\n",
279                                         attr->a_desc->ad_cname.bv_val, i, rc );
280 #endif
281                                 return rc;
282                         }
283                 }
284         } else {
285                 for ( i = 0; i < nvals; i++ ) {
286                         ber_dupbv( &attr->a_nvals[i], &attr->a_vals[i] ); 
287                 }
288         }
289                         
290         attr->a_nvals[i].bv_val = NULL;
291         attr->a_nvals[i].bv_len = 0;
292
293         return LDAP_SUCCESS;
294 }