]> git.sur5r.net Git - openldap/blob - servers/slapd/back-meta/cache-merge.c
211ec672e372dba2c359499644a1880a267be5c3
[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 static struct berval bv_queryid_any = BER_BVC( "(queryid=*)" );
38
39 static Attribute* 
40 add_attribute(AttributeDescription *ad,
41         Entry* e,
42         BerVarray value_array
43 ); 
44
45 static int
46 null_response (
47         Operation       *op,
48         SlapReply       *rs
49 ); 
50
51 static int 
52 normalize_values( Attribute* attr );    
53
54 struct entry_info {
55         int                     size_init; 
56         int                     size_final; 
57         int                     added; 
58         Entry*                  entry; 
59         struct berval*          uuid; 
60         struct timeval          tv;     /* time */ 
61         enum type_of_result     err; 
62         Backend*                glue_be; 
63 }; 
64
65
66 int 
67 get_entry_size(
68         Entry* e, 
69         int size_init, 
70         struct exception* result )
71 {
72         Attribute       *a;
73         struct berval   bv;
74         int             i; 
75         int             tmplen;
76         int             size=0;
77
78         if ( result )
79                 result->type = SUCCESS; 
80
81         if ( e->e_dn != NULL ) {
82                 tmplen = strlen( e->e_dn );
83                 size = LDIF_SIZE_NEEDED( 2, tmplen );
84         }
85
86         for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
87                 for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
88                         bv = a->a_vals[i];
89                         tmplen = a->a_desc->ad_cname.bv_len;
90                         size += LDIF_SIZE_NEEDED( tmplen, bv.bv_len);
91                 }
92         }
93         if ((size < size_init) && result) {
94                 result->type = SIZE_ERR; 
95         }
96         return size;
97 }
98
99 int
100 merge_entry(
101         Operation               *op,
102         SlapReply               *rs,
103         struct berval*          query_uuid, 
104         struct exception*       result )
105 {
106         struct entry_info info;
107         int             rc;
108         Modifications* modlist = NULL;
109         const char*     text = NULL;
110         BerVarray               value_array; 
111         Attribute               *uuid_attr, *attr;
112         Entry                   *e;
113
114         SlapReply sreply = {REP_RESULT};
115
116         Operation op_tmp = *op;
117         slap_callback cb;
118
119         sreply.sr_entry = NULL; 
120         sreply.sr_nentries = 0; 
121
122         e = ( Entry * ) ch_calloc( 1, sizeof( Entry )); 
123         dnPrettyNormal(0, &rs->sr_entry->e_name, &e->e_name, &e->e_nname, op->o_tmpmemctx);
124
125         e->e_private = NULL;
126         e->e_attrs = NULL; 
127         e->e_bv.bv_val = NULL; 
128
129         /* add queryid attribute */     
130         value_array = (struct berval *)malloc(2 * sizeof( struct berval) );
131         ber_dupbv(value_array, query_uuid);
132         value_array[1].bv_val = NULL;
133         value_array[1].bv_len = 0;
134
135         uuid_attr = add_attribute(slap_schema.si_ad_queryid, e, value_array); 
136
137         /* append the attribute list from the fetched entry */
138         uuid_attr->a_next = rs->sr_entry->e_attrs;
139         rs->sr_entry->e_attrs = NULL;
140
141         for ( attr = e->e_attrs; attr; attr = attr->a_next ) {
142                 if ( normalize_values( attr ) ) {
143                         info.err = MERGE_ERR; 
144                         result->rc = info.err;
145                         return 0;
146                 }
147         }
148
149         info.entry = e;
150         info.uuid = query_uuid;
151         info.size_init = get_entry_size( rs->sr_entry, 0, 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         cb.sc_response = null_response;
158
159         op_tmp.o_tag = LDAP_REQ_ADD;
160         op_tmp.o_protocol = LDAP_VERSION3;
161         op_tmp.o_callback = &cb;
162         op_tmp.o_time = slap_get_time();
163         op_tmp.o_do_not_cache = 1;
164
165         op_tmp.ora_e = e;
166         op_tmp.o_req_dn = e->e_name;
167         op_tmp.o_req_ndn = e->e_nname;
168         rc = op->o_bd->be_add( &op_tmp, &sreply );
169
170         if ( rc != LDAP_SUCCESS ) {
171                 if ( rc == LDAP_ALREADY_EXISTS ) {
172                         slap_entry2mods( e, &modlist, &text );
173                         op_tmp.o_tag = LDAP_REQ_MODIFY;
174                         op_tmp.orm_modlist = modlist;
175                         op_tmp.o_req_dn = e->e_name;
176                         op_tmp.o_req_ndn = e->e_nname;
177                         rc = op->o_bd->be_modify( &op_tmp, &sreply );
178                         result->rc = info.added;
179                 } else if ( rc == LDAP_REFERRAL ||
180                                         rc == LDAP_NO_SUCH_OBJECT ) {
181                         slap_entry2mods( e, &modlist, &text );
182                         syncrepl_add_glue( NULL, NULL, &op_tmp, e, modlist, 0, NULL, NULL );
183                         result->rc = info.added;
184                 } else {
185                         result->rc = 0;
186                 }
187                 if ( modlist != NULL ) slap_mods_free( modlist );
188         } else {
189                 info.size_init = 0;
190                 result->rc = info.added;
191                 be_entry_release_w( &op_tmp, e );
192         }
193
194         if ( result->rc )
195                 info.size_final = get_entry_size( e, info.size_init, result );
196         else
197                 info.size_final = info.size_init;
198
199         return ( info.size_final - info.size_init );
200 }
201
202 static Attribute* 
203 add_attribute(AttributeDescription *ad,
204         Entry* e, 
205         BerVarray value_array) 
206 {
207         Attribute* new_attr, *last_attr; 
208         const char* text; 
209
210         if (e->e_attrs == NULL) 
211                 last_attr = NULL; 
212         else 
213                 for (last_attr = e->e_attrs; last_attr->a_next;
214                                 last_attr = last_attr->a_next)
215                         ; 
216
217         new_attr = (Attribute*)malloc(sizeof(Attribute));               
218         if (last_attr) 
219                 last_attr->a_next = new_attr;
220         else 
221                 e->e_attrs = new_attr; 
222
223         new_attr->a_next = NULL; 
224         new_attr->a_desc = NULL;
225         new_attr->a_vals = value_array; 
226         new_attr->a_desc = ad;
227
228         return new_attr; 
229 }
230
231 static int
232 null_response (
233         Operation       *op,
234         SlapReply       *rs )
235 {
236         return 0;
237 }
238
239 static int 
240 normalize_values( Attribute* attr ) 
241 {
242         int nvals, rc, i; 
243  
244         if (attr->a_vals == NULL) {
245                 attr->a_nvals = NULL; 
246                 return 0; 
247         } 
248
249         for ( nvals = 0; attr->a_vals[nvals].bv_val; nvals++ ) 
250                 ; 
251
252         attr->a_nvals = (struct berval*)ch_malloc((nvals+1)*sizeof(struct berval));
253
254         if ( attr->a_desc->ad_type->sat_equality &&
255                                 attr->a_desc->ad_type->sat_equality->smr_normalize )
256         {
257                 for ( i = 0; i < nvals; i++ ) {
258                         rc = attr->a_desc->ad_type->sat_equality->smr_normalize(
259                                 0,
260                                 attr->a_desc->ad_type->sat_syntax,
261                                 attr->a_desc->ad_type->sat_equality,
262                                 &attr->a_vals[i], &attr->a_nvals[i], NULL );
263                         if ( rc ) {
264 #ifdef NEW_LOGGING
265                                 LDAP_LOG( OPERATION, DETAIL1,
266                                         "Error in normalizing attribute %s value %d (%d)\n",
267                                         attr->a_desc->ad_cname.bv_val, i, rc );
268 #else
269                                 Debug( LDAP_DEBUG_ANY,
270                                         "Error in normalizing attribute %s value %d (%d)\n",
271                                         attr->a_desc->ad_cname.bv_val, i, rc );
272 #endif
273                                 return rc;
274                         }
275                 }
276         } else {
277                 for ( i = 0; i < nvals; i++ ) {
278                         ber_dupbv( &attr->a_nvals[i], &attr->a_vals[i] ); 
279                 }
280         }
281                         
282         attr->a_nvals[i].bv_val = NULL;
283         attr->a_nvals[i].bv_len = 0;
284
285         return LDAP_SUCCESS;
286 }