https://bugs.openldap.org/show_bug.cgi?id=9397
--- Comment #4 from github@nicwatson.org github@nicwatson.org --- (In reply to Howard Chu from comment #3) ...
1st: "Don't do that." The docs for mdb_env_mapsize() make it clear that it's up to the caller to ensure that no other txns are active at the time it is called. We can first expand this statement in the docs and say that the caller is responsible to ensure that no other *users* are active - processes, threads, txns, whatever.
I have a finite view on the users of LMDB, but I know of 3 libraries built on LMDB this change in contract would impact. It is common (sense) to dynamically increase the map size when the map gets full. We would essentially be asking our downstreams to implement external file locking.
2nd: We can simply skip ftruncate on any requests to shrink the map. There is no pressing reason to perform the operation. Since we don't use fallocate, the excess size isn't actually consuming any disk space yet, so ftruncate doesn't save any disk space.
I was planning on passing the "excl" value from mdb_env_open2 to a new parameter to mdb_env_map, and only allow the filesize to decrease when excl is True (and the running process has an exclusive lock). This would preserve the existing behavior with a single process user.
The file size/ftruncate race still remains though. In fact, any two processes that call ftruncate on the same file will have this problem.
Now that I think about it, an fcntl exclusive lock on the first byte of the data file would work (just for the period between checking the file size and ftruncate), and it does somewhat capture the semantics of protecting the file.