ObjectiveRocks
An Objective-C wrapper for RocksDB - A Persistent Key-Value Store for Flash and RAM Storage.
Install / Use
/learn @iabudiab/ObjectiveRocksREADME
ObjectiveRocks
ObjectiveRocks is an Objective-C wrapper of Facebook's RocksDB - A Persistent Key-Value Store for Flash and RAM Storage.
<!-- [](https://cocoapods.org/pods/ObjectiveRocks) [](http://cocoadocs.org/docsets/ObjectiveRocks) [](http://cocoadocs.org/docsets/ObjectiveRocks) -->Current RocksDB Version: v6.2.4
- Quick Overview
- Installation
- Usage
- Open & Close a DB Instance
- Basic Operations
- Iteration
- Column Families
- Atomic Updates
- Snapshot
- Checkpoint
- Keys Comparator
- Merge Operator
- Env & Thread Status
- Backup & Restore
- Statistics
- Properties
- Configuration
Quick Overview
RocksDB is a key-value store, where the keys and values are arbitrarily-sized byte streams. The keys are ordered within the key value store according to a specified comparator function. RocksDB supports atomic reads and writes, snapshots, iteration and features many configuration options.
ObjectiveRocks provides an easy interface to RocksDB and an Objective-C friendly API that abstracts away the underlying C++ implementation, so you don't have to deal with it. While there is no need to learn the details about RocksDB to use this wrapper, a basic understanding of the internals is recommended and would explain the design decisions behind the, somewhat opinionated, API.
If you are interested in the internals of RocksDB, please refer to the RocksDB Wiki.
Swift
ObjectiveRocks has a pure Objective-C interface and can be used in Swift projects. Additionally, all ObjectiveRocks tests are also ported to Swift. You can check the Tests targets and source code which also contain bridging headers for OSX and iOS ObjectiveRocks implementations.
The Minimum You Need to Know
- Keys and values are byte arrays
- All data in the database is logically arranged in sorted order via a given
Comparator - RocksDB supports
Column Families- Column Families provide a way to logically partition the database, think collections in MongoDB
- Can be configured independently
- Can be added/dropped on the fly
- Key-value pairs are associated with exactly one
Column Familyin the database. - If no column family is specified, the
defaultcolumn family is used
- RocksDB provides three basic operations:
- Get(key)
- Put(key, value)
- Delete(key)
- Applications can define a merge operation via a
Merge Operator- A merge is an atomic Read-Modify-Write
- RocksDB features an
IteratorAPI to performRangeScanon the database - RocksDB provides a
SnapshotAPI allows an application to create a point-in-time view of a database - There are many configuration options:
- DBOptions: Controls the behavior of the database
- ColumnFamilyOptions: Controls the behavior of column families
- ReadOptions: apply to single read operations
- WriteOptions: apply to single write operations
RocksDB Lite
ObjectiveRocks incldues two targets, for iOS and macOS. The iOS target builds the RocksDB Lite version, which doesn't include the complete feature set.
These features are only available in macOS:
- Column Family Metadata
- Write Batch with Index
- Plain and Cuckoo Table Factories
- Vector, HashSkipList, HashLinkList and HashCuckoo Memtable Rep Factories
- Database Backups
- Database Statistics
- Database Properties
- Thread Status
Installation
Carthage
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
If you don't have Carthage yet, you can install it with Homebrew using the following command:
$ brew update
$ brew install carthage
To add ObjectiveRocks as a dependency into your project using Carthage just add the following line in your Cartfile:
github "iabudiab/ObjectiveRocks"
Then run the following command to build the framework and drag the built ObjectiveRocks.framework into your Xcode project.
$ carthage update
Manually
1- Add ObjectiveRocks as git submodule
$ git submodule add https://github.com/iabudiab/ObjectiveRocks.git
2- Open the ObjectiveRocks folder and drag'n'drop the ObjectiveRocks.xcodeproj into the Project Navigator in Xcode to add it as a sub-project.
3- In the General panel of your target add ObjectiveRocks.framework under the Embedded Binaries
Notice that ObjectiveRocks depends on RocksDB and includes it as a Git submodule.
Usage
The README will use the
NSStringnotation in place ofNSDatakeys and values for brevity!
Open & close a DB instance
To open a database you have to specify its location:
RocksDB *db = [RocksDB databaseAtPath:@"path/to/db"];
...
[db close];
RocksDB features many configuration settings, that can be specified when opening the database. ObjectiveRocks offers a blocks-based initializer for this purpose. The minimum configuration that you'll need is createIfMissing in order to create a new database if it doesn't already exist:
RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
options.createIfMissing = YES;
}];
The configuration guide, lists all currently available options along with their description.
A more production ready setup could look like this:
RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
options.createIfMissing = YES;
options.maxOpenFiles = 50000;
options.tableFacotry = [RocksDBTableFactory blockBasedTableFactoryWithOptions:^(RocksDBBlockBasedTableOptions *options) {
options.filterPolicy = [RocksDBFilterPolicy bloomFilterPolicyWithBitsPerKey:10];
options.blockCache = [RocksDBCache LRUCacheWithCapacity:1024 * 1024 * 1024];
options.blockSize = 64 * 1024;
}];
options.writeBufferSize = 64 * 1024 * 1024;
options.maxWriteBufferNumber = 7;
options.targetFileSizeBase = 64 * 1024 * 1024;
options.numLevels = 7;
options.maxLogFileSize = 50 * 1024 * 1024;
options.keepLogFileNum = 30;
}];
Basic Operations
The database provides three basic operations, Put, Get, and Delete to store/query data. Keys and values in RocksDB are arbitrary byte arrays:
RocksDB *db = [RocksDB databaseAtPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) {
options.createIfMissing = YES;
}];
NSData *data = [@"World" dataUsingEncoding:NSUTF8StringEncoding]
NSData *key = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding]
[db storeData:data forKey:key];
NSData *get = [db getDataForKey:key];
[db deleteDataForKey:key];
Read & Write Errors
Database operations can be passed a NSError reference to check for any errors that have occurred:
NSError *error = nil;
[db setObject:object forKey:key error:&error];
NSMutableDictionary *dictionary = [db dataForKey:@"Hello" error:&error];
[db deleteDataForKey:@"Hello" error:&error];
Read & Write Options
Each single read or write operation can be tuned via specific options:
[db setObject:anObject forKey:aKey writeOptions:^(RocksDBWriteOptions *writeOptions) {
writeOptions.syncWrites = YES;
writeOptions.disableWriteAheadLog = YES;
writeOptions.timeoutHint = 5;
writeOptions.ignoreMissingColumnFamilies = NO;
}];
[db dataForKey:aKey readOptions:^(RocksDBReadOptions *readOptions) {
readOptions.verifyChecksums = YES;
readOptions.fillCache = NO;
}];
Default options can also be set on a RocksDB or RocksDBColumnFamily instance:
[db setDefaultReadOptions:^(RocksDBReadOptions *readOptions) {
readOptions.fillCache = YES;
readOptions.verifyChecksums = YES;
} andWriteOptions:^(RocksDBWriteOptions *writeOptions) {
writeOptions.syncWrites = YES;
writeOptions.timeoutHint = 5;
}];
You can read about the read and write options in the configuration guide
Iteration
Iteration is provided via the RocksDBIterator class.
You can either iterate manually:
RocksDB *db = ...;
RocksDBColumnFamily *stuffColumnFamily = .../
RocksDBIterator *iterator = [db iterator];
RocksDBIterator *cfIterator = [stuffColumnFamily iterator];
// Alternatively, you can get an iterator with specific read options
iterator = [db iteratorWithReadOptions:^(RocksDBReadOptions *readOptions) {
// Read options here
}];
for ([iterator seekToKey:@"start"]; [iterator isValid]; [iterator next]) {
NSLog(@"%@: %@", [iterator key], [iterator value]);
// Iterates all keys starting from key "start"
}
or use one of the provided enumeration-blocks:
[db setData:@"Value 1" forKey:@"A"];
[db setData:@"Value 2" forKey:@"B"];
[db setData:@"Value 3" forKey:@"C"];
[db setData:@"Value 3" forKey:@"D"];
RocksDBIterator *iterator = [db iterator];
/* Keys Enumeration */
[db enumerateKeysUsingBlock:^(NSData *key, BOOL *stop) {
NSLog(@"%@", key);
// A, B, C, D
}];
// reverse
