- A **database** is contained in a file, normally wrapped in directory for it's associated lock.
- Each database can contain multiple named **collections**.
- Each collection can contain any number of **keys**, and their associated **values**. A collection may optionally support multiple values per key (or duplicate keys, which is the same thing).
- A **cursor** lets you iterate a collection's keys and values in order.
(Note, this should be enumerable and built in to the Ruby interface)
- A **snapshot** is a self-consistent read-only view of the database. It stays the same even if some other thread or process makes changes. *The only way to access keys and values is within a snapshot*.
- A **transaction** is a writable snapshot. Changes made within a transaction are private until committed. *The only way to modify the database is within a transaction*.
Example Usage
----------------
### Create database handle
```ruby
db = MDBX::Database.create( "/path/to/file", options )
db = MDBX::Database.open( "/path/to/file", options )
# perhaps a block mode that yields the handle, closing on block exit?
MDBX::Database.open( 'database' ) do |db|
puts db[ 'key1' ]
end
```
### Access data
```ruby
db[ 'key1' ] #=> val
# In the backend, automatically creates the snapshot, retrieves the value, and removes the snapshot before returning.
# read-only block
db.snapshot do
db[ 'key1' ] #=> val
...
end
# This is much faster for retrieving many values
# Maybe have a snapshot object that acts like a DB while it exists?
snap = db.snapshot
snap[ 'whatever' ] #=> data
snap.close
```
### Write data
```ruby
db[ 'key1' ] = val
# In the backend, automatically creates a transaction, stores the value, and closes the transaction before returning.
# writable block
db.transaction do
db[ 'key1' ] = val
end
# Much faster for writing many values, should commit on success or abort on any exception
# Maybe have a transaction object that acts like a DB while it exists?
# ALL OTHER TRANSACTIONS will block until this is closed
txn = db.transaction
txn[ 'whatever' ] = data
txn.commit # or txn.abort
```
### Collections
Identical interface to top-level databases. Just have to pull the collection first.
```ruby
collection = db.collection( 'stuff' ) # raise if nonexistent
# This now works just like the main db object
collection.transaction.do
...
end
```
### Cleaning up
```ruby
db.close
```
### Stats!
TODO
-------
gem install mdbx -- --with-opt-dir=/usr/local
- [ ] Multiple value per key -- .insert, .delete? iterator for multi-val keys
- [ ] each_pair?
- [ ] document how serialization works
- [ ] document everything, really
- [x] transaction/snapshot blocks
- [ ] Arbitrary keys instead of forcing to strings?
- [ ] Disallow collection switching if there is an open transaction