Full_Name: Hallvard B Furuseth
Version: mdb.master 27aaecc744955d08d2bfe7a3ca786d742267c5bd
OS: Linux x86_64
URL:
Submission from: (NULL) (193.69.163.163)
Submitted by: hallvard
If the malloc at mdb_page_malloc() line 1348 fails, me_pgfirst
has already been incremented and those pages can be lost.
I'll fix that one. Not this, however:
If a child transaction aborts, it loses pages it used up: It does
not give them back to me_pghead, nor to the parent's mt_free_pgs.
It does not rewind me_pgfirst/me_last to their state at txn_begin.
This program illustrates. The DB grows to 107 pages. mdb_stat
can see 10 of them, same as if everything was done in the main
txn. MainDB will have max 1 entry while running.
#include <lmdb.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int rc, i;
MDB_val key = { sizeof(i), &i }, data = { 0, "" };
MDB_env *env;
MDB_txn *txn, *ctxn;
MDB_dbi dbi;
# define dbname "test.mdb"
# define E(e) { rc = (e); if (rc) { fprintf(stderr, "%d: %s: %s\n", \
__LINE__, #e, mdb_strerror(rc)); return rc; } }
E(mdb_env_create(&env));
E(mdb_env_open(env, dbname, MDB_NOSYNC|MDB_NOSUBDIR, 0666));
for (i = 0; i < 100; ) {
E(mdb_txn_begin(env, NULL, 0, &txn));
if (!i) {
E(mdb_dbi_open(txn, NULL, MDB_CREATE, &dbi));
} else {
E(mdb_txn_begin(env, txn, 0, &ctxn));
E(mdb_put(ctxn, dbi, &key, &data, 0));
mdb_txn_abort(ctxn);
E(mdb_del(txn, dbi, &key, NULL));
}
i++;
E(mdb_put(txn, dbi, &key, &data, 0));
E(mdb_txn_commit(txn));
if (i % 20 == 0) system("du " dbname);
}
mdb_env_close(env);
return 0;
}
Show replies by date