[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#8062) Assertion 'IS_LEAF(mp)' failed in mdb_cursor_next()



This is a multi-part message in MIME format.
--------------030305070307090003010905
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Gawen ARAB wrote:
>     Thanks for the report. Unfortunately, it appears the DB was
>     constructed incorrectly at some time in the past, so even updating
>     to later revisions of the code won't avoid the crash. It's more
>     important now to find the sequence of steps that recreates the
>     invalid DB in the first place, or verify that the same sequence
>     doesn't crash using the 0.9.15 release candidate.
>
>
> OK. I'll try to reproduce the steps.

I reproduced an occurrence of this assert using the attached test 
program. This particular bug is now fixed in git, but since we never had 
a test case for your original situation it's still unconfirmed whether 
this fix addresses your issue. Were you able to do any further testing?

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

--------------030305070307090003010905
Content-Type: text/x-csrc;
 name="its8062.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="its8062.c"

/* mtest.c - memory-mapped database tester/toy */
/*
 * Copyright 2011-2015 Howard Chu, Symas Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lmdb.h"

#define E(expr) CHECK((rc = (expr)) == MDB_SUCCESS, #expr)
#define RES(err, expr) ((rc = expr) == (err) || (CHECK(!rc, #expr), 0))
#define CHECK(test, msg) ((test) ? (void)0 : ((void)fprintf(stderr, \
	"%s:%d: %s: %s\n", __FILE__, __LINE__, msg, mdb_strerror(rc)), abort()))

/* Write an 8 byte integer in big-endian order */
void L2B(unsigned long l, char *c)
{
	int i;

	for (i=7; i>=0; i--) {
		c[i] = l & 0xff;
		l >>= 8;
	}
}

int main(int argc,char * argv[])
{
	int i = 0, j = 0, rc;
	MDB_env *env;
	MDB_dbi dbi;
	MDB_val headkey1, headkey2, headkey3, TERMINATOR;
	MDB_val key, data;
	MDB_txn *txn;
	MDB_cursor *cursor;
	int count = 1024;

	char ck1[24], ck2[24], ck3[24], ckx[32],
		cterm[511];
	char cvar[1024];

	E(mdb_env_create(&env));
	E(mdb_env_set_mapsize(env, 1024*1024*1024));
	E(mdb_env_set_maxdbs(env, 2));
	E(mdb_env_open(env, "./testdb", MDB_NOSYNC, 0664));

	E(mdb_txn_begin(env, NULL, 0, &txn));
	E(mdb_dbi_open(txn, "test", MDB_CREATE, &dbi));
	E(mdb_txn_commit(txn));

	/* set up 3 partitions of data */
	headkey1.mv_size = 24; headkey1.mv_data = ck1;
	headkey2.mv_size = 24; headkey2.mv_data = ck2;
	headkey3.mv_size = 24; headkey3.mv_data = ck3;

	/* and a final record */
	TERMINATOR.mv_size = sizeof(cterm); TERMINATOR.mv_data = cterm;
	memset(cterm, 255, sizeof(cterm));

	memset(ck1, 0, 24);
	memset(ck2, 0, 24);
	memset(ck3, 0, 24);
	memset(ckx, 0, 24);

	/* Assign the 3 partition keys */
	L2B(1, ck1);
	L2B(-1, ck2);
	L2B(0, ck3);

	E(mdb_txn_begin(env, NULL, 0, &txn));

	/* Terminator data is a single NUL byte */
	data.mv_size = 1;
	data.mv_data = cvar;
	cvar[0] = 0;
	E(mdb_put(txn, dbi, &TERMINATOR, &data, 0));

	/* Partition data is 24 NUL bytes */
	memset(cvar, 0, 24);
	data.mv_size = 24;

	E(mdb_put(txn, dbi, &headkey1, &data, 0));
	E(mdb_put(txn, dbi, &headkey2, &data, 0));
	E(mdb_put(txn, dbi, &headkey3, &data, 0));

	/* Main data is 35 NUL bytes, keys are 32 bytes */
	memset(cvar, 0, 35);
	data.mv_size = 35;
	key.mv_data = ckx;
	key.mv_size = 32;
	for (i=1; i<=count; i++) {
		L2B(i, ckx+24);
		memcpy(ckx, headkey1.mv_data, 24);
		E(mdb_put(txn, dbi, &key, &data, 0));
		memcpy(ckx, headkey2.mv_data, 24);
		E(mdb_put(txn, dbi, &key, &data, 0));
		memcpy(ckx, headkey3.mv_data, 24);
		E(mdb_put(txn, dbi, &key, &data, 0));
	}

	/* Delete from 1st partition */
	E(mdb_cursor_open(txn, dbi, &cursor));
	E(mdb_cursor_get(cursor, &headkey1, &data, MDB_SET));

	for (i=0; i<count; i++) {
		E(mdb_cursor_del(cursor, 0));
		E(mdb_cursor_get(cursor, &key, &data, MDB_NEXT));
	}
	mdb_cursor_close(cursor);

	/* Delete from 2nd partition - assert happens here */
	E(mdb_cursor_open(txn, dbi, &cursor));
	E(mdb_cursor_get(cursor, &headkey2, &data, MDB_SET));

	for (i=0; i<count; i++) {
		E(mdb_cursor_del(cursor, 0));
		E(mdb_cursor_get(cursor, &key, &data, MDB_NEXT));
	}
	mdb_cursor_close(cursor);

	/* Delete from 3rd partition - not reached */
	E(mdb_cursor_open(txn, dbi, &cursor));
	E(mdb_cursor_get(cursor, &headkey3, &data, MDB_SET));

	for (i=0; i<count; i++) {
		E(mdb_cursor_del(cursor, 0));
		E(mdb_cursor_get(cursor, &key, &data, MDB_NEXT));
	}
	mdb_cursor_close(cursor);

	E(mdb_txn_commit(txn));

	mdb_dbi_close(env, dbi);
	mdb_env_close(env);

	return 0;
}

--------------030305070307090003010905--