Current mdb.master can change MDB_meta.mm_mapsize when another process has the database open. That can break when one MDB_env grows the DB file beyond another MDB_env's me_mapsize.
Coexisting MDB_env's must use the same mapsize. Any mm_mapsize change must be written while mdb_env_open() has the exlusive lock.
For writing the mapsize:
- I presume the cleanest way wouldbe to write it to the not-current meta page. But mdb_page_alloc() and mdb_txn_commit()'s "Delete IDLs" loop look like they expect each recent txnid to have a freelist entry. Is that right? page_alloc uses MDB_SET, should maybe be MDB_SET_RANGE. I think older libmdb's seeing such a missing entry would grow the map instead of grabbing the next freelist entry.
- Or overwrite (current meta).mm_mapsize, but then I don't know what to do at a failed write. env_open cannot get around that by writing back an older txnid like mdb_env_write_meta() does. Maybe just try to write back the old mapsize before returning failure.
BTW, write_meta with WRITEMAP should undo the change if msync fails.
- Or do mdb_txn_begin(); mdb_txn_commit(); with the new mm_mapsize and a dummy freelist entry. Simple enough, if excessive.
As for determining the mapsize, I think it goes something like branch "mdb/mapsize" in http://folk.uio.no/hbf/OpenLDAP/openldap.git.