1 /* add.c - ldap BerkeleyDB back-end add routine */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
11 #include <ac/string.h>
17 bdb_add(Operation *op, SlapReply *rs )
19 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
23 char textbuf[SLAP_TEXT_BUFLEN];
24 size_t textlen = sizeof textbuf;
25 AttributeDescription *children = slap_schema.si_ad_children;
26 AttributeDescription *entry = slap_schema.si_ad_entry;
27 DB_TXN *ltid = NULL, *lt2;
28 struct bdb_op_info opinfo;
45 LDAP_LOG ( OPERATION, ARGS, "==> bdb_add: %s\n", op->oq_add.rs_e->e_name.bv_val, 0, 0 );
47 Debug(LDAP_DEBUG_ARGS, "==> bdb_add: %s\n", op->oq_add.rs_e->e_name.bv_val, 0, 0);
50 /* check entry's schema */
51 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e, NULL, &rs->sr_text, textbuf, textlen );
52 if ( rs->sr_err != LDAP_SUCCESS ) {
54 LDAP_LOG ( OPERATION, ERR,
55 "bdb_add: entry failed schema check: %s (%d)\n", rs->sr_text, rs->sr_err, 0 );
57 Debug( LDAP_DEBUG_TRACE,
58 "bdb_add: entry failed schema check: %s (%d)\n",
59 rs->sr_text, rs->sr_err, 0 );
65 subentry = is_entry_subentry( op->oq_add.rs_e );
69 * acquire an ID outside of the operation transaction
70 * to avoid serializing adds.
72 rs->sr_err = bdb_next_id( op->o_bd, NULL, &op->oq_add.rs_e->e_id );
73 if( rs->sr_err != 0 ) {
75 LDAP_LOG ( OPERATION, ERR,
76 "bdb_add: next_id failed (%d)\n", rs->sr_err, 0, 0 );
78 Debug( LDAP_DEBUG_TRACE,
79 "bdb_add: next_id failed (%d)\n", rs->sr_err, 0, 0 );
81 rs->sr_err = LDAP_OTHER;
82 rs->sr_text = "internal error";
87 retry: /* transaction retry */
89 /* free parent and reader lock */
90 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
93 rs->sr_err = TXN_ABORT( ltid );
96 op->o_do_not_cache = opinfo.boi_acl_cache;
97 if( rs->sr_err != 0 ) {
98 rs->sr_err = LDAP_OTHER;
99 rs->sr_text = "internal error";
102 bdb_trans_backoff( ++num_retries );
103 ldap_pvt_thread_yield();
106 /* begin transaction */
107 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, <id,
108 bdb->bi_db_opflags );
110 if( rs->sr_err != 0 ) {
112 LDAP_LOG ( OPERATION, ERR,
113 "bdb_add: txn_begin failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
115 Debug( LDAP_DEBUG_TRACE,
116 "bdb_add: txn_begin failed: %s (%d)\n",
117 db_strerror(rs->sr_err), rs->sr_err, 0 );
119 rs->sr_err = LDAP_OTHER;
120 rs->sr_text = "internal error";
124 locker = TXN_ID ( ltid );
126 opinfo.boi_bdb = op->o_bd;
127 opinfo.boi_txn = ltid;
128 opinfo.boi_locker = locker;
130 opinfo.boi_acl_cache = op->o_do_not_cache;
131 op->o_private = &opinfo;
134 * Get the parent dn and see if the corresponding entry exists.
135 * If the parent does not exist, only allow the "root" user to
138 if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
141 dnParent( &op->oq_add.rs_e->e_nname, &pdn );
144 /* get entry or parent */
145 rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
147 switch( rs->sr_err ) {
149 rs->sr_err = LDAP_ALREADY_EXISTS;
153 case DB_LOCK_DEADLOCK:
154 case DB_LOCK_NOTGRANTED:
157 rs->sr_text = "ldap server busy";
160 rs->sr_err = LDAP_OTHER;
161 rs->sr_text = "internal error";
167 if ( !bvmatch( &pdn, &p->e_nname ) ) {
168 rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
170 rs->sr_ref = is_entry_referral( p )
171 ? get_entry_referrals( op, p )
173 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
176 LDAP_LOG ( OPERATION, DETAIL1,
177 "bdb_add: parent does not exist\n", 0, 0, 0 );
179 Debug( LDAP_DEBUG_TRACE, "bdb_add: parent does not exist\n",
183 rs->sr_err = LDAP_REFERRAL;
184 send_ldap_result( op, rs );
186 ber_bvarray_free( rs->sr_ref );
187 op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx );
189 rs->sr_matched = NULL;
194 rs->sr_err = access_allowed( op, p,
195 children, NULL, ACL_WRITE, NULL );
197 if ( ! rs->sr_err ) {
198 switch( opinfo.boi_err ) {
199 case DB_LOCK_DEADLOCK:
200 case DB_LOCK_NOTGRANTED:
205 LDAP_LOG ( OPERATION, DETAIL1,
206 "bdb_add: no write access to parent\n", 0, 0, 0 );
208 Debug( LDAP_DEBUG_TRACE, "bdb_add: no write access to parent\n",
211 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
212 rs->sr_text = "no write access to parent";
213 goto return_results;;
216 #ifdef BDB_SUBENTRIES
217 if ( is_entry_subentry( p ) ) {
218 /* parent is a subentry, don't allow add */
220 LDAP_LOG ( OPERATION, DETAIL1,
221 "bdb_add: parent is subentry\n", 0, 0, 0 );
223 Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is subentry\n",
226 rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
227 rs->sr_text = "parent is a subentry";
228 goto return_results;;
232 if ( is_entry_alias( p ) ) {
233 /* parent is an alias, don't allow add */
235 LDAP_LOG ( OPERATION, DETAIL1,
236 "bdb_add: parent is alias\n", 0, 0, 0 );
238 Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is alias\n",
241 rs->sr_err = LDAP_ALIAS_PROBLEM;
242 rs->sr_text = "parent is an alias";
243 goto return_results;;
247 if ( is_entry_referral( p ) ) {
248 /* parent is a referral, don't allow add */
249 rs->sr_matched = p->e_name.bv_val;
250 rs->sr_ref = get_entry_referrals( op, p );
253 LDAP_LOG ( OPERATION, DETAIL1,
254 "bdb_add: parent is referral\n", 0, 0, 0 );
256 Debug( LDAP_DEBUG_TRACE, "bdb_add: parent is referral\n",
260 rs->sr_err = LDAP_REFERRAL;
261 send_ldap_result( op, rs );
263 ber_bvarray_free( rs->sr_ref );
264 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
266 rs->sr_matched = NULL;
271 #ifdef BDB_SUBENTRIES
274 /* parent must be an administrative point of the required kind */
278 /* free parent and reader lock */
279 bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, p );
285 * must be adding entry at suffix or with parent ""
287 if ( !be_isroot( op->o_bd, &op->o_ndn )) {
288 if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
289 || be_isupdate( op->o_bd, &op->o_ndn ) )
291 p = (Entry *)&slap_entry_root;
293 /* check parent for "children" acl */
294 rs->sr_err = access_allowed( op, p,
295 children, NULL, ACL_WRITE, NULL );
299 if ( ! rs->sr_err ) {
300 switch( opinfo.boi_err ) {
301 case DB_LOCK_DEADLOCK:
302 case DB_LOCK_NOTGRANTED:
307 LDAP_LOG ( OPERATION, DETAIL1,
308 "bdb_add: no write access to parent\n", 0, 0, 0 );
310 Debug( LDAP_DEBUG_TRACE,
311 "bdb_add: no write access to parent\n",
314 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
315 rs->sr_text = "no write access to parent";
318 } else if ( !is_entry_glue( op->oq_add.rs_e )) {
320 LDAP_LOG ( OPERATION, DETAIL1, "bdb_add: %s denied\n",
321 pdn.bv_len == 0 ? "suffix" : "entry at root", 0, 0 );
323 Debug( LDAP_DEBUG_TRACE, "bdb_add: %s denied\n",
324 pdn.bv_len == 0 ? "suffix" : "entry at root",
327 rs->sr_err = LDAP_NO_SUCH_OBJECT;
332 #ifdef BDB_SUBENTRIES
335 LDAP_LOG ( OPERATION, DETAIL1,
336 "bdb_add: no parent, cannot add subentry\n", 0, 0, 0 );
338 Debug( LDAP_DEBUG_TRACE,
339 "bdb_add: no parent, cannot add subentry\n",
342 rs->sr_err = LDAP_NO_SUCH_OBJECT;
343 rs->sr_text = "no parent, cannot add subentry";
349 if ( get_assert( op ) &&
350 ( test_filter( op, op->oq_add.rs_e, get_assertion( op ))
351 != LDAP_COMPARE_TRUE ))
353 rs->sr_err = LDAP_ASSERTION_FAILED;
357 rs->sr_err = access_allowed( op, op->oq_add.rs_e,
358 entry, NULL, ACL_WRITE, NULL );
360 if ( ! rs->sr_err ) {
361 switch( opinfo.boi_err ) {
362 case DB_LOCK_DEADLOCK:
363 case DB_LOCK_NOTGRANTED:
368 LDAP_LOG ( OPERATION, DETAIL1,
369 "bdb_add: no write access to entry\n", 0, 0, 0 );
371 Debug( LDAP_DEBUG_TRACE, "bdb_add: no write access to entry\n",
374 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
375 rs->sr_text = "no write access to entry";
376 goto return_results;;
379 /* nested transaction */
380 rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, <2,
381 bdb->bi_db_opflags );
383 if( rs->sr_err != 0 ) {
385 LDAP_LOG ( OPERATION, ERR,
386 "bdb_add: txn_begin(2) failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
388 Debug( LDAP_DEBUG_TRACE,
389 "bdb_add: txn_begin(2) failed: %s (%d)\n",
390 db_strerror(rs->sr_err), rs->sr_err, 0 );
392 rs->sr_err = LDAP_OTHER;
393 rs->sr_text = "internal error";
398 rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->oq_add.rs_e );
399 if ( rs->sr_err != 0 ) {
401 LDAP_LOG ( OPERATION, ERR,
402 "bdb_add: dn2id_add failed: %s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
404 Debug( LDAP_DEBUG_TRACE, "bdb_add: dn2id_add failed: %s (%d)\n",
405 db_strerror(rs->sr_err), rs->sr_err, 0 );
408 switch( rs->sr_err ) {
409 case DB_LOCK_DEADLOCK:
410 case DB_LOCK_NOTGRANTED:
413 rs->sr_err = LDAP_ALREADY_EXISTS;
416 rs->sr_err = LDAP_OTHER;
422 rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->oq_add.rs_e );
423 if ( rs->sr_err != 0 ) {
425 LDAP_LOG ( OPERATION, ERR, "bdb_add: id2entry_add failed\n", 0, 0, 0 );
427 Debug( LDAP_DEBUG_TRACE, "bdb_add: id2entry_add failed\n",
430 switch( rs->sr_err ) {
431 case DB_LOCK_DEADLOCK:
432 case DB_LOCK_NOTGRANTED:
435 rs->sr_err = LDAP_OTHER;
437 rs->sr_text = "entry store failed";
441 /* attribute indexes */
442 rs->sr_err = bdb_index_entry_add( op, lt2, op->oq_add.rs_e );
443 if ( rs->sr_err != LDAP_SUCCESS ) {
445 LDAP_LOG ( OPERATION, ERR,
446 "bdb_add: index_entry_add failed\n", 0, 0, 0 );
448 Debug( LDAP_DEBUG_TRACE, "bdb_add: index_entry_add failed\n",
451 switch( rs->sr_err ) {
452 case DB_LOCK_DEADLOCK:
453 case DB_LOCK_NOTGRANTED:
456 rs->sr_err = LDAP_OTHER;
458 rs->sr_text = "index generation failed";
461 if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
462 rs->sr_err = LDAP_OTHER;
463 rs->sr_text = "txn_commit(2) failed";
467 if ( !op->o_bd->syncinfo ) {
468 rc = bdb_csn_commit( op, rs, ltid, ei, &suffix_ei, &ctxcsn_e, &ctxcsn_added, locker );
478 if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
479 rs->sr_text = "txn_abort (no-op) failed";
482 rs->sr_err = LDAP_SUCCESS;
486 char gid[DB_XIDDATASIZE];
488 snprintf( gid, sizeof( gid ), "%s-%08lx-%08lx",
489 bdb_uuid.bv_val, (long) op->o_connid, (long) op->o_opid );
491 if (( rs->sr_err=TXN_PREPARE( ltid, gid )) != 0 ) {
492 rs->sr_text = "txn_prepare failed";
496 struct berval ctx_nrdn;
499 nrdn.bv_val = op->ora_e->e_nname.bv_val;
500 nrdn.bv_len = pdn.bv_val - nrdn.bv_val - 1;
502 nrdn = op->ora_e->e_nname;
505 bdb_cache_add( bdb, ei, op->oq_add.rs_e, &nrdn, locker );
507 if ( suffix_ei == NULL ) {
508 suffix_ei = op->oq_add.rs_e->e_private;
511 if ( !op->o_bd->syncinfo ) {
512 if ( ctxcsn_added ) {
513 ctx_nrdn.bv_val = "cn=ldapsync";
514 ctx_nrdn.bv_len = strlen( ctx_nrdn.bv_val );
515 bdb_cache_add( bdb, suffix_ei, ctxcsn_e, &ctx_nrdn, locker );
519 if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
520 rs->sr_text = "txn_commit failed";
522 rs->sr_err = LDAP_SUCCESS;
528 op->o_private = NULL;
530 if (rs->sr_err == LDAP_SUCCESS) {
532 LDAP_LOG ( OPERATION, RESULTS,
533 "bdb_add: added%s id=%08lx dn=\"%s\"\n",
534 op->o_noop ? " (no-op)" : "", op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
536 Debug(LDAP_DEBUG_TRACE, "bdb_add: added%s id=%08lx dn=\"%s\"\n",
537 op->o_noop ? " (no-op)" : "", op->oq_add.rs_e->e_id, op->oq_add.rs_e->e_dn );
543 LDAP_LOG ( OPERATION, ERR,
544 "bdb_add: %s : %s (%d)\n", rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
546 Debug( LDAP_DEBUG_TRACE, "bdb_add: %s : %s (%d)\n",
547 rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
549 rs->sr_err = LDAP_OTHER;
553 send_ldap_result( op, rs );
555 if ( rs->sr_err == LDAP_SUCCESS && !noop ) {
556 LDAP_LIST_FOREACH ( ps_list, &bdb->bi_psearch_list, o_ps_link ) {
557 bdb_psearch( op, rs, ps_list, op->oq_add.rs_e, LDAP_PSEARCH_BY_ADD );
561 if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp ) {
562 ldap_pvt_thread_yield();
563 TXN_CHECKPOINT( bdb->bi_dbenv,
564 bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
571 op->o_private = NULL;
574 return ( ( rs->sr_err == LDAP_SUCCESS ) ? noop : rs->sr_err );