Exemplo n.º 1
0
int main(int argc,char * argv[])
{
	int i = 0, j = 0, rc;
	MDB_env *env;
	MDB_dbi dbi;
	MDB_val key, data;
	MDB_txn *txn;
	MDB_stat mst;
	MDB_cursor *cursor;
	int count;
	int *values;
	char sval[32] = "";
	int env_oflags;
	struct stat db_stat, exe_stat;

	srand(time(NULL));

	count = (rand()%384) + 64;
	values = (int *)malloc(count*sizeof(int));

	for(i = 0;i<count;i++) {
		values[i] = rand()%1024;
	}

	E(mdb_env_create(&env));
	E(mdb_env_set_maxreaders(env, 1));
	E(mdb_env_set_mapsize(env, 10485760));
	E(mdb_env_set_maxdbs(env, 4));

	E(stat("/proc/self/exe", &exe_stat)?errno:0);
	E(stat(DBPATH "/.", &db_stat)?errno:0);
	env_oflags = MDB_FIXEDMAP | MDB_NOSYNC;
	if (major(db_stat.st_dev) != major(exe_stat.st_dev)) {
		/* LY: Assume running inside a CI-environment:
		 *  1) don't use FIXEDMAP to avoid EBUSY in case collision,
		 *     which could be inspired by address space randomisation feature.
		 *  2) drop MDB_NOSYNC expecting that DBPATH is at a tmpfs or some dedicated storage.
		 */
		env_oflags = 0;
	}
	/* LY: especially here we always needs MDB_NOSYNC
	 * for testing mdb_env_close_ex() and "redo-to-steady" on open. */
	env_oflags |= MDB_NOSYNC;
	E(mdb_env_open(env, DBPATH, env_oflags, 0664));

	E(mdb_txn_begin(env, NULL, 0, &txn));
	if (mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi) == MDB_SUCCESS)
		E(mdb_drop(txn, dbi, 1));
	E(mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi));

	key.mv_size = sizeof(int);
	key.mv_data = sval;
	data.mv_size = sizeof(sval);
	data.mv_data = sval;

	printf("Adding %d values\n", count);
	for (i=0;i<count;i++) {
		sprintf(sval, "%03x %d foo bar", values[i], values[i]);
		if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE)))
			j++;
	}
	if (j) printf("%d duplicates skipped\n", j);
	E(mdb_txn_commit(txn));
	E(mdb_env_stat(env, &mst));

	printf("check-preset-a\n");
	E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
	E(mdb_cursor_open(txn, dbi, &cursor));
	int present_a = 0;
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
		printf("key: %p %.*s, data: %p %.*s\n",
			key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
			data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		++present_a;
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	CHECK(present_a == count - j, "mismatch");
	mdb_cursor_close(cursor);
	mdb_txn_abort(txn);
	mdb_env_sync(env, 1);

	j=0;
	key.mv_data = sval;
	for (i= count - 1; i > -1; i-= (rand()%5)) {
		j++;
		txn=NULL;
		E(mdb_txn_begin(env, NULL, 0, &txn));
		sprintf(sval, "%03x ", values[i]);
		if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) {
			j--;
			mdb_txn_abort(txn);
		} else {
			E(mdb_txn_commit(txn));
		}
	}
	free(values);
	printf("Deleted %d values\n", j);

	printf("check-preset-b.cursor-next\n");
	E(mdb_env_stat(env, &mst));
	E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
	E(mdb_cursor_open(txn, dbi, &cursor));
	int present_b = 0;
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
		++present_b;
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	CHECK(present_b == present_a - j, "mismatch");

	printf("check-preset-b.cursor-prev\n");
	j = 1;
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
		++j;
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	CHECK(present_b == j, "mismatch");
	mdb_cursor_close(cursor);
	mdb_txn_abort(txn);

	mdb_dbi_close(env, dbi);
	/********************* LY: kept DB dirty ****************/
	mdb_env_close_ex(env, 1);
	E(mdb_env_create(&env));
	E(mdb_env_set_maxdbs(env, 4));
	E(mdb_env_open(env, DBPATH, env_oflags, 0664));

	printf("check-preset-c.cursor-next\n");
	E(mdb_env_stat(env, &mst));
	E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn));
	E(mdb_dbi_open(txn, "id1", 0, &dbi));
	E(mdb_cursor_open(txn, dbi, &cursor));
	int present_c = 0;
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
		++present_c;
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	CHECK(present_c == present_a, "mismatch");

	printf("check-preset-d.cursor-prev\n");
	j = 1;
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
		++j;
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	CHECK(present_c == j, "mismatch");
	mdb_cursor_close(cursor);
	mdb_txn_abort(txn);

	mdb_dbi_close(env, dbi);
	mdb_env_close_ex(env, 0);

	return 0;
}
Exemplo n.º 2
0
void LMDBFileIndex::del_internal(const SIndexKey& key, bool log, bool handle_enosp)
{		
	MDB_val mdb_tkey;
	mdb_tkey.mv_data=const_cast<void*>(static_cast<const void*>(&key));
	mdb_tkey.mv_size=sizeof(SIndexKey);

	int rc = mdb_del(txn, dbi, &mdb_tkey, NULL);

	if(rc==MDB_MAP_FULL && handle_enosp)
	{
		mdb_txn_abort(txn);

		if(_has_error)
		{
			Server->Log("LMDB had error during increase (on del). Aborting...", LL_ERROR);
			start_transaction();
			return;
		}

		{
			read_transaction_lock.reset();

			IScopedWriteLock lock(mutex);

			destroy_env();

			map_size*=2;

			Server->Log("Increased LMDB database size to "+PrettyPrintBytes(map_size)+" (on delete)", LL_DEBUG);

			if(!create_env())
			{
				Server->Log("Error creating env after database file size increase", LL_ERROR);
				_has_error=true;
				start_transaction();
				return;
			}
			
		}

		start_transaction();

		replay_transaction_log();

		del(key);
	}
	else if(rc==MDB_BAD_TXN && handle_enosp)
	{
		mdb_txn_abort(txn);
		
		if(_has_error)
		{
			Server->Log("LMDB had error on BAD_TXN (on del). Aborting...", LL_ERROR);
			start_transaction();
			return;
		}
		
		start_transaction();
		
		replay_transaction_log();
		
		del_internal(key, true, false);
	}
	else if (rc == MDB_NOTFOUND)
	{
		FILEENTRY_DEBUG(Server->Log("LMDB: Failed to delete data (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR));
	}
	else if(rc)
	{
		Server->Log("LMDB: Failed to delete data ("+(std::string)mdb_strerror(rc)+")", LL_ERROR);
		_has_error=true;
	}

	if(log)
	{
		STransactionLogItem item = { key, 0, 0 };
		transaction_log.push_back(item);
	}	
}
Exemplo n.º 3
0
ID mdb_tool_entry_modify(
	BackendDB *be,
	Entry *e,
	struct berval *text )
{
	int rc;
	struct mdb_info *mdb;
	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(mdb_tool_entry_modify) "( %ld, \"%s\" )\n",
		(long) e->e_id, e->e_dn, 0 );

	mdb = (struct mdb_info *) be->be_private;

	if( cursor ) {
		mdb_cursor_close( cursor );
		cursor = NULL;
	}
	if ( !txn ) {
		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"txn_begin failed: %s (%d)",
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
	}

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

	/* id2entry index */
	rc = mdb_id2entry_update( &op, txn, NULL, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"id2entry_update failed: err=%d", rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}

done:
	if( rc == 0 ) {
		rc = mdb_txn_commit( txn );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
					"txn_commit failed: %s (%d)",
					mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_modify) ": "
				"%s\n", text->bv_val, 0, 0 );
			e->e_id = NOID;
		}

	} else {
		mdb_txn_abort( txn );
		snprintf( text->bv_val, text->bv_len,
			"txn_aborted! %s (%d)",
			mdb_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n",
			text->bv_val, 0, 0 );
		e->e_id = NOID;
	}
	txn = NULL;
	idcursor = NULL;

	return e->e_id;
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
	int n, c, rc, ec = EXIT_FAILURE, fd_in = -1, fd_out = -1, verbosity = 0;
	uint32_t ts_start = 0, ts_end = 0, count = 0, nmsg_cnt = 0;
	MDB_env *env = NULL;
	MDB_txn *txn = NULL;
	MDB_dbi dbi;
	MDB_val key, data;
	MDB_cursor *cursor = NULL;
	struct timespec ts, msg_ts;
	off_t *offset;
	nmsg_input_t nmsg_in = NULL;
	nmsg_output_t nmsg_out = NULL;
	nmsg_res res;
	nmsg_message_t msg;
	char *json;
	bool input_json = false, input_nmsg = false, is_counting = false, need_exact = false;
	const char *lmdb_filename = NULL, *nmsg_filename_in = NULL;
	char nmsg_filename_out[BUFSIZ] = {0};

	while ((c = getopt(argc, argv, "c:e:f:j:r:s:hvx")) != EOF) {
		switch (c) {
			case 'c':
				count = atoi(optarg);
				is_counting = true;
				break;
			case 'e':
				ts_end = atoi(optarg);
				break;
			case 'f':
				lmdb_filename = optarg;
				break;
			case 'j':
				nmsg_filename_in = optarg;
				input_json = true;
				break;
			case 'r':
				nmsg_filename_in = optarg;
				input_nmsg = true;
				break;
			case 's':
				ts_start = atoi(optarg);
				break;
			case 'v':
				verbosity++;
				break;
			case 'x':
				need_exact = true;
				break;
			case 'h':
			default:
				usage(argv[0], NULL);
				goto done;
		}
	}

	if (ts_start == 0) {
		usage(argv[0], "Need a starting timestamp (-s).");
		goto done;
	}
	if (lmdb_filename == NULL) {
		usage(argv[0], "Need a tsindex file (-f).");
		goto done;
		return (EXIT_FAILURE);
	}
	if ((input_json == false && input_nmsg == false) ||
			(input_json && input_nmsg)) {
		usage(argv[0], "Need either an nmsg json file (-j) or binary nmsg file (-r).");
		goto done;
		return (EXIT_FAILURE);
	}
	if ((ts_end == 0 && count == 0) ||
			(ts_end != 0 && count != 0)) {
		usage(argv[0], "Need either an ending timestamp (-e) or a count (-c).");
		goto done;
		return (EXIT_FAILURE);
	}

	res = nmsg_init();
	if (res != nmsg_res_success) {
		fprintf(stderr, "Error initializing NMSG library: %s\n",
				nmsg_res_lookup(res));
		goto done;
		return (EXIT_FAILURE);
	}

	fd_in = open(nmsg_filename_in, O_RDONLY);
	if (fd_in < 0) {
		fprintf(stderr, "Can't open nmsg input file \"%s\": %s\n",
				nmsg_filename_in, strerror(errno));
		goto done;
		return (EXIT_FAILURE);
	}
	n = strlcpy(nmsg_filename_out, nmsg_filename_in,
			sizeof (nmsg_filename_out));
	snprintf(nmsg_filename_out + n, sizeof (nmsg_filename_out) - n,
			"-tsindex.%u.%s", getpid(),
			input_json ? "json" : "nmsg");

	fd_out = open(nmsg_filename_out, O_CREAT | O_WRONLY, 0644);
	if (fd_out < 0) {
		fprintf(stderr, "Can't open nmsg output file \"%s\": %s\n",
				nmsg_filename_out, strerror(errno));
		goto done;
		return (EXIT_FAILURE);
	}

	if (input_json) {
		nmsg_in = nmsg_input_open_json(fd_in);
		if (nmsg_in == NULL) {
			fprintf(stderr, "nmsg_input_open_json() failed\n");
			goto done;
		}
		nmsg_out = nmsg_output_open_json(fd_out);
		if (nmsg_out == NULL) {
			fprintf(stderr, "nmsg_ouput_open_json() failed\n");
			goto done;
		}
	}
	else if (input_nmsg) {
		nmsg_in = nmsg_input_open_file(fd_in);
		if (nmsg_in == NULL) {
			fprintf(stderr, "nmsg_input_open_file() failed\n");
			goto done;
		}
		nmsg_out = nmsg_output_open_file(fd_out, NMSG_WBUFSZ_MAX);
		if (nmsg_out == NULL) {
			fprintf(stderr, "nmsg_ouput_open_file() failed\n");
			goto done;
		}
	}

	rc = mdb_env_create(&env);
	if (rc != 0) {
		fprintf(stderr, "mdb_create() failed: %s\n", mdb_strerror(rc));
		goto done;
	}

	rc = mdb_env_open(env, lmdb_filename, MDB_NOSUBDIR | MDB_RDONLY, 0664);
	if (rc != 0) {
		fprintf(stderr, "mdb_env_open failed(): %s\n",
				mdb_strerror(rc));
		goto done;
	}

	rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
	if (rc != 0) {
		fprintf(stderr, "mdb_txn_begin failed(): %s\n",
				mdb_strerror(rc));
		goto done;
	}

	rc = mdb_open(txn, NULL, MDB_INTEGERKEY, &dbi);
	if (rc) {
		fprintf(stderr, "mdb_open(): %s\n", mdb_strerror(rc));
		goto done;
	}

	rc = mdb_set_compare(txn, dbi, axa_tsi_mdb_cmp);
	if (rc) {
		fprintf(stderr, "mdb_set_compare(): %s\n", mdb_strerror(rc));
		goto done;
	}

	ts.tv_sec = ts_start;
	ts.tv_nsec = 0;

	key.mv_size = sizeof (ts);
	key.mv_data = &ts;

	rc = mdb_cursor_open(txn, dbi, &cursor);
	if (rc) {
		fprintf(stderr, "mdb_cursor_open(): %s\n", mdb_strerror(rc));
		goto done;
	}

	rc = mdb_cursor_get(cursor, &key, &data,
			need_exact ? MDB_SET : MDB_SET_RANGE);
	if (rc == MDB_NOTFOUND) {
		printf("Did not find starting timestamp %u in %s.\n",
				ts_start, lmdb_filename);
		goto done;
	}
	if (rc) {
		fprintf(stderr, "mdb_cursor_get(): %s\n", mdb_strerror(rc));
		goto done;
	}

	(void) mdb_cursor_close(cursor);

	offset = (off_t *)data.mv_data;
	if (verbosity > 0)
		printf("Found %u at offset 0x%"PRIu64".\n", ts_start, *offset);

	if (lseek(fd_in, *offset, SEEK_SET) == sizeof (off_t) - 1) {
		fprintf(stderr, "lseek(): %s\n", strerror(errno));
		goto done;
	}

	while (1) {
		if (is_counting) {
			if (count-- <= 0)
				break;
		}
		res = nmsg_input_read(nmsg_in, &msg);
		if (res == nmsg_res_eof) {
			if (verbosity > 0)
				printf("End of file reached.\n");
			break;
		}
		if (res != nmsg_res_success) {
			fprintf(stderr, "nmsg_input_read(): %s\n", nmsg_res_lookup(res));
			goto done;
		}

		if (is_counting == false) {
			nmsg_message_get_time(msg, &msg_ts);
			if (msg_ts.tv_sec >= ts_end) {
				nmsg_message_destroy(&msg);
				break;
			}
		}

		res = nmsg_output_write(nmsg_out, msg);
		if (res != nmsg_res_success) {
			fprintf(stderr, "nmsg_output_write(): %s\n", nmsg_res_lookup(res));
			nmsg_message_destroy(&msg);
			goto done;
		}

		if (verbosity > 1) {
			res = nmsg_message_to_json(msg, &json);
			if (res != nmsg_res_success) {
				fprintf(stderr, "nmsg_message_to_pres(): %s\n", nmsg_res_lookup(res));
				nmsg_message_destroy(&msg);
				goto done;
			}

			printf("%s\n", json);
			free(json);
		}
		nmsg_cnt++;
		nmsg_message_destroy(&msg);
	}

	ec = EXIT_SUCCESS;
	printf("Wrote %u nmsgs to %s.\n", nmsg_cnt, nmsg_filename_out);
done:
	if (fd_in != -1)
		close(fd_in);
	if (fd_out != -1)
		close(fd_out);
	if (nmsg_in != NULL)
		nmsg_input_close(&nmsg_in);
	if (nmsg_out != NULL)
		nmsg_output_close(&nmsg_out);
	if (txn != NULL)
		mdb_txn_abort(txn);
	if (env != NULL)
		mdb_env_close(env);

	return (ec);
}
Exemplo n.º 5
0
static int
mdb_db_open( BackendDB *be, ConfigReply *cr )
{
	int rc, i;
	struct mdb_info *mdb = (struct mdb_info *) be->be_private;
	struct stat stat1;
	uint32_t flags;
	char *dbhome;
	MDB_txn *txn;

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

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

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

	/* mdb is always clean */
	be->be_flags |= SLAP_DBFLAG_CLEAN;

	rc = mdb_env_create( &mdb->mi_dbenv );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\": "
			"mdb_env_create failed: %s (%d).\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

	if ( mdb->mi_readers ) {
		rc = mdb_env_set_maxreaders( mdb->mi_dbenv, mdb->mi_readers );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_db_open) ": database \"%s\": "
				"mdb_env_set_maxreaders failed: %s (%d).\n",
				be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
			goto fail;
		}
	}

	rc = mdb_env_set_mapsize( mdb->mi_dbenv, mdb->mi_mapsize );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\": "
			"mdb_env_set_mapsize failed: %s (%d).\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

	rc = mdb_env_set_maxdbs( mdb->mi_dbenv, MDB_INDICES );
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\": "
			"mdb_env_set_maxdbs failed: %s (%d).\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

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

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

	flags = mdb->mi_dbenv_flags;

	if ( slapMode & SLAP_TOOL_QUICK )
		flags |= MDB_NOSYNC;

	if ( slapMode & SLAP_TOOL_READONLY)
		flags |= MDB_RDONLY;

	rc = mdb_env_open( mdb->mi_dbenv, dbhome,
			flags, mdb->mi_dbenv_mode );

	if ( rc ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened, err %d. "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, rc, 0 );
		goto fail;
	}

	rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
	if ( rc ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened, err %d. "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, rc, 0 );
		goto fail;
	}

	/* open (and create) main databases */
	for( i = 0; mdmi_databases[i].bv_val; i++ ) {
		flags = MDB_INTEGERKEY;
		if( i == MDB_ID2ENTRY ) {
			if ( !(slapMode & (SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY) ))
				flags |= MDB_CREATE;
		} else {
			if ( i == MDB_DN2ID )
				flags |= MDB_DUPSORT;
			if ( !(slapMode & SLAP_TOOL_READONLY) )
				flags |= MDB_CREATE;
		}

		rc = mdb_open( txn,
			mdmi_databases[i].bv_val,
			flags,
			&mdb->mi_dbis[i] );

		if ( rc != 0 ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"mdb_open(%s/%s) failed: %s (%d).", 
				be->be_suffix[0].bv_val, 
				mdb->mi_dbenv_home, mdmi_databases[i].bv_val,
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_db_open) ": %s\n",
				cr->msg, 0, 0 );
			goto fail;
		}

		if ( i == MDB_ID2ENTRY )
			mdb_set_compare( txn, mdb->mi_dbis[i], mdb_id_compare );
		else if ( i == MDB_DN2ID )
			mdb_set_dupsort( txn, mdb->mi_dbis[i], mdb_dup_compare );

	}

	rc = mdb_ad_read( mdb, txn );
	if ( rc ) {
		mdb_txn_abort( txn );
		goto fail;
	}

	rc = mdb_attr_dbs_open( be, txn, cr );
	if ( rc ) {
		mdb_txn_abort( txn );
		goto fail;
	}

	rc = mdb_txn_commit(txn);
	if ( rc != 0 ) {
		goto fail;
	}

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

	mdb->mi_flags |= MDB_IS_OPEN;

	return 0;

fail:
	mdb_db_close( be, NULL );
	return rc;
}
Exemplo n.º 6
0
ID mdb_tool_entry_put(
	BackendDB *be,
	Entry *e,
	struct berval *text )
{
	int rc;
	struct mdb_info *mdb;
	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(mdb_tool_entry_put)
		"( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 );

	mdb = (struct mdb_info *) be->be_private;

	if ( !txn ) {
		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"txn_begin failed: %s (%d)",
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
		rc = mdb_cursor_open( txn, mdb->mi_id2entry, &idcursor );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"cursor_open failed: %s (%d)",
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
		if ( !mdb->mi_nextid ) {
			ID dummy;
			mdb_next_id( be, idcursor, &dummy );
		}
		rc = mdb_cursor_open( txn, mdb->mi_dn2id, &mcp );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"cursor_open failed: %s (%d)",
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
		rc = mdb_cursor_open( txn, mdb->mi_dn2id, &mcd );
		if( rc != 0 ) {
			snprintf( text->bv_val, text->bv_len,
				"cursor_open failed: %s (%d)",
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
				 text->bv_val, 0, 0 );
			return NOID;
		}
	}

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

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

	rc = mdb_tool_index_add( &op, txn, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"index_entry_add failed: err=%d", rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}


	/* id2entry index */
	rc = mdb_id2entry_add( &op, txn, idcursor, e );
	if( rc != 0 ) {
		snprintf( text->bv_val, text->bv_len,
				"id2entry_add failed: err=%d", rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		goto done;
	}

done:
	if( rc == 0 ) {
		mdb_writes++;
		if ( mdb_writes >= mdb_writes_per_commit ) {
			unsigned i;
			MDB_TOOL_IDL_FLUSH( be, txn );
			rc = mdb_txn_commit( txn );
			for ( i=0; i<mdb->mi_nattrs; i++ )
				mdb->mi_attrs[i]->ai_cursor = NULL;
			mdb_writes = 0;
			txn = NULL;
			idcursor = NULL;
			if( rc != 0 ) {
				snprintf( text->bv_val, text->bv_len,
						"txn_commit failed: %s (%d)",
						mdb_strerror(rc), rc );
				Debug( LDAP_DEBUG_ANY,
					"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
					text->bv_val, 0, 0 );
				e->e_id = NOID;
			}
		}

	} else {
		unsigned i;
		mdb_txn_abort( txn );
		txn = NULL;
		idcursor = NULL;
		for ( i=0; i<mdb->mi_nattrs; i++ )
			mdb->mi_attrs[i]->ai_cursor = NULL;
		mdb_writes = 0;
		snprintf( text->bv_val, text->bv_len,
			"txn_aborted! %s (%d)",
			rc == LDAP_OTHER ? "Internal error" :
			mdb_strerror(rc), rc );
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n",
			text->bv_val, 0, 0 );
		e->e_id = NOID;
	}

	return e->e_id;
}
Exemplo n.º 7
0
 virtual ~LMDBCursor() {
   mdb_cursor_close(mdb_cursor_);
   mdb_txn_abort(mdb_txn_);
 }
Exemplo n.º 8
0
static int
lmdb_storage_init(struct lmdb_storage* s, char* db_env_path)
{
	int result;
	MDB_env* env = NULL;
	MDB_txn* txn = NULL;
	MDB_dbi dbi = 0;

	if ((result = mdb_env_create(&env)) != 0) {
		paxos_log_error("Could not create lmdb environment. %s",
		mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_env_set_mapsize(env, paxos_config.lmdb_mapsize)) != 0) {
		paxos_log_error("Could not set lmdb map size. %s", mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_env_open(env, db_env_path,
		!paxos_config.lmdb_sync ? MDB_NOSYNC : 0 | MDB_INTEGERKEY,
		S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)) != 0) {
		paxos_log_error("Could not open lmdb environment at %s. %s",
		db_env_path, mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_txn_begin(env, NULL, 0, &txn)) != 0) {
		paxos_log_error("Could not start txn on lmdb environment at %s. %s",
		db_env_path, mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_open(txn, NULL, 0, &dbi)) != 0) {
		paxos_log_error("Could not open db on lmdb environment at %s. %s",
		db_env_path, mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_set_compare(txn, dbi, lmdb_compare_iid)) != 0) {
		paxos_log_error("Could setup compare function on lmdb "
			"environment at %s. %s", db_env_path, mdb_strerror(result));
		goto error;
	}
	if ((result = mdb_txn_commit(txn)) != 0) {
		paxos_log_error("Could commit txn on lmdb environment at %s. %s",
		db_env_path, mdb_strerror(result));
		goto error;
	}

	s->env = env;
	s->dbi = dbi;

	return 0;
	error:
	if (txn) {
		mdb_txn_abort(txn);
	}
	if (dbi) {
		mdb_close(env, dbi);
	}
	if (env) {
		mdb_env_close(env);
	}
	return -1;
}
Exemplo n.º 9
0
int main(int argc, char *argv[])
{
	if (argc < 3) {
		return help();
	}

	/* Get mandatory parameters. */
	int ret = EXIT_SUCCESS;
	char *dbdir  = argv[1];
	char *action = argv[2];
	argv += 3;
	argc -= 3;

	g_scanner = zs_scanner_create(".", KNOT_CLASS_IN, 0, NULL, parse_err, NULL);
	if (g_scanner == NULL) {
		return EXIT_FAILURE;
	}

	/* Open cache for operations. */
	struct cache *cache = cache_open(dbdir, 0, NULL);
	if (cache == NULL) {
		fprintf(stderr, "failed to open db '%s'\n", dbdir);
		zs_scanner_free(g_scanner);
		return EXIT_FAILURE;
	}

	/* Execute action. */
	bool found = false;
	for (unsigned i = 0; i < TOOL_ACTION_COUNT; ++i) {
		struct tool_action *ta = &TOOL_ACTION[i];
		if (strcmp(ta->name, action) == 0) {

			/* Check param count. */
			if (argc < ta->min_args) {
				break;
			}

			/* Now set as found. */
			found = true;

			MDB_txn *txn = NULL;
			int ret = mdb_txn_begin(cache->env, NULL, 0, &txn);
			if (ret != MDB_SUCCESS) {
				fprintf(stderr, "failed to open transaction, aborting\n");
				break;
			}

			/* Execute operation handler. */
			ret = ta->func(cache, txn, argc, argv);
			if (ret != 0) {
				fprintf(stderr, "'%s' failed, aborting transaction\n", action);
				mdb_txn_abort(txn);
			} else {
				mdb_txn_commit(txn);
			}

			break;
		}
	}

	cache_close(cache);
	zs_scanner_free(g_scanner);

	if (!found) {
		return help();
	}

	return ret;
}
Exemplo n.º 10
0
struct gcache *gcache_open(char *path, char *dbname, int rdonly)
{
	MDB_txn *txn = NULL;
	int rc;
	unsigned int flags = 0, dbiflags = 0, perms = 0664;
	struct gcache *gc;

	if (!is_directory(path)) {
		olog(LOG_ERR, "gcache_open: %s is not a directory", path);
		return (NULL);
	}

	if ((gc = malloc(sizeof (struct gcache))) == NULL)
		return (NULL);

	memset(gc, 0, sizeof(struct gcache));

	if (rdonly) {
		flags |= MDB_RDONLY;
		perms = 0444;
		perms = 0664;
	} else {
		dbiflags = MDB_CREATE;
	}

	rc = mdb_env_create(&gc->env);
	if (rc != 0) {
		olog(LOG_ERR, "gcache_open: mdb_env_create: %s", mdb_strerror(rc));
		free(gc);
		return (NULL);
	}

	mdb_env_set_mapsize(gc->env, LMDB_DB_SIZE);

	rc = mdb_env_set_maxdbs(gc->env, 10);
	if (rc != 0) {
		olog(LOG_ERR, "gcache_open: mdb_env_set_maxdbs%s", mdb_strerror(rc));
		free(gc);
		return (NULL);
	}

	rc = mdb_env_open(gc->env, path, flags, perms);
	if (rc != 0) {
		olog(LOG_ERR, "gcache_open: mdb_env_open: %s", mdb_strerror(rc));
		free(gc);
		return (NULL);
	}

	/* Open a pseudo TX so that we can open DBI */

	mdb_txn_begin(gc->env, NULL, flags, &txn);
	if (rc != 0) {
		olog(LOG_ERR, "gcache_open: mdb_txn_begin: %s", mdb_strerror(rc));
		mdb_env_close(gc->env);
		free(gc);
		return (NULL);
	}

	rc = mdb_dbi_open(txn, dbname, dbiflags, &gc->dbi);
	if (rc != 0) {
		olog(LOG_ERR, "gcache_open: mdb_dbi_open for `%s': %s", dbname, mdb_strerror(rc));
		mdb_txn_abort(txn);
		mdb_env_close(gc->env);
		free(gc);
		return (NULL);
	}

	rc = mdb_txn_commit(txn);
	if (rc != 0) {
		olog(LOG_ERR, "cogcache_open: mmit after open %s", mdb_strerror(rc));
		mdb_env_close(gc->env);
		free(gc);
		return (NULL);
	}

	return (gc);
}
Exemplo n.º 11
0
DBPriv *DBPrivOpenDB(const char *dbpath, dbid id)
{
    DBPriv *db = xcalloc(1, sizeof(DBPriv));
    MDB_txn *txn = NULL;
    int rc;

    rc = pthread_key_create(&db->txn_key, &DestroyTransaction);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not create transaction key. (pthread_key_create: '%s')",
            GetErrorStrFromCode(rc));
        free(db);
        return NULL;
    }

    rc = mdb_env_create(&db->env);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not create handle for database %s: %s",
              dbpath, mdb_strerror(rc));
        goto err;
    }
    rc = mdb_env_set_mapsize(db->env, LMDB_MAXSIZE);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not set mapsize for database %s: %s",
              dbpath, mdb_strerror(rc));
        goto err;
    }
    if (DB_MAX_READERS > 0)
    {
        rc = mdb_env_set_maxreaders(db->env, DB_MAX_READERS);
        if (rc)
        {
            Log(LOG_LEVEL_ERR, "Could not set maxreaders for database %s: %s",
                dbpath, mdb_strerror(rc));
            goto err;
        }
    }

    unsigned int open_flags = MDB_NOSUBDIR;
    if (id == dbid_locks
        || (GetAmPolicyHub() && id == dbid_lastseen))
    {
        open_flags |= MDB_NOSYNC;
    }

#ifdef __hpux
    /*
     * On HP-UX, a unified file cache was not introduced until version 11.31.
     * This means that on 11.23 there are separate file caches for mmap()'ed
     * files and open()'ed files. When these two are mixed, changes made using
     * one mode won't be immediately seen by the other mode, which is an
     * assumption LMDB is relying on. The MDB_WRITEMAP flag causes LMDB to use
     * mmap() only, so that we stay within one file cache.
     */
    open_flags |= MDB_WRITEMAP;
#endif

    rc = mdb_env_open(db->env, dbpath, open_flags, 0644);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not open database %s: %s",
              dbpath, mdb_strerror(rc));
        goto err;
    }
    if (DB_MAX_READERS > 0)
    {
        int max_readers;
        rc = mdb_env_get_maxreaders(db->env, &max_readers);
        if (rc)
        {
            Log(LOG_LEVEL_ERR, "Could not get maxreaders for database %s: %s",
                dbpath, mdb_strerror(rc));
            goto err;
        }
        if (max_readers < DB_MAX_READERS)
        {
            // LMDB will only reinitialize maxreaders if no database handles are
            // open, including in other processes, which is how we might end up
            // here.
            Log(LOG_LEVEL_VERBOSE, "Failed to set LMDB max reader limit on database '%s', "
                "consider restarting CFEngine",
                dbpath);
        }
    }
    rc = mdb_txn_begin(db->env, NULL, MDB_RDONLY, &txn);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not open database txn %s: %s",
              dbpath, mdb_strerror(rc));
        goto err;
    }
    rc = mdb_open(txn, NULL, 0, &db->dbi);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not open database dbi %s: %s",
              dbpath, mdb_strerror(rc));
        mdb_txn_abort(txn);
        goto err;
    }
    rc = mdb_txn_commit(txn);
    if (rc)
    {
        Log(LOG_LEVEL_ERR, "Could not commit database dbi %s: %s",
              dbpath, mdb_strerror(rc));
        goto err;
    }

    return db;

err:
    if (db->env)
    {
        mdb_env_close(db->env);
    }
    pthread_key_delete(db->txn_key);
    free(db);
    if (rc == MDB_INVALID)
    {
        return DB_PRIV_DATABASE_BROKEN;
    }
    return NULL;
}
Exemplo n.º 12
0
int main(int argc,char * argv[])
{
	int i = 0, j = 0, rc;
	MDB_env *env;
	MDB_dbi dbi;
	MDB_val key, data;
	MDB_txn *txn;
	MDB_stat mst;
	MDB_cursor *cursor, *cur2;
	int count;
	int *values;
	char sval[32];

	srandom(time(NULL));

	    count = (random()%384) + 64;
	    values = (int *)malloc(count*sizeof(int));

	    for(i = 0;i<count;i++) {
			values[i] = random()%1024;
	    }
    
		rc = mdb_env_create(&env);
		rc = mdb_env_set_mapsize(env, 10485760);
		rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664);
		rc = mdb_txn_begin(env, NULL, 0, &txn);
		rc = mdb_open(txn, NULL, 0, &dbi);
   
		key.mv_size = sizeof(int);
		key.mv_data = sval;
		data.mv_size = sizeof(sval);
		data.mv_data = sval;

		printf("Adding %d values\n", count);
	    for (i=0;i<count;i++) {	
			sprintf(sval, "%03x %d foo bar", values[i], values[i]);
			rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
			if (rc) {
				j++;
				data.mv_size = sizeof(sval);
				data.mv_data = sval;
			}
	    }
		if (j) printf("%d duplicates skipped\n", j);
		rc = mdb_txn_commit(txn);
		rc = mdb_env_stat(env, &mst);

		rc = mdb_txn_begin(env, NULL, 1, &txn);
		rc = mdb_cursor_open(txn, dbi, &cursor);
		while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
			printf("key: %p %.*s, data: %p %.*s\n",
				key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
				data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		}
		mdb_cursor_close(cursor);
		mdb_txn_abort(txn);

		j=0;
		key.mv_data = sval;
	    for (i= count - 1; i > -1; i-= (random()%5)) {	
			j++;
			txn=NULL;
			rc = mdb_txn_begin(env, NULL, 0, &txn);
			sprintf(sval, "%03x ", values[i]);
			rc = mdb_del(txn, dbi, &key, NULL);
			if (rc) {
				j--;
				mdb_txn_abort(txn);
			} else {
				rc = mdb_txn_commit(txn);
			}
	    }
	    free(values);
		printf("Deleted %d values\n", j);

		rc = mdb_env_stat(env, &mst);
		rc = mdb_txn_begin(env, NULL, 1, &txn);
		rc = mdb_cursor_open(txn, dbi, &cursor);
		printf("Cursor next\n");
		while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
			printf("key: %.*s, data: %.*s\n",
				(int) key.mv_size,  (char *) key.mv_data,
				(int) data.mv_size, (char *) data.mv_data);
		}
		printf("Cursor last\n");
		rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
		printf("Cursor prev\n");
		while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
			printf("key: %.*s, data: %.*s\n",
				(int) key.mv_size,  (char *) key.mv_data,
				(int) data.mv_size, (char *) data.mv_data);
		}
		printf("Cursor last/prev\n");
		rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
			printf("key: %.*s, data: %.*s\n",
				(int) key.mv_size,  (char *) key.mv_data,
				(int) data.mv_size, (char *) data.mv_data);
		rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV);
			printf("key: %.*s, data: %.*s\n",
				(int) key.mv_size,  (char *) key.mv_data,
				(int) data.mv_size, (char *) data.mv_data);

		mdb_txn_abort(txn);

		printf("Deleting with cursor\n");
		rc = mdb_txn_begin(env, NULL, 0, &txn);
		rc = mdb_cursor_open(txn, dbi, &cur2);
		for (i=0; i<50; i++) {
			rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT);
			if (rc)
				break;
			printf("key: %p %.*s, data: %p %.*s\n",
				key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
				data.mv_data, (int) data.mv_size, (char *) data.mv_data);
			rc = mdb_del(txn, dbi, &key, NULL);
		}

		printf("Restarting cursor in txn\n");
		rc = mdb_cursor_get(cur2, &key, &data, MDB_FIRST);
		printf("key: %p %.*s, data: %p %.*s\n",
			key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
			data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		for (i=0; i<32; i++) {
			rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT);
			if (rc) break;
			printf("key: %p %.*s, data: %p %.*s\n",
				key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
				data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		}
		mdb_cursor_close(cur2);
		rc = mdb_txn_commit(txn);

		printf("Restarting cursor outside txn\n");
		rc = mdb_txn_begin(env, NULL, 0, &txn);
		rc = mdb_cursor_open(txn, dbi, &cursor);
		rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
		printf("key: %p %.*s, data: %p %.*s\n",
			key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
			data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		for (i=0; i<32; i++) {
			rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT);
			if (rc) break;
			printf("key: %p %.*s, data: %p %.*s\n",
				key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
				data.mv_data, (int) data.mv_size, (char *) data.mv_data);
		}
		mdb_cursor_close(cursor);
		mdb_close(env, dbi);

		mdb_txn_abort(txn);
		mdb_env_close(env);

	return 0;
}
Exemplo n.º 13
0
int     slmdb_cursor_get(SLMDB *slmdb, MDB_val *mdb_key,
			         MDB_val *mdb_value, MDB_cursor_op op)
{
    MDB_txn *txn;
    int     status = 0;

    /*
     * Open a read transaction and cursor if needed.
     */
    if (slmdb->cursor == 0) {
	if ((status = slmdb_txn_begin(slmdb, MDB_RDONLY, &txn)) != 0)
	    SLMDB_API_RETURN(slmdb, status);
	if ((status = mdb_cursor_open(txn, slmdb->dbi, &slmdb->cursor)) != 0) {
	    mdb_txn_abort(txn);
	    if ((status = slmdb_recover(slmdb, status)) == 0)
		status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op);
	    SLMDB_API_RETURN(slmdb, status);
	}

	/*
	 * Restore the cursor position from the saved key information.
	 */
	if (HAVE_SLMDB_SAVED_KEY(slmdb) && op != MDB_FIRST)
	    status = mdb_cursor_get(slmdb->cursor, &slmdb->saved_key,
				    (MDB_val *) 0, MDB_SET);
    }

    /*
     * Database lookup.
     */
    if (status == 0)
	status = mdb_cursor_get(slmdb->cursor, mdb_key, mdb_value, op);

    /*
     * Save the cursor position if successful. This can fail only with
     * ENOMEM.
     * 
     * Close the cursor read transaction if in MDB_NOLOCK mode, because the
     * caller may release the external lock after we return.
     */
    if (status == 0) {
	status = slmdb_saved_key_assign(slmdb, mdb_key);
	if (slmdb->lmdb_flags & MDB_NOLOCK)
	    slmdb_cursor_close(slmdb);
    }

    /*
     * Handle end-of-database or other error.
     */
    else {
	/* Do not hand-optimize out the slmdb_cursor_close() calls below. */
	if (status == MDB_NOTFOUND) {
	    slmdb_cursor_close(slmdb);
	    if (HAVE_SLMDB_SAVED_KEY(slmdb))
		slmdb_saved_key_free(slmdb);
	} else {
	    slmdb_cursor_close(slmdb);
	    if ((status = slmdb_recover(slmdb, status)) == 0)
		status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op);
	    SLMDB_API_RETURN(slmdb, status);
	    /* Do not hand-optimize out the above return statement. */
	}
    }
    SLMDB_API_RETURN(slmdb, status);
}
Exemplo n.º 14
0
int
mdb_add(Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	struct berval	pdn;
	Entry		*p = NULL, *oe = op->ora_e;
	char textbuf[SLAP_TEXT_BUFLEN];
	size_t textlen = sizeof textbuf;
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	MDB_txn		*txn = NULL;
	MDB_cursor	*mc = NULL;
	MDB_cursor	*mcd;
	ID eid, pid = 0;
	mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo;
	int subentry;
	int numads = mdb->mi_numads;

	int		success;

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

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

#ifdef LDAP_X_TXN
	if( op->o_txnSpec && txn_preop( 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(mdb_add) ": entry failed schema check: "
			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
		goto return_results;
	}

	/* begin transaction */
	rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": txn_begin failed: %s (%d)\n",
			mdb_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	txn = moi->moi_txn;

	/* 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(mdb_add) ": entry failed op attrs add: "
			"%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
		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 );

	/*
	 * 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 );
	}

	rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mcd );
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n",
			rs->sr_err, 0, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	/* get entry or parent */
	rs->sr_err = mdb_dn2entry( op, txn, mcd, &op->ora_e->e_nname, &p, NULL, 1 );
	switch( rs->sr_err ) {
	case 0:
		rs->sr_err = LDAP_ALREADY_EXISTS;
		mdb_entry_return( op, p );
		p = NULL;
		goto return_results;
	case MDB_NOTFOUND:
		break;
	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 ( !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 );
		if ( p != (Entry *)&slap_entry_root && is_entry_referral( p )) {
			BerVarray ref = get_entry_referrals( op, p );
			rs->sr_ref = referral_rewrite( ref, &p->e_name,
				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
			ber_bvarray_free( ref );
		} else {
			rs->sr_ref = NULL;
		}
		if ( p != (Entry *)&slap_entry_root )
			mdb_entry_return( op, p );
		p = NULL;
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": parent "
			"does not exist\n", 0, 0, 0 );

		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 ) {
		if ( p != (Entry *)&slap_entry_root )
			mdb_entry_return( op, p );
		p = NULL;

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": no write access to parent\n",
			0, 0, 0 );
		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 ) ) {
			mdb_entry_return( op, p );
			p = NULL;
			/* parent is a subentry, don't allow add */
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(mdb_add) ": parent is subentry\n",
				0, 0, 0 );
			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			rs->sr_text = "parent is a subentry";
			goto return_results;;
		}

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

		if ( is_entry_referral( p ) ) {
			BerVarray ref = get_entry_referrals( op, 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 = referral_rewrite( ref, &p->e_name,
				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
			ber_bvarray_free( ref );
			mdb_entry_return( op, p );
			p = NULL;
			Debug( LDAP_DEBUG_TRACE,
				LDAP_XSTRING(mdb_add) ": parent is referral\n",
				0, 0, 0 );

			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 */
	if ( p != (Entry *)&slap_entry_root ) {
		pid = p->e_id;
		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 ... */
			}
		}

		mdb_entry_return( op, p );
	}
	p = NULL;

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

	if ( ! rs->sr_err ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": no write access to entry\n",
			0, 0, 0 );
		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)) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": no write access to attribute\n",
			0, 0, 0 );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		rs->sr_text = "no write access to attribute";
		goto return_results;;
	}

	rs->sr_err = mdb_cursor_open( txn, mdb->mi_id2entry, &mc );
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n",
			rs->sr_err, 0, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

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

	/* dn2id index */
	rs->sr_err = mdb_dn2id_add( op, mcd, mcd, pid, 1, 1, op->ora_e );
	mdb_cursor_close( mcd );
	if ( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": dn2id_add failed: %s (%d)\n",
			mdb_strerror(rs->sr_err), rs->sr_err, 0 );

		switch( rs->sr_err ) {
		case MDB_KEYEXIST:
			rs->sr_err = LDAP_ALREADY_EXISTS;
			break;
		default:
			rs->sr_err = LDAP_OTHER;
		}
		goto return_results;
	}

	/* attribute indexes */
	rs->sr_err = mdb_index_entry_add( op, txn, op->ora_e );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": index_entry_add failed\n",
			0, 0, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "index generation failed";
		goto return_results;
	}

	/* id2entry index */
	rs->sr_err = mdb_id2entry_add( op, txn, mc, op->ora_e );
	if ( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_add) ": id2entry_add failed\n",
			0, 0, 0 );
		if ( rs->sr_err == LDAP_ADMINLIMIT_EXCEEDED ) {
			rs->sr_text = "entry is too big";
		} else {
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "entry store 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(mdb_add) ": 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 ( moi == &opinfo ) {
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
		opinfo.moi_oe.oe_key = NULL;
		if ( op->o_noop ) {
			mdb->mi_numads = numads;
			mdb_txn_abort( txn );
			rs->sr_err = LDAP_X_NO_OPERATION;
			txn = NULL;
			goto return_results;
		}

		rs->sr_err = mdb_txn_commit( txn );
		txn = NULL;
		if ( rs->sr_err != 0 ) {
			mdb->mi_numads = numads;
			rs->sr_text = "txn_commit failed";
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_add) ": %s : %s (%d)\n",
				rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err );
			rs->sr_err = LDAP_OTHER;
			goto return_results;
		}
	}

	Debug(LDAP_DEBUG_TRACE,
		LDAP_XSTRING(mdb_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 );

	if( moi == &opinfo ) {
		if( txn != NULL ) {
			mdb->mi_numads = numads;
			mdb_txn_abort( txn );
		}
		if ( opinfo.moi_oe.oe_key ) {
			LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
		}
	} else {
		moi->moi_ref--;
	}

	if( success == LDAP_SUCCESS ) {
#if 0
		if ( mdb->bi_txn_cp_kbyte ) {
			TXN_CHECKPOINT( mdb->bi_dbenv,
				mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 );
		}
#endif
	}

	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;
}
Exemplo n.º 15
0
int main(int argc, char *argv[])
{
	int i, rc;
	MDB_env *env;
	MDB_txn *txn;
	MDB_cursor *mc;
	MDB_dbi dbi;
	char *envname;
	int envflags = MDB_NOSYNC, putflags = 0;
	int dohdr = 0, append = 0;
	MDB_val prevk;

	prog = argv[0];

	if (argc < 2) {
		usage();
	}

	/* -a: append records in input order
	 * -f: load file instead of stdin
	 * -n: use NOSUBDIR flag on env_open
	 * -s: load into named subDB
	 * -N: use NOOVERWRITE on puts
	 * -T: read plaintext
	 * -V: print version and exit
	 */
	while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) {
		switch(i) {
		case 'V':
			printf("%s\n", MDB_VERSION_STRING);
			exit(0);
			break;
		case 'a':
			append = 1;
			break;
		case 'f':
			if (freopen(optarg, "r", stdin) == NULL) {
				fprintf(stderr, "%s: %s: reopen: %s\n",
					prog, optarg, strerror(errno));
				exit(EXIT_FAILURE);
			}
			break;
		case 'n':
			envflags |= MDB_NOSUBDIR;
			break;
		case 's':
			subname = strdup(optarg);
			break;
		case 'N':
			putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
			break;
		case 'T':
			mode |= NOHDR | PRINT;
			break;
		default:
			usage();
		}
	}

	if (optind != argc - 1)
		usage();

	dbuf.mv_size = 4096;
	dbuf.mv_data = malloc(dbuf.mv_size);

	if (!(mode & NOHDR))
		readhdr();

	envname = argv[optind];
	rc = mdb_env_create(&env);
	if (rc) {
		fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
		return EXIT_FAILURE;
	}

	mdb_env_set_maxdbs(env, 2);

	if (info.me_maxreaders)
		mdb_env_set_maxreaders(env, info.me_maxreaders);

	if (info.me_mapsize)
		mdb_env_set_mapsize(env, info.me_mapsize);

	if (info.me_mapaddr)
		envflags |= MDB_FIXEDMAP;

	rc = mdb_env_open(env, envname, envflags, 0664);
	if (rc) {
		fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
		goto env_close;
	}

	kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
	kbuf.mv_data = malloc(kbuf.mv_size * 2);
	k0buf.mv_size = kbuf.mv_size;
	k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size;
	prevk.mv_data = k0buf.mv_data;

	while(!Eof) {
		MDB_val key, data;
		int batch = 0;
		int appflag;

		if (!dohdr) {
			dohdr = 1;
		} else if (!(mode & NOHDR))
			readhdr();
		
		rc = mdb_txn_begin(env, NULL, 0, &txn);
		if (rc) {
			fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
			goto env_close;
		}

		rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi);
		if (rc) {
			fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}
		prevk.mv_size = 0;
		if (append) {
			mdb_set_compare(txn, dbi, greater);
			if (flags & MDB_DUPSORT)
				mdb_set_dupsort(txn, dbi, greater);
		}

		rc = mdb_cursor_open(txn, dbi, &mc);
		if (rc) {
			fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}

		while(1) {
			rc = readline(&key, &kbuf);
			if (rc)  /* rc == EOF */
				break;

			rc = readline(&data, &dbuf);
			if (rc) {
				fprintf(stderr, "%s: line %"Yu": failed to read key value\n", prog, lineno);
				goto txn_abort;
			}

			if (append) {
				appflag = MDB_APPEND;
				if (flags & MDB_DUPSORT) {
					if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size))
						appflag = MDB_CURRENT|MDB_APPENDDUP;
					else {
						memcpy(prevk.mv_data, key.mv_data, key.mv_size);
						prevk.mv_size = key.mv_size;
					}
				}
			} else {
				appflag = 0;
			}
			rc = mdb_cursor_put(mc, &key, &data, putflags|appflag);
			if (rc == MDB_KEYEXIST && putflags)
				continue;
			if (rc) {
				fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc));
				goto txn_abort;
			}
			batch++;
			if (batch == 100) {
				rc = mdb_txn_commit(txn);
				if (rc) {
					fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
						prog, lineno, mdb_strerror(rc));
					goto env_close;
				}
				rc = mdb_txn_begin(env, NULL, 0, &txn);
				if (rc) {
					fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
					goto env_close;
				}
				rc = mdb_cursor_open(txn, dbi, &mc);
				if (rc) {
					fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
					goto txn_abort;
				}
				if (appflag & MDB_APPENDDUP) {
					MDB_val k, d;
					mdb_cursor_get(mc, &k, &d, MDB_LAST);
				}
				batch = 0;
			}
		}
		rc = mdb_txn_commit(txn);
		txn = NULL;
		if (rc) {
			fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n",
				prog, lineno, mdb_strerror(rc));
			goto env_close;
		}
		mdb_dbi_close(env, dbi);
	}

txn_abort:
	mdb_txn_abort(txn);
env_close:
	mdb_env_close(env);

	return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemplo n.º 16
0
int main(int argc, char *argv[])
{
	int i, rc;
	MDB_env *env;
	MDB_txn *txn;
	MDB_cursor *mc;
	MDB_dbi dbi;
	char *envname;
	int envflags = 0, putflags = 0;
	int dohdr = 0;

	prog = argv[0];

	if (argc < 2) {
		usage();
	}

	/* -f: load file instead of stdin
	 * -n: use NOSUBDIR flag on env_open
	 * -s: load into named subDB
	 * -N: use NOOVERWRITE on puts
	 * -T: read plaintext
	 * -V: print version and exit
	 */
	while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) {
		switch(i) {
		case 'V':
			printf("%s\n", MDB_VERSION_STRING);
			exit(0);
			break;
		case 'f':
			if (freopen(optarg, "r", stdin) == NULL) {
				fprintf(stderr, "%s: %s: reopen: %s\n",
					prog, optarg, strerror(errno));
				exit(EXIT_FAILURE);
			}
			break;
		case 'n':
			envflags |= MDB_NOSUBDIR;
			break;
		case 's':
			subname = strdup(optarg);
			break;
		case 'N':
			putflags = MDB_NOOVERWRITE|MDB_NODUPDATA;
			break;
		case 'T':
			mode |= NOHDR;
			break;
		default:
			usage();
		}
	}

	if (optind != argc - 1)
		usage();

	dbuf.mv_size = 4096;
	dbuf.mv_data = malloc(dbuf.mv_size);

	if (!(mode & NOHDR))
		readhdr();

	envname = argv[optind];
	rc = mdb_env_create(&env);
	if (rc) {
		fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
		return EXIT_FAILURE;
	}

	mdb_env_set_maxdbs(env, 2);

	if (info.me_maxreaders)
		mdb_env_set_maxreaders(env, info.me_maxreaders);

	if (info.me_mapsize)
		mdb_env_set_mapsize(env, info.me_mapsize);

	if (info.me_mapaddr)
		envflags |= MDB_FIXEDMAP;

	rc = mdb_env_open(env, envname, envflags, 0664);
	if (rc) {
		fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
		goto env_close;
	}

	kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2;
	kbuf.mv_data = malloc(kbuf.mv_size);

	while(!Eof) {
		MDB_val key, data;
		int batch = 0;
		flags = 0;

		if (!dohdr) {
			dohdr = 1;
		} else if (!(mode & NOHDR))
			readhdr();
		
		rc = mdb_txn_begin(env, NULL, 0, &txn);
		if (rc) {
			fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
			goto env_close;
		}

		rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi);
		if (rc) {
			fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}

		rc = mdb_cursor_open(txn, dbi, &mc);
		if (rc) {
			fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}

		while(1) {
			rc = readline(&key, &kbuf);
			if (rc == EOF)
				break;
			if (rc)
				goto txn_abort;

			rc = readline(&data, &dbuf);
			if (rc)
				goto txn_abort;
			
			rc = mdb_cursor_put(mc, &key, &data, putflags);
			if (rc == MDB_KEYEXIST && putflags)
				continue;
			if (rc)
				goto txn_abort;
			batch++;
			if (batch == 100) {
				rc = mdb_txn_commit(txn);
				if (rc) {
					fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n",
						prog, lineno, mdb_strerror(rc));
					goto env_close;
				}
				rc = mdb_txn_begin(env, NULL, 0, &txn);
				if (rc) {
					fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
					goto env_close;
				}
				rc = mdb_cursor_open(txn, dbi, &mc);
				if (rc) {
					fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
					goto txn_abort;
				}
				batch = 0;
			}
		}
		rc = mdb_txn_commit(txn);
		txn = NULL;
		if (rc) {
			fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n",
				prog, lineno, mdb_strerror(rc));
			goto env_close;
		}
		mdb_dbi_close(env, dbi);
	}

txn_abort:
	mdb_txn_abort(txn);
env_close:
	mdb_env_close(env);

	return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemplo n.º 17
0
/* Open all un-opened index DB handles */
int
mdb_attr_dbs_open(
	BackendDB *be, MDB_txn *tx0, ConfigReply *cr )
{
	struct mdb_info *mdb = (struct mdb_info *) be->be_private;
	MDB_txn *txn;
	MDB_dbi *dbis = NULL;
	int i, flags;
	int rc;

	txn = tx0;
	if ( txn == NULL ) {
		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
		if ( rc ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"txn_begin failed: %s (%d).",
				be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
				cr->msg, 0, 0 );
			return rc;
		}
		dbis = ch_calloc( 1, mdb->mi_nattrs * sizeof(MDB_dbi) );
	} else {
		rc = 0;
	}

	flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP;
	if ( !(slapMode & SLAP_TOOL_READONLY) )
		flags |= MDB_CREATE;

	for ( i=0; i<mdb->mi_nattrs; i++ ) {
		if ( mdb->mi_attrs[i]->ai_dbi )	/* already open */
			continue;
		rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
			flags, &mdb->mi_attrs[i]->ai_dbi );
		if ( rc ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"mdb_dbi_open(%s) failed: %s (%d).",
				be->be_suffix[0].bv_val,
				mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
				cr->msg, 0, 0 );
			break;
		}
		/* Remember newly opened DBI handles */
		if ( dbis )
			dbis[i] = mdb->mi_attrs[i]->ai_dbi;
	}

	/* Only commit if this is our txn */
	if ( tx0 == NULL ) {
		if ( !rc ) {
			rc = mdb_txn_commit( txn );
			if ( rc ) {
				snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
					"txn_commit failed: %s (%d).",
					be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
				Debug( LDAP_DEBUG_ANY,
					LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
					cr->msg, 0, 0 );
			}
		} else {
			mdb_txn_abort( txn );
		}
		/* Something failed, forget anything we just opened */
		if ( rc ) {
			for ( i=0; i<mdb->mi_nattrs; i++ ) {
				if ( dbis[i] ) {
					mdb->mi_attrs[i]->ai_dbi = 0;
					mdb->mi_attrs[i]->ai_indexmask |= MDB_INDEX_DELETING;
				}
			}
			mdb_attr_flush( mdb );
		}
		ch_free( dbis );
	}

	return rc;
}
Exemplo n.º 18
0
int main(int argc, char *argv[])
{
	int i, rc;
	MDB_env *env;
	MDB_txn *txn;
	MDB_dbi dbi;
	MDB_stat mst;
	MDB_envinfo mei;
	char *prog = argv[0];
	char *envname;
	char *subname = NULL;
	int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0;

	if (argc < 2) {
		usage(prog);
	}

	/* -a: print stat of main DB and all subDBs
	 * -s: print stat of only the named subDB
	 * -e: print env info
	 * -f: print freelist info
	 * -r: print reader info
	 * -n: use NOSUBDIR flag on env_open
	 * -V: print version and exit
	 * (default) print stat of only the main DB
	 */
	while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) {
		switch(i) {
		case 'V':
			printf("%s\n", MDB_VERSION_STRING);
			exit(0);
			break;
		case 'a':
			if (subname)
				usage(prog);
			alldbs++;
			break;
		case 'e':
			envinfo++;
			break;
		case 'f':
			freinfo++;
			break;
		case 'n':
			envflags |= MDB_NOSUBDIR;
			break;
		case 'r':
			rdrinfo++;
			break;
		case 's':
			if (alldbs)
				usage(prog);
			subname = optarg;
			break;
		default:
			usage(prog);
		}
	}

	if (optind != argc - 1)
		usage(prog);

	envname = argv[optind];
	rc = mdb_env_create(&env);
	if (rc) {
		fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc));
		return EXIT_FAILURE;
	}

	if (alldbs || subname) {
		mdb_env_set_maxdbs(env, 4);
	}

	rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664);
	if (rc) {
		fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc));
		goto env_close;
	}

	if (envinfo) {
		(void)mdb_env_stat(env, &mst);
		(void)mdb_env_info(env, &mei);
		printf("Environment Info\n");
		printf("  Map address: %p\n", mei.me_mapaddr);
		printf("  Map size: %"Z"u\n", mei.me_mapsize);
		printf("  Page size: %u\n", mst.ms_psize);
		printf("  Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize);
		printf("  Number of pages used: %"Z"u\n", mei.me_last_pgno+1);
		printf("  Last transaction ID: %"Z"u\n", mei.me_last_txnid);
		printf("  Max readers: %u\n", mei.me_maxreaders);
		printf("  Number of readers used: %u\n", mei.me_numreaders);
	}

	if (rdrinfo) {
		printf("Reader Table Status\n");
		rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
		if (rdrinfo > 1) {
			int dead;
			mdb_reader_check(env, &dead);
			printf("  %d stale readers cleared.\n", dead);
			rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout);
		}
		if (!(subname || alldbs || freinfo))
			goto env_close;
	}

	rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
	if (rc) {
		fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc));
		goto env_close;
	}

	if (freinfo) {
		MDB_cursor *cursor;
		MDB_val key, data;
		size_t pages = 0, *iptr;

		printf("Freelist Status\n");
		dbi = 0;
		rc = mdb_cursor_open(txn, dbi, &cursor);
		if (rc) {
			fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}
		rc = mdb_stat(txn, dbi, &mst);
		if (rc) {
			fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}
		prstat(&mst);
		while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
			iptr = data.mv_data;
			pages += *iptr;
			if (freinfo > 1) {
				char * bad = (char *)"";
				size_t pg, prev;
				ssize_t i, j, span = 0;
				j = *iptr++;
				for (i = j, prev = 1; --i >= 0; ) {
					pg = iptr[i];
					if (pg <= prev)
						bad = (char *)" [bad sequence]";
					prev = pg;
					pg += span;
					for (; i >= span && iptr[i-span] == pg; span++, pg++) ;
				}
				printf("    Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n",
					*(size_t *)key.mv_data, j, span, bad);
				if (freinfo > 2) {
					for (--j; j >= 0; ) {
						pg = iptr[j];
						for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ;
						printf(span>1 ? "     %9"Z"u[%"Z"d]\n" : "     %9"Z"u\n",
							pg, span);
					}
				}
			}
		}
		mdb_cursor_close(cursor);
		printf("  Free pages: %"Z"u\n", pages);
	}

	rc = mdb_open(txn, subname, 0, &dbi);
	if (rc) {
		fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc));
		goto txn_abort;
	}

	rc = mdb_stat(txn, dbi, &mst);
	if (rc) {
		fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
		goto txn_abort;
	}
	printf("Status of %s\n", subname ? subname : "Main DB");
	prstat(&mst);

	if (alldbs) {
		MDB_cursor *cursor;
		MDB_val key;

		rc = mdb_cursor_open(txn, dbi, &cursor);
		if (rc) {
			fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc));
			goto txn_abort;
		}
		while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) {
			char *str;
			MDB_dbi db2;
			if (memchr(key.mv_data, '\0', key.mv_size))
				continue;
			str = malloc(key.mv_size+1);
			memcpy(str, key.mv_data, key.mv_size);
			str[key.mv_size] = '\0';
			rc = mdb_open(txn, str, 0, &db2);
			if (rc == MDB_SUCCESS)
				printf("Status of %s\n", str);
			free(str);
			if (rc) continue;
			rc = mdb_stat(txn, db2, &mst);
			if (rc) {
				fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc));
				goto txn_abort;
			}
			prstat(&mst);
			mdb_close(env, db2);
		}
		mdb_cursor_close(cursor);
	}

	if (rc == MDB_NOTFOUND)
		rc = MDB_SUCCESS;

	mdb_close(env, dbi);
txn_abort:
	mdb_txn_abort(txn);
env_close:
	mdb_env_close(env);

	return rc ? EXIT_FAILURE : EXIT_SUCCESS;
}
Exemplo n.º 19
0
void B_ACCURATE_LMDB::destroy(JCR *jcr)
{
   /*
    * Abort any pending read transaction.
    */
   if (m_db_ro_txn) {
      mdb_txn_abort(m_db_ro_txn);
      m_db_ro_txn = NULL;
   }

   /*
    * Abort any pending write transaction.
    */
   if (m_db_rw_txn) {
      mdb_txn_abort(m_db_rw_txn);
      m_db_rw_txn = NULL;
   }

   if (m_db_env) {
      /*
       * Drop the contents of the LMDB.
       */
      if (m_db_dbi) {
         int result;
         MDB_txn *txn;

         result = mdb_txn_begin(m_db_env, NULL, 0, &txn);
         if (result == 0) {
            result = mdb_drop(txn, m_db_dbi, 1);
            if (result == 0) {
               mdb_txn_commit(txn);
            } else {
               mdb_txn_abort(txn);
            }
         }
         m_db_dbi = 0;
      }

      /*
       * Close the environment.
       */
      mdb_env_close(m_db_env);
      m_db_env = NULL;
   }

   if (m_pay_load) {
      free_pool_memory(m_pay_load);
      m_pay_load = NULL;
   }

   if (m_lmdb_name) {
      unlink(m_lmdb_name);
      free_pool_memory(m_lmdb_name);
      m_lmdb_name = NULL;
   }

   if (m_seen_bitmap) {
      free(m_seen_bitmap);
      m_seen_bitmap = NULL;
   }

   m_filenr = 0;
}
Exemplo n.º 20
0
ID mdb_tool_entry_next(
	BackendDB *be )
{
	int rc;
	ID id;
	struct mdb_info *mdb;

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

	mdb = (struct mdb_info *) be->be_private;
	assert( mdb != NULL );

	if ( !txn ) {
		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, MDB_RDONLY, &txn );
		if ( rc )
			return NOID;
		rc = mdb_cursor_open( txn, mdb->mi_id2entry, &cursor );
		if ( rc ) {
			mdb_txn_abort( txn );
			return NOID;
		}
	}

next:;
	rc = mdb_cursor_get( cursor, &key, &data, MDB_NEXT );

	if( rc ) {
		return NOID;
	}

	previd = *(ID *)key.mv_data;
	id = previd;

	if ( tool_filter || tool_base ) {
		static Operation op = {0};
		static Opheader ohdr = {0};

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

		if ( tool_next_entry ) {
			mdb_entry_release( &op, tool_next_entry, 0 );
			tool_next_entry = NULL;
		}

		rc = mdb_tool_entry_get_int( be, id, &tool_next_entry );
		if ( rc == LDAP_NO_SUCH_OBJECT ) {
			goto next;
		}

		assert( tool_next_entry != NULL );

		if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE )
		{
			mdb_entry_release( &op, tool_next_entry, 0 );
			tool_next_entry = NULL;
			goto next;
		}
	}

	return id;
}
Exemplo n.º 21
0
bool B_ACCURATE_LMDB::init(JCR *jcr, uint32_t nbfile)
{
   int result;
   MDB_env *env;
   size_t mapsize = 10485760;

   if (!m_db_env) {
      result = mdb_env_create(&env);
      if (result) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to create MDB environment: %s\n"), mdb_strerror(result));
         return false;
      }

      if ((nbfile * AVG_NR_BYTES_PER_ENTRY) > mapsize) {
         size_t pagesize;

#ifdef HAVE_GETPAGESIZE
         pagesize = getpagesize();
#else
         pagesize = B_PAGE_SIZE;
#endif

         mapsize = (((nbfile * AVG_NR_BYTES_PER_ENTRY) / pagesize) + 1) * pagesize;
      }
      result = mdb_env_set_mapsize(env, mapsize);
      if (result) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to set MDB mapsize: %s\n"), mdb_strerror(result));
         goto bail_out;
      }

      /*
       * Explicitly set the number of readers to 1.
       */
      result = mdb_env_set_maxreaders(env, 1);
      if (result) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to set MDB maxreaders: %s\n"), mdb_strerror(result));
         goto bail_out;
      }

      Mmsg(m_lmdb_name, "%s/.accurate_lmdb.%d", me->working_directory, jcr->JobId);
      result = mdb_env_open(env, m_lmdb_name, MDB_NOSUBDIR | MDB_NOLOCK | MDB_NOSYNC, 0600);
      if (result) {
         Jmsg2(jcr, M_FATAL, 0, _("Unable create LDMD database %s: %s\n"), m_lmdb_name, mdb_strerror(result));
         goto bail_out;
      }

      result = mdb_txn_begin(env, NULL, 0, &m_db_rw_txn);
      if (result) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to start a write transaction: %s\n"), mdb_strerror(result));
         goto bail_out;
      }

      result = mdb_dbi_open(m_db_rw_txn, NULL, MDB_CREATE, &m_db_dbi);
      if (result) {
         Jmsg1(jcr, M_FATAL, 0, _("Unable to open LMDB internal database: %s\n"), mdb_strerror(result));
         mdb_txn_abort(m_db_rw_txn);
         m_db_rw_txn = NULL;
         goto bail_out;
      }

      m_db_env = env;
   }

   if (!m_pay_load) {
      m_pay_load = get_pool_memory(PM_MESSAGE);
   }

   if (!m_lmdb_name) {
      m_pay_load = get_pool_memory(PM_FNAME);
   }

   if (!m_seen_bitmap) {
      m_seen_bitmap = (char *)malloc(nbytes_for_bits(nbfile));
      clear_all_bits(nbfile, m_seen_bitmap);
   }

   return true;

bail_out:
   if (env) {
      mdb_env_close(env);
   }

   return false;
}
Exemplo n.º 22
0
int mdb_tool_entry_reindex(
	BackendDB *be,
	ID id,
	AttributeDescription **adv )
{
	struct mdb_info *mi = (struct mdb_info *) be->be_private;
	int rc;
	Entry *e;
	Operation op = {0};
	Opheader ohdr = {0};

	Debug( LDAP_DEBUG_ARGS,
		"=> " LDAP_XSTRING(mdb_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 (!mi->mi_attrs) {
		return 0;
	}

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

		if ( mi->mi_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 ( mi->mi_attrs[i]->ai_desc != adv[i] ) {
				for ( j = i+1; j < mi->mi_nattrs; j++ ) {
					if ( mi->mi_attrs[j]->ai_desc == adv[i] ) {
						AttrInfo *ai = mi->mi_attrs[i];
						mi->mi_attrs[i] = mi->mi_attrs[j];
						mi->mi_attrs[j] = ai;
						break;
					}
				}
				if ( j == mi->mi_nattrs ) {
					Debug( LDAP_DEBUG_ANY,
						LDAP_XSTRING(mdb_tool_entry_reindex)
						": no index configured for %s\n",
						adv[i]->ad_cname.bv_val, 0, 0 );
					return -1;
				}
			}
		}
		mi->mi_nattrs = i;
	}

	e = mdb_tool_entry_get( be, id );

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

	if ( !txi ) {
		rc = mdb_txn_begin( mi->mi_dbenv, NULL, 0, &txi );
		if( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"=> " LDAP_XSTRING(mdb_tool_entry_reindex) ": "
				"txn_begin failed: %s (%d)\n",
				mdb_strerror(rc), rc, 0 );
			goto done;
		}
	}

	if ( slapMode & SLAP_TRUNCATE_MODE ) {
		int i;
		for ( i=0; i < mi->mi_nattrs; i++ ) {
			rc = mdb_drop( txi, mi->mi_attrs[i]->ai_dbi, 0 );
			if ( rc ) {
				Debug( LDAP_DEBUG_ANY,
					LDAP_XSTRING(mdb_tool_entry_reindex)
					": (Truncate) mdb_drop(%s) failed: %s (%d)\n",
					mi->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
					mdb_strerror(rc), rc );
				return -1;
			}
		}
		slapMode ^= SLAP_TRUNCATE_MODE;
	}

	/*
	 * just (re)add them for now
	 * Use truncate mode to empty/reset index databases
	 */

	Debug( LDAP_DEBUG_TRACE,
		"=> " LDAP_XSTRING(mdb_tool_entry_reindex) "( %ld )\n",
		(long) id, 0, 0 );

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

	rc = mdb_tool_index_add( &op, txi, e );

done:
	if( rc == 0 ) {
		mdb_writes++;
		if ( mdb_writes >= mdb_writes_per_commit ) {
			unsigned i;
			MDB_TOOL_IDL_FLUSH( be, txi );
			rc = mdb_txn_commit( txi );
			mdb_writes = 0;
			for ( i=0; i<mi->mi_nattrs; i++ )
				mi->mi_attrs[i]->ai_cursor = NULL;
			if( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
					"=> " LDAP_XSTRING(mdb_tool_entry_reindex)
					": txn_commit failed: %s (%d)\n",
					mdb_strerror(rc), rc, 0 );
				e->e_id = NOID;
			}
			txi = NULL;
		}

	} else {
		unsigned i;
		mdb_writes = 0;
		mdb_txn_abort( txi );
		for ( i=0; i<mi->mi_nattrs; i++ )
			mi->mi_attrs[i]->ai_cursor = NULL;
		Debug( LDAP_DEBUG_ANY,
			"=> " LDAP_XSTRING(mdb_tool_entry_reindex)
			": txn_aborted! err=%d\n",
			rc, 0, 0 );
		e->e_id = NOID;
		txi = NULL;
	}
	mdb_entry_release( &op, e, 0 );

	return rc;
}
Exemplo n.º 23
0
/* reindex entries on the fly */
static void *
mdb_online_index( void *ctx, void *arg )
{
	struct re_s *rtask = arg;
	BackendDB *be = rtask->arg;
	struct mdb_info *mdb = be->be_private;

	Connection conn = {0};
	OperationBuffer opbuf;
	Operation *op;

	MDB_cursor *curs;
	MDB_val key, data;
	MDB_txn *txn;
	ID id;
	Entry *e;
	int rc, getnext = 1;
	int i;

	connection_fake_init( &conn, &opbuf, ctx );
	op = &opbuf.ob_op;

	op->o_bd = be;

	id = 1;
	key.mv_size = sizeof(ID);

	while ( 1 ) {
		if ( slapd_shutdown )
			break;

		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
		if ( rc )
			break;
		rc = mdb_cursor_open( txn, mdb->mi_id2entry, &curs );
		if ( rc ) {
			mdb_txn_abort( txn );
			break;
		}
		if ( getnext ) {
			getnext = 0;
			key.mv_data = &id;
			rc = mdb_cursor_get( curs, &key, &data, MDB_SET_RANGE );
			if ( rc ) {
				mdb_txn_abort( txn );
				if ( rc == MDB_NOTFOUND )
					rc = 0;
				break;
			}
			memcpy( &id, key.mv_data, sizeof( id ));
		}

		rc = mdb_id2entry( op, curs, id, &e );
		mdb_cursor_close( curs );
		if ( rc ) {
			mdb_txn_abort( txn );
			if ( rc == MDB_NOTFOUND ) {
				id++;
				getnext = 1;
				continue;
			}
			break;
		}
		rc = mdb_index_entry( op, txn, MDB_INDEX_UPDATE_OP, e );
		mdb_entry_return( op, e );
		if ( rc == 0 ) {
			rc = mdb_txn_commit( txn );
			txn = NULL;
		} else {
			mdb_txn_abort( txn );
			txn = NULL;
		}
		if ( rc )
			break;
		id++;
		getnext = 1;
	}

	for ( i = 0; i < mdb->mi_nattrs; i++ ) {
		if ( mdb->mi_attrs[ i ]->ai_indexmask & MDB_INDEX_DELETING
			|| mdb->mi_attrs[ i ]->ai_newmask == 0 )
		{
			continue;
		}
		mdb->mi_attrs[ i ]->ai_indexmask = mdb->mi_attrs[ i ]->ai_newmask;
		mdb->mi_attrs[ i ]->ai_newmask = 0;
	}

	ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
	ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
	mdb->mi_index_task = NULL;
	ldap_pvt_runqueue_remove( &slapd_rq, rtask );
	ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );

	return NULL;
}
Exemplo n.º 24
0
int main(int argc,char * argv[])
{
	int i = 0, j = 0, rc;
	MDB_env *env;
	MDB_dbi dbi;
	MDB_val key, data;
	MDB_txn *txn;
	MDB_stat mst;
	MDB_cursor *cursor;
	int count;
	int *values;
	char sval[32];
	char kval[sizeof(int)];

	srand(time(NULL));

	memset(sval, 0, sizeof(sval));

	count = (rand()%384) + 64;
	values = (int *)malloc(count*sizeof(int));

	for(i = 0;i<count;i++) {
		values[i] = rand()%1024;
	}

	E(mdb_env_create(&env));
	E(mdb_env_set_mapsize(env, 10485760));
	E(mdb_env_set_maxdbs(env, 4));
	E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664));
	E(mdb_txn_begin(env, NULL, 0, &txn));
	E(mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi));
	E(mdb_cursor_open(txn, dbi, &cursor));

	key.mv_size = sizeof(int);
	key.mv_data = kval;
	data.mv_size = sizeof(sval);
	data.mv_data = sval;

	printf("Adding %d values\n", count);
	for (i=0;i<count;i++) {
		if (!(i & 0x0f))
			sprintf(kval, "%03x", values[i]);
		sprintf(sval, "%03x %d foo bar", values[i], values[i]);
		if (RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA)))
			j++;
	}
	if (j) printf("%d duplicates skipped\n", j);
	mdb_cursor_close(cursor);
	E(mdb_txn_commit(txn));
	E(mdb_env_stat(env, &mst));

	E(mdb_txn_begin(env, NULL, 1, &txn));
	E(mdb_cursor_open(txn, dbi, &cursor));
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
		printf("key: %p %.*s, data: %p %.*s\n",
			key.mv_data,  (int) key.mv_size,  (char *) key.mv_data,
			data.mv_data, (int) data.mv_size, (char *) data.mv_data);
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	mdb_cursor_close(cursor);
	mdb_txn_abort(txn);

	j=0;

	for (i= count - 1; i > -1; i-= (rand()%5)) {
		j++;
		txn=NULL;
		E(mdb_txn_begin(env, NULL, 0, &txn));
		sprintf(kval, "%03x", values[i & ~0x0f]);
		sprintf(sval, "%03x %d foo bar", values[i], values[i]);
		key.mv_size = sizeof(int);
		key.mv_data = kval;
		data.mv_size = sizeof(sval);
		data.mv_data = sval;
		if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) {
			j--;
			mdb_txn_abort(txn);
		} else {
			E(mdb_txn_commit(txn));
		}
	}
	free(values);
	printf("Deleted %d values\n", j);

	E(mdb_env_stat(env, &mst));
	E(mdb_txn_begin(env, NULL, 1, &txn));
	E(mdb_cursor_open(txn, dbi, &cursor));
	printf("Cursor next\n");
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	printf("Cursor prev\n");
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) {
		printf("key: %.*s, data: %.*s\n",
			(int) key.mv_size,  (char *) key.mv_data,
			(int) data.mv_size, (char *) data.mv_data);
	}
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	mdb_cursor_close(cursor);
	mdb_close(env, dbi);

	mdb_txn_abort(txn);
	mdb_env_close(env);

	return 0;
}
Exemplo n.º 25
0
void LMDBFileIndex::put_internal(const SIndexKey& key, int64 value, int flags, bool log, bool handle_enosp)
{
	CWData vdata;
	vdata.addVarInt(value);
			
	MDB_val mdb_tkey;
	mdb_tkey.mv_data=const_cast<void*>(static_cast<const void*>(&key));
	mdb_tkey.mv_size=sizeof(SIndexKey);

	MDB_val mdb_tvalue;
	mdb_tvalue.mv_data=vdata.getDataPtr();
	mdb_tvalue.mv_size=vdata.getDataSize();

	int rc = mdb_put(txn, dbi, &mdb_tkey, &mdb_tvalue, flags);

	if(rc==MDB_MAP_FULL && handle_enosp)
	{
		mdb_txn_abort(txn);

		if(_has_error)
		{
			Server->Log("LMDB had error during increase (on put). Aborting...", LL_ERROR);
			start_transaction();
			return;
		}

		{
			read_transaction_lock.reset();

			IScopedWriteLock lock(mutex);

			destroy_env();

			map_size*=2;

			Server->Log("Increased LMDB database size to "+PrettyPrintBytes(map_size)+" (on put)", LL_DEBUG);

			if(!create_env())
			{
				Server->Log("Error creating env after database file size increase", LL_ERROR);
				_has_error=true;
				start_transaction();
				return;
			}
			
		}

		start_transaction();

		replay_transaction_log();
		
		put_internal(key, value, flags, false, true);
	}
	else if(rc==MDB_BAD_TXN && handle_enosp)
	{
		mdb_txn_abort(txn);
		
		if(_has_error)
		{
			Server->Log("LMDB had error on BAD_TXN (on put). Aborting...", LL_ERROR);
			start_transaction();
			return;
		}
		
		start_transaction();
		
		replay_transaction_log();
		
		put_internal(key, value, flags, false, false);
	}
	else if(rc)
	{
		Server->Log("LMDB: Failed to put data ("+(std::string)mdb_strerror(rc)+")", LL_ERROR);
		_has_error=true;
	}

	if(!_has_error && log)
	{
		STransactionLogItem item = { key, value, flags};
		transaction_log.push_back(item);
	}
}
Exemplo n.º 26
0
int
mdb_delete( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	struct berval	pdn = {0, NULL};
	Entry	*e = NULL;
	Entry	*p = NULL;
	int		manageDSAit = get_manageDSAit( op );
	AttributeDescription *children = slap_schema.si_ad_children;
	AttributeDescription *entry = slap_schema.si_ad_entry;
	MDB_txn		*txn = NULL;
	MDB_cursor	*mc;
	mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo;

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

	int	parent_is_glue = 0;
	int parent_is_leaf = 0;

#ifdef LDAP_X_TXN
	int settle = 0;
#endif

	Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_delete) ": %s\n",
		op->o_req_dn.bv_val, 0, 0 );

#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;

	/* begin transaction */
	rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi );
	rs->sr_text = NULL;
	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_delete) ": txn_begin failed: "
			"%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	txn = moi->moi_txn;

	/* allocate CSN */
	if ( BER_BVISNULL( &op->o_csn ) ) {
		struct berval csn;
		char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE];

		csn.bv_val = csnbuf;
		csn.bv_len = sizeof(csnbuf);
		slap_get_csn( op, &csn, 1 );
	}

	if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
		dnParent( &op->o_req_ndn, &pdn );
	}

	rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mc );
	if ( rs->sr_err ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}
	/* get parent */
	rs->sr_err = mdb_dn2entry( op, txn, mc, &pdn, &p, NULL, 1 );
	switch( rs->sr_err ) {
	case 0:
	case MDB_NOTFOUND:
		break;
	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 ( rs->sr_err == MDB_NOTFOUND ) {
		Debug( LDAP_DEBUG_ARGS,
			"<=- " LDAP_XSTRING(mdb_delete) ": no such object %s\n",
			op->o_req_dn.bv_val, 0, 0);

		if ( p && !BER_BVISEMPTY( &p->e_name )) {
			rs->sr_matched = ch_strdup( p->e_name.bv_val );
			if ( is_entry_referral( p )) {
				BerVarray ref = get_entry_referrals( op, p );
				rs->sr_ref = referral_rewrite( ref, &p->e_name,
					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
				ber_bvarray_free( ref );
			} else {
				rs->sr_ref = NULL;
			}
		} else {
			rs->sr_ref = referral_rewrite( default_referral, NULL,
					&op->o_req_dn, LDAP_SCOPE_DEFAULT );
		}
		if ( p ) {
			mdb_entry_return( op, p );
			p = NULL;
		}

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

	/* get entry */
	rs->sr_err = mdb_dn2entry( op, txn, mc, &op->o_req_ndn, &e, NULL, 0 );
	switch( rs->sr_err ) {
	case MDB_NOTFOUND:
		e = p;
		p = NULL;
	case 0:
		break;
	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;
	}

	/* FIXME : dn2entry() should return non-glue entry */
	if ( rs->sr_err == MDB_NOTFOUND || ( !manageDSAit && is_entry_glue( e ))) {
		Debug( LDAP_DEBUG_ARGS,
			"<=- " LDAP_XSTRING(mdb_delete) ": no such object %s\n",
			op->o_req_dn.bv_val, 0, 0);

		rs->sr_matched = ch_strdup( e->e_dn );
		if ( is_entry_referral( e )) {
			BerVarray ref = get_entry_referrals( op, e );
			rs->sr_ref = referral_rewrite( ref, &e->e_name,
				&op->o_req_dn, LDAP_SCOPE_DEFAULT );
			ber_bvarray_free( ref );
		} else {
			rs->sr_ref = NULL;
		}
		mdb_entry_return( op, e );
		e = NULL;

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

	if ( pdn.bv_len != 0 ) {
		/* check parent for "children" acl */
		rs->sr_err = access_allowed( op, p,
			children, NULL, ACL_WDEL, NULL );

		if ( !rs->sr_err  ) {
			Debug( LDAP_DEBUG_TRACE,
				"<=- " LDAP_XSTRING(mdb_delete) ": no write "
				"access to parent\n", 0, 0, 0 );
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
			rs->sr_text = "no write access to parent";
			goto return_results;
		}

	} else {
		/* no parent, must be root to delete */
		if( ! be_isroot( op ) ) {
			if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv )
				|| be_shadow_update( op ) ) {
				p = (Entry *)&slap_entry_root;

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

				p = NULL;

				if ( !rs->sr_err  ) {
					Debug( LDAP_DEBUG_TRACE,
						"<=- " LDAP_XSTRING(mdb_delete)
						": no access to parent\n",
						0, 0, 0 );
					rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
					rs->sr_text = "no write access to parent";
					goto return_results;
				}

			} else {
				Debug( LDAP_DEBUG_TRACE,
					"<=- " LDAP_XSTRING(mdb_delete)
					": no parent and not root\n", 0, 0, 0 );
				rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
				goto return_results;
			}
		}
	}

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

	rs->sr_err = access_allowed( op, e,
		entry, NULL, ACL_WDEL, NULL );

	if ( !rs->sr_err  ) {
		Debug( LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(mdb_delete) ": no write access "
			"to entry\n", 0, 0, 0 );
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		rs->sr_text = "no write access to entry";
		goto return_results;
	}

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

		Debug( LDAP_DEBUG_TRACE,
			LDAP_XSTRING(mdb_delete) ": entry is referral\n",
			0, 0, 0 );

		rs->sr_err = LDAP_REFERRAL;
		rs->sr_matched = ch_strdup( e->e_name.bv_val );
		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
		goto return_results;
	}

	/* pre-read */
	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(mdb_delete) ": 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;
			}
		}
	}

	rs->sr_text = NULL;

	/* Can't do it if we have kids */
	rs->sr_err = mdb_dn2id_children( op, txn, e );
	if( rs->sr_err != MDB_NOTFOUND ) {
		switch( rs->sr_err ) {
		case 0:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(mdb_delete)
				": non-leaf %s\n",
				op->o_req_dn.bv_val, 0, 0);
			rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
			rs->sr_text = "subordinate objects must be deleted first";
			break;
		default:
			Debug(LDAP_DEBUG_ARGS,
				"<=- " LDAP_XSTRING(mdb_delete)
				": has_children failed: %s (%d)\n",
				mdb_strerror(rs->sr_err), rs->sr_err, 0 );
			rs->sr_err = LDAP_OTHER;
			rs->sr_text = "internal error";
		}
		goto return_results;
	}

	/* delete from dn2id */
	rs->sr_err = mdb_dn2id_delete( op, mc, e->e_id, 1 );
	mdb_cursor_close( mc );
	if ( rs->sr_err != 0 ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(mdb_delete) ": dn2id failed: "
			"%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_text = "DN index delete failed";
		rs->sr_err = LDAP_OTHER;
		goto return_results;
	}

	/* delete indices for old attributes */
	rs->sr_err = mdb_index_entry_del( op, txn, e );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		Debug(LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(mdb_delete) ": index failed: "
			"%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_text = "entry index delete failed";
		rs->sr_err = LDAP_OTHER;
		goto return_results;
	}

	/* fixup delete CSN */
	if ( !SLAP_SHADOW( op->o_bd )) {
		struct berval vals[2];

		assert( !BER_BVISNULL( &op->o_csn ) );
		vals[0] = op->o_csn;
		BER_BVZERO( &vals[1] );
		rs->sr_err = mdb_index_values( op, txn, slap_schema.si_ad_entryCSN,
			vals, 0, SLAP_INDEX_ADD_OP );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			rs->sr_text = "entryCSN index update failed";
			rs->sr_err = LDAP_OTHER;
			goto return_results;
		}
	}

	/* delete from id2entry */
	rs->sr_err = mdb_id2entry_delete( op->o_bd, txn, e );
	if ( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_TRACE,
			"<=- " LDAP_XSTRING(mdb_delete) ": id2entry failed: "
			"%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 );
		rs->sr_text = "entry delete failed";
		rs->sr_err = LDAP_OTHER;
		goto return_results;
	}

	if ( pdn.bv_len != 0 ) {
		parent_is_glue = is_entry_glue(p);
		rs->sr_err = mdb_dn2id_children( op, txn, p );
		if ( rs->sr_err != MDB_NOTFOUND ) {
			switch( rs->sr_err ) {
			case 0:
				break;
			default:
				Debug(LDAP_DEBUG_ARGS,
					"<=- " LDAP_XSTRING(mdb_delete)
					": has_children failed: %s (%d)\n",
					mdb_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;
		}
		mdb_entry_return( op, p );
		p = NULL;
	}

	if( moi == &opinfo ) {
		LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
		opinfo.moi_oe.oe_key = NULL;
		if( op->o_noop ) {
			mdb_txn_abort( txn );
			rs->sr_err = LDAP_X_NO_OPERATION;
			txn = NULL;
			goto return_results;
		} else {
			rs->sr_err = mdb_txn_commit( txn );
		}
		txn = NULL;
	}

	if( rs->sr_err != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_delete) ": txn_%s failed: %s (%d)\n",
			op->o_noop ? "abort (no-op)" : "commit",
			mdb_strerror(rs->sr_err), rs->sr_err );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "commit failed";

		goto return_results;
	}

	Debug( LDAP_DEBUG_TRACE,
		LDAP_XSTRING(mdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n",
		op->o_noop ? " (no-op)" : "",
		e->e_id, op->o_req_dn.bv_val );
	rs->sr_err = LDAP_SUCCESS;
	rs->sr_text = NULL;
	if( num_ctrls ) rs->sr_ctrls = ctrls;

return_results:
	if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) {
		op->o_delete_glue_parent = 1;
	}

	if ( p != NULL ) {
		mdb_entry_return( op, p );
	}

	/* free entry */
	if( e != NULL ) {
		mdb_entry_return( op, e );
	}

	if( moi == &opinfo ) {
		if( txn != NULL ) {
			mdb_txn_abort( txn );
		}
		if ( opinfo.moi_oe.oe_key ) {
			LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next );
		}
	} else {
		moi->moi_ref--;
	}

	send_ldap_result( op, rs );
	slap_graduate_commit_csn( op );

	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 0
	if( rs->sr_err == LDAP_SUCCESS && mdb->bi_txn_cp_kbyte ) {
		TXN_CHECKPOINT( mdb->bi_dbenv,
			mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 );
	}
#endif
	return rs->sr_err;
}
Exemplo n.º 27
0
Arquivo: attr.c Projeto: MPlatform/mdb
/* Open all un-opened index DB handles */
int
mdb_attr_dbs_open(
	BackendDB *be, MDB_txn *tx0, ConfigReply *cr )
{
	struct mdb_info *mdb = (struct mdb_info *) be->be_private;
	MDB_txn *txn;
	int i, flags;
	int rc;

	txn = tx0;
	if ( txn == NULL ) {
		rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn );
		if ( rc ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"txn_begin failed: %s (%d).",
				be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
				cr->msg, 0, 0 );
			return rc;
		}
	} else {
		rc = 0;
	}

	flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP;
	if ( !(slapMode & SLAP_TOOL_READONLY) )
		flags |= MDB_CREATE;

	for ( i=0; i<mdb->mi_nattrs; i++ ) {
		if ( mdb->mi_attrs[i]->ai_dbi )	/* already open */
			continue;
		rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
			flags, &mdb->mi_attrs[i]->ai_dbi );
		if ( rc ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"mdb_dbi_open(%s) failed: %s (%d).",
				be->be_suffix[0].bv_val,
				mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val,
				mdb_strerror(rc), rc );
			Debug( LDAP_DEBUG_ANY,
				LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
				cr->msg, 0, 0 );
			break;
		}
	}

	/* Only commit if this is our txn */
	if ( tx0 == NULL ) {
		if ( !rc ) {
			rc = mdb_txn_commit( txn );
			if ( rc ) {
				snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
					"txn_commit failed: %s (%d).",
					be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
				Debug( LDAP_DEBUG_ANY,
					LDAP_XSTRING(mdb_attr_dbs) ": %s\n",
					cr->msg, 0, 0 );
			}
		} else {
			mdb_txn_abort( txn );
		}
	}

	return rc;
}