@@ -2717,7 +2717,6 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
2717
2717
if (env -> me_flags & MDB_RDONLY & ~flags ) /* write txn in RDONLY env */
2718
2718
return EACCES ;
2719
2719
2720
- size = tsize = sizeof (MDB_txn );
2721
2720
if (parent ) {
2722
2721
/* Nested transactions: Max 1 child, write txns only, no writemap */
2723
2722
flags |= parent -> mt_flags ;
@@ -2727,40 +2726,31 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
2727
2726
return (parent -> mt_flags & MDB_TXN_RDONLY ) ? EINVAL : MDB_BAD_TXN ;
2728
2727
}
2729
2728
/* Child txns save MDB_pgstate and use own copy of cursors */
2730
- size = tsize = sizeof (MDB_ntxn );
2731
- size += env -> me_maxdbs * sizeof (MDB_cursor * );
2732
- } else if (!(flags & MDB_RDONLY )) {
2729
+ size = env -> me_maxdbs * (sizeof (MDB_db )+ sizeof (MDB_cursor * )+1 );
2730
+ size += tsize = sizeof (MDB_ntxn );
2731
+ } else if (flags & MDB_RDONLY ) {
2732
+ size = env -> me_maxdbs * (sizeof (MDB_db )+ 1 );
2733
+ size += tsize = sizeof (MDB_txn );
2734
+ } else {
2733
2735
/* Reuse preallocated write txn. However, do not touch it until
2734
2736
* mdb_txn_renew0() succeeds, since it currently may be active.
2735
2737
*/
2736
2738
txn = env -> me_txn0 ;
2737
2739
goto renew ;
2738
2740
}
2739
- size += env -> me_maxdbs * (sizeof (MDB_db )+ 1 );
2740
-
2741
2741
if ((txn = calloc (1 , size )) == NULL ) {
2742
2742
DPRINTF (("calloc: %s" , strerror (errno )));
2743
2743
return ENOMEM ;
2744
2744
}
2745
2745
txn -> mt_dbs = (MDB_db * ) ((char * )txn + tsize );
2746
- if (flags & MDB_RDONLY ) {
2747
- txn -> mt_dbflags = (unsigned char * )(txn -> mt_dbs + env -> me_maxdbs );
2748
- txn -> mt_dbiseqs = env -> me_dbiseqs ;
2749
- } else {
2750
- txn -> mt_cursors = (MDB_cursor * * )(txn -> mt_dbs + env -> me_maxdbs );
2751
- if (parent ) {
2752
- txn -> mt_dbiseqs = parent -> mt_dbiseqs ;
2753
- txn -> mt_dbflags = (unsigned char * )(txn -> mt_cursors + env -> me_maxdbs );
2754
- } else {
2755
- txn -> mt_dbiseqs = (unsigned int * )(txn -> mt_cursors + env -> me_maxdbs );
2756
- txn -> mt_dbflags = (unsigned char * )(txn -> mt_dbiseqs + env -> me_maxdbs );
2757
- }
2758
- }
2746
+ txn -> mt_dbflags = (unsigned char * )txn + size - env -> me_maxdbs ;
2759
2747
txn -> mt_flags = flags ;
2760
2748
txn -> mt_env = env ;
2761
2749
2762
2750
if (parent ) {
2763
2751
unsigned int i ;
2752
+ txn -> mt_cursors = (MDB_cursor * * )(txn -> mt_dbs + env -> me_maxdbs );
2753
+ txn -> mt_dbiseqs = parent -> mt_dbiseqs ;
2764
2754
txn -> mt_u .dirty_list = malloc (sizeof (MDB_ID2 )* MDB_IDL_UM_SIZE );
2765
2755
if (!txn -> mt_u .dirty_list ||
2766
2756
!(txn -> mt_free_pgs = mdb_midl_alloc (MDB_IDL_UM_MAX )))
@@ -2797,15 +2787,16 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret)
2797
2787
rc = mdb_cursor_shadow (parent , txn );
2798
2788
if (rc )
2799
2789
mdb_txn_reset0 (txn , "beginchild-fail" );
2800
- } else {
2790
+ } else { /* MDB_RDONLY */
2791
+ txn -> mt_dbiseqs = env -> me_dbiseqs ;
2801
2792
renew :
2802
2793
rc = mdb_txn_renew0 (txn );
2803
2794
}
2804
2795
if (rc ) {
2805
2796
if (txn != env -> me_txn0 )
2806
2797
free (txn );
2807
2798
} else {
2808
- txn -> mt_flags |= flags ; /* for txn== me_txn0, no effect otherwise */
2799
+ txn -> mt_flags |= flags ; /* could not change txn=me_txn0 earlier */
2809
2800
* ret = txn ;
2810
2801
DPRINTF (("begin txn %" Z "u%c %p on mdbenv %p, root page %" Z "u" ,
2811
2802
txn -> mt_txnid , (flags & MDB_RDONLY ) ? 'r' : 'w' ,
0 commit comments