コード例 #1
0
ファイル: modrdn.c プロジェクト: DanahBlanahaseth/cniiag_ldap
int
bdb_modrdn( Operation	*op, SlapReply *rs )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	struct berval	p_dn, p_ndn;
	struct berval	new_dn = {0, NULL}, new_ndn = {0, NULL};
	Entry		*e = NULL;
	Entry		*p = NULL;
	EntryInfo	*ei = NULL, *eip = NULL, *nei = NULL, *neip = NULL;
	/* LDAP v2 supporting correct attribute handling. */
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;
	DB_TXN		*ltid = NULL, *lt2;
	struct bdb_op_info opinfo = {{{ 0 }}};
	Entry dummy = {0};

	Entry		*np = NULL;			/* newSuperior Entry */
	struct berval	*np_dn = NULL;			/* newSuperior dn */
	struct berval	*np_ndn = NULL;			/* newSuperior ndn */
	struct berval	*new_parent_dn = NULL;	/* np_dn, p_dn, or NULL */

	int		manageDSAit = get_manageDSAit( op );

	DB_LOCK		lock, plock, nplock;

	int		num_retries = 0;

	LDAPControl **preread_ctrl = NULL;
	LDAPControl **postread_ctrl = NULL;
	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
	int num_ctrls = 0;

	int	rc;

	int parent_is_glue = 0;
	int parent_is_leaf = 0;

#ifdef LDAP_X_TXN
	int settle = 0;
#endif

	Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n",
		op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val,
		op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" );

#ifdef LDAP_X_TXN
	if( op->o_txnSpec ) {
		/* acquire connection lock */
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
			rs->sr_text = "invalid transaction identifier";
			rs->sr_err = LDAP_X_TXN_ID_INVALID;
			goto txnReturn;
		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
			settle=1;
			goto txnReturn;
		}

		if( op->o_conn->c_txn_backend == NULL ) {
			op->o_conn->c_txn_backend = op->o_bd;

		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
			rs->sr_text = "transaction cannot span multiple database contexts";
			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
			goto txnReturn;
		}

		/* insert operation into transaction */

		rs->sr_text = "transaction specified";
		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;

txnReturn:
		/* release connection lock */
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );

		if( !settle ) {
			send_ldap_result( op, rs );
			return rs->sr_err;
		}
	}
#endif

	ctrls[num_ctrls] = NULL;

	slap_mods_opattrs( op, &op->orr_modlist, 1 );

	if( 0 ) {
retry:	/* transaction retry */
		if ( dummy.e_attrs ) {
			attrs_free( dummy.e_attrs );
			dummy.e_attrs = NULL;
		}
		if (e != NULL) {
			bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
			e = NULL;
		}
		if (p != NULL) {
			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
			p = NULL;
		}
		if (np != NULL) {
			bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
			np = NULL;
		}
		Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn)
				": retrying...\n", 0, 0, 0 );

		rs->sr_err = TXN_ABORT( ltid );
		ltid = NULL;
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
		opinfo.boi_oe.oe_key = NULL;
		op->o_do_not_cache = opinfo.boi_acl_cache;
		if( rs->sr_err != 0 ) {
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}
		if ( op->o_abandon ) {
			rs->sr_err = SLAPD_ABANDON;
			goto return_results;
		}
		parent_is_glue = 0;
		parent_is_leaf = 0;
		bdb_trans_backoff( ++num_retries );
	}

	/* begin transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
		bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn) ": txn_begin failed: "
			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn1 id: %x\n",
		ltid->id(ltid), 0, 0 );

	opinfo.boi_oe.oe_key = bdb;
	opinfo.boi_txn = ltid;
	opinfo.boi_err = 0;
	opinfo.boi_acl_cache = op->o_do_not_cache;
	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );

	/* get entry */
	rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
		&lock );

	switch( rs->sr_err ) {
	case 0:
	case DB_NOTFOUND:
		break;
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	e = ei->bei_e;
	/* FIXME: dn2entry() should return non-glue entry */
	if (( rs->sr_err == DB_NOTFOUND ) ||
		( !manageDSAit && e && is_entry_glue( e )))
	{
		if( e != NULL ) {
			rs->sr_matched = ch_strdup( e->e_dn );
			rs->sr_ref = is_entry_referral( e )
				? get_entry_referrals( op, e )
				: NULL;
			bdb_unlocked_cache_return_entry_r( &bdb->bi_cache, e);
			e = NULL;

		} else {
			rs->sr_ref = referral_rewrite( default_referral, NULL,
					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
		}

		rs->sr_err = LDAP_REFERRAL;
		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		free( (char *)rs->sr_matched );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;

		goto done;
	}

	if ( get_assert( op ) &&
		( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto return_results;
	}

	/* check write on old entry */
	rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WRITE, NULL );
	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old entry";
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		goto return_results;
	}

#ifndef BDB_HIER
	rs->sr_err = bdb_cache_children( op, ltid, e );
	if ( rs->sr_err != DB_NOTFOUND ) {
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		case 0:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": non-leaf %s\n",
				op->o_req_dn.bv_val, 0, 0);
			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
			rs->sr_text = "subtree rename not supported";
			break;
		default:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": has_children failed: %s (%d)\n",
				db_strerror(rs->sr_err), rs->sr_err, 0 );
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
		}
		goto return_results;
	}
	ei->bei_state |= CACHE_ENTRY_NO_KIDS;
#endif

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* parent is a referral, don't allow add */
		rs->sr_ref = get_entry_referrals( op, e );

		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
			": entry %s is referral\n", e->e_dn, 0, 0 );

		rs->sr_err = LDAP_REFERRAL,
		rs->sr_matched = e->e_name.bv_val;
		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	if ( be_issuffix( op->o_bd, &e->e_nname ) ) {
#ifdef BDB_MULTIPLE_SUFFIXES
		/* Allow renaming one suffix entry to another */
		p_ndn = slap_empty_bv;
#else
		/* There can only be one suffix entry */
		rs->sr_err = LDAP_NAMING_VIOLATION;
		rs->sr_text = "cannot rename suffix entry";
		goto return_results;
#endif
	} else {
		dnParent( &e->e_nname, &p_ndn );
	}
	np_ndn = &p_ndn;
	eip = ei->bei_parent;
	if ( eip && eip->bei_id ) {
		/* Make sure parent entry exist and we can write its 
		 * children.
		 */
		rs->sr_err = bdb_cache_find_id( op, ltid,
			eip->bei_id, &eip, 0, &plock );

		switch( rs->sr_err ) {
		case 0:
		case DB_NOTFOUND:
			break;
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		case LDAP_BUSY:
			rs->sr_text = "ldap server busy";
			goto return_results;
		default:
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}

		p = eip->bei_e;
		if( p == NULL) {
			Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn)
				": parent does not exist\n", 0, 0, 0);
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "old entry's parent does not exist";
			goto return_results;
		}
	} else {
		p = (Entry *)&slap_entry_root;
	}

	/* check parent for "children" acl */
	rs->sr_err = access_allowed( op, p,
		children, NULL,
		op->oq_modrdn.rs_newSup == NULL ?
			ACL_WRITE : ACL_WDEL,
		NULL );

	if ( !p_ndn.bv_len )
		p = NULL;

	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
			0, 0 );
		rs->sr_text = "no write access to old parent's children";
		goto return_results;
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn) ": wr to children "
		"of entry %s OK\n", p_ndn.bv_val, 0, 0 );
	
	if ( p_ndn.bv_val == slap_empty_bv.bv_val ) {
		p_dn = slap_empty_bv;
	} else {
		dnParent( &e->e_name, &p_dn );
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn) ": parent dn=%s\n",
		p_dn.bv_val, 0, 0 );

	new_parent_dn = &p_dn;	/* New Parent unless newSuperior given */

	if ( op->oq_modrdn.rs_newSup != NULL ) {
		Debug( LDAP_DEBUG_TRACE, 
			LDAP_XSTRING(bdb_modrdn)
			": new parent \"%s\" requested...\n",
			op->oq_modrdn.rs_newSup->bv_val, 0, 0 );

		/*  newSuperior == oldParent? */
		if( dn_match( &p_ndn, op->oq_modrdn.rs_nnewSup ) ) {
			Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: "
				"new parent \"%s\" same as the old parent \"%s\"\n",
				op->oq_modrdn.rs_newSup->bv_val, p_dn.bv_val, 0 );
			op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */
		}
	}

	/* There's a BDB_MULTIPLE_SUFFIXES case here that this code doesn't
	 * support. E.g., two suffixes dc=foo,dc=com and dc=bar,dc=net.
	 * We do not allow modDN
	 *   dc=foo,dc=com
	 *    newrdn dc=bar
	 *    newsup dc=net
	 * and we probably should. But since MULTIPLE_SUFFIXES is deprecated
	 * I'm ignoring this problem for now.
	 */
	if ( op->oq_modrdn.rs_newSup != NULL ) {
		if ( op->oq_modrdn.rs_newSup->bv_len ) {
			np_dn = op->oq_modrdn.rs_newSup;
			np_ndn = op->oq_modrdn.rs_nnewSup;

			/* newSuperior == oldParent? - checked above */
			/* newSuperior == entry being moved?, if so ==> ERROR */
			if ( dnIsSuffix( np_ndn, &e->e_nname )) {
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
				rs->sr_text = "new superior not found";
				goto return_results;
			}
			/* Get Entry with dn=newSuperior. Does newSuperior exist? */

			rs->sr_err = bdb_dn2entry( op, ltid, np_ndn,
				&neip, 0, &nplock );

			switch( rs->sr_err ) {
			case 0: np = neip->bei_e;
			case DB_NOTFOUND:
				break;
			case DB_LOCK_DEADLOCK:
			case DB_LOCK_NOTGRANTED:
				goto retry;
			case LDAP_BUSY:
				rs->sr_text = "ldap server busy";
				goto return_results;
			default:
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";
				goto return_results;
			}

			if( np == NULL) {
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": newSup(ndn=%s) not here!\n",
					np_ndn->bv_val, 0, 0);
				rs->sr_text = "new superior not found";
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
				goto return_results;
			}

			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_modrdn)
				": wr to new parent OK np=%p, id=%ld\n",
				(void *) np, (long) np->e_id, 0 );

			/* check newSuperior for "children" acl */
			rs->sr_err = access_allowed( op, np, children,
				NULL, ACL_WADD, NULL );

			if( ! rs->sr_err ) {
				switch( opinfo.boi_err ) {
				case DB_LOCK_DEADLOCK:
				case DB_LOCK_NOTGRANTED:
					goto retry;
				}

				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": no wr to newSup children\n",
					0, 0, 0 );
				rs->sr_text = "no write access to new superior's children";
				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
				goto return_results;
			}

			if ( is_entry_alias( np ) ) {
				/* parent is an alias, don't allow add */
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": entry is alias\n",
					0, 0, 0 );
				rs->sr_text = "new superior is an alias";
				rs->sr_err = LDAP_ALIAS_PROBLEM;
				goto return_results;
			}

			if ( is_entry_referral( np ) ) {
				/* parent is a referral, don't allow add */
				Debug( LDAP_DEBUG_TRACE,
					LDAP_XSTRING(bdb_modrdn)
					": entry is referral\n",
					0, 0, 0 );
				rs->sr_text = "new superior is a referral";
				rs->sr_err = LDAP_OTHER;
				goto return_results;
			}

		} else {
			np_dn = NULL;

			/* no parent, modrdn entry directly under root */
			if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
				|| be_isupdate( op ) ) {
				np = (Entry *)&slap_entry_root;

				/* check parent for "children" acl */
				rs->sr_err = access_allowed( op, np,
					children, NULL, ACL_WADD, NULL );

				np = NULL;

				if ( ! rs->sr_err ) {
					switch( opinfo.boi_err ) {
					case DB_LOCK_DEADLOCK:
					case DB_LOCK_NOTGRANTED:
						goto retry;
					}

					rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
					Debug( LDAP_DEBUG_TRACE, 
						"no access to new superior\n", 
						0, 0, 0 );
					rs->sr_text =
						"no write access to new superior's children";
					goto return_results;
				}
			}
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn)
			": wr to new parent's children OK\n",
			0, 0, 0 );

		new_parent_dn = np_dn;
	}

	/* Build target dn and make sure target entry doesn't exist already. */
	if (!new_dn.bv_val) {
		build_new_dn( &new_dn, new_parent_dn, &op->oq_modrdn.rs_newrdn, NULL ); 
	}

	if (!new_ndn.bv_val) {
		struct berval bv = {0, NULL};
		dnNormalize( 0, NULL, NULL, &new_dn, &bv, op->o_tmpmemctx );
		ber_dupbv( &new_ndn, &bv );
		/* FIXME: why not call dnNormalize() w/o ctx? */
		op->o_tmpfree( bv.bv_val, op->o_tmpmemctx );
	}

	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": new ndn=%s\n",
		new_ndn.bv_val, 0, 0 );

	/* Shortcut the search */
	nei = neip ? neip : eip;
	rs->sr_err = bdb_cache_find_ndn ( op, ltid, &new_ndn, &nei );
	if ( nei ) bdb_cache_entryinfo_unlock( nei );
	switch( rs->sr_err ) {
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
	case DB_NOTFOUND:
		break;
	case 0:
		/* Allow rename to same DN */
		if ( nei == ei )
			break;
		rs->sr_err = LDAP_ALREADY_EXISTS;
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	assert( op->orr_modlist != NULL );

	if( op->o_preread ) {
		if( preread_ctrl == NULL ) {
			preread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, e,
			&slap_pre_read_bv, preread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,        
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": pre-read failed!\n", 0, 0, 0 );
			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}                   
	}

	/* nested transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2, bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn)
			": txn_begin(2) failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_modrdn) ": txn2 id: %x\n",
		lt2->id(lt2), 0, 0 );

	/* delete old DN */
	rs->sr_err = bdb_dn2id_delete( op, lt2, eip, e );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": dn2id del failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index delete fail";
		goto return_results;
	}

	/* copy the entry, then override some fields */
	dummy = *e;
	dummy.e_name = new_dn;
	dummy.e_nname = new_ndn;
	dummy.e_attrs = NULL;

	/* add new DN */
	rs->sr_err = bdb_dn2id_add( op, lt2, neip ? neip : eip, &dummy );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": dn2id add failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "DN index add failed";
		goto return_results;
	}

	dummy.e_attrs = e->e_attrs;

	/* modify entry */
	rs->sr_err = bdb_modify_internal( op, lt2, op->orr_modlist, &dummy,
		&rs->sr_text, textbuf, textlen );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": modify failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		if ( ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) && opinfo.boi_err ) {
			rs->sr_err = opinfo.boi_err;
		}
		if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		goto return_results;
	}

	/* id2entry index */
	rs->sr_err = bdb_id2entry_update( op->o_bd, lt2, &dummy );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(bdb_modrdn)
			": id2entry failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err, 0 );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "entry update failed";
		goto return_results;
	}

	if ( p_ndn.bv_len != 0 ) {
		parent_is_glue = is_entry_glue(p);
		rs->sr_err = bdb_cache_children( op, lt2, p );
		if ( rs->sr_err != DB_NOTFOUND ) {
			switch( rs->sr_err ) {
			case DB_LOCK_DEADLOCK:
			case DB_LOCK_NOTGRANTED:
				goto retry;
			case 0:
				break;
			default:
				Debug(LDAP_DEBUG_ARGS,
					"<=- " LDAP_XSTRING(bdb_modrdn)
					": has_children failed: %s (%d)\n",
					db_strerror(rs->sr_err), rs->sr_err, 0 );
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "internal error";
				goto return_results;
			}
			parent_is_leaf = 1;
		}
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
		p = NULL;
	}

	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "txn_commit(2) failed";
		goto return_results;
	}

	if( op->o_postread ) {
		if( postread_ctrl == NULL ) {
			postread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if( slap_read_controls( op, rs, &dummy,
			&slap_post_read_bv, postread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,        
				"<=- " LDAP_XSTRING(bdb_modrdn)
				": post-read failed!\n", 0, 0, 0 );
			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}                   
	}

	if( op->o_noop ) {
		if(( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
			rs->sr_text = "txn_abort (no-op) failed";
		} else {
			rs->sr_err = LDAP_X_NO_OPERATION;
			ltid = NULL;
			/* Only free attrs if they were dup'd.  */
			if ( dummy.e_attrs == e->e_attrs ) dummy.e_attrs = NULL;
			goto return_results;
		}

	} else {
		rc = bdb_cache_modrdn( bdb, e, &op->orr_nnewrdn, &dummy, neip,
			ltid, &lock );
		switch( rc ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}
		dummy.e_attrs = NULL;
		new_dn.bv_val = NULL;
		new_ndn.bv_val = NULL;

		if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
			rs->sr_text = "txn_commit failed";
		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
	}
 
	ltid = NULL;
	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	opinfo.boi_oe.oe_key = NULL;
 
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_modrdn) ": %s : %s (%d)\n",
			rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;

		goto return_results;
	}

	Debug(LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_modrdn)
		": rdn modified%s id=%08lx dn=\"%s\"\n",
		op->o_noop ? " (no-op)" : "",
		dummy.e_id, op->o_req_dn.bv_val );
	rs->sr_text = NULL;
	if( num_ctrls ) rs->sr_ctrls = ctrls;

return_results:
	if ( dummy.e_attrs ) {
		attrs_free( dummy.e_attrs );
	}
	send_ldap_result( op, rs );

	if( rs->sr_err == LDAP_SUCCESS && bdb->bi_txn_cp_kbyte ) {
		TXN_CHECKPOINT( bdb->bi_dbenv,
			bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
	}
	
	if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
		op->o_delete_glue_parent = 1;
	}

done:
	slap_graduate_commit_csn( op );

	if( new_dn.bv_val != NULL ) free( new_dn.bv_val );
	if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val );

	/* LDAP v3 Support */
	if( np != NULL ) {
		/* free new parent and reader lock */
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, np);
	}

	if( p != NULL ) {
		/* free parent and reader lock */
		bdb_unlocked_cache_return_entry_r(&bdb->bi_cache, p);
	}

	/* free entry */
	if( e != NULL ) {
		bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e);
	}

	if( ltid != NULL ) {
		TXN_ABORT( ltid );
	}
	if ( opinfo.boi_oe.oe_key ) {
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	}

	if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
		slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *preread_ctrl, op->o_tmpmemctx );
	}
	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
	}
	return rs->sr_err;
}
コード例 #2
0
/*
 * Query table for specified rows
 * _con: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _c: column names to return
 * _n: number of key=values pairs to compare
 * _nc: number of columns to return
 * _o: order by the specified column
 */
int bdb_query(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
              db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    u_int32_t i, len, ret;
    int klen=MAX_ROW_SIZE;
    int *lkey=NULL, *lres=NULL;
    str s;
    DBT key, data;
    DB *db;
    DBC *dbcp;

    if ((!_con) || (!_r) || !CON_TABLE(_con))
    {
#ifdef BDB_EXTRA_DEBUG
        LM_ERR("Invalid parameter value\n");
#endif
        return -1;
    }
    *_r = NULL;

    /*check if underlying DB file has changed inode */
    if(auto_reload)
        bdb_check_reload(_con);

    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -1;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -1;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("QUERY in %.*s\n", _tp->name.len, _tp->name.s);

    if (_o)  LM_DBG("DONT-CARE : _o: order by the specified column \n");
    if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
#endif

    db = _tp->db;
    if(!db) return -1;

    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, MAX_ROW_SIZE);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* if _c is NULL and _nc is zero, you will get all table
       columns in the result
    */
    if (_c)
    {   lres = bdb_get_colmap(_tbc->dtp, _c, _nc);
        if(!lres)
        {   ret = -1;
            goto error;
        }
    }

    if(_k)
    {   lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }
    else
    {
        DB_HASH_STAT st;
        memset(&st, 0, sizeof(DB_HASH_STAT));
        i =0 ;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("SELECT * FROM %.*s\n", _tp->name.len, _tp->name.s);
#endif

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*count the number of records*/
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {   if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
            i++;
        }

        dbcp->c_close(dbcp);
        ret=0;

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("%i = SELECT COUNT(*) FROM %.*s\n", i, _tp->name.len, _tp->name.s);
#endif

        *_r = db_new_result();
        if (!*_r)
        {   LM_ERR("no memory left for result \n");
            ret = -2;
            goto error;
        }

        if(i == 0)
        {
            /*return empty table*/
            RES_ROW_N(*_r) = 0;
            BDB_CON_RESULT(_con) = *_r;
            return 0;
        }

        /*allocate N rows in the result*/
        RES_ROW_N(*_r) = i;
        len  = sizeof(db_row_t) * i;
        RES_ROWS(*_r) = (db_row_t*)pkg_malloc( len );
        memset(RES_ROWS(*_r), 0, len);

        /*fill in the column part of db_res_t (metadata) */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }

        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, 0)) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        /*convert each record into a row in the result*/
        i =0 ;
        while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\nDATA: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data
                   , (int)   data.size
                   , (char *)data.data);
#endif

            /*fill in the row part of db_res_t */
            if ((ret=bdb_append_row( *_r, dbuf, lres, i)) < 0)
            {   LM_ERR("Error while converting row\n");
                goto error;
            }
            i++;
        }

        dbcp->c_close(dbcp);
        BDB_CON_RESULT(_con) = *_r;
        return 0;
    }

    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("error in query key \n");
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /*create an empty db_res_t which gets returned even if no result*/
    *_r = db_new_result();
    if (!*_r)
    {   LM_ERR("no memory left for result \n");
        ret = -2;
        goto error;
    }
    RES_ROW_N(*_r) = 0;
    BDB_CON_RESULT(_con) = *_r;

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("SELECT  KEY: [%.*s]\n"
           , (int)   key.size
           , (char *)key.data );
#endif

    /*query Berkely DB*/
    if ((ret = db->get(db, NULL, &key, &data, 0)) == 0)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("RESULT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   data.size
               , (char *)data.data);
#endif

        /*fill in the col part of db_res_t */
        if ((ret = bdb_get_columns(_tbc->dtp, *_r, lres, _nc)) < 0)
        {   LM_ERR("Error while getting column names\n");
            goto error;
        }
        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( *_r, dbuf, lres)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

    }
    else
    {
        /*Berkeley DB error handler*/
        switch(ret)
        {

        case DB_NOTFOUND:

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("NO RESULT for QUERY \n");
#endif

            ret=0;
            break;
        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        // The operation was selected to resolve a deadlock.
        case DB_SECONDARY_BAD:
        // A secondary index references a nonexistent primary key.
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
            bdblib_recover(_tp,ret);
            goto error;
        }
    }

    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);

    return ret;

error:
    if(lkey)
        pkg_free(lkey);
    if(lres)
        pkg_free(lres);
    if(*_r)
        bdb_free_result(*_r);
    *_r = NULL;

    return ret;
}
コード例 #3
0
/*
 * Delete a row from table
 *
 * To delete ALL rows:
 *   do Not specify any keys, or values, and _n <=0
 *
 */
int bdb_delete(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    int i, j, ret, klen;
    int *lkey=NULL;
    DBT key;
    DB *db;
    DBC *dbcp;
    str s;

    i = j = ret = 0;
    klen=MAX_ROW_SIZE;

    if (_op)
        return ( _bdb_delete_cursor(_h, _k, _op, _v, _n) );

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);

    if(!_k || !_v || _n<=0)
    {
        /* Acquire a cursor for the database. */
        if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR) ) != 0)
        {   LM_ERR("Error creating cursor\n");
            goto error;
        }

        while ((ret = dbcp->c_get(dbcp, &key, NULL, DB_NEXT)) == 0)
        {
            if(!strncasecmp((char*)key.data,"METADATA",8))
                continue;
#ifdef BDB_EXTRA_DEBUG
            LM_DBG("KEY: [%.*s]\n"
                   , (int)   key.size
                   , (char *)key.data);
#endif
            ret = dbcp->c_del(dbcp, 0);
        }

        dbcp->c_close(dbcp);
        return 0;
    }

    lkey = bdb_get_colmap(_tp, _k, _n);
    if(!lkey)  return -5;

    /* make the key */
    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in bdblib_makekey\n");
        ret = -6;
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    if ((ret = db->del(db, NULL, &key, 0)) == 0)
    {
        bdblib_log(JLOG_DELETE, _tp, kbuf, klen);

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("DELETED ROW \n KEY: %s \n", (char *)key.data);
#endif
    }
    else
    {   /*Berkeley DB error handler*/
        switch(ret) {

        case DB_NOTFOUND:
            ret = 0;
            break;

        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        /* The operation was selected to resolve a deadlock. */
        case DB_SECONDARY_BAD:
        /* A secondary index references a nonexistent primary key. */
        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->del error: %s.\n"
                    , db_strerror(ret));
            bdblib_recover(_tp, ret);
            goto error;
        }
    }

    ret = 0;

error:
    if(lkey)
        pkg_free(lkey);

    return ret;

}
コード例 #4
0
ファイル: init.c プロジェクト: Joywar/openldap
static int
bdb_db_close( BackendDB *be, ConfigReply *cr )
{
	int rc;
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	struct bdb_db_info *db;
	bdb_idl_cache_entry_t *entry, *next_entry;

	/* monitor handling */
	(void)bdb_monitor_db_close( be );

	{
		Entry *e = bdb->bi_cache.c_dntree.bei_e;
		if ( e ) {
			bdb->bi_cache.c_dntree.bei_e = NULL;
			e->e_private = NULL;
			bdb_entry_return( e );
		}
	}

	bdb->bi_flags &= ~BDB_IS_OPEN;

	ber_bvarray_free( bdb->bi_db_config );
	bdb->bi_db_config = NULL;

	if( bdb->bi_dbenv ) {
		/* Free cache locker if we enabled locking.
		 * TXNs must all be closed before DBs...
		 */
		if ( !( slapMode & SLAP_TOOL_QUICK ) && bdb->bi_cache.c_txn ) {
			TXN_ABORT( bdb->bi_cache.c_txn );
			bdb->bi_cache.c_txn = NULL;
		}
		bdb_reader_flush( bdb->bi_dbenv );
	}

	while( bdb->bi_databases && bdb->bi_ndatabases-- ) {
		db = bdb->bi_databases[bdb->bi_ndatabases];
		rc = db->bdi_db->close( db->bdi_db, 0 );
		/* Lower numbered names are not strdup'd */
		if( bdb->bi_ndatabases >= BDB_NDB )
			free( db->bdi_name.bv_val );
		free( db );
	}
	free( bdb->bi_databases );
	bdb->bi_databases = NULL;

	bdb_cache_release_all (&bdb->bi_cache);

	if ( bdb->bi_idl_cache_size ) {
		avl_free( bdb->bi_idl_tree, NULL );
		bdb->bi_idl_tree = NULL;
		entry = bdb->bi_idl_lru_head;
		do {
			next_entry = entry->idl_lru_next;
			if ( entry->idl )
				free( entry->idl );
			free( entry->kstr.bv_val );
			free( entry );
			entry = next_entry;
		} while ( entry != bdb->bi_idl_lru_head );
		bdb->bi_idl_lru_head = bdb->bi_idl_lru_tail = NULL;
	}

	/* close db environment */
	if( bdb->bi_dbenv ) {
		/* force a checkpoint, but not if we were ReadOnly,
		 * and not in Quick mode since there are no transactions there.
		 */
		if ( !( slapMode & ( SLAP_TOOL_QUICK|SLAP_TOOL_READONLY ))) {
			rc = TXN_CHECKPOINT( bdb->bi_dbenv, 0, 0, DB_FORCE );
			if( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
					"bdb_db_close: database \"%s\": "
					"txn_checkpoint failed: %s (%d).\n",
					be->be_suffix[0].bv_val, db_strerror(rc), rc );
			}
		}

		rc = bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
		bdb->bi_dbenv = NULL;
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_close: database \"%s\": "
				"close failed: %s (%d)\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			return rc;
		}
	}

	rc = alock_close( &bdb->bi_alock_info, slapMode & SLAP_TOOL_QUICK );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_close: database \"%s\": alock_close failed\n",
			be->be_suffix[0].bv_val, 0, 0 );
		return -1;
	}

	return 0;
}
コード例 #5
0
int
bdb_db_cache(
	Backend	*be,
	struct berval *name,
	DB **dbout )
{
	int i, flags;
	int rc;
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	struct bdb_db_info *db;
	char *file;

	*dbout = NULL;

	for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
		if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
			*dbout = bdb->bi_databases[i]->bdi_db;
			return 0;
		}
	}

	ldap_pvt_thread_mutex_lock( &bdb->bi_database_mutex );

	/* check again! may have been added by another thread */
	for( i=BDB_NDB; i < bdb->bi_ndatabases; i++ ) {
		if( !ber_bvcmp( &bdb->bi_databases[i]->bdi_name, name) ) {
			*dbout = bdb->bi_databases[i]->bdi_db;
			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
			return 0;
		}
	}

	if( i >= BDB_INDICES ) {
		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
		return -1;
	}

	db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));

	ber_dupbv( &db->bdi_name, name );

	rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_cache: db_create(%s) failed: %s (%d)\n",
			bdb->bi_dbenv_home, db_strerror(rc), rc );
		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
		ch_free( db );
		return rc;
	}

	if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
		rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
		if ( rc ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_cache: db set_flags(DB_ENCRYPT)(%s) failed: %s (%d)\n",
				bdb->bi_dbenv_home, db_strerror(rc), rc );
			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
			db->bdi_db->close( db->bdi_db, 0 );
			ch_free( db );
			return rc;
		}
	}

	if( bdb->bi_flags & BDB_CHKSUM ) {
		rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
		if ( rc ) {
			Debug( LDAP_DEBUG_ANY,
				"bdb_db_cache: db set_flags(DB_CHKSUM)(%s) failed: %s (%d)\n",
				bdb->bi_dbenv_home, db_strerror(rc), rc );
			ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
			db->bdi_db->close( db->bdi_db, 0 );
			ch_free( db );
			return rc;
		}
	}

	/* If no explicit size set, use the FS default */
	flags = bdb_db_findsize( bdb, name );
	if ( flags )
		rc = db->bdi_db->set_pagesize( db->bdi_db, flags );

#ifdef BDB_INDEX_USE_HASH
	rc = db->bdi_db->set_h_hash( db->bdi_db, bdb_db_hash );
#endif
	rc = db->bdi_db->set_flags( db->bdi_db, DB_DUP | DB_DUPSORT );

	file = ch_malloc( db->bdi_name.bv_len + sizeof(BDB_SUFFIX) );
	strcpy( file, db->bdi_name.bv_val );
	strcpy( file+db->bdi_name.bv_len, BDB_SUFFIX );

#ifdef HAVE_EBCDIC
	__atoe( file );
#endif
	flags = DB_CREATE | DB_THREAD;
#ifdef DB_AUTO_COMMIT
	if ( !( slapMode & SLAP_TOOL_QUICK ))
		flags |= DB_AUTO_COMMIT;
#endif
	/* Cannot Truncate when Transactions are in use */
	if ( (slapMode & (SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE)) ==
		(SLAP_TOOL_QUICK|SLAP_TRUNCATE_MODE))
			flags |= DB_TRUNCATE;

	rc = DB_OPEN( db->bdi_db,
		file, NULL /* name */,
		BDB_INDEXTYPE, bdb->bi_db_opflags | flags, bdb->bi_dbenv_mode );

	ch_free( file );

	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"bdb_db_cache: db_open(%s) failed: %s (%d)\n",
			name->bv_val, db_strerror(rc), rc );
		ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
		return rc;
	}

	bdb->bi_databases[i] = db;
	bdb->bi_ndatabases = i+1;

	*dbout = db->bdi_db;

	ldap_pvt_thread_mutex_unlock( &bdb->bi_database_mutex );
	return 0;
}
コード例 #6
0
/** probe if the directory contains an environment, and if so,
 * if it has transactions
 */
e_txn probe_txn(bfpath *bfp)
{
    DB_ENV *dbe;
    int r;
#if DB_AT_LEAST(4,2)
    u_int32_t flags;
#endif

    r = db_env_create(&dbe, 0);
    if (r) {
	print_error(__FILE__, __LINE__, "cannot create environment handle: %s",
		db_strerror(r));
	return T_ERROR;
    }

    /* we might call dbe->set_flags here to set DB_NOPANIC, but this is
     * only supported from 4.1 onwards and probably not worth the
     * effort, we'll just check for DB_RUNRECOVERY */

#if DB_AT_LEAST(3,2)
    r = dbe->open(dbe, bfp->dirname, DB_JOINENV, DS_MODE);
#else
    r = ENOENT;
#endif
    if (r == DB_RUNRECOVERY) {
	dbe->close(dbe, 0);
	return T_ENABLED;
    }

    if (r == ENOENT) {
	struct stat st;
	int w;
	char *t = bfp->filepath;
	struct dirent *de;
	e_txn rc = T_DONT_KNOW;
	DIR *d;

	/* no environment found by JOINENV, but clean up handle */
	dbe->close(dbe, 0);

	/* retry, looking for log\.[0-9]{10} files - needed for instance
	 * after bogoutil --db-remove DIR or when DB_JOINENV is
	 * unsupported */
	d = opendir(bfp->dirname);
	if (d == NULL) {
	    print_error(__FILE__, __LINE__, "cannot open directory %s: %s",
		    t, strerror(r));
	    rc = T_ERROR;
	} else {
	    while ((errno = 0, de = readdir(d))) {
		if (strlen(de->d_name) == 14
		    && strncmp(de->d_name, "log.", 4) == 0
		    && strspn(de->d_name + 4, "0123456789") == 10)
		{
		    rc = T_ENABLED;
		    break;
		}
	    }
	    if (errno)
		rc = T_ERROR;
	    closedir(d);

	    if (rc != T_ERROR && rc != T_ENABLED) {
		w = stat(t, &st);
		if (w == 0) {
		    rc = T_DISABLED;
		} else if (errno != ENOENT) {
		    rc = T_ERROR;
		    print_error(__FILE__, __LINE__, "cannot stat %s: %s",
			    t, db_strerror(r));
		}
	    }
	}
	return rc;
    } /* if (r == ENOENT) for environment join */

    if (r != 0) {
	print_error(__FILE__, __LINE__, "cannot join environment: %s",
		db_strerror(r));
	return T_ERROR;
    }

    /* environment found, validate if it has transactions */
#if DB_AT_LEAST(4,2)
    r = dbe->get_open_flags(dbe, &flags);
    if (r) {
	print_error(__FILE__, __LINE__, "cannot query flags: %s",
		db_strerror(r));
	return T_ERROR;
    }

    dbe->close(dbe, 0);
    if ((flags & DB_INIT_TXN) == 0) {
	print_error(__FILE__, __LINE__,
		"environment found but does not support transactions.");
	return T_ERROR;
    }
#else
    dbe->close(dbe, 0);
#endif
    return T_ENABLED;
}
コード例 #7
0
ファイル: item.c プロジェクト: cyberrbob/memcachedb
item *item_cget(DBC *cursorp, char *start, size_t nstart, u_int32_t flags){
    item *it = NULL;
    DBT dbkey, dbdata;
    bool stop;
    int ret;
    
    /* first, alloc a fixed size */
    it = item_alloc2(settings.item_buf_size);
    if (it == 0) {
        return NULL;
    }

    BDB_CLEANUP_DBT();
    dbkey.data = start;
    dbkey.size = nstart;
    dbkey.dlen = 0;
    dbkey.doff = 0;
    dbkey.flags = DB_DBT_PARTIAL;
    dbdata.ulen = settings.item_buf_size;
    dbdata.data = it;
    dbdata.flags = DB_DBT_USERMEM;

    stop = false;
    /* try to get a item from bdb */
    while (!stop) {
        switch (ret = cursorp->get(cursorp, &dbkey, &dbdata, flags)) {
        case DB_BUFFER_SMALL:    /* user mem small */
            if (settings.verbose > 1) {
                fprintf(stderr, "cursorp->get: %s\n", db_strerror(ret));
            }
            /* free the original smaller buffer */
            item_free(it);
            /* alloc the correct size */
            it = item_alloc2(dbdata.size);
            if (it == NULL) {
                return NULL;
            }
            dbkey.data = start;
            dbkey.size = nstart;
            dbdata.ulen = dbdata.size;
            dbdata.data = it;
            break;
        case 0:                  /* Success. */
            stop = true;
            break;
        case DB_NOTFOUND:
            stop = true;
            item_free(it);
            it = NULL;
            break;
        default:
            /* TODO: may cause bug here, if return DB_BUFFER_SMALL then retun non-zero again
             * here 'it' may not a full one. a item buffer larger than item_buf_size may be added to freelist */
            stop = true;
            item_free(it);
            it = NULL;
            if (settings.verbose > 1) {
                fprintf(stderr, "cursorp->get: %s\n", db_strerror(ret));
            }
        }
    }
    return it;    
}
コード例 #8
0
ファイル: ua_update.c プロジェクト: anarexia/bacula
/*
 * Update a Job record -- allows you to change the
 *  date fields in a Job record. This helps when
 *  providing migration from other vendors.
 */
static bool update_job(UAContext *ua)
{
   int i;
   char ed1[50], ed2[50];
   POOL_MEM cmd(PM_MESSAGE);
   JOB_DBR jr;
   CLIENT_DBR cr;
   utime_t StartTime;
   char *client_name = NULL;
   char *start_time = NULL;
   const char *kw[] = {
      NT_("starttime"),                   /* 0 */
      NT_("client"),                      /* 1 */
      NULL };

   Dmsg1(200, "cmd=%s\n", ua->cmd);
   i = find_arg_with_value(ua, NT_("jobid"));
   if (i < 0) {
      ua->error_msg(_("Expect JobId keyword, not found.\n"));
      return false;
   }
   memset(&jr, 0, sizeof(jr));
   memset(&cr, 0, sizeof(cr));
   jr.JobId = str_to_int64(ua->argv[i]);
   if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
      ua->error_msg("%s", db_strerror(ua->db));
      return false;
   }

   for (i=0; kw[i]; i++) {
      int j;
      if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
         switch (i) {
         case 0:                         /* start time */
            start_time = ua->argv[j];
            break;
         case 1:                         /* Client name */
            client_name = ua->argv[j];
            break;
         }
      }
   }
   if (!client_name && !start_time) {
      ua->error_msg(_("Neither Client nor StartTime specified.\n"));
      return 0;
   }
   if (client_name) {
      if (!get_client_dbr(ua, &cr)) {
         return false;
      }
      jr.ClientId = cr.ClientId;
   }
   if (start_time) {
      utime_t delta_start;

      StartTime = str_to_utime(start_time);
      if (StartTime == 0) {
         ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
         return false;
      }
      delta_start = StartTime - jr.StartTime;
      Dmsg3(200, "ST=%lld jr.ST=%lld delta=%lld\n", StartTime, 
            (utime_t)jr.StartTime, delta_start);
      jr.StartTime = (time_t)StartTime;
      jr.SchedTime += (time_t)delta_start;
      jr.EndTime += (time_t)delta_start;
      jr.JobTDate += delta_start;
      /* Convert to DB times */
      bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
      bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
      bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
   }
   Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
             "EndTime='%s',JobTDate=%s WHERE JobId=%s", 
             edit_int64(jr.ClientId, ed1), 
             jr.cStartTime,
             jr.cSchedTime,
             jr.cEndTime,
             edit_uint64(jr.JobTDate, ed1), 
             edit_int64(jr.JobId, ed2));
   if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
      ua->error_msg("%s", db_strerror(ua->db));
      return false;
   }
   return true;
}
コード例 #9
0
ファイル: smallapi.c プロジェクト: HanumathRao/Galax
int GalaxDBopen_internal(DB **dbp, char * dbname, DBTYPE type, 
			 unsigned int open_flags, unsigned int set_flags, 
			 int buffsize, int bfixed, int fixed_length) {
	
	int retval, i;
	char * argument[2];

	#ifdef DEBUG
	printf("C: creating database : %s and %d size | open flags %d\n", dbname, buffsize,open_flags);
	fflush(stdout);
	#endif
	retval = db_create(dbp, NULL, open_flags);	
	if(retval != 0) {
		#ifdef DEBUG
		printf("C: Error in creating Database: %s\n", db_strerror(retval));
		fflush(stdout);
		#endif
		return retval;
	}

	#ifdef DEBUG
	printf("C: database created [name: %s|dbp: %X],  now setting flags = %u\n", dbname, *dbp, set_flags);
	fflush(stdout);
	#endif

	retval = (*dbp)->set_flags((*dbp), set_flags);
	if(retval != 0) {
		#ifdef DEBUG
		printf("C: Error in setting flags : %s\n", db_strerror(retval));
		fflush(stdout);
		#endif
		(*dbp)->err((*dbp), retval, "%s", "GalaxDB", dbname);	
		return retval;
	}

	#ifdef DEBUG
	printf("C: flag set now opening database\n");
	printf("C: Setting Cachesize: %d\n", buffsize);
	fflush(stdout);
	#endif
	
	retval = (*dbp)->set_cachesize((*dbp), 0, buffsize, 1); 
	if(retval != 0) {
		printf("C: Error in setting such a large cache\n");
		fflush(stdout);
		(*dbp)->err((*dbp), retval, "%s", "GalaxDB", dbname);	
		return retval;
	}
	
	if (bfixed) { 
	  if ((retval = (*dbp)->set_re_len(*dbp, fixed_length)) != 0) {
#ifdef DEBUG
	    printf("C: Error in setting to fixed length : %s\n", db_strerror(retval));
	    fflush(stdout);
#endif
	    (*dbp)->err(*dbp, retval, "%s", "GalaxDBrec_fixed_length [fixed]");
	    return retval;
	  }
	  
	  if((retval = (*dbp)->set_re_pad(*dbp, 0)) != 0) {
#ifdef DEBUG
	    printf("C: Error in setting padding : %s\n", db_strerror(retval));
	    fflush(stdout);
#endif
	    (*dbp)->err(*dbp, retval, "%s", "GalaxDBrec_fixed_length [pad]");
	    }	
	  #ifdef DEBUG
	  printf("C: Succeded in setting fixed size of %d\n", fixed_length);
	  fflush(stdout);
	  #endif 
	}

  

	retval = (*dbp)->open((*dbp), NULL, dbname, NULL, type, DB_CREATE, 0664);
	if(retval != 0) {
		(*dbp)->err((*dbp), retval, "%s", "GalaxDB", dbname);	
		return retval;
	}

	#ifdef DEBUG
	printf("C: Database %s opened \n", dbname);
	fflush(stdout);
	#endif

	return retval;
}
コード例 #10
0
ファイル: add.c プロジェクト: osstech-jp/ReOpenLDAP
int
bdb_add(Operation *op, SlapReply *rs )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	struct berval	pdn;
	Entry		*p = NULL, *oe = op->ora_e;
	EntryInfo	*ei;
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	DB_TXN		*ltid = NULL, *lt2;
	ID eid = NOID;
	struct bdb_op_info opinfo = {{{ 0 }}};
	int subentry;
	DB_LOCK		lock;

	int		num_retries = 0;
	int		success;

	LDAPControl **postread_ctrl = NULL;
	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
	int num_ctrls = 0;

#ifdef LDAP_X_TXN
	int settle = 0;
#endif

	Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n",
		op->ora_e->e_name.bv_val);

#ifdef LDAP_X_TXN
	if( op->o_txnSpec ) {
		/* acquire connection lock */
		ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
		if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) {
			rs->sr_text = "invalid transaction identifier";
			rs->sr_err = LDAP_X_TXN_ID_INVALID;
			goto txnReturn;
		} else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) {
			settle=1;
			goto txnReturn;
		}

		if( op->o_conn->c_txn_backend == NULL ) {
			op->o_conn->c_txn_backend = op->o_bd;

		} else if( op->o_conn->c_txn_backend != op->o_bd ) {
			rs->sr_text = "transaction cannot span multiple database contexts";
			rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS;
			goto txnReturn;
		}

		/* insert operation into transaction */

		rs->sr_text = "transaction specified";
		rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY;

txnReturn:
		/* release connection lock */
		ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );

		if( !settle ) {
			send_ldap_result( op, rs );
			return rs->sr_err;
		}
	}
#endif

	ctrls[num_ctrls] = 0;

	/* check entry's schema */
	rs->sr_err = entry_schema_check( op, op->ora_e, NULL,
		get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": entry failed schema check: "
			"%s (%d)\n", rs->sr_text, rs->sr_err );
		goto return_results;
	}

	/* add opattrs to shadow as well, only missing attrs will actually
	 * be added; helps compatibility with older OL versions */
	rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": entry failed op attrs add: "
			"%s (%d)\n", rs->sr_text, rs->sr_err );
		goto return_results;
	}

	if ( get_assert( op ) &&
		( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto return_results;
	}

	subentry = is_entry_subentry( op->ora_e );

	if( 0 ) {
retry:	/* transaction retry */
		if( p ) {
			/* free parent and reader lock */
			if ( p != (Entry *)&slap_entry_root ) {
				bdb_unlocked_cache_return_entry_r( bdb, p );
			}
			p = NULL;
		}
		rs->sr_err = TXN_ABORT( ltid );
		ltid = NULL;
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
		opinfo.boi_oe.oe_key = NULL;
		op->o_do_not_cache = opinfo.boi_acl_cache;
		if( rs->sr_err != 0 ) {
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}
		if ( slap_get_op_abandon(op) ) {
			rs->sr_err = SLAPD_ABANDON;
			goto return_results;
		}
		bdb_trans_backoff( ++num_retries );
	}

	/* begin transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid,
		bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": txn_begin failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn1 id: %x\n",
		ltid->id(ltid) );

	opinfo.boi_oe.oe_key = bdb;
	opinfo.boi_txn = ltid;
	opinfo.boi_err = 0;
	opinfo.boi_acl_cache = op->o_do_not_cache;
	LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );

	/*
	 * Get the parent dn and see if the corresponding entry exists.
	 */
	if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
		pdn = slap_empty_bv;
	} else {
		dnParent( &op->ora_e->e_nname, &pdn );
	}

	/* get entry or parent */
	rs->sr_err = bdb_dn2entry( op, ltid, &op->ora_e->e_nname, &ei,
		1, &lock );
	switch( rs->sr_err ) {
	case 0:
		rs->sr_err = LDAP_ALREADY_EXISTS;
		goto return_results;
	case DB_NOTFOUND:
		break;
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto retry;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	p = ei->bei_e;
	if ( !p )
		p = (Entry *)&slap_entry_root;

	if ( !bvmatch( &pdn, &p->e_nname ) ) {
		rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
			op->o_tmpmemctx );
		rs->sr_ref = is_entry_referral( p )
			? get_entry_referrals( op, p )
			: NULL;
		if ( p != (Entry *)&slap_entry_root )
			bdb_unlocked_cache_return_entry_r( bdb, p );
		p = NULL;
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": parent "
			"does not exist\n" );

		rs->sr_err = LDAP_REFERRAL;
		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
		goto return_results;
	}

	rs->sr_err = access_allowed( op, p,
		children, NULL, ACL_WADD, NULL );

	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		if ( p != (Entry *)&slap_entry_root )
			bdb_unlocked_cache_return_entry_r( bdb, p );
		p = NULL;

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": no write access to parent\n" );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		rs->sr_text = "no write access to parent";
		goto return_results;
	}

	if ( p != (Entry *)&slap_entry_root ) {
		if ( is_entry_subentry( p ) ) {
			bdb_unlocked_cache_return_entry_r( bdb, p );
			p = NULL;
			/* parent is a subentry, don't allow add */
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_add) ": parent is subentry\n" );
			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			rs->sr_text = "parent is a subentry";
			goto return_results;
		}

		if ( is_entry_alias( p ) ) {
			bdb_unlocked_cache_return_entry_r( bdb, p );
			p = NULL;
			/* parent is an alias, don't allow add */
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_add) ": parent is alias\n" );
			rs->sr_err = LDAP_ALIAS_PROBLEM;
			rs->sr_text = "parent is an alias";
			goto return_results;
		}

		if ( is_entry_referral( p ) ) {
			/* parent is a referral, don't allow add */
			rs->sr_matched = ber_strdup_x( p->e_name.bv_val,
				op->o_tmpmemctx );
			rs->sr_ref = get_entry_referrals( op, p );
			bdb_unlocked_cache_return_entry_r( bdb, p );
			p = NULL;
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_add) ": parent is referral\n" );

			rs->sr_err = LDAP_REFERRAL;
			rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
			goto return_results;
		}

	}

	if ( subentry ) {
		/* FIXME: */
		/* parent must be an administrative point of the required kind */
	}

	/* free parent and reader lock */
	if ( p != (Entry *)&slap_entry_root ) {
		if ( p->e_nname.bv_len ) {
			struct berval ppdn;

			/* ITS#5326: use parent's DN if differs from provided one */
			dnParent( &op->ora_e->e_name, &ppdn );
			if ( !dn_match( &p->e_name, &ppdn ) ) {
				struct berval rdn;
				struct berval newdn;

				dnRdn( &op->ora_e->e_name, &rdn );

				build_new_dn( &newdn, &p->e_name, &rdn, NULL );
				if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val )
					ber_memfree( op->ora_e->e_name.bv_val );
				op->ora_e->e_name = newdn;

				/* FIXME: should check whether
				 * dnNormalize(newdn) == e->e_nname ... */
			}
		}

		bdb_unlocked_cache_return_entry_r( bdb, p );
	}
	p = NULL;

	rs->sr_err = access_allowed( op, op->ora_e,
		entry, NULL, ACL_WADD, NULL );

	if ( ! rs->sr_err ) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": no write access to entry\n" );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		rs->sr_text = "no write access to entry";
		goto return_results;
	}

	/*
	 * Check ACL for attribute write access
	 */
	if (!acl_check_modlist(op, oe, op->ora_modlist)) {
		switch( opinfo.boi_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		}

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": no write access to attribute\n" );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		rs->sr_text = "no write access to attribute";
		goto return_results;
	}

	if ( eid == NOID ) {
		rs->sr_err = bdb_next_id( op->o_bd, &eid );
		if( rs->sr_err != 0 ) {
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(bdb_add) ": next_id failed (%d)\n",
				rs->sr_err );
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
			goto return_results;
		}
		op->ora_e->e_id = eid;
	}

	/* nested transaction */
	rs->sr_err = TXN_BEGIN( bdb->bi_dbenv, ltid, &lt2,
		bdb->bi_db_opflags );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": txn_begin(2) failed: "
			"%s (%d)\n", db_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_add) ": txn2 id: %x\n",
		lt2->id(lt2) );

	/* dn2id index */
	rs->sr_err = bdb_dn2id_add( op, lt2, ei, op->ora_e );
	if ( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": dn2id_add failed: %s (%d)\n",
			db_strerror(rs->sr_err), rs->sr_err );

		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		case DB_KEYEXIST:
			rs->sr_err = LDAP_ALREADY_EXISTS;
			break;
		default:
			rs->sr_err = LDAP_OTHER;
		}
		goto return_results;
	}

	/* attribute indexes */
	rs->sr_err = bdb_index_entry_add( op, lt2, op->ora_e );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": index_entry_add failed\n" );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		default:
			rs->sr_err = LDAP_OTHER;
		}
		rs->sr_text = "index generation failed";
		goto return_results;
	}

	/* id2entry index */
	rs->sr_err = bdb_id2entry_add( op->o_bd, lt2, op->ora_e );
	if ( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": id2entry_add failed\n" );
		switch( rs->sr_err ) {
		case DB_LOCK_DEADLOCK:
		case DB_LOCK_NOTGRANTED:
			goto retry;
		default:
			rs->sr_err = LDAP_OTHER;
		}
		rs->sr_text = "entry store failed";
		goto return_results;
	}

	if ( TXN_COMMIT( lt2, 0 ) != 0 ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "txn_commit(2) failed";
		goto return_results;
	}

	/* post-read */
	if( op->o_postread ) {
		if( postread_ctrl == NULL ) {
			postread_ctrl = &ctrls[num_ctrls++];
			ctrls[num_ctrls] = NULL;
		}
		if ( slap_read_controls( op, rs, op->ora_e,
			&slap_post_read_bv, postread_ctrl ) )
		{
			Debug( LDAP_DEBUG_TRACE,
				"<=- " LDAP_XSTRING(bdb_add) ": post-read "
				"failed!\n" );
			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
				/* FIXME: is it correct to abort
				 * operation if control fails? */
				goto return_results;
			}
		}
	}

	if ( op->o_noop ) {
		if (( rs->sr_err=TXN_ABORT( ltid )) != 0 ) {
			rs->sr_text = "txn_abort (no-op) failed";
		} else {
			rs->sr_err = LDAP_X_NO_OPERATION;
			ltid = NULL;
			goto return_results;
		}

	} else {
		struct berval nrdn;

		/* pick the RDN if not suffix; otherwise pick the entire DN */
		if (pdn.bv_len) {
			nrdn.bv_val = op->ora_e->e_nname.bv_val;
			nrdn.bv_len = pdn.bv_val - op->ora_e->e_nname.bv_val - 1;
		} else {
			nrdn = op->ora_e->e_nname;
		}

		bdb_cache_add( bdb, ei, op->ora_e, &nrdn, ltid, &lock );

		if(( rs->sr_err=TXN_COMMIT( ltid, 0 )) != 0 ) {
			rs->sr_text = "txn_commit failed";
		} else {
			rs->sr_err = LDAP_SUCCESS;
		}
	}

	ltid = NULL;
	LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	opinfo.boi_oe.oe_key = NULL;

	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(bdb_add) ": %s : %s (%d)\n",
			rs->sr_text, db_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;
		goto return_results;
	}

	Debug(LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_add) ": added%s id=%08lx dn=\"%s\"\n",
		op->o_noop ? " (no-op)" : "",
		op->ora_e->e_id, op->ora_e->e_dn );

	rs->sr_text = NULL;
	if( num_ctrls ) rs->sr_ctrls = ctrls;

return_results:
	success = rs->sr_err;
	send_ldap_result( op, rs );
	rs_send_cleanup( rs );

	if( ltid != NULL ) {
		TXN_ABORT( ltid );
	}
	if ( opinfo.boi_oe.oe_key ) {
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
	}

	if( success == LDAP_SUCCESS ) {
		/* We own the entry now, and it can be purged at will
		 * Check to make sure it's the same entry we entered with.
		 * Possibly a callback may have mucked with it, although
		 * in general callbacks should treat the entry as read-only.
		 */
		bdb_cache_deref( oe->e_private );
		if ( op->ora_e == oe )
			op->ora_e = NULL;

		if ( bdb->bi_txn_cp_kbyte ) {
			TXN_CHECKPOINT( bdb->bi_dbenv,
				bdb->bi_txn_cp_kbyte, bdb->bi_txn_cp_min, 0 );
		}
	}

	slap_graduate_commit_csn( op );

	if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) {
		slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
		slap_sl_free( *postread_ctrl, op->o_tmpmemctx );
	}
	return rs->sr_err;
}
コード例 #11
0
ファイル: ua_update.c プロジェクト: anarexia/bacula
/*
 * Update a media record -- allows you to change the
 *  Volume status. E.g. if you want Bacula to stop
 *  writing on the volume, set it to anything other
 *  than Append.
 */
static int update_volume(UAContext *ua)
{
   MEDIA_DBR mr;
   POOL *pool;
   POOL_DBR pr;
   POOLMEM *query;
   POOL_MEM ret;
   char buf[1000];
   char ed1[130];
   bool done = false;
   int i;
   const char *kw[] = {
      NT_("VolStatus"),                /* 0 */
      NT_("VolRetention"),             /* 1 */
      NT_("VolUse"),                   /* 2 */
      NT_("MaxVolJobs"),               /* 3 */
      NT_("MaxVolFiles"),              /* 4 */
      NT_("MaxVolBytes"),              /* 5 */
      NT_("Recycle"),                  /* 6 */
      NT_("InChanger"),                /* 7 */
      NT_("Slot"),                     /* 8 */
      NT_("Pool"),                     /* 9 */
      NT_("FromPool"),                 /* 10 */
      NT_("AllFromPool"),              /* 11 !!! see below !!! */
      NT_("Enabled"),                  /* 12 */
      NT_("RecyclePool"),              /* 13 */
      NT_("ActionOnPurge"),            /* 14 */
      NULL };

#define AllFromPool 11               /* keep this updated with above */

   for (i=0; kw[i]; i++) {
      int j;
      POOL_DBR pr;

      if ((j=find_arg_with_value(ua, kw[i])) > 0) {
         /* If all from pool don't select a media record */
         if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
            return 0;
         }
         switch (i) {
         case 0:
            update_volstatus(ua, ua->argv[j], &mr);
            break;
         case 1:
            update_volretention(ua, ua->argv[j], &mr);
            break;
         case 2:
            update_voluseduration(ua, ua->argv[j], &mr);
            break;
         case 3:
            update_volmaxjobs(ua, ua->argv[j], &mr);
            break;
         case 4:
            update_volmaxfiles(ua, ua->argv[j], &mr);
            break;
         case 5:
            update_volmaxbytes(ua, ua->argv[j], &mr);
            break;
         case 6:
            update_volrecycle(ua, ua->argv[j], &mr);
            break;
         case 7:
            update_volinchanger(ua, ua->argv[j], &mr);
            break;
         case 8:
            update_volslot(ua, ua->argv[j], &mr);
            break;
         case 9:
            memset(&pr, 0, sizeof(POOL_DBR));
            pr.PoolId = mr.PoolId;
            if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
               ua->error_msg("%s", db_strerror(ua->db));
               break;
            }
            update_vol_pool(ua, ua->argv[j], &mr, &pr);
            break;
         case 10:
            update_vol_from_pool(ua, &mr);
            return 1;
         case 11:
            update_all_vols_from_pool(ua, ua->argv[j]);
            return 1;
         case 12:
            update_volenabled(ua, ua->argv[j], &mr);
            break;
         case 13:
            update_vol_recyclepool(ua, ua->argv[j], &mr);
            break;
         case 14:
            update_vol_actiononpurge(ua, ua->argv[j], &mr);
            break;
         }
         done = true;
      }
   }

   /* Allow user to simply update all volumes */
   if (find_arg(ua, NT_("fromallpools")) > 0) {
      update_all_vols(ua);
      return 1;
   }

   for ( ; !done; ) {
      start_prompt(ua, _("Parameters to modify:\n"));
      add_prompt(ua, _("Volume Status"));              /* 0 */
      add_prompt(ua, _("Volume Retention Period"));    /* 1 */
      add_prompt(ua, _("Volume Use Duration"));        /* 2 */
      add_prompt(ua, _("Maximum Volume Jobs"));        /* 3 */
      add_prompt(ua, _("Maximum Volume Files"));       /* 4 */
      add_prompt(ua, _("Maximum Volume Bytes"));       /* 5 */
      add_prompt(ua, _("Recycle Flag"));               /* 6 */
      add_prompt(ua, _("Slot"));                       /* 7 */
      add_prompt(ua, _("InChanger Flag"));             /* 8 */
      add_prompt(ua, _("Volume Files"));               /* 9 */
      add_prompt(ua, _("Pool"));                       /* 10 */
      add_prompt(ua, _("Volume from Pool"));           /* 11 */
      add_prompt(ua, _("All Volumes from Pool"));      /* 12 */
      add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
      add_prompt(ua, _("Enabled")),                    /* 14 */
      add_prompt(ua, _("RecyclePool")),                /* 15 */
      add_prompt(ua, _("Action On Purge")),            /* 16 */
      add_prompt(ua, _("Done"));                       /* 17 */
      i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);  

      /* For All Volumes, All Volumes from Pool, and Done, we don't need
           * a Volume record */
      if ( i != 12 && i != 13 && i != 17) {
         if (!select_media_dbr(ua, &mr)) {  /* Get Volume record */
            return 0;
         }
         ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
      }
      switch (i) {
      case 0:                         /* Volume Status */
         /* Modify Volume Status */
         ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
         start_prompt(ua, _("Possible Values are:\n"));
         add_prompt(ua, NT_("Append")); 
         add_prompt(ua, NT_("Archive"));
         add_prompt(ua, NT_("Disabled"));
         add_prompt(ua, NT_("Full"));
         add_prompt(ua, NT_("Used"));
         add_prompt(ua, NT_("Cleaning"));
         if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
            add_prompt(ua, NT_("Recycle"));
         }
         add_prompt(ua, NT_("Read-Only"));
         if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
            return 1;
         }
         update_volstatus(ua, ua->cmd, &mr);
         break;
      case 1:                         /* Retention */
         ua->info_msg(_("Current retention period is: %s\n"),
            edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
         if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
            return 0;
         }
         update_volretention(ua, ua->cmd, &mr);
         break;

      case 2:                         /* Use Duration */
         ua->info_msg(_("Current use duration is: %s\n"),
            edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
         if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
            return 0;
         }
         update_voluseduration(ua, ua->cmd, &mr);
         break;

      case 3:                         /* Max Jobs */
         ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
         if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
            return 0;
         }
         update_volmaxjobs(ua, ua->cmd, &mr);
         break;

      case 4:                         /* Max Files */
         ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
         if (!get_pint(ua, _("Enter new Maximum Files: "))) {
            return 0;
         }
         update_volmaxfiles(ua, ua->cmd, &mr);
         break;

      case 5:                         /* Max Bytes */
         ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
         if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
            return 0;
         }
         update_volmaxbytes(ua, ua->cmd, &mr);
         break;


      case 6:                         /* Recycle */
         ua->info_msg(_("Current recycle flag is: %s\n"),
            mr.Recycle==1?_("yes"):_("no"));
         if (!get_yesno(ua, _("Enter new Recycle status: "))) {
            return 0;
         }
         update_volrecycle(ua, ua->cmd, &mr);
         break;

      case 7:                         /* Slot */
         ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
         if (!get_pint(ua, _("Enter new Slot: "))) {
            return 0;
         }
         update_volslot(ua, ua->cmd, &mr);
         break;
         
      case 8:                         /* InChanger */
         ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
         bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
            mr.VolumeName);
         if (!get_yesno(ua, buf)) {
            return 0;
         }
         mr.InChanger = ua->pint32_val;
         /*
          * Make sure to use db_update... rather than doing this directly,
          *   so that any Slot is handled correctly.
          */
         if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
            ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
         } else {
            ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
         }
         break;


      case 9:                         /* Volume Files */
         int32_t VolFiles;
         ua->warning_msg(_("Warning changing Volume Files can result\n"
                        "in loss of data on your Volume\n\n"));
         ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
         if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
            return 0;
         }
         VolFiles = ua->pint32_val;
         if (VolFiles != (int)(mr.VolFiles + 1)) {
            ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
            if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
               break;
            }
         }
         query = get_pool_memory(PM_MESSAGE);
         Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
            VolFiles, edit_int64(mr.MediaId, ed1));
         if (!db_sql_query(ua->db, query, NULL, NULL)) {
            ua->error_msg("%s", db_strerror(ua->db));
         } else {
            ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
         }
         free_pool_memory(query);
         break;

      case 10:                        /* Volume's Pool */
         memset(&pr, 0, sizeof(POOL_DBR));
         pr.PoolId = mr.PoolId;
         if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
            ua->error_msg("%s", db_strerror(ua->db));
            return 0;
         }
         ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
         if (!get_cmd(ua, _("Enter new Pool name: "))) {
            return 0;
         }
         update_vol_pool(ua, ua->cmd, &mr, &pr);
         return 1;

      case 11:
         update_vol_from_pool(ua, &mr);
         return 1;
      case 12:
         pool = select_pool_resource(ua);
         if (pool) {
            update_all_vols_from_pool(ua, pool->name());
         }
         return 1;

      case 13:
         update_all_vols(ua);
         return 1;

      case 14:
         ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
         if (!get_cmd(ua, _("Enter new Enabled: "))) {
            return 0;
         }
         if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
            mr.Enabled = 1;
         } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
            mr.Enabled = 0;
         } else if (strcasecmp(ua->cmd, "archived") == 0) { 
            mr.Enabled = 2;
         } else {
            mr.Enabled = atoi(ua->cmd);
         }
         update_volenabled(ua, ua->cmd, &mr);
         break;

      case 15:
         memset(&pr, 0, sizeof(POOL_DBR));
         pr.PoolId = mr.RecyclePoolId;
         if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
            ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
         } else {
            ua->info_msg(_("No current RecyclePool\n"));
         }
         if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
            return 0;
         }
         update_vol_recyclepool(ua, pr.Name, &mr);
         return 1;

      case 16:
         pm_strcpy(ret, "");
         ua->info_msg(_("Current ActionOnPurge is: %s\n"), 
                      action_on_purge_to_string(mr.ActionOnPurge, ret));
         if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
            return 0;
         }

         update_vol_actiononpurge(ua, ua->cmd, &mr);
         break;

      default:                        /* Done or error */
         ua->info_msg(_("Selection terminated.\n"));
         return 1;
      }
   }
   return 1;
}
コード例 #12
0
ファイル: txn_guide.c プロジェクト: Wushaowei001/omnibus
int
main(int argc, char *argv[])
{
    /* Initialize our handles */
    DB *dbp = NULL;
    DB_ENV *envp = NULL;

    thread_t writer_threads[NUMWRITERS];
    int ch, i, ret, ret_t;
    u_int32_t env_flags;
    char *db_home_dir;
    /* Application name */
    const char *prog_name = "txn_guide";
    /* Database file name */
    const char *file_name = "mydb.db";

    /* Parse the command line arguments */
#ifdef _WIN32
    db_home_dir = ".\\";
#else
    db_home_dir = "./";
#endif
    while ((ch = getopt(argc, argv, "h:")) != EOF)
	switch (ch) {
	case 'h':
	    db_home_dir = optarg;
	    break;
	case '?':
	default:
	    return (usage());
	}

    /* Create the environment */
    ret = db_env_create(&envp, 0);
    if (ret != 0) {
	fprintf(stderr, "Error creating environment handle: %s\n",
	    db_strerror(ret));
	goto err;
    }

     /*
     * Indicate that we want db to perform lock detection internally.
     * Also indicate that the transaction with the fewest number of
     * write locks will receive the deadlock notification in
     * the event of a deadlock.
     */
    ret = envp->set_lk_detect(envp, DB_LOCK_MINWRITE);
    if (ret != 0) {
	fprintf(stderr, "Error setting lock detect: %s\n",
	    db_strerror(ret));
	goto err;
    }

    env_flags =
      DB_CREATE     |  /* Create the environment if it does not exist */
      DB_RECOVER    |  /* Run normal recovery. */
      DB_INIT_LOCK  |  /* Initialize the locking subsystem */
      DB_INIT_LOG   |  /* Initialize the logging subsystem */
      DB_INIT_TXN   |  /* Initialize the transactional subsystem. This
			* also turns on logging. */
      DB_INIT_MPOOL |  /* Initialize the memory pool (in-memory cache) */
      DB_THREAD;       /* Cause the environment to be free-threaded */

    /* Now actually open the environment */
    ret = envp->open(envp, db_home_dir, env_flags, 0);
    if (ret != 0) {
	fprintf(stderr, "Error opening environment: %s\n",
	    db_strerror(ret));
	goto err;
    }

    /*
     * If we had utility threads (for running checkpoints or
     * deadlock detection, for example) we would spawn those
     * here. However, for a simple example such as this,
     * that is not required.
     */

    /* Open the database */
    ret = open_db(&dbp, prog_name, file_name,
      envp, DB_DUPSORT);
    if (ret != 0)
	goto err;

    /* Initialize a mutex. Used to help provide thread ids. */
    (void)mutex_init(&thread_num_lock, NULL);

    /* Start the writer threads. */
    for (i = 0; i < NUMWRITERS; i++)
	(void)thread_create(
	   &writer_threads[i], NULL, writer_thread, (void *)dbp);

    /* Join the writers */
    for (i = 0; i < NUMWRITERS; i++)
	(void)thread_join(writer_threads[i], NULL);

err:
    /* Close our database handle, if it was opened. */
    if (dbp != NULL) {
	ret_t = dbp->close(dbp, 0);
	if (ret_t != 0) {
	    fprintf(stderr, "%s database close failed: %s\n",
		file_name, db_strerror(ret_t));
	    ret = ret_t;
	}
    }

    /* Close our environment, if it was opened. */
    if (envp != NULL) {
	ret_t = envp->close(envp, 0);
	if (ret_t != 0) {
	    fprintf(stderr, "environment close failed: %s\n",
		db_strerror(ret_t));
		ret = ret_t;
	}
    }

    /* Final status message and return. */
    printf("I'm all done.\n");
    return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
コード例 #13
0
static void SLNFilterResultsWrite(SLNSessionRef const session, SLNFilterRef const filter, SLNFilterOpts *const opts, HTTPConnectionRef const conn) {
	// TODO: Accept count and use it for the total number of results.
	opts->count = 0;

	// We're sending a series of batches, so reversing one batch
	// doesn't make sense.
	opts->outdir = opts->dir;

	static strarg_t const fields[] = { "wait" };
	str_t *values[numberof(fields)] = {};
	QSValuesParse(qs, values, fields, numberof(fields));
	bool const wait = parse_wait(values[0]);
	QSValuesCleanup(values, numberof(values));

	// I'm aware that we're abusing HTTP for sending real-time push data.
	// I'd also like to support WebSocket at some point, but this is simpler
	// and frankly probably more widely supported.
	// Note that the protocol doesn't really break even if this data is
	// cached. It DOES break if a proxy tries to buffer the whole response
	// before passing it back to the client. I'd be curious to know whether
	// such proxies still exist in 2015.
	HTTPConnectionWriteResponse(conn, 200, "OK");
	HTTPConnectionWriteHeader(conn, "Transfer-Encoding", "chunked");
	HTTPConnectionWriteHeader(conn,
		"Content-Type", "text/uri-list; charset=utf-8");
	HTTPConnectionWriteHeader(conn, "Cache-Control", "no-store");
	HTTPConnectionWriteHeader(conn, "Vary", "*");
	HTTPConnectionBeginBody(conn);
	int rc;

	for(;;) {
		rc = sendURIBatch(session, filter, opts, conn);
		if(DB_NOTFOUND == rc) break;
		if(DB_SUCCESS == rc) continue;
		fprintf(stderr, "Query error: %s\n", db_strerror(rc));
		goto cleanup;
	}

	if(!wait || opts->dir < 0) goto cleanup;

	SLNRepoRef const repo = SLNSessionGetRepo(session);
	for(;;) {
		uint64_t const timeout = uv_now(async_loop)+(1000 * 30);
		rc = SLNRepoSubmissionWait(repo, opts->sortID, timeout);
		if(UV_ETIMEDOUT == rc) {
			uv_buf_t const parts[] = { uv_buf_init((char *)STR_LEN("\r\n")) };
			rc = HTTPConnectionWriteChunkv(conn, parts, numberof(parts));
			if(rc < 0) break;
			continue;
		}
		assert(rc >= 0); // TODO: Handle cancellation?

		for(;;) {
			rc = sendURIBatch(session, filter, opts, conn);
			if(DB_NOTFOUND == rc) break;
			if(DB_SUCCESS == rc) continue;
			fprintf(stderr, "Query error: %s\n", db_strerror(rc));
			goto cleanup;
		}
	}

cleanup:
	HTTPConnectionWriteChunkEnd(conn);
	HTTPConnectionEnd(conn);
	SLNFilterOptsCleanup(opts);
}
コード例 #14
0
/* ------------------------ */
cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
                const cnid_t did, char *name, const size_t len, 
		cnid_t hint)
{
    CNID_private *db;
    DBT key, data;
    int rc;

    if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
        errno = CNID_ERR_PARAM;
        return CNID_INVALID;
    }

#if 0
    /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */
    /* Do a lookup. */
    id = cnid_cdb_lookup(cdb, st, did, name, len);
    /* ... Return id if it is valid, or if Rootinfo is read-only. */
    if (id || (db->flags & CNIDFLAG_DB_RO)) {
#ifdef DEBUG
        LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
#endif
        return id;
    }
#endif

    /* Initialize our DBT data structures. */
    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));

    if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
        LOG(log_error, logtype_default, "cnid_add: Path name is too long");
        errno = CNID_ERR_PATH;
        return CNID_INVALID;
    }
    data.size = CNID_HEADER_LEN + len + 1;
    
    memcpy(data.data, &hint, sizeof(hint));
    
    key.data = &hint;
    key.size = sizeof(hint);

    /* Now we need to add the CNID data to the databases. */
    if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
            LOG(log_error, logtype_default
                   , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 
                   name, ntohl(hint), db_strerror(rc));  
            errno = CNID_ERR_DB;
	    goto cleanup;
    }

    if (set_max_cnid(db, hint) == CNID_INVALID) {
	    errno = CNID_ERR_DB;
	    goto cleanup;
    }

#ifdef DEBUG
    LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif

    return hint;

cleanup:
    return CNID_INVALID;
}
コード例 #15
0
ファイル: tools.c プロジェクト: rouzier/openldap
int bdb_tool_entry_reindex(
	BackendDB *be,
	ID id,
	AttributeDescription **adv )
{
	struct bdb_info *bi = (struct bdb_info *) be->be_private;
	int rc;
	Entry *e;
	DB_TXN *tid = NULL;
	Operation op = {0};
	Opheader ohdr = {0};

	Debug( LDAP_DEBUG_ARGS,
		"=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld )\n",
		(long) id, 0, 0 );
	assert( tool_base == NULL );
	assert( tool_filter == NULL );

	/* No indexes configured, nothing to do. Could return an
	 * error here to shortcut things.
	 */
	if (!bi->bi_attrs) {
		return 0;
	}

	/* Check for explicit list of attrs to index */
	if ( adv ) {
		int i, j, n;

		if ( bi->bi_attrs[0]->ai_desc != adv[0] ) {
			/* count */
			for ( n = 0; adv[n]; n++ ) ;

			/* insertion sort */
			for ( i = 0; i < n; i++ ) {
				AttributeDescription *ad = adv[i];
				for ( j = i-1; j>=0; j--) {
					if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break;
					adv[j+1] = adv[j];
				}
				adv[j+1] = ad;
			}
		}

		for ( i = 0; adv[i]; i++ ) {
			if ( bi->bi_attrs[i]->ai_desc != adv[i] ) {
				for ( j = i+1; j < bi->bi_nattrs; j++ ) {
					if ( bi->bi_attrs[j]->ai_desc == adv[i] ) {
						AttrInfo *ai = bi->bi_attrs[i];
						bi->bi_attrs[i] = bi->bi_attrs[j];
						bi->bi_attrs[j] = ai;
						break;
					}
				}
				if ( j == bi->bi_nattrs ) {
					Debug( LDAP_DEBUG_ANY,
						LDAP_XSTRING(bdb_tool_entry_reindex)
						": no index configured for %s\n",
						adv[i]->ad_cname.bv_val, 0, 0 );
					return -1;
				}
			}
		}
		bi->bi_nattrs = i;
	}

	/* Get the first attribute to index */
	if (bi->bi_linear_index && !index_nattrs) {
		index_nattrs = bi->bi_nattrs - 1;
		bi->bi_nattrs = 1;
	}

	e = bdb_tool_entry_get( be, id );

	if( e == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_tool_entry_reindex)
			": could not locate id=%ld\n",
			(long) id, 0, 0 );
		return -1;
	}

	if (! (slapMode & SLAP_TOOL_QUICK)) {
	rc = TXN_BEGIN( bi->bi_dbenv, NULL, &tid, bi->bi_db_opflags );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_reindex) ": "
			"txn_begin failed: %s (%d)\n",
			db_strerror(rc), rc, 0 );
		goto done;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_reindex) ": txn id: %x\n",
		tid->id(tid), 0, 0 );
	}
 	
	/*
	 * just (re)add them for now
	 * assume that some other routine (not yet implemented)
	 * will zap index databases
	 *
	 */

	Debug( LDAP_DEBUG_TRACE,
		"=> " LDAP_XSTRING(bdb_tool_entry_reindex) "( %ld, \"%s\" )\n",
		(long) id, e->e_dn, 0 );

	op.o_hdr = &ohdr;
	op.o_bd = be;
	op.o_tmpmemctx = NULL;
	op.o_tmpmfuncs = &ch_mfuncs;

	rc = bdb_tool_index_add( &op, tid, e );

done:
	if( rc == 0 ) {
		if (! (slapMode & SLAP_TOOL_QUICK)) {
		rc = TXN_COMMIT( tid, 0 );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(bdb_tool_entry_reindex)
				": txn_commit failed: %s (%d)\n",
				db_strerror(rc), rc, 0 );
			e->e_id = NOID;
		}
		}

	} else {
		if (! (slapMode & SLAP_TOOL_QUICK)) {
		TXN_ABORT( tid );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_reindex)
			": txn_aborted! %s (%d)\n",
			db_strerror(rc), rc, 0 );
		}
		e->e_id = NOID;
	}
	bdb_entry_release( &op, e, 0 );

	return rc;
}
コード例 #16
0
ファイル: bdblib.c プロジェクト: changjiang1124/crabdb
int
find_record(struct bdb_t *bdbp, DBT **dbt_ptr, void *key_ptr, size_t key_len, size_t *value_len)
{
    assert(dbt_ptr != NULL);
    assert(key_ptr != NULL);
    assert(value_len != NULL);

    void *value_ptr = NULL;
    int ret;
    DBT query_cond;
    int alloc_flag;

    alloc_flag = 0;

    if (*dbt_ptr == NULL)
    {
        if ((*dbt_ptr = slab_alloc(sizeof **dbt_ptr)) == NULL)
        {
            ret = -1;
            REPORT_ERR("memory is not enough");
        }
        alloc_flag = alloc_flag | FIND_RECORD_ALLOC_DBT_PTR;
    }
    if ((value_ptr = slab_alloc(*value_len)) == NULL)
    {
        ret = -1;
        REPORT_ERR("memory is not enough");
    }
    alloc_flag = alloc_flag | FIND_RECORD_ALLOC_VAL_PTR;

    memset(&query_cond, 0, sizeof query_cond);
    memset(*dbt_ptr, 0, sizeof **dbt_ptr);
    memset(value_ptr, 0, *value_len);

    query_cond.data = key_ptr;
    query_cond.size = key_len;
    (*dbt_ptr)->data = value_ptr;
    (*dbt_ptr)->ulen = *value_len;
    (*dbt_ptr)->flags = DB_DBT_USERMEM;

    BUILD_DB_PREFIX;
    if ((ret = bdbp->dbp->get(bdbp->dbp, NULL, &query_cond, *dbt_ptr, 0)) != 0)
    {
        if (ret != DB_NOTFOUND)
            REPORT_ERR("bdb query failed: %s", db_strerror(ret));
    }

err:
    if (ret != 0)
    {
        if ((alloc_flag & FIND_RECORD_ALLOC_DBT_PTR) && (*dbt_ptr != NULL))
        {
            slab_free(*dbt_ptr);
            *dbt_ptr = NULL;
        }
        if ((alloc_flag & FIND_RECORD_ALLOC_VAL_PTR) && (value_ptr != NULL))
        {
            slab_free(value_ptr);
            if (*dbt_ptr != NULL)
                (*dbt_ptr)->data = NULL;
        }
    }
    return ret;
}
コード例 #17
0
ファイル: tools.c プロジェクト: rouzier/openldap
ID bdb_tool_entry_modify(
	BackendDB *be,
	Entry *e,
	struct berval *text )
{
	int rc;
	struct bdb_info *bdb;
	DB_TXN *tid = NULL;
	Operation op = {0};
	Opheader ohdr = {0};

	assert( be != NULL );
	assert( slapMode & SLAP_TOOL_MODE );

	assert( text != NULL );
	assert( text->bv_val != NULL );
	assert( text->bv_val[0] == '\0' );	/* overconservative? */

	assert ( e->e_id != NOID );

	Debug( LDAP_DEBUG_TRACE,
		"=> " LDAP_XSTRING(bdb_tool_entry_modify) "( %ld, \"%s\" )\n",
		(long) e->e_id, e->e_dn, 0 );

	bdb = (struct bdb_info *) be->be_private;

	if (! (slapMode & SLAP_TOOL_QUICK)) {
		if( cursor ) {
			cursor->c_close( cursor );
			cursor = NULL;
		}
		rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
			bdb->bi_db_opflags );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"txn_begin failed: %s (%d)",
				db_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
		Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_modify) ": txn id: %x\n",
			tid->id(tid), 0, 0 );
	}

	op.o_hdr = &ohdr;
	op.o_bd = be;
	op.o_tmpmemctx = NULL;
	op.o_tmpmfuncs = &ch_mfuncs;

	/* id2entry index */
	rc = bdb_id2entry_update( be, tid, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"id2entry_add failed: %s (%d)",
				db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}

done:
	if( rc == 0 ) {
		if (! (slapMode & SLAP_TOOL_QUICK)) {
		rc = TXN_COMMIT( tid, 0 );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
					"txn_commit failed: %s (%d)",
					db_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": "
				"%s\n", text->bv_val, 0, 0 );
			e->e_id = NOID;
		}
		}

	} else {
		if (! (slapMode & SLAP_TOOL_QUICK)) {
		TXN_ABORT( tid );
		snprintf( text->bv_val, text->bv_len,
			"txn_aborted! %s (%d)",
			db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_modify) ": %s\n",
			text->bv_val, 0, 0 );
		}
		e->e_id = NOID;
	}

	if ( cursor == NULL )
	{
		int rc = bdb->bi_id2entry->bdi_db->cursor(
			bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
			bdb->bi_db_opflags );
		if ( rc != 0 )
			e->e_id = NOID;
	}

	return e->e_id;
}
コード例 #18
0
ファイル: tags_cache.c プロジェクト: nihlaeth/read-the-room
static void tags_cache_gc (struct tags_cache *c)
{
	DBC *cur;
	DBT key;
	DBT serialized_cache_rec;
	int ret;
	char *last_referenced = NULL;
	time_t last_referenced_atime = time (NULL) + 1;
	int nitems = 0;

	c->db->cursor (c->db, NULL, &cur, 0);

	memset (&key, 0, sizeof(key));
	memset (&serialized_cache_rec, 0, sizeof(serialized_cache_rec));

	key.flags = DB_DBT_MALLOC;
	serialized_cache_rec.flags = DB_DBT_MALLOC;

	while (true) {
		struct cache_record rec;

#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6
		ret = cur->c_get (cur, &key, &serialized_cache_rec, DB_NEXT);
#else
		ret = cur->get (cur, &key, &serialized_cache_rec, DB_NEXT);
#endif

		if (ret != 0)
			break;

		if (cache_record_deserialize (&rec, serialized_cache_rec.data,
					serialized_cache_rec.size, 1)
				&& rec.atime < last_referenced_atime) {
			last_referenced_atime = rec.atime;

			if (last_referenced)
				free (last_referenced);
			last_referenced = (char *)xmalloc (key.size + 1);
			memcpy (last_referenced, key.data, key.size);
			last_referenced[key.size] = '\0';
		}

		// TODO: remove objects with serialization error.

		nitems++;

		free (key.data);
		free (serialized_cache_rec.data);
	}

	if (ret != DB_NOTFOUND)
		logit ("Searching for element to remove failed (cursor): %s",
				db_strerror (ret));

#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6
	cur->c_close (cur);
#else
	cur->close (cur);
#endif

	debug ("Elements in cache: %d (limit %d)", nitems, c->max_items);

	if (last_referenced) {
		if (nitems >= c->max_items)
			tags_cache_remove_rec (c, last_referenced);
		free (last_referenced);
	}
	else
		debug ("Cache empty");
}
コード例 #19
0
ファイル: dbconverter-2.c プロジェクト: Jakuje/cyrus-sasl
int listusers(const char *path, listcb_t *cb)
{
    int result;
    DB *mbdb = NULL;
    DBC *cursor;
    DBT key, data;

    /* open the db */
    result=berkeleydb_open(path, &mbdb);
    if (result!=SASL_OK) goto cleanup;

    /* make cursor */
#if DB_VERSION_FULL < 0x03060000
    result = mbdb->cursor(mbdb, NULL,&cursor); 
#else
    result = mbdb->cursor(mbdb, NULL,&cursor, 0); 
#endif /* DB_VERSION_FULL < 0x03060000 */

    if (result!=0) {
	fprintf(stderr,"Making cursor failure: %s\n",db_strerror(result));
      result = SASL_FAIL;
      goto cleanup;
    }

    memset(&key,0, sizeof(key));
    memset(&data,0,sizeof(data));

    /* loop thru */
    result = cursor->c_get(cursor, &key, &data,
			   DB_FIRST);

    while (result != DB_NOTFOUND)
    {
	char *authid;
	char *realm;
	char *tmp;
	unsigned int len;
	char mech[1024];
	int numnulls = 0;
	unsigned int lup;

	/* make sure there are exactly 2 null's */
	for (lup=0;lup<key.size;lup++)
	    if (((char *)key.data)[lup]=='\0')
		numnulls++;

	if (numnulls != 2) {
	    fprintf(stderr,"warning: probable database corruption\n");
	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
	    continue;
	}

	authid = key.data;
	realm  = authid + strlen(authid)+1;
	tmp    = realm + strlen(realm)+1;
	len = key.size - (tmp - authid);

	/* make sure we have enough space of mech */
	if (len >=sizeof(mech)) {
	    fprintf(stderr,"warning: absurdly long mech name\n");
	    result = cursor->c_get(cursor, &key, &data, DB_NEXT);
	    continue;
	}

	memcpy(mech, tmp, key.size - (tmp - ((char *)key.data)));
	mech[key.size - (tmp - ((char *)key.data))] = '\0';

	if (*authid) {
	    /* don't check return values */
	    cb(authid,realm,mech,data.data,data.size);
	}

	result = cursor->c_get(cursor, &key, &data, DB_NEXT);
    }

    if (result != DB_NOTFOUND) {
	fprintf(stderr,"failure: %s\n",db_strerror(result));
	result = SASL_FAIL;
	goto cleanup;
    }

    result = cursor->c_close(cursor);
    if (result!=0) result = SASL_FAIL;

    result = SASL_OK;

 cleanup:

    if (mbdb != NULL) berkeleydb_close(mbdb);
    return result;
}
コード例 #20
0
int getInfo(int id)
{
	DB_ENV *dbenv = radacct_dbenv;
	DB *dbp = radacct_dbp;
	DB_TXN *tid = NULL;
	DBT key, data;
	db_recno_t recno;
	int info = 0;
	char buf[REC_SIZE];
	int ret;
	clock_t t1, t2;
	clock_t t3, t4;
	struct tms buf1, buf2;
	struct tms buf3, buf4;

	memset(&key, 0, sizeof(DBT));
	memset(&data, 0, sizeof(DBT));

	key.data = &recno;
	key.size = key.ulen = sizeof(recno);
	key.flags = DB_DBT_USERMEM;

	data.data = buf;
	data.ulen = sizeof(buf);
	data.flags = DB_DBT_USERMEM;

	if((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0)
	{
		printf("getInfo: transaction failed: %s\n", db_strerror(ret));
		return 0;
	}
	t1 = times(&buf1);
	ret = dbp->get(dbp, tid, &key, &data, DB_CONSUME);
	t2 = times(&buf2);
	get_total_time[id] += (t2 - t1);
	get_time_buf[id].tms_utime += (buf2.tms_utime - buf1.tms_utime);
	get_time_buf[id].tms_stime += (buf2.tms_stime - buf1.tms_stime);
	get_time_buf[id].tms_cutime += (buf2.tms_cutime - buf1.tms_cutime);
	get_time_buf[id].tms_cstime += (buf2.tms_cstime - buf1.tms_cstime);
	switch(ret)
	{

		case DB_LOCK_DEADLOCK:
			printf("getInfo: deadlock: %s\n", db_strerror(ret));
			break;

		case 0:
			t3 = times(&buf3);	
			removeInfo(tid);
			t4 = times(&buf4);
			remove_total_time[id] = (t4 - t3);
			remove_time_buf[id].tms_utime += (buf4.tms_utime - buf3.tms_utime);
			remove_time_buf[id].tms_stime += (buf4.tms_stime - buf3.tms_stime);
			remove_time_buf[id].tms_cutime += (buf4.tms_cutime - buf3.tms_cutime);
			remove_time_buf[id].tms_cstime += (buf4.tms_cstime - buf3.tms_cstime);
			break;

		default:
			printf("getInfo: oops: %d\n", ret);
			break;
	}

	return info;
}
コード例 #21
0
ファイル: init.c プロジェクト: Joywar/openldap
static int
bdb_db_open( BackendDB *be, ConfigReply *cr )
{
	int rc, i;
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	struct stat stat1, stat2;
	u_int32_t flags;
	char path[MAXPATHLEN];
	char *dbhome;
	Entry *e = NULL;
	int do_recover = 0, do_alock_recover = 0;
	int alockt, quick = 0;
	int do_retry = 1;

	if ( be->be_suffix == NULL ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": need suffix.\n",
			1, 0, 0 );
		return -1;
	}

	Debug( LDAP_DEBUG_ARGS,
		LDAP_XSTRING(bdb_db_open) ": \"%s\"\n",
		be->be_suffix[0].bv_val, 0, 0 );

	/* Check existence of dbenv_home. Any error means trouble */
	rc = stat( bdb->bi_dbenv_home, &stat1 );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"cannot access database directory \"%s\" (%d).\n",
			be->be_suffix[0].bv_val, bdb->bi_dbenv_home, errno );
		return -1;
	}

	/* Perform database use arbitration/recovery logic */
	alockt = (slapMode & SLAP_TOOL_READONLY) ? ALOCK_LOCKED : ALOCK_UNIQUE;
	if ( slapMode & SLAP_TOOL_QUICK ) {
		alockt |= ALOCK_NOSAVE;
		quick = 1;
	}

	rc = alock_open( &bdb->bi_alock_info, 
				"slapd", 
				bdb->bi_dbenv_home, alockt );

	/* alockt is TRUE if the existing environment was created in Quick mode */
	alockt = (rc & ALOCK_NOSAVE) ? 1 : 0;
	rc &= ~ALOCK_NOSAVE;

	if( rc == ALOCK_RECOVER ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"unclean shutdown detected; attempting recovery.\n", 
			be->be_suffix[0].bv_val, 0, 0 );
		do_alock_recover = 1;
		do_recover = DB_RECOVER;
	} else if( rc == ALOCK_BUSY ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"database already in use.\n", 
			be->be_suffix[0].bv_val, 0, 0 );
		return -1;
	} else if( rc != ALOCK_CLEAN ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"alock package is unstable.\n", 
			be->be_suffix[0].bv_val, 0, 0 );
		return -1;
	}
	if ( rc == ALOCK_CLEAN )
		be->be_flags |= SLAP_DBFLAG_CLEAN;

	/*
	 * The DB_CONFIG file may have changed. If so, recover the
	 * database so that new settings are put into effect. Also
	 * note the possible absence of DB_CONFIG in the log.
	 */
	if( stat( bdb->bi_db_config_path, &stat1 ) == 0 ) {
		if ( !do_recover ) {
			char *ptr = lutil_strcopy(path, bdb->bi_dbenv_home);
			*ptr++ = LDAP_DIRSEP[0];
			strcpy( ptr, "__db.001" );
			if( stat( path, &stat2 ) == 0 ) {
				if( stat2.st_mtime < stat1.st_mtime ) {
					Debug( LDAP_DEBUG_ANY,
						LDAP_XSTRING(bdb_db_open) ": DB_CONFIG for suffix \"%s\" has changed.\n",
							be->be_suffix[0].bv_val, 0, 0 );
					if ( quick ) {
						Debug( LDAP_DEBUG_ANY,
							"Cannot use Quick mode; perform manual recovery first.\n",
							0, 0, 0 );
						slapMode ^= SLAP_TOOL_QUICK;
						rc = -1;
						goto fail;
					} else {
						Debug( LDAP_DEBUG_ANY,
							"Performing database recovery to activate new settings.\n",
							0, 0, 0 );
					}
					do_recover = DB_RECOVER;
				}
			}
		}
	}
	else {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": warning - no DB_CONFIG file found "
			"in directory %s: (%d).\n"
			"Expect poor performance for suffix \"%s\".\n",
			bdb->bi_dbenv_home, errno, be->be_suffix[0].bv_val );
	}

	/* Always let slapcat run, regardless of environment state.
	 * This can be used to cause a cache flush after an unclean
	 * shutdown.
	 */
	if ( do_recover && ( slapMode & SLAP_TOOL_READONLY )) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"recovery skipped in read-only mode. "
			"Run manual recovery if errors are encountered.\n",
			be->be_suffix[0].bv_val, 0, 0 );
		do_recover = 0;
		do_alock_recover = 0;
		quick = alockt;
	}

	/* An existing environment in Quick mode has nothing to recover. */
	if ( alockt && do_recover ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"cannot recover, database must be reinitialized.\n", 
			be->be_suffix[0].bv_val, 0, 0 );
		rc = -1;
		goto fail;
	}

	rc = db_env_create( &bdb->bi_dbenv, 0 );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
			"db_env_create failed: %s (%d).\n",
			be->be_suffix[0].bv_val, db_strerror(rc), rc );
		goto fail;
	}

#ifdef HAVE_EBCDIC
	strcpy( path, bdb->bi_dbenv_home );
	__atoe( path );
	dbhome = path;
#else
	dbhome = bdb->bi_dbenv_home;
#endif

	/* If existing environment is clean but doesn't support
	 * currently requested modes, remove it.
	 */
	if ( !do_recover && ( alockt ^ quick )) {
shm_retry:
		rc = bdb->bi_dbenv->remove( bdb->bi_dbenv, dbhome, DB_FORCE );
		if ( rc ) {
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
				"dbenv remove failed: %s (%d).\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			bdb->bi_dbenv = NULL;
			goto fail;
		}
		rc = db_env_create( &bdb->bi_dbenv, 0 );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
				"db_env_create failed: %s (%d).\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			goto fail;
		}
	}

	bdb->bi_dbenv->set_errpfx( bdb->bi_dbenv, be->be_suffix[0].bv_val );
	bdb->bi_dbenv->set_errcall( bdb->bi_dbenv, bdb_errcall );

	bdb->bi_dbenv->set_lk_detect( bdb->bi_dbenv, bdb->bi_lock_detect );

	if ( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
		rc = bdb->bi_dbenv->set_encrypt( bdb->bi_dbenv, bdb->bi_db_crypt_key.bv_val,
			DB_ENCRYPT_AES );
		if ( rc ) {
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
				"dbenv set_encrypt failed: %s (%d).\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			goto fail;
		}
	}

	/* One long-lived TXN per thread, two TXNs per write op */
	bdb->bi_dbenv->set_tx_max( bdb->bi_dbenv, connection_pool_max * 3 );

	if( bdb->bi_dbenv_xflags != 0 ) {
		rc = bdb->bi_dbenv->set_flags( bdb->bi_dbenv,
			bdb->bi_dbenv_xflags, 1);
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
				"dbenv_set_flags failed: %s (%d).\n",
				be->be_suffix[0].bv_val, db_strerror(rc), rc );
			goto fail;
		}
	}

#define	BDB_TXN_FLAGS	(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(bdb_db_open) ": database \"%s\": "
		"dbenv_open(%s).\n",
		be->be_suffix[0].bv_val, bdb->bi_dbenv_home, 0);

	flags = DB_INIT_MPOOL | DB_CREATE | DB_THREAD;

	if ( !quick )
		flags |= BDB_TXN_FLAGS;

	/* If a key was set, use shared memory for the BDB environment */
	if ( bdb->bi_shm_key ) {
		bdb->bi_dbenv->set_shm_key( bdb->bi_dbenv, bdb->bi_shm_key );
		flags |= DB_SYSTEM_MEM;
	}
	rc = (bdb->bi_dbenv->open)( bdb->bi_dbenv, dbhome,
			flags | do_recover, bdb->bi_dbenv_mode );

	if ( rc ) {
		/* Regular open failed, probably a missing shm environment.
		 * Start over, do a recovery.
		 */
		if ( !do_recover && bdb->bi_shm_key && do_retry ) {
			bdb->bi_dbenv->close( bdb->bi_dbenv, 0 );
			rc = db_env_create( &bdb->bi_dbenv, 0 );
			if( rc == 0 ) {
				Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(bdb_db_open)
					": database \"%s\": "
					"shared memory env open failed, assuming stale env.\n",
					be->be_suffix[0].bv_val, 0, 0 );
				do_retry = 0;
				goto shm_retry;
			}
		}
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\" cannot be %s, err %d. "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, do_recover ? "recovered" : "opened", rc );
		goto fail;
	}

	if ( do_alock_recover && alock_recover (&bdb->bi_alock_info) != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": database \"%s\": alock_recover failed\n",
			be->be_suffix[0].bv_val, 0, 0 );
		rc = -1;
		goto fail;
	}

#ifdef SLAP_ZONE_ALLOC
	if ( bdb->bi_cache.c_maxsize ) {
		bdb->bi_cache.c_zctx = slap_zn_mem_create(
			SLAP_ZONE_INITSIZE, SLAP_ZONE_MAXSIZE,
			SLAP_ZONE_DELTA, SLAP_ZONE_SIZE);
	}
#endif

	/* dncache defaults to 0 == unlimited
	 * must be >= entrycache
	 */
	if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_eimax < bdb->bi_cache.c_maxsize ) {
		bdb->bi_cache.c_eimax = bdb->bi_cache.c_maxsize;
	}

	if ( bdb->bi_idl_cache_max_size ) {
		bdb->bi_idl_tree = NULL;
		bdb->bi_idl_cache_size = 0;
	}

	flags = DB_THREAD | bdb->bi_db_opflags;

#ifdef DB_AUTO_COMMIT
	if ( !quick )
		flags |= DB_AUTO_COMMIT;
#endif

	bdb->bi_databases = (struct bdb_db_info **) ch_malloc(
		BDB_INDICES * sizeof(struct bdb_db_info *) );

	/* open (and create) main database */
	for( i = 0; bdbi_databases[i].name.bv_val; i++ ) {
		struct bdb_db_info *db;

		db = (struct bdb_db_info *) ch_calloc(1, sizeof(struct bdb_db_info));

		rc = db_create( &db->bdi_db, bdb->bi_dbenv, 0 );
		if( rc != 0 ) {
			snprintf(cr->msg, sizeof(cr->msg),
				"database \"%s\": db_create(%s) failed: %s (%d).",
				be->be_suffix[0].bv_val, 
				bdb->bi_dbenv_home, db_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": %s\n",
				cr->msg, 0, 0 );
			goto fail;
		}

		if( !BER_BVISNULL( &bdb->bi_db_crypt_key )) {
			rc = db->bdi_db->set_flags( db->bdi_db, DB_ENCRYPT );
			if ( rc ) {
				snprintf(cr->msg, sizeof(cr->msg),
					"database \"%s\": db set_flags(DB_ENCRYPT)(%s) failed: %s (%d).",
					be->be_suffix[0].bv_val, 
					bdb->bi_dbenv_home, db_strerror(rc), rc );
				Debug( LDAP_DEBUG_ANY,
					LDAP_XSTRING(bdb_db_open) ": %s\n",
					cr->msg, 0, 0 );
				goto fail;
			}
		}

		if( bdb->bi_flags & BDB_CHKSUM ) {
			rc = db->bdi_db->set_flags( db->bdi_db, DB_CHKSUM );
			if ( rc ) {
				snprintf(cr->msg, sizeof(cr->msg),
					"database \"%s\": db set_flags(DB_CHKSUM)(%s) failed: %s (%d).",
					be->be_suffix[0].bv_val, 
					bdb->bi_dbenv_home, db_strerror(rc), rc );
				Debug( LDAP_DEBUG_ANY,
					LDAP_XSTRING(bdb_db_open) ": %s\n",
					cr->msg, 0, 0 );
				goto fail;
			}
		}

		rc = bdb_db_findsize( bdb, (struct berval *)&bdbi_databases[i].name );

		if( i == BDB_ID2ENTRY ) {
			if ( !rc ) rc = BDB_ID2ENTRY_PAGESIZE;
			rc = db->bdi_db->set_pagesize( db->bdi_db, rc );

			if ( slapMode & SLAP_TOOL_MODE )
				db->bdi_db->mpf->set_priority( db->bdi_db->mpf,
					DB_PRIORITY_VERY_LOW );

			if ( slapMode & SLAP_TOOL_READMAIN ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
		} else {
			/* Use FS default size if not configured */
			if ( rc )
				rc = db->bdi_db->set_pagesize( db->bdi_db, rc );

			rc = db->bdi_db->set_flags( db->bdi_db, 
				DB_DUP | DB_DUPSORT );
#ifndef BDB_HIER
			if ( slapMode & SLAP_TOOL_READONLY ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
#else
			rc = db->bdi_db->set_dup_compare( db->bdi_db,
				bdb_dup_compare );
			if ( slapMode & (SLAP_TOOL_READONLY|SLAP_TOOL_READMAIN) ) {
				flags |= DB_RDONLY;
			} else {
				flags |= DB_CREATE;
			}
#endif
		}

#ifdef HAVE_EBCDIC
		strcpy( path, bdbi_databases[i].file );
		__atoe( path );
		rc = DB_OPEN( db->bdi_db,
			path,
		/*	bdbi_databases[i].name, */ NULL,
			bdbi_databases[i].type,
			bdbi_databases[i].flags | flags,
			bdb->bi_dbenv_mode );
#else
		rc = DB_OPEN( db->bdi_db,
			bdbi_databases[i].file,
		/*	bdbi_databases[i].name, */ NULL,
			bdbi_databases[i].type,
			bdbi_databases[i].flags | flags,
			bdb->bi_dbenv_mode );
#endif

		if ( rc != 0 ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"db_open(%s/%s) failed: %s (%d).", 
				be->be_suffix[0].bv_val, 
				bdb->bi_dbenv_home, bdbi_databases[i].file,
				db_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(bdb_db_open) ": %s\n",
				cr->msg, 0, 0 );
			db->bdi_db->close( db->bdi_db, 0 );
			goto fail;
		}

		flags &= ~(DB_CREATE | DB_RDONLY);
		db->bdi_name = bdbi_databases[i].name;
		bdb->bi_databases[i] = db;
	}

	bdb->bi_databases[i] = NULL;
	bdb->bi_ndatabases = i;

	/* get nextid */
	rc = bdb_last_id( be, NULL );
	if( rc != 0 ) {
		snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
			"last_id(%s) failed: %s (%d).",
			be->be_suffix[0].bv_val, bdb->bi_dbenv_home,
			db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(bdb_db_open) ": %s\n",
			cr->msg, 0, 0 );
		goto fail;
	}

	if ( !quick ) {
		TXN_BEGIN(bdb->bi_dbenv, NULL, &bdb->bi_cache.c_txn, DB_READ_COMMITTED | DB_TXN_NOWAIT);
	}

	entry_prealloc( bdb->bi_cache.c_maxsize );
	attr_prealloc( bdb->bi_cache.c_maxsize * 20 );

	/* setup for empty-DN contexts */
	if ( BER_BVISEMPTY( &be->be_nsuffix[0] )) {
		rc = bdb_id2entry( be, NULL, 0, &e );
	}
	if ( !e ) {
		struct berval gluebv = BER_BVC("glue");
		Operation op = {0};
		Opheader ohdr = {0};
		e = entry_alloc();
		e->e_id = 0;
		ber_dupbv( &e->e_name, (struct berval *)&slap_empty_bv );
		ber_dupbv( &e->e_nname, (struct berval *)&slap_empty_bv );
		attr_merge_one( e, slap_schema.si_ad_objectClass,
			&gluebv, NULL );
		attr_merge_one( e, slap_schema.si_ad_structuralObjectClass,
			&gluebv, NULL );
		op.o_hdr = &ohdr;
		op.o_bd = be;
		op.ora_e = e;
		op.o_dn = be->be_rootdn;
		op.o_ndn = be->be_rootndn;
		slap_add_opattrs( &op, NULL, NULL, 0, 0 );
	}
	e->e_ocflags = SLAP_OC_GLUE|SLAP_OC__END;
	e->e_private = &bdb->bi_cache.c_dntree;
	bdb->bi_cache.c_dntree.bei_e = e;

	/* monitor setup */
	rc = bdb_monitor_db_open( be );
	if ( rc != 0 ) {
		goto fail;
	}

	bdb->bi_flags |= BDB_IS_OPEN;

	return 0;

fail:
	bdb_db_close( be, NULL );
	return rc;
}
コード例 #22
0
int
main(void)
{
    /* Initialize our handles */
    DB *dbp = NULL;
    DB_ENV *envp = NULL;

    thread_t writer_threads[NUMWRITERS];
    int i, ret, ret_t;
    u_int32_t env_flags;

    /* Application name */
    const char *prog_name = "txn_guide_inmemory";

    /* Create the environment */
    ret = db_env_create(&envp, 0);
    if (ret != 0) {
	fprintf(stderr, "Error creating environment handle: %s\n",
	    db_strerror(ret));
	goto err;
    }

    env_flags =
      DB_CREATE     |  /* Create the environment if it does not exist */
      DB_INIT_LOCK  |  /* Initialize the locking subsystem */
      DB_INIT_LOG   |  /* Initialize the logging subsystem */
      DB_INIT_TXN   |  /* Initialize the transactional subsystem. This
			* also turns on logging. */
      DB_INIT_MPOOL |  /* Initialize the memory pool (in-memory cache) */
      DB_PRIVATE    |  /* Region files are backed by heap memory.  */
      DB_THREAD;       /* Cause the environment to be free-threaded */

    /* Specify in-memory logging */
    ret = envp->log_set_config(envp, DB_LOG_IN_MEMORY, 1);
    if (ret != 0) {
	fprintf(stderr, "Error setting log subsystem to in-memory: %s\n",
	    db_strerror(ret));
	goto err;
    }

    /*
     * Specify the size of the in-memory log buffer.
     */
    ret = envp->set_lg_bsize(envp, 10 * 1024 * 1024);
    if (ret != 0) {
	fprintf(stderr, "Error increasing the log buffer size: %s\n",
	    db_strerror(ret));
	goto err;
    }

    /*
     * Specify the size of the in-memory cache.
     */
    ret = envp->set_cachesize(envp, 0, 10 * 1024 * 1024, 1);
    if (ret != 0) {
	fprintf(stderr, "Error increasing the cache size: %s\n",
	    db_strerror(ret));
	goto err;
    }

     /*
     * Indicate that we want db to perform lock detection internally.
     * Also indicate that the transaction with the fewest number of
     * write locks will receive the deadlock notification in
     * the event of a deadlock.
     */
    ret = envp->set_lk_detect(envp, DB_LOCK_MINWRITE);
    if (ret != 0) {
	fprintf(stderr, "Error setting lock detect: %s\n",
	    db_strerror(ret));
	goto err;
    }

    /* Now actually open the environment */
    ret = envp->open(envp, NULL, env_flags, 0);
    if (ret != 0) {
	fprintf(stderr, "Error opening environment: %s\n",
	    db_strerror(ret));
	goto err;
    }

    /*
     * If we had utility threads (for running checkpoints or
     * deadlock detection, for example) we would spawn those
     * here. However, for a simple example such as this,
     * that is not required.
     */

    /* Open the database */
    ret = open_db(&dbp, prog_name, NULL,
      envp, DB_DUPSORT);
    if (ret != 0)
	goto err;

    /* Initialize a mutex. Used to help provide thread ids. */
    (void)mutex_init(&thread_num_lock, NULL);

    /* Start the writer threads. */
    for (i = 0; i < NUMWRITERS; i++)
	(void)thread_create(
	    &writer_threads[i], NULL, writer_thread, (void *)dbp);

    /* Join the writers */
    for (i = 0; i < NUMWRITERS; i++)
	(void)thread_join(writer_threads[i], NULL);

err:
    /* Close our database handle, if it was opened. */
    if (dbp != NULL) {
	ret_t = dbp->close(dbp, 0);
	if (ret_t != 0) {
	    fprintf(stderr, "%s database close failed.\n",
		db_strerror(ret_t));
	    ret = ret_t;
	}
    }

    /* Close our environment, if it was opened. */
    if (envp != NULL) {
	ret_t = envp->close(envp, 0);
	if (ret_t != 0) {
	    fprintf(stderr, "environment close failed: %s\n",
		db_strerror(ret_t));
		ret = ret_t;
	}
    }

    /* Final status message and return. */
    printf("I'm all done.\n");
    return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
コード例 #23
0
ファイル: gw_acct.c プロジェクト: hep-gc/Gridway
int gw_acct_db_open(gw_boolean_t server)
{
	int       rc;
	u_int32_t flags;
	u_int32_t env_flags;
	DB        *db;
	DB_ENV    *db_env;
	char      env_dir[PATH_MAX];
	char *    gw_location;
	mode_t    mask;
	
    gw_location = getenv("GW_LOCATION");
    
    if ( gw_location == NULL)
    {
		if (server == GW_TRUE)
           gw_log_print("GW",'E',"Variable GW_LOCATION is not defined.\n");
        else
			fprintf(stderr,"Variable GW_LOCATION is not defined!\n");
			
        return -1;
    }
     
    snprintf(env_dir, PATH_MAX-1, "%s/" GW_VAR_DIR "/acct/", gw_location);
	
	/* ----- Open the environment ------ */
	
	mask = umask(002);
	
	rc = db_env_create(&(gw_acct_db.env_db), 0);
	
	if ( rc != 0 )
	{
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error initializing environment structure (%s).\n",
				db_strerror(rc));
		else
			fprintf(stderr,"Error initializing environment structure (%s).\n",
				db_strerror(rc));
				
		return -1;
	}
	db_env = gw_acct_db.env_db;
	
	env_flags = DB_INIT_CDB	| DB_INIT_MPOOL;
	
	if (server == GW_TRUE)
		env_flags = env_flags | DB_CREATE | DB_THREAD;
	
	rc = db_env->open(db_env,env_dir,env_flags,0664);

	if (rc!=0)
	{
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error openning environment (%s).\n",db_strerror(rc));
		else
			fprintf(stderr,"Error openning environment (%s).\n",db_strerror(rc));

		return -1;
	}

	umask(mask);
	
	/* ----- Primary Database, acct.db ------ */
	
	rc = db_create(&(gw_acct_db.acct_db), db_env, 0);
	
	if ( rc != 0 )
	{		
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error initializing database structure (%s).\n",
					db_strerror(rc));
		else
			fprintf(stderr,"Error initializing database structure (%s).\n",
					db_strerror(rc));

		return -1;
	}
	
	db = gw_acct_db.acct_db;
	
	if (server == GW_TRUE)
	{
		db->set_errcall(db,gw_acct_db_error);
		db->set_errpfx(db,"ACCT-DB");		
		flags = DB_CREATE | DB_THREAD;
	}
	else
		flags = DB_RDONLY;

	rc = db->open(db,
	              NULL, 
	              "acct.db",
                  NULL, 
                  DB_BTREE, 
                  flags, 
                  0644);
	if (rc!=0)
	{
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error openning database.\n");
		else
			fprintf(stderr,"Error openning database.\n");

		return -1;
	}

	/* ----- Secondary Database (user index), uidx.db ------ */
	
	rc = db_create(&(gw_acct_db.uinx_db), db_env, 0);
	
	if ( rc != 0 )
	{		
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error initializing database structure (%s).\n",
					db_strerror(rc));
		else
			fprintf(stderr,"Error initializing database structure (%s).\n",
					db_strerror(rc));

		return -1;
	}
	
	db = gw_acct_db.uinx_db;
	
	db->set_flags(db,DB_DUPSORT);

	if (server == GW_TRUE)
	{
		db->set_errcall(db,gw_acct_db_error);
		db->set_errpfx(db,"UINX-DB");		
		
		flags = DB_CREATE | DB_THREAD;
	}
	else
		flags = DB_RDONLY;
	
	rc = db->open(db,
	              NULL, 
	              "uinx.db",
                  NULL, 
                  DB_BTREE, 
                  flags, 
                  0644);
	if (rc!=0)
	{
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error openning database.\n");
		else
			fprintf(stderr,"Error openning database.\n");

		return -1;
	}

	gw_acct_db.acct_db->associate(gw_acct_db.acct_db,
	                              NULL,
	                              db,
	                              gw_acct_uidx_cb,
	                              DB_CREATE);
	                              
	/* ----- Secondary Database (host index), hidx.db ------ */
		
	rc = db_create(&(gw_acct_db.hinx_db), db_env, 0);

	if ( rc != 0 )
	{		
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error initializing database structure (%s).\n",
					db_strerror(rc));
		else
			fprintf(stderr,"Error initializing database structure (%s).\n",
					db_strerror(rc));

		return -1;
	}
	
	db = gw_acct_db.hinx_db;
	
	db->set_flags(db,DB_DUPSORT);

	if (server == GW_TRUE)
	{
		db->set_errcall(db,gw_acct_db_error);
		db->set_errpfx(db,"HINX-DB");
		
		flags = DB_CREATE | DB_THREAD;
	}
	else
		flags = DB_RDONLY;
	
	rc = db->open(db,
	              NULL, 
	              "hinx.db",
                  NULL, 
                  DB_BTREE, 
                  flags, 
                  0644);
	if (rc!=0)
	{
		if (server == GW_TRUE)
			gw_log_print("DB",'E',"Error openning database.\n");
		else
			fprintf(stderr,"Error openning database.\n");

		return -1;
	}

	gw_acct_db.acct_db->associate(gw_acct_db.acct_db,
	                              NULL,
	                              db,
	                              gw_acct_hidx_cb,
	                              DB_CREATE);

	if (server == GW_TRUE)	                              		
		gw_log_print ("DB",'I',"Accounting databases opened.\n");
	
	return 0;
}
コード例 #24
0
///-------------------------------------------------------------------------------------------------
///  Scan a single file. Everything that applies to ms_scan also applies to this function. If
///   you know the type of the file, set the type paramter to one of TYPE_AUDIO, TYPE_VIDEO, or
///   TYPE_IMAGE. Set it to TYPE_UNKNOWN to have it determined automatically.
///
/// @author Andy Grundman
/// @date 03/15/2011
///
/// @param [in,out] s If non-null, the.
/// @param full_path  Full pathname of the full file.
///
/// ### remarks .
///-------------------------------------------------------------------------------------------------
void ms_scan_file(MediaScan *s, const char *full_path, enum media_type type) {
  MediaScanError *e = NULL;
  MediaScanResult *r = NULL;
  int ret;
  uint32_t hash;
  int mtime = 0;
  uint64_t size = 0;
  DBT key, data;
  char tmp_full_path[MAX_PATH_STR_LEN];

#ifdef WIN32
  char *ext = strrchr(full_path, '.');
#endif

  if (s == NULL) {
    ms_errno = MSENO_NULLSCANOBJ;
    LOG_ERROR("MediaScan = NULL, aborting scan\n");
    return;
  }

  if (s->on_result == NULL) {
    ms_errno = MSENO_NORESULTCALLBACK;
    LOG_ERROR("Result callback not set, aborting scan\n");
    return;
  }

#if (defined(__APPLE__) && defined(__MACH__))
  if (isAlias(full_path)) {
    LOG_INFO("File  %s is a mac alias\n", full_path);
    // Check if this file is a shortcut and if so resolve it
    if (!CheckMacAlias(full_path, tmp_full_path)) {
      LOG_ERROR("Failure to follow symlink or alias, skipping file\n");
      return;
    }
  }
  else {
    strcpy(tmp_full_path, full_path);
  }
#elif defined(__unix__) || defined(__unix)
  if (isAlias(full_path)) {
    LOG_INFO("File %s is a unix symlink\n", full_path);
    // Check if this file is a shortcut and if so resolve it
    FollowLink(full_path, tmp_full_path);
  }
  else {
    strcpy(tmp_full_path, full_path);
  }
#elif defined(WIN32)
  if (strcasecmp(ext, ".lnk") == 0) {
    // Check if this file is a shortcut and if so resolve it
    parse_lnk(full_path, tmp_full_path, MAX_PATH_STR_LEN);
    if (PathIsDirectory(tmp_full_path))
      return;
  }
  else {
    strcpy(tmp_full_path, full_path);
  }
#endif

  // Check if the file has been recently scanned
  hash = HashFile(tmp_full_path, &mtime, &size);

  // Skip 0-byte files
  if (unlikely(size == 0)) {
    LOG_WARN("Skipping 0-byte file: %s\n", tmp_full_path);
    return;
  }

  // Setup DBT values
  memset(&key, 0, sizeof(DBT));
  memset(&data, 0, sizeof(DBT));
  key.data = (char *)full_path;
  key.size = strlen(full_path) + 1;
  data.data = &hash;
  data.size = sizeof(uint32_t);

  if ((s->flags & MS_RESCAN) || (s->flags & MS_FULL_SCAN)) {
    // s->dbp will be null if this function is called directly, if not check if this file is
    // already scanned.
    if (s->dbp != NULL) {
      // DB_GET_BOTH will only return OK if both key and data match, this avoids the need to check
      // the returned data against hash
      int ret = s->dbp->get(s->dbp, NULL, &key, &data, DB_GET_BOTH);
      if (ret != DB_NOTFOUND) {
        //  LOG_INFO("File %s already scanned, skipping\n", tmp_full_path);
        return;
      }
    }
  }

  LOG_INFO("Scanning file %s\n", tmp_full_path);

  if (type == TYPE_UNKNOWN || type == TYPE_LNK) {
    // auto-detect type
    type = _should_scan(s, tmp_full_path);
    if (!type) {
      if (s->on_error) {
        ms_errno = MSENO_SCANERROR;
        e = error_create(tmp_full_path, MS_ERROR_TYPE_UNKNOWN, "Unrecognized file extension");
        send_error(s, e);
        return;
      }
    }
  }

  r = result_create(s);
  if (r == NULL)
    return;

  r->type = type;
  r->path = strdup(full_path);

  if (result_scan(r)) {
    // These were determined by HashFile
    r->mtime = mtime;
    r->size = size;
    r->hash = hash;

    // Store path -> hash data in cache
    if (s->dbp != NULL) {
      memset(&data, 0, sizeof(DBT));
      data.data = &hash;
      data.size = sizeof(uint32_t);

      ret = s->dbp->put(s->dbp, NULL, &key, &data, 0);
      if (ret != 0) {
        s->dbp->err(s->dbp, ret, "Cache store failed: %s", db_strerror(ret));
      }
    }
    send_result(s, r);
  }
  else {
    if (s->on_error && r->error) {
      // Copy the error, because the original will be cleaned up by result_destroy below
      MediaScanError *ecopy = error_copy(r->error);
      send_error(s, ecopy);
    }

    result_destroy(r);
  }
}                               /* ms_scan_file() */
コード例 #25
0
/*
 * Updates a row in table
 * Limitation: only knows how to update a single row
 *
 * _con: structure representing database connection
 * _k: key names
 * _op: operators
 * _v: values of the keys that must match
 * _uk: update keys; cols that need to be updated
 * _uv: update values; col values that need to be commited
 * _un: number of rows to update
 */
int bdb_update(db_con_t* _con, db_key_t* _k, db_op_t* _op, db_val_t* _v,
               db_key_t* _uk, db_val_t* _uv, int _n, int _un)
{
    str s;
    char *c, *t;
    int ret, i, qcol, len, sum;
    int *lkey=NULL;
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char qbuf[MAX_ROW_SIZE];
    char ubuf[MAX_ROW_SIZE];
    DBT key, qdata, udata;
    DB *db;

    sum = ret = i = qcol = len = 0;

    if (!_con || !CON_TABLE(_con) || !_uk || !_uv || _un <= 0)
        return -1;

    s.s = (char*)CON_TABLE(_con);
    s.len = strlen(CON_TABLE(_con));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_con), &s);
    if(!_tbc)
    {   LM_ERR("table does not exist\n");
        return -1;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_ERR("table not loaded\n");
        return -1;
    }

    db = _tp->db;
    if(!db)
    {   LM_ERR("DB null ptr\n");
        return -1;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("UPDATE in %.*s\n", _tp->name.len, _tp->name.s);
    if (_op) LM_DBG("DONT-CARE : _op: operators for refining query \n");
#endif

    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, MAX_ROW_SIZE);
    memset(&qdata, 0, sizeof(DBT));
    memset(qbuf, 0, MAX_ROW_SIZE);

    qdata.data = qbuf;
    qdata.ulen = MAX_ROW_SIZE;
    qdata.flags = DB_DBT_USERMEM;

    if(_k)
    {   lkey = bdb_get_colmap(_tbc->dtp, _k, _n);
        if(!lkey) return -4;
    }
    else
    {
        LM_ERR("Null keys in update _k=0 \n");
        return -1;
    }

    len = MAX_ROW_SIZE;

    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &len, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in query key \n");
        goto cleanup;
    }

    if(lkey) pkg_free(lkey);

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = len;

    /*stage 1: QUERY Berkely DB*/
    if ((ret = db->get(db, NULL, &key, &qdata, 0)) == 0)
    {

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("RESULT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   qdata.size
               , (char *)qdata.data);
#endif

    }
    else
    {   goto db_error;
    }

    /* stage 2: UPDATE row with new values */

    /* map the provided keys to those in our schema */
    lkey = bdb_get_colmap(_tbc->dtp, _uk, _un);
    if(!lkey) return -4;

    /* build a new row for update data (udata) */
    memset(&udata, 0, sizeof(DBT));
    memset(ubuf, 0, MAX_ROW_SIZE);

    /* loop over each column of the qbuf and copy it to our new ubuf unless
       its a field that needs to update
    */
    c = strtok(qbuf, DELIM);
    t = ubuf;
    while( c!=NULL)
    {   char* delim = DELIM;
        int k;

        len = strlen(c);
        sum+=len;

        if(sum > MAX_ROW_SIZE)
        {   LM_ERR("value too long for string \n");
            ret = -3;
            goto cleanup;
        }

        for(i=0; i<_un; i++)
        {
            k = lkey[i];
            if (qcol == k)
            {   /* update this col */
                int j = MAX_ROW_SIZE - sum;
                if( bdb_val2str( &_uv[i], t, &j) )
                {   LM_ERR("value too long for string \n");
                    ret = -3;
                    goto cleanup;
                }

                goto next;
            }

        }

        /* copy original column to the new column */
        strncpy(t, c, len);

next:
        t+=len;

        /* append DELIM */
        sum += DELIM_LEN;
        if(sum > MAX_ROW_SIZE)
        {   LM_ERR("value too long for string \n");
            ret = -3;
            goto cleanup;
        }

        strncpy(t, delim, DELIM_LEN);
        t += DELIM_LEN;

        c = strtok(NULL, DELIM);
        qcol++;
    }

    ubuf[sum]  = '0';
    udata.data = ubuf;
    udata.ulen  = MAX_ROW_SIZE;
    udata.flags = DB_DBT_USERMEM;
    udata.size  = sum;

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("MODIFIED Data\nKEY:  [%.*s]\nDATA: [%.*s]\n"
           , (int)   key.size
           , (char *)key.data
           , (int)   udata.size
           , (char *)udata.data);
#endif
    /* stage 3: DELETE old row using key*/
    if ((ret = db->del(db, NULL, &key, 0)) == 0)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("DELETED ROW\nKEY: %s \n", (char *)key.data);
#endif
    }
    else
    {   goto db_error;
    }

    /* stage 4: INSERT new row with key*/
    if ((ret = db->put(db, NULL, &key, &udata, 0)) == 0)
    {
        bdblib_log(JLOG_UPDATE, _tp, ubuf, sum);
#ifdef BDB_EXTRA_DEBUG
        LM_DBG("INSERT \nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   udata.size
               , (char *)udata.data);
#endif
    }
    else
    {   goto db_error;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("UPDATE COMPLETE \n");
#endif


cleanup:
    if(lkey)
        pkg_free(lkey);

    return ret;


db_error:

    /*Berkeley DB error handler*/
    switch(ret)
    {

    case DB_NOTFOUND:

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("NO RESULT \n");
#endif
        return -1;

    /* The following are all critical/fatal */
    case DB_LOCK_DEADLOCK:
    /* The operation was selected to resolve a deadlock. */
    case DB_SECONDARY_BAD:
    /* A secondary index references a nonexistent primary key.*/
    case DB_RUNRECOVERY:
    default:
        LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
        bdblib_recover(_tp,ret);
    }

    if(lkey)
        pkg_free(lkey);

    return ret;
}
コード例 #26
0
ファイル: tools.c プロジェクト: rouzier/openldap
static int bdb_tool_next_id(
	Operation *op,
	DB_TXN *tid,
	Entry *e,
	struct berval *text,
	int hole )
{
	struct berval dn = e->e_name;
	struct berval ndn = e->e_nname;
	struct berval pdn, npdn;
	EntryInfo *ei = NULL, eidummy;
	int rc;

	if (ndn.bv_len == 0) {
		e->e_id = 0;
		return 0;
	}

	rc = bdb_cache_find_ndn( op, tid, &ndn, &ei );
	if ( ei ) bdb_cache_entryinfo_unlock( ei );
	if ( rc == DB_NOTFOUND ) {
		if ( !be_issuffix( op->o_bd, &ndn ) ) {
			ID eid = e->e_id;
			dnParent( &dn, &pdn );
			dnParent( &ndn, &npdn );
			e->e_name = pdn;
			e->e_nname = npdn;
			rc = bdb_tool_next_id( op, tid, e, text, 1 );
			e->e_name = dn;
			e->e_nname = ndn;
			if ( rc ) {
				return rc;
			}
			/* If parent didn't exist, it was created just now
			 * and its ID is now in e->e_id. Make sure the current
			 * entry gets added under the new parent ID.
			 */
			if ( eid != e->e_id ) {
				eidummy.bei_id = e->e_id;
				ei = &eidummy;
			}
		}
		rc = bdb_next_id( op->o_bd, &e->e_id );
		if ( rc ) {
			snprintf( text->bv_val, text->bv_len,
				"next_id failed: %s (%d)",
				db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
			return rc;
		}
		rc = bdb_dn2id_add( op, tid, ei, e );
		if ( rc ) {
			snprintf( text->bv_val, text->bv_len, 
				"dn2id_add failed: %s (%d)",
				db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> bdb_tool_next_id: %s\n", text->bv_val, 0, 0 );
		} else if ( hole ) {
			if ( nholes == nhmax - 1 ) {
				if ( holes == hbuf ) {
					holes = ch_malloc( nhmax * sizeof(dn_id) * 2 );
					AC_MEMCPY( holes, hbuf, sizeof(hbuf) );
				} else {
					holes = ch_realloc( holes, nhmax * sizeof(dn_id) * 2 );
				}
				nhmax *= 2;
			}
			ber_dupbv( &holes[nholes].dn, &ndn );
			holes[nholes++].id = e->e_id;
		}
	} else if ( !hole ) {
		unsigned i, j;

		e->e_id = ei->bei_id;

		for ( i=0; i<nholes; i++) {
			if ( holes[i].id == e->e_id ) {
				free(holes[i].dn.bv_val);
				for (j=i;j<nholes;j++) holes[j] = holes[j+1];
				holes[j].id = 0;
				nholes--;
				break;
			} else if ( holes[i].id > e->e_id ) {
				break;
			}
		}
	}
	return rc;
}
コード例 #27
0
/*
 * Insert a row into table
 */
int bdb_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    int i, j, ret, klen, dlen;
    int *lkey=NULL;
    DBT key, data;
    DB *db;
    str s;

    i = j = ret = 0;
    klen=MAX_ROW_SIZE;
    dlen=MAX_ROW_SIZE;

    if ((!_h) || (!_v) || !CON_TABLE(_h))
    {   return -1;
    }

    if (!_k)
    {
#ifdef BDB_EXTRA_DEBUG
        LM_ERR("DB INSERT without KEYs not implemented! \n");
#endif
        return -2;
    }

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("INSERT in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);

    if(_tp->ncols<_n)
    {   LM_WARN("more values than columns!!\n");
        return -5;
    }

    lkey = bdb_get_colmap(_tp, _k, _n);
    if(!lkey)  return -7;

    /* verify col types provided */
    for(i=0; i<_n; i++)
    {   j = (lkey)?lkey[i]:i;
        if(bdb_is_neq_type(_tp->colp[j]->type, _v[i].type))
        {
            LM_WARN("incompatible types v[%d] - c[%d]!\n", i, j);
            ret = -8;
            goto error;
        }
    }

    /* make the key */
    if ( (ret = bdblib_valtochar(_tp, lkey, kbuf, &klen, _v, _n, BDB_KEY)) != 0 )
    {   LM_ERR("Error in bdblib_valtochar  \n");
        ret = -9;
        goto error;
    }

    key.data = kbuf;
    key.ulen = MAX_ROW_SIZE;
    key.flags = DB_DBT_USERMEM;
    key.size = klen;

    //make the value (row)
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    if ( (ret = bdblib_valtochar(_tp, lkey, dbuf, &dlen, _v, _n, BDB_VALUE)) != 0 )
    {   LM_ERR("Error in bdblib_valtochar \n");
        ret = -9;
        goto error;
    }

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;
    data.size = dlen;

    if ((ret = db->put(db, NULL, &key, &data, 0)) == 0)
    {
        bdblib_log(JLOG_INSERT, _tp, dbuf, dlen);

#ifdef BDB_EXTRA_DEBUG
        LM_DBG("INSERT\nKEY:  [%.*s]\nDATA: [%.*s]\n"
               , (int)   key.size
               , (char *)key.data
               , (int)   data.size
               , (char *)data.data);
#endif
    }
    else
    {   /*Berkeley DB error handler*/
        switch(ret)
        {
        /*The following are all critical/fatal */
        case DB_LOCK_DEADLOCK:
        /* The operation was selected to resolve a deadlock. */

        case DB_RUNRECOVERY:
        default:
            LM_CRIT("DB->put error: %s.\n", db_strerror(ret));
            bdblib_recover(_tp, ret);
            goto error;
        }
    }

error:
    if(lkey)
        pkg_free(lkey);

    return ret;

}
コード例 #28
0
ファイル: tools.c プロジェクト: rouzier/openldap
ID bdb_tool_entry_put(
	BackendDB *be,
	Entry *e,
	struct berval *text )
{
	int rc;
	struct bdb_info *bdb;
	DB_TXN *tid = NULL;
	Operation op = {0};
	Opheader ohdr = {0};

	assert( be != NULL );
	assert( slapMode & SLAP_TOOL_MODE );

	assert( text != NULL );
	assert( text->bv_val != NULL );
	assert( text->bv_val[0] == '\0' );	/* overconservative? */

	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_tool_entry_put)
		"( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );

	bdb = (struct bdb_info *) be->be_private;

	if (! (slapMode & SLAP_TOOL_QUICK)) {
	rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &tid, 
		bdb->bi_db_opflags );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
			"txn_begin failed: %s (%d)",
			db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
			 text->bv_val, 0, 0 );
		return NOID;
	}
	Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(bdb_tool_entry_put) ": txn id: %x\n",
		tid->id(tid), 0, 0 );
	}

	op.o_hdr = &ohdr;
	op.o_bd = be;
	op.o_tmpmemctx = NULL;
	op.o_tmpmfuncs = &ch_mfuncs;

	/* add dn2id indices */
	rc = bdb_tool_next_id( &op, tid, e, text, 0 );
	if( rc != 0 ) {
		goto done;
	}

#ifdef USE_TRICKLE
	if (( slapMode & SLAP_TOOL_QUICK ) && (( e->e_id & 0xfff ) == 0xfff )) {
		ldap_pvt_thread_cond_signal( &bdb_tool_trickle_cond );
	}
#endif

	if ( !bdb->bi_linear_index )
		rc = bdb_tool_index_add( &op, tid, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"index_entry_add failed: %s (%d)",
				rc == LDAP_OTHER ? "Internal error" :
				db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}

	/* id2entry index */
	rc = bdb_id2entry_add( be, tid, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"id2entry_add failed: %s (%d)",
				db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}

done:
	if( rc == 0 ) {
		if ( !( slapMode & SLAP_TOOL_QUICK )) {
		rc = TXN_COMMIT( tid, 0 );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
					"txn_commit failed: %s (%d)",
					db_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
				text->bv_val, 0, 0 );
			e->e_id = NOID;
		}
		}

	} else {
		if ( !( slapMode & SLAP_TOOL_QUICK )) {
		TXN_ABORT( tid );
		snprintf( text->bv_val, text->bv_len,
			"txn_aborted! %s (%d)",
			rc == LDAP_OTHER ? "Internal error" :
			db_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(bdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		}
		e->e_id = NOID;
	}

	if ( cursor == NULL )
	{
		int rc = bdb->bi_id2entry->bdi_db->cursor(
			bdb->bi_id2entry->bdi_db, bdb->bi_cache.c_txn, &cursor,
			bdb->bi_db_opflags );
		if ( rc != 0 )
			e->e_id = NOID;
	}

	return e->e_id;
}
コード例 #29
0
/*
_bdb_delete_cursor -- called from bdb_delete when the query involves operators
  other than equal '='. Adds support for queries like this:
	DELETE from SomeTable WHERE _k[0] < _v[0]
  In this case, the keys _k are not the actually schema keys, so we need to
  iterate via cursor to perform this operation.
*/
int _bdb_delete_cursor(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n)
{
    tbl_cache_p _tbc = NULL;
    table_p _tp = NULL;
    db_res_t* _r   = NULL;
    char kbuf[MAX_ROW_SIZE];
    char dbuf[MAX_ROW_SIZE];
    int i, ret, klen=MAX_ROW_SIZE;
    DBT key, data;
    DB *db;
    DBC *dbcp;
    int *lkey=NULL;
    str s;

    i = ret = 0;

    if ((!_h) || !CON_TABLE(_h))
        return -1;

    s.s = (char*)CON_TABLE(_h);
    s.len = strlen(CON_TABLE(_h));

    _tbc = bdblib_get_table(BDB_CON_CONNECTION(_h), &s);
    if(!_tbc)
    {   LM_WARN("table does not exist!\n");
        return -3;
    }

    _tp = _tbc->dtp;
    if(!_tp)
    {   LM_WARN("table not loaded!\n");
        return -4;
    }

#ifdef BDB_EXTRA_DEBUG
    LM_DBG("DELETE by cursor in %.*s\n", _tp->name.len, _tp->name.s );
#endif

    if(_k)
    {   lkey = bdb_get_colmap(_tp, _k, _n);
        if(!lkey)
        {   ret = -1;
            goto error;
        }
    }

    /* create an empty db_res_t which gets returned even if no result */
    _r = db_new_result();
    if (!_r)
    {   LM_ERR("no memory for result \n");
    }

    RES_ROW_N(_r) = 0;

    /* fill in the col part of db_res_t */
    if ((ret = bdb_get_columns(_tp, _r, 0, 0)) != 0)
    {   LM_ERR("Error while getting column names\n");
        goto error;
    }

    db = _tp->db;
    memset(&key, 0, sizeof(DBT));
    memset(kbuf, 0, klen);
    memset(&data, 0, sizeof(DBT));
    memset(dbuf, 0, MAX_ROW_SIZE);

    data.data = dbuf;
    data.ulen = MAX_ROW_SIZE;
    data.flags = DB_DBT_USERMEM;

    /* Acquire a cursor for the database. */
    if ((ret = db->cursor(db, NULL, &dbcp, DB_WRITECURSOR)) != 0)
    {   LM_ERR("Error creating cursor\n");
    }

    while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
    {
        if(!strncasecmp((char*)key.data,"METADATA",8))
            continue;

        /*fill in the row part of db_res_t */
        if ((ret=bdb_convert_row( _r, dbuf, 0)) < 0)
        {   LM_ERR("Error while converting row\n");
            goto error;
        }

        if(bdb_row_match(_k, _op, _v, _n, _r, lkey ))
        {

#ifdef BDB_EXTRA_DEBUG
            LM_DBG("DELETE ROW by KEY:  [%.*s]\n", (int) key.size,
                   (char *)key.data);
#endif

            if((ret = dbcp->c_del(dbcp, 0)) != 0)
            {
                /* Berkeley DB error handler */
                LM_CRIT("DB->get error: %s.\n", db_strerror(ret));
                bdblib_recover(_tp,ret);
            }

        }

        memset(dbuf, 0, MAX_ROW_SIZE);
        bdb_free_rows( _r);
    }
    ret = 0;

error:
    if(dbcp)
        dbcp->c_close(dbcp);
    if(_r)
        bdb_free_result(_r);
    if(lkey)
        pkg_free(lkey);

    return ret;
}
コード例 #30
0
ファイル: dn2id.c プロジェクト: RevanthPar/openldap
int
hdb_dn2id(
	Operation	*op,
	struct berval	*in,
	EntryInfo	*ei,
	DB_TXN *txn,
	DBC **cursor )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	DB *db = bdb->bi_dn2id->bdi_db;
	DBT		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	unsigned char dlen[2];
	ID idp, parentID;

	Debug( LDAP_DEBUG_TRACE, "=> hdb_dn2id(\"%s\")\n", in->bv_val, 0, 0 );

	nrlen = dn_rdnlen( op->o_bd, in );
	if (!nrlen) nrlen = in->bv_len;

	DBTzero(&key);
	key.size = sizeof(ID);
	key.data = &idp;
	key.ulen = sizeof(ID);
	key.flags = DB_DBT_USERMEM;
	parentID = ( ei->bei_parent != NULL ) ? ei->bei_parent->bei_id : 0;
	BDB_ID2DISK( parentID, &idp );

	DBTzero(&data);
	data.size = sizeof(diskNode) + nrlen - sizeof(ID) - 1;
	data.ulen = data.size * 3;
	data.dlen = data.ulen;
	data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;

	rc = db->cursor( db, txn, cursor, bdb->bi_db_opflags );
	if ( rc ) return rc;

	d = op->o_tmpalloc( data.size * 3, op->o_tmpmemctx );
	d->nrdnlen[1] = nrlen & 0xff;
	d->nrdnlen[0] = (nrlen >> 8) | 0x80;
	dlen[0] = d->nrdnlen[0];
	dlen[1] = d->nrdnlen[1];
	ptr = lutil_strncopy( d->nrdn, in->bv_val, nrlen );
	*ptr = '\0';
	data.data = d;

	rc = (*cursor)->c_get( *cursor, &key, &data, DB_GET_BOTH_RANGE );
	if ( rc == 0 && (dlen[1] != d->nrdnlen[1] || dlen[0] != d->nrdnlen[0] ||
		strncmp( d->nrdn, in->bv_val, nrlen ))) {
		rc = DB_NOTFOUND;
	}
	if ( rc == 0 ) {
		ptr = (char *) data.data + data.size - sizeof(ID);
		BDB_DISK2ID( ptr, &ei->bei_id );
		ei->bei_rdn.bv_len = data.size - sizeof(diskNode) - nrlen;
		ptr = d->nrdn + nrlen + 1;
		ber_str2bv( ptr, ei->bei_rdn.bv_len, 1, &ei->bei_rdn );
		if ( ei->bei_parent != NULL && !ei->bei_parent->bei_dkids ) {
			db_recno_t dkids;
			/* How many children does the parent have? */
			/* FIXME: do we need to lock the parent
			 * entryinfo? Seems safe...
			 */
			(*cursor)->c_count( *cursor, &dkids, 0 );
			ei->bei_parent->bei_dkids = dkids;
		}
	}

	op->o_tmpfree( d, op->o_tmpmemctx );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: get failed: %s (%d)\n",
			db_strerror( rc ), rc, 0 );
	} else {
		Debug( LDAP_DEBUG_TRACE, "<= hdb_dn2id: got id=0x%lx\n",
			ei->bei_id, 0, 0 );
	}

	return rc;
}