basho/eleveldb — pull request #33 by jonmeredith (2012-07-18 03:53:57+00:00)
Title: Add eleveldb:close 

Added to fix the missing MANIFEST race around handoff / destroy / open.

This adds a mutex to the db_handle object to make sure it had not been closed from underneath any operations. All iterators created from the DB Ref are tracked and cleaned up when the database is closed. Any folds will throw exceptions if in progress and any other operation should return {error, einval} (modelled after the socket library).

As well as adding close, this also fixes a use-after-free bug to do with garbage collection. Although the NIF resources are released in the previous code, the order that the cleanup run is determined by the position in the heap by the garbage collector. The two examples show different ordering of cleanup.

```

11> spawn(fun() -> {ok, Db} = eleveldb:open("/tmp/t.db",[{create_if_missing, true}]), eleveldb:put(Db, <<"k">>,<<"v">>,[]), eleveldb:fold(Db, fun(_,_) -> lists:seq(1,10000) end, undefined, []) end).
**** db 0x7f8b220fda28 cleanup
**** iterator 0x1e261ae8 cleanup for db 0x7f8b220fda28
<0.54.0>
12> spawn(fun() -> {ok, Db} = eleveldb:open("/tmp/t.db",[{create_if_missing, true}]), eleveldb:put(Db, <<"k">>,<<"v">>,[]), eleveldb:fold(Db, fun(_,_) -> lists:seq(1,10000) end, undefined, []), garbage_collect() end).
**** iterator 0x7f8b220fca58 cleanup for db 0x7f8b220fc9c0
**** db 0x7f8b220fc9c0 cleanup
```

The code needs to be benchmarked before merging which we'll work on, but can be reviewed before then.