Tier 1 Escape Hatch
Tier 2 wraps the parts of RocksDB's C API that come up often, but it doesn't wrap everything – and it never will, on purpose (see the "escape hatch" note in Where to start). When you need something Tier 2 doesn't expose, drop down to RocksDB.LibRocksDB, Tier 1's near-direct, auto-generated ccall wrappers over the full C API.
Pattern: drop down from Tier 2 to Tier 1
Every Tier 2 struct that wraps a C pointer stores it in a .ptr field – db.ptr, options.ptr, env.ptr, and so on. That's the same pointer Tier 1's functions expect, so you can call them directly:
using RocksDB
db = RocksDB.opendb(mktempdir() * "/mydb")
put!(db, "a", "1")
# rocksdb.jl has no Checkpoint wrapper -- but the C API does. Call it
# directly on db.ptr:
errptr = Ref{Ptr{Cchar}}(C_NULL)
cp = RocksDB.LibRocksDB.rocksdb_checkpoint_object_create(db.ptr, errptr)
errptr[] != C_NULL && error(unsafe_string(errptr[]))
checkpoint_dir = mktempdir() * "/checkpoint"
errptr2 = Ref{Ptr{Cchar}}(C_NULL)
RocksDB.LibRocksDB.rocksdb_checkpoint_create(cp, checkpoint_dir, UInt64(0), errptr2)
errptr2[] != C_NULL && error(unsafe_string(errptr2[]))
RocksDB.LibRocksDB.rocksdb_checkpoint_object_destroy(cp) # your responsibility -- no finalizer down here
close(db)
# The checkpoint is a fully independent, openable database:
db2 = RocksDB.opendb(checkpoint_dir; create_if_missing = false)
String(get(db2, "a")) # "1"
close(db2)A checkpoint is a cheap, hard-linked (same-filesystem) point-in-time copy of a database – conceptually a lighter-weight cousin of the Backups this package does wrap in Tier 2, useful when you want a fast local snapshot on disk rather than a versioned, prunable backup archive.
What you give up
Tier 1 has none of Tier 2's conveniences:
No finalizers. Every
rocksdb_*_create/_openyou call has a matching_destroy/_closeyou must call yourself, in atry/finallyif there's any chance of an exception in between – as in the checkpoint example above.No exceptions. Every fallible Tier 1 function takes a
char **errptrout-parameter instead of throwing. You check it yourself:errptr = Ref{Ptr{Cchar}}(C_NULL) result = RocksDB.LibRocksDB.rocksdb_some_function(..., errptr) if errptr[] != C_NULL msg = unsafe_string(errptr[]) RocksDB.LibRocksDB.rocksdb_free(errptr[]) error(msg) # or throw(RocksDB.RocksDBException(msg)) to match Tier 2's own exception type endThis is exactly what Tier 2's internal
checkedhelper automates for every Tier 2 function – it isn't exported, but it's four lines you can replicate by hand, or call asRocksDB.checkedif you're comfortable reaching into an internal.No defaults. Tier 2's
Optionssets zstd compression, a bloom filter, a block cache, andcreate_if_missing=truefor you; Tier 1'srocksdb_options_create()starts from RocksDB's own bare defaults.
When this was exactly backups
Until BackupEngine was added to Tier 2, backups were the textbook case for this tutorial: the only way to call rocksdb_backup_engine_open_opts was through RocksDB.LibRocksDB directly on db.ptr, managing the backup engine options object, the errptr, and the close call all by hand. See the Backups tutorial for what moving that into Tier 2 bought: a BackupEngine struct with a finalizer, keyword arguments with sensible defaults, RocksDBException on failure, and a do-block form. That's the trade this tutorial is about – Tier 1 access whenever you need it, Tier 2 wrappers for whatever comes up often enough to be worth writing one.