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