The basis of RocksDB

RocksDB

Rocksdb is an embeddable persistent key-value store for fast storage.

Basic Operations and Examples

Opening & Closing

Writing & Reading

Definition

// Set the database entry for "key" to "value".
// If "key" already exists, it will be overwritten.
// Returns OK on success, and a non-OK status on error.
// Note: consider setting options.sync = true.
virtual Status Put(const WriteOptions& options, const Slice& key,
                   const Slice& value);
                     
// If the database contains an entry for "key" store the
// corresponding value in *value and return OK.
//
// If there is no entry for "key" leave *value unchanged and return
// a status for which Status::IsNotFound() returns true.
//
// May return some other Status on an error.
virtual Status Get(const ReadOptions& options, const Slice& key,
                   std::string* value) {

Example - Writing & Reading

// Put key-value
s = db->Put(WriteOptions(), "key1", "value");
assert(s.ok());
std::string value;
//
// Get value
s = db->Get(ReadOptions(), "key1", &value);
assert(s.ok());
assert(value == "value");
//
// Delete value
if (s.ok()) s = db->Delete(rocksdb::WriteOptions(), key1);
assert(s.ok());

Atomically writing

// Atomically apply a set of updates
{
  WriteBatch batch;
  batch.Delete("key1");
  batch.Put("key2", value);
  s = db->Write(WriteOptions(), &batch);
}

Slice (Efficient std::string)

Convert between std::string and rocksdb::Slice

// Convert slice to string
rocksdb::Slice s1 = "hello";
//
std::string str("world");
rocksdb::Slice s2 = str;
// Convert string to slice
std::string str = s1.ToString();
assert(str == std::string("hello"));
// Careful
// it is up to the caller to ensure that the external byte array into which the Slice points remains live while the Slice is in use. For example, the following is buggy
rocksdb::Slice slice;
if (...) {
  std::string str = ...;
  slice = str;
}
Use(slice);

PinnableSlice(The data pinned in memory)

Column Families

Definition

struct ColumnFamilyOptions;
struct ColumnFamilyDescriptor; // Option + name
class ColumnFamilyHandle;
// Create a column_family and return the handle of column family
// through the argument handle.
virtual Status CreateColumnFamily(const ColumnFamilyOptions& options,
                                    const std::string& column_family_name,
                                    ColumnFamilyHandle** handle);
//
// Bulk create column families.
// Return the handles of the column families through the argument handles.
// In case of error, the request may succeed partially, and handles will
// contain column family handles that it managed to create, and have size
// equal to the number of created column families.
virtual Status CreateColumnFamilies(
    const std::vector<ColumnFamilyDescriptor>& column_families,
    std::vector<ColumnFamilyHandle*>* handles);
//
// Bulk create column families with the same column family options.
// Return the handles of the column families through the argument handles.
// In case of error, the request may succeed partially, and handles will
// contain column family handles that it managed to create, and have size
// equal to the number of created column families.
virtual Status CreateColumnFamilies(
    const ColumnFamilyOptions& options,
    const std::vector<std::string>& column_family_names,
    std::vector<ColumnFamilyHandle*>* handles);

Example - Create ColumnFamilyhandle

// open DB
Options options;
options.create_if_missing = true;
DB* db;
Status s = DB::Open(options, kDBPath, &db);
assert(s.ok());

// create column family
ColumnFamilyHandle* cf;
s = db->CreateColumnFamily(ColumnFamilyOptions(), "new_cf", &cf);
assert(s.ok());

// close DB
delete cf;
delete db;

Example - Writing & Reading with ColumnFamily

// open DB with two column families
std::vector<ColumnFamilyDescriptor> column_families;
//
// have to open default column family
column_families.push_back(ColumnFamilyDescriptor(
    kDefaultColumnFamilyName, ColumnFamilyOptions()));
//
// open the new one, too
column_families.push_back(ColumnFamilyDescriptor(
    "new_cf", ColumnFamilyOptions()));
std::vector<ColumnFamilyHandle*> handles;
s = DB::Open(DBOptions(), kDBPath, column_families, &handles, &db);
assert(s.ok());
//
// put and get from non-default column family
s = db->Put(WriteOptions(), handles[1], Slice("key"), Slice("value"));
assert(s.ok());
std::string value;
s = db->Get(ReadOptions(), handles[1], Slice("key"), &value);
assert(s.ok());
//
// atomic write
WriteBatch batch;
batch.Put(handles[0], Slice("key2"), Slice("value2"));
batch.Put(handles[1], Slice("key3"), Slice("value3"));
batch.Delete(handles[0], Slice("key"));
s = db->Write(WriteOptions(), &batch);
assert(s.ok());
//
// drop column family
s = db->DropColumnFamily(handles[1]);
assert(s.ok());
//
// close db
for (auto handle : handles) {
  delete handle;
}
delete db;

References