]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/modify.c
comment cleanup
[openldap] / servers / slapd / back-bdb / modify.c
1 /* modify.c - bdb backend modify routine */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12 #include <ac/time.h>
13
14 #include "back-bdb.h"
15 #include "external.h"
16
17 int bdb_modify_internal(
18         Operation *op,
19         DB_TXN *tid,
20         Modifications *modlist,
21         Entry *e,
22         const char **text,
23         char *textbuf,
24         size_t textlen )
25 {
26         int rc, err;
27         Modification    *mod;
28         Modifications   *ml;
29         Attribute       *save_attrs;
30         Attribute       *ap;
31
32 #ifdef NEW_LOGGING
33         LDAP_LOG ( OPERATION, ENTRY, "bdb_modify_internal: 0x%08lx: %s\n", 
34                 e->e_id, e->e_dn, 0 );
35 #else
36         Debug( LDAP_DEBUG_TRACE, "bdb_modify_internal: 0x%08lx: %s\n",
37                 e->e_id, e->e_dn, 0);
38 #endif
39
40         if ( !acl_check_modlist( op, e, modlist )) {
41                 return LDAP_INSUFFICIENT_ACCESS;
42         }
43
44         /* save_attrs will be disposed of by bdb_cache_modify */
45         save_attrs = e->e_attrs;
46         e->e_attrs = attrs_dup( e->e_attrs );
47
48         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
49                 mod = &ml->sml_mod;
50
51                 switch ( mod->sm_op ) {
52                 case LDAP_MOD_ADD:
53 #ifdef NEW_LOGGING
54                         LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify_internal: add\n", 0,0,0);
55 #else
56                         Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: add\n", 0, 0, 0);
57 #endif
58                         err = modify_add_values( e, mod, get_permissiveModify(op),
59                                 text, textbuf, textlen );
60                         if( err != LDAP_SUCCESS ) {
61 #ifdef NEW_LOGGING
62                                 LDAP_LOG ( OPERATION, ERR, 
63                                         "bdb_modify_internal: %d %s\n", err, *text, 0 );
64 #else
65                                 Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
66                                         err, *text, 0);
67 #endif
68                         }
69                         break;
70
71                 case LDAP_MOD_DELETE:
72 #ifdef NEW_LOGGING
73                         LDAP_LOG ( OPERATION, DETAIL1, 
74                                 "bdb_modify_internal: delete\n", 0, 0, 0 );
75 #else
76                         Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: delete\n", 0, 0, 0);
77 #endif
78                         err = modify_delete_values( e, mod, get_permissiveModify(op),
79                                 text, textbuf, textlen );
80                         assert( err != LDAP_TYPE_OR_VALUE_EXISTS );
81                         if( err != LDAP_SUCCESS ) {
82 #ifdef NEW_LOGGING
83                                 LDAP_LOG ( OPERATION, ERR, 
84                                         "bdb_modify_internal: %d %s\n", err, *text, 0 );
85 #else
86                                 Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
87                                         err, *text, 0);
88 #endif
89                         }
90                         break;
91
92                 case LDAP_MOD_REPLACE:
93 #ifdef NEW_LOGGING
94                         LDAP_LOG ( OPERATION, DETAIL1, 
95                                 "bdb_modify_internal: replace\n", 0, 0, 0 );
96 #else
97                         Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: replace\n", 0, 0, 0);
98 #endif
99                         err = modify_replace_values( e, mod, get_permissiveModify(op),
100                                 text, textbuf, textlen );
101                         if( err != LDAP_SUCCESS ) {
102 #ifdef NEW_LOGGING
103                                 LDAP_LOG ( OPERATION, ERR, 
104                                         "bdb_modify_internal: %d %s\n", err, *text, 0 );
105 #else
106                                 Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
107                                         err, *text, 0);
108 #endif
109                         }
110                         break;
111
112                 case SLAP_MOD_SOFTADD:
113 #ifdef NEW_LOGGING
114                         LDAP_LOG ( OPERATION, DETAIL1, 
115                                 "bdb_modify_internal: softadd\n",0,0,0 );
116 #else
117                         Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: softadd\n", 0, 0, 0);
118 #endif
119                         /* Avoid problems in index_add_mods()
120                          * We need to add index if necessary.
121                          */
122                         mod->sm_op = LDAP_MOD_ADD;
123
124                         err = modify_add_values( e, mod, get_permissiveModify(op),
125                                 text, textbuf, textlen );
126
127                         mod->sm_op = SLAP_MOD_SOFTADD;
128
129                         if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) {
130                                 err = LDAP_SUCCESS;
131                         }
132
133                         if( err != LDAP_SUCCESS ) {
134 #ifdef NEW_LOGGING
135                                 LDAP_LOG ( OPERATION, ERR, 
136                                         "bdb_modify_internal: %d %s\n", err, *text, 0 );
137 #else
138                                 Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
139                                         err, *text, 0);
140 #endif
141                         }
142                         break;
143
144                 default:
145 #ifdef NEW_LOGGING
146                                 LDAP_LOG ( OPERATION, ERR, 
147                                         "bdb_modify_internal: invalid op %d\n", mod->sm_op, 0, 0 );
148 #else
149                         Debug(LDAP_DEBUG_ANY, "bdb_modify_internal: invalid op %d\n",
150                                 mod->sm_op, 0, 0);
151 #endif
152                         *text = "Invalid modify operation";
153                         err = LDAP_OTHER;
154 #ifdef NEW_LOGGING
155                                 LDAP_LOG ( OPERATION, ERR, 
156                                         "bdb_modify_internal: %d %s\n", err, *text, 0 );
157 #else
158                         Debug(LDAP_DEBUG_ARGS, "bdb_modify_internal: %d %s\n",
159                                 err, *text, 0);
160 #endif
161                 }
162
163                 if ( err != LDAP_SUCCESS ) {
164                         attrs_free( e->e_attrs );
165                         e->e_attrs = save_attrs;
166                         /* unlock entry, delete from cache */
167                         return err; 
168                 }
169
170                 /* If objectClass was modified, reset the flags */
171                 if ( mod->sm_desc == slap_schema.si_ad_objectClass ) {
172                         e->e_ocflags = 0;
173                 }
174
175                 /* check if modified attribute was indexed
176                  * but not in case of NOOP... */
177                 err = bdb_index_is_indexed( op->o_bd, mod->sm_desc );
178                 if ( err == LDAP_SUCCESS && !op->o_noop ) {
179                         ap = attr_find( save_attrs, mod->sm_desc );
180                         if ( ap ) ap->a_flags |= SLAP_ATTR_IXDEL;
181
182                         ap = attr_find( e->e_attrs, mod->sm_desc );
183                         if ( ap ) ap->a_flags |= SLAP_ATTR_IXADD;
184                 }
185         }
186
187         /* check that the entry still obeys the schema */
188         rc = entry_schema_check( op->o_bd, e, save_attrs, text, textbuf, textlen );
189         if ( rc != LDAP_SUCCESS || op->o_noop ) {
190                 attrs_free( e->e_attrs );
191                 e->e_attrs = save_attrs;
192
193                 if ( rc != LDAP_SUCCESS ) {
194 #ifdef NEW_LOGGING
195                         LDAP_LOG ( OPERATION, ERR, "bdb_modify_internal: "
196                                 "entry failed schema check %s\n", 
197                                 *text, 0, 0 );
198 #else
199                         Debug( LDAP_DEBUG_ANY,
200                                 "entry failed schema check: %s\n",
201                                 *text, 0, 0 );
202 #endif
203                 }
204
205                 /* if NOOP then silently revert to saved attrs */
206                 return rc;
207         }
208
209         /* update the indices of the modified attributes */
210
211         /* start with deleting the old index entries */
212         for ( ap = save_attrs; ap != NULL; ap = ap->a_next ) {
213                 if ( ap->a_flags & SLAP_ATTR_IXDEL ) {
214                         rc = bdb_index_values( op, tid, ap->a_desc,
215                                 ap->a_nvals,
216                                 e->e_id, SLAP_INDEX_DELETE_OP );
217                         if ( rc != LDAP_SUCCESS ) {
218                                 attrs_free( e->e_attrs );
219                                 e->e_attrs = save_attrs;
220 #ifdef NEW_LOGGING
221                                 LDAP_LOG ( OPERATION, ERR, 
222                                         "bdb_modify_internal: attribute index delete failure\n",
223                                         0, 0, 0 );
224 #else
225                                 Debug( LDAP_DEBUG_ANY,
226                                        "Attribute index delete failure",
227                                        0, 0, 0 );
228 #endif
229                                 return rc;
230                         }
231                         ap->a_flags &= ~SLAP_ATTR_IXDEL;
232                 }
233         }
234
235         /* add the new index entries */
236         for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
237                 if (ap->a_flags & SLAP_ATTR_IXADD) {
238                         rc = bdb_index_values( op, tid, ap->a_desc,
239                                 ap->a_nvals,
240                                 e->e_id, SLAP_INDEX_ADD_OP );
241                         if ( rc != LDAP_SUCCESS ) {
242                                 attrs_free( e->e_attrs );
243                                 e->e_attrs = save_attrs;
244 #ifdef NEW_LOGGING
245                                 LDAP_LOG ( OPERATION, ERR, 
246                                         "bdb_modify_internal: attribute index add failure\n", 
247                                         0, 0, 0 );
248 #else
249                                 Debug( LDAP_DEBUG_ANY,
250                                        "Attribute index add failure",
251                                        0, 0, 0 );
252 #endif
253                                 return rc;
254                         }
255                         ap->a_flags &= ~SLAP_ATTR_IXADD;
256                 }
257         }
258
259         return rc;
260 }
261
262
263 int
264 bdb_modify( Operation *op, SlapReply *rs )
265 {
266         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
267         Entry           *e = NULL;
268         EntryInfo       *ei = NULL;
269         int             manageDSAit = get_manageDSAit( op );
270         char textbuf[SLAP_TEXT_BUFLEN];
271         size_t textlen = sizeof textbuf;
272         DB_TXN  *ltid = NULL, *lt2;
273         struct bdb_op_info opinfo;
274         Entry           dummy;
275
276         u_int32_t       locker = 0;
277         DB_LOCK         lock;
278
279         int             noop = 0;
280
281 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
282         Operation* ps_list;
283         struct psid_entry *pm_list, *pm_prev;
284 #endif
285
286 #ifdef NEW_LOGGING
287         LDAP_LOG ( OPERATION, ENTRY, "bdb_modify: %s\n", op->o_req_dn.bv_val, 0, 0 );
288 #else
289         Debug( LDAP_DEBUG_ARGS, "bdb_modify: %s\n", op->o_req_dn.bv_val, 0, 0 );
290 #endif
291
292         if( 0 ) {
293 retry:  /* transaction retry */
294                 if( e != NULL ) {
295                         bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
296                         e = NULL;
297                 }
298 #ifdef NEW_LOGGING
299                 LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify: retrying...\n", 0, 0, 0 );
300 #else
301                 Debug(LDAP_DEBUG_TRACE,
302                         "bdb_modify: retrying...\n", 0, 0, 0);
303 #endif
304
305 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
306                 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
307                 while ( pm_list != NULL ) {
308                         LDAP_LIST_REMOVE ( pm_list, ps_link );
309                         pm_prev = pm_list;
310                         pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
311                         ch_free( pm_prev );
312                 }
313 #endif
314
315                 rs->sr_err = TXN_ABORT( ltid );
316                 ltid = NULL;
317                 op->o_private = NULL;
318                 op->o_do_not_cache = opinfo.boi_acl_cache;
319                 if( rs->sr_err != 0 ) {
320                         rs->sr_err = LDAP_OTHER;
321                         rs->sr_text = "internal error";
322                         goto return_results;
323                 }
324                 ldap_pvt_thread_yield();
325         }
326
327         /* begin transaction */
328         rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
329                 bdb->bi_db_opflags );
330         rs->sr_text = NULL;
331         if( rs->sr_err != 0 ) {
332 #ifdef NEW_LOGGING
333                 LDAP_LOG ( OPERATION, DETAIL1, 
334                         "bdb_modify: txn_begin failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
335 #else
336                 Debug( LDAP_DEBUG_TRACE,
337                         "bdb_modify: txn_begin failed: %s (%d)\n",
338                         db_strerror(rs->sr_err), rs->sr_err, 0 );
339 #endif
340                 rs->sr_err = LDAP_OTHER;
341                 rs->sr_text = "internal error";
342                 goto return_results;
343         }
344
345         locker = TXN_ID ( ltid );
346
347         opinfo.boi_bdb = op->o_bd;
348         opinfo.boi_txn = ltid;
349         opinfo.boi_locker = locker;
350         opinfo.boi_err = 0;
351         opinfo.boi_acl_cache = op->o_do_not_cache;
352         op->o_private = &opinfo;
353
354         /* get entry or ancestor */
355         rs->sr_err = bdb_dn2entry( op->o_bd, ltid, &op->o_req_ndn, &ei, 1,
356                 locker, &lock, op->o_tmpmemctx );
357
358         if ( rs->sr_err != 0 ) {
359 #ifdef NEW_LOGGING
360                 LDAP_LOG ( OPERATION, DETAIL1, 
361                         "bdb_modify: dn2entry failed: (%d)\n", rs->sr_err, 0, 0 );
362 #else
363                 Debug( LDAP_DEBUG_TRACE,
364                         "bdb_modify: dn2entry failed (%d)\n",
365                         rs->sr_err, 0, 0 );
366 #endif
367                 switch( rs->sr_err ) {
368                 case DB_LOCK_DEADLOCK:
369                 case DB_LOCK_NOTGRANTED:
370                         goto retry;
371                 case DB_NOTFOUND:
372                         break;
373                 case LDAP_BUSY:
374                         rs->sr_text = "ldap server busy";
375                         goto return_results;
376                 default:
377                         rs->sr_err = LDAP_OTHER;
378                         rs->sr_text = "internal error";
379                         goto return_results;
380                 }
381         }
382
383         e = ei->bei_e;
384         /* acquire and lock entry */
385         if ( rs->sr_err == DB_NOTFOUND ) {
386                 if ( e != NULL ) {
387                         rs->sr_matched = ch_strdup( e->e_dn );
388                         rs->sr_ref = is_entry_referral( e )
389                                 ? get_entry_referrals( op, e )
390                                 : NULL;
391                         bdb_unlocked_cache_return_entry_r (&bdb->bi_cache, e);
392                         e = NULL;
393
394                 } else {
395                         rs->sr_ref = referral_rewrite( default_referral,
396                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
397                 }
398
399                 rs->sr_err = LDAP_REFERRAL;
400                 send_ldap_result( op, rs );
401
402                 ber_bvarray_free( rs->sr_ref );
403                 free( (char *)rs->sr_matched );
404                 rs->sr_ref = NULL;
405                 rs->sr_matched = NULL;
406
407                 goto done;
408         }
409
410         if ( !manageDSAit && is_entry_referral( e ) ) {
411                 /* entry is a referral, don't allow modify */
412                 rs->sr_ref = get_entry_referrals( op, e );
413
414 #ifdef NEW_LOGGING
415                 LDAP_LOG ( OPERATION, DETAIL1, "bdb_modify: entry is referral\n", 0, 0, 0 );
416 #else
417                 Debug( LDAP_DEBUG_TRACE,
418                         "bdb_modify: entry is referral\n",
419                         0, 0, 0 );
420 #endif
421
422                 rs->sr_err = LDAP_REFERRAL;
423                 rs->sr_matched = e->e_name.bv_val;
424                 send_ldap_result( op, rs );
425
426                 ber_bvarray_free( rs->sr_ref );
427                 rs->sr_ref = NULL;
428                 rs->sr_matched = NULL;
429                 goto done;
430         }
431
432 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
433         if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
434                 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
435                         bdb_psearch(op, rs, ps_list, e, LDAP_PSEARCH_BY_PREMODIFY );
436                 }
437         }
438 #endif
439         
440         /* nested transaction */
441         rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, 
442                 bdb->bi_db_opflags );
443         rs->sr_text = NULL;
444         if( rs->sr_err != 0 ) {
445 #ifdef NEW_LOGGING
446                 LDAP_LOG ( OPERATION, ERR, 
447                         "bdb_modify: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
448 #else
449                 Debug( LDAP_DEBUG_TRACE,
450                         "bdb_modify: txn_begin(2) failed: %s (%d)\n",
451                         db_strerror(rs->sr_err), rs->sr_err, 0 );
452 #endif
453                 rs->sr_err = LDAP_OTHER;
454                 rs->sr_text = "internal error";
455                 goto return_results;
456         }
457         /* Modify the entry */
458         dummy = *e;
459         rs->sr_err = bdb_modify_internal( op, lt2, op->oq_modify.rs_modlist,
460                 &dummy, &rs->sr_text, textbuf, textlen );
461
462         if( rs->sr_err != LDAP_SUCCESS ) {
463 #ifdef NEW_LOGGING
464                 LDAP_LOG ( OPERATION, ERR, 
465                         "bdb_modify: modify failed (%d)\n", rs->sr_err, 0, 0 );
466 #else
467                 Debug( LDAP_DEBUG_TRACE,
468                         "bdb_modify: modify failed (%d)\n",
469                         rs->sr_err, 0, 0 );
470 #endif
471                 if ( (rs->sr_err == LDAP_INSUFFICIENT_ACCESS) && opinfo.boi_err ) {
472                         rs->sr_err = opinfo.boi_err;
473                 }
474                 switch( rs->sr_err ) {
475                 case DB_LOCK_DEADLOCK:
476                 case DB_LOCK_NOTGRANTED:
477                         goto retry;
478                 }
479                 goto return_results;
480         }
481
482         /* change the entry itself */
483         rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
484         if ( rs->sr_err != 0 ) {
485 #ifdef NEW_LOGGING
486                 LDAP_LOG ( OPERATION, ERR, 
487                         "bdb_modify: id2entry update failed (%d)\n", rs->sr_err, 0, 0 );
488 #else
489                 Debug( LDAP_DEBUG_TRACE,
490                         "bdb_modify: id2entry update failed (%d)\n",
491                         rs->sr_err, 0, 0 );
492 #endif
493                 switch( rs->sr_err ) {
494                 case DB_LOCK_DEADLOCK:
495                 case DB_LOCK_NOTGRANTED:
496                         goto retry;
497                 }
498                 rs->sr_text = "entry update failed";
499                 goto return_results;
500         }
501         if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
502                 rs->sr_err = LDAP_OTHER;
503                 rs->sr_text = "txn_commit(2) failed";
504                 goto return_results;
505         }
506
507         if( op->o_noop ) {
508                 if ( ( rs->sr_err = TXN_ABORT( ltid ) ) != 0 ) {
509                         rs->sr_text = "txn_abort (no-op) failed";
510                 } else {
511                         noop = 1;
512                         rs->sr_err = LDAP_SUCCESS;
513                 }
514         } else {
515                 bdb_cache_modify( e, dummy.e_attrs, bdb->bi_dbenv, locker, &lock );
516                 rs->sr_err = TXN_COMMIT( ltid, 0 );
517         }
518         ltid = NULL;
519         op->o_private = NULL;
520
521         if( rs->sr_err != 0 ) {
522 #ifdef NEW_LOGGING
523                 LDAP_LOG ( OPERATION, ERR, 
524                         "bdb_modify: txn_%s failed %s (%d)\n", 
525                         op->o_noop ? "abort (no_op)" : "commit", db_strerror(rs->sr_err), rs->sr_err );
526 #else
527                 Debug( LDAP_DEBUG_TRACE,
528                         "bdb_modify: txn_%s failed: %s (%d)\n",
529                         op->o_noop ? "abort (no-op)" : "commit",
530                         db_strerror(rs->sr_err), rs->sr_err );
531 #endif
532                 rs->sr_err = LDAP_OTHER;
533                 rs->sr_text = "commit failed";
534
535         } else {
536 #ifdef NEW_LOGGING
537                 LDAP_LOG ( OPERATION, DETAIL1, 
538                         "bdb_modify: updated%s id=%08lx dn=\"%s\"\n", 
539                         op->o_noop ? " (no_op)" : "", e->e_id, e->e_dn );
540 #else
541                 Debug( LDAP_DEBUG_TRACE,
542                         "bdb_modify: updated%s id=%08lx dn=\"%s\"\n",
543                         op->o_noop ? " (no-op)" : "",
544                         e->e_id, e->e_dn );
545 #endif
546                 rs->sr_err = LDAP_SUCCESS;
547                 rs->sr_text = NULL;
548         }
549
550 return_results:
551         send_ldap_result( op, rs );
552
553 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
554         if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
555                 /* Loop through in-scope entries for each psearch spec */
556                 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
557                         bdb_psearch( op, rs, ps_list, e, LDAP_PSEARCH_BY_MODIFY );
558                 }
559                 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
560                 while ( pm_list != NULL ) {
561                         bdb_psearch(op, rs, pm_list->ps_op,
562                                                 e, LDAP_PSEARCH_BY_SCOPEOUT);
563                         LDAP_LIST_REMOVE ( pm_list, ps_link );
564                         pm_prev = pm_list;
565                         pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
566                         ch_free( pm_prev );
567                 }
568         }
569 #endif
570
571         if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
572                 ldap_pvt_thread_yield();
573                 TXN_CHECKPOINT( bdb->bi_dbenv,
574                         bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
575         }
576
577 done:
578         if( ltid != NULL ) {
579 #if defined(LDAP_CLIENT_UPDATE) || defined(LDAP_SYNC)
580                 pm_list = LDAP_LIST_FIRST(&op->o_pm_list);
581                 while ( pm_list != NULL ) {
582                         LDAP_LIST_REMOVE ( pm_list, ps_link );
583                         pm_prev = pm_list;
584                         pm_list = LDAP_LIST_NEXT ( pm_list, ps_link );
585                         ch_free( pm_prev );
586                 }
587 #endif
588                 TXN_ABORT( ltid );
589                 op->o_private = NULL;
590         }
591
592         if( e != NULL ) {
593                 bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
594         }
595         return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err );
596 }