diff --git a/libraries/liblmdb/mdb.c b/libraries/liblmdb/mdb.c index 2a7ca54d83..80336831e1 100644 --- a/libraries/liblmdb/mdb.c +++ b/libraries/liblmdb/mdb.c @@ -1941,7 +1941,7 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned int flags, MDB_txn **ret) unsigned int i; txn->mt_u.dirty_list = malloc(sizeof(MDB_ID2)*MDB_IDL_UM_SIZE); if (!txn->mt_u.dirty_list || - !(txn->mt_free_pgs = mdb_midl_alloc())) + !(txn->mt_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX))) { free(txn->mt_u.dirty_list); free(txn); @@ -3472,7 +3472,7 @@ mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode /* silently ignore WRITEMAP when we're only getting read access */ flags &= ~MDB_WRITEMAP; } else { - if (!((env->me_free_pgs = mdb_midl_alloc()) && + if (!((env->me_free_pgs = mdb_midl_alloc(MDB_IDL_UM_MAX)) && (env->me_dirty_list = calloc(MDB_IDL_UM_SIZE, sizeof(MDB_ID2))))) rc = ENOMEM; } diff --git a/libraries/liblmdb/midl.c b/libraries/liblmdb/midl.c index 8020edc0ae..42c809fd4d 100644 --- a/libraries/liblmdb/midl.c +++ b/libraries/liblmdb/midl.c @@ -117,16 +117,18 @@ int mdb_midl_insert( MDB_IDL ids, MDB_ID id ) } #endif -MDB_IDL mdb_midl_alloc(void) +MDB_IDL mdb_midl_alloc(int num) { - MDB_IDL ids = malloc((MDB_IDL_UM_MAX+1) * sizeof(MDB_ID)); - *ids++ = MDB_IDL_UM_MAX; + MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID)); + if (ids) + *ids++ = num; return ids; } void mdb_midl_free(MDB_IDL ids) { - free(ids-1); + if (ids) + free(ids-1); } int mdb_midl_shrink( MDB_IDL *idp ) @@ -141,19 +143,26 @@ int mdb_midl_shrink( MDB_IDL *idp ) return 0; } +int mdb_midl_grow( MDB_IDL *idp, int num ) +{ + MDB_IDL idn = *idp-1; + /* grow it */ + idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID)); + if (!idn) + return ENOMEM; + *idn++ += num; + *idp = idn; + return 0; +} + int mdb_midl_append( MDB_IDL *idp, MDB_ID id ) { MDB_IDL ids = *idp; /* Too big? */ if (ids[0] >= ids[-1]) { - MDB_IDL idn = ids-1; - /* grow it */ - idn = realloc(idn, (*idn + MDB_IDL_UM_MAX + 1) * sizeof(MDB_ID)); - if (!idn) - return -1; - *idn++ += MDB_IDL_UM_MAX; - ids = idn; - *idp = ids; + if (mdb_midl_grow(idp, MDB_IDL_UM_MAX)) + return ENOMEM; + ids = *idp; } ids[0]++; ids[ids[0]] = id; @@ -165,14 +174,9 @@ int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app ) MDB_IDL ids = *idp; /* Too big? */ if (ids[0] + app[0] >= ids[-1]) { - MDB_IDL idn = ids-1; - /* grow it */ - idn = realloc(idn, (*idn + app[-1]) * sizeof(MDB_ID)); - if (!idn) - return -1; - *idn++ += app[-1]; - ids = idn; - *idp = ids; + if (mdb_midl_grow(idp, app[0])) + return ENOMEM; + ids = *idp; } memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID)); ids[0] += app[0]; diff --git a/libraries/liblmdb/midl.h b/libraries/liblmdb/midl.h index a284223ab3..9319fb590b 100644 --- a/libraries/liblmdb/midl.h +++ b/libraries/liblmdb/midl.h @@ -115,10 +115,10 @@ int mdb_midl_insert( MDB_IDL ids, MDB_ID id ); #endif /** Allocate an IDL. - * Allocates memory for an IDL of a default size. + * Allocates memory for an IDL of the given size. * @return IDL on success, NULL on failure. */ -MDB_IDL mdb_midl_alloc(void); +MDB_IDL mdb_midl_alloc(int num); /** Free an IDL. * @param[in] ids The IDL to free. @@ -132,6 +132,14 @@ void mdb_midl_free(MDB_IDL ids); */ int mdb_midl_shrink(MDB_IDL *idp); + /** Grow an IDL. + * Add room for num additional elements. + * @param[in,out] idp Address of the IDL to grow. + * @param[i] num Number of elements to add. + * @return 0 on success, -1 on failure. + */ +int mdb_midl_grow(MDB_IDL *idp, int num); + /** Append an ID onto an IDL. * @param[in,out] idp Address of the IDL to append to. * @param[in] id The ID to append.