From 0a0c5efafb79d912ccacbe704c05778c6cad8e25 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 5 Jan 2015 15:55:07 +0100 Subject: [PATCH 01/22] Fix some typos and variables in Readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f11ef69..f0bce5d 100644 --- a/README.md +++ b/README.md @@ -597,16 +597,16 @@ Backups are incremental and only the new data will be copied to backup directory ```objecgtive-c RocksDB *db = ... -RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:_backupPath]; +RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:@"path/to/backup"]; [db setObject:@"Value 1" forKey:@"A"]; -[backupEngine createBackupForDatabase:_rocks error:nil]; +[backupEngine createBackupForDatabase:db error:nil]; [db setObject:@"Value 2" forKey:@"B"]; -[backupEngine createBackupForDatabase:_rocks error:nil]; +[backupEngine createBackupForDatabase:db error:nil]; [db setObject:@"Value 3" forKey:@"C"]; -[backupEngine createBackupForDatabase:_rocks error:nil]; +[backupEngine createBackupForDatabase:db error:nil]; // An array containing RocksDBBackupInfo objects NSArray *backupInfo = backupEngine.backupInfo; @@ -628,7 +628,7 @@ You can collect those statistics by creating and setting the `RocksDBStatistics` ```objective-c RocksDBStatistics *dbStatistics = [RocksDBStatistics new]; -RocksDB *db = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { +RocksDB *db = [[RocksDB alloc] initWithPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) { options.statistics = dbStatistics; }]; ... From 46e614fbbe4f411eec57e8193f4fa75b0d3cfd5b Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 5 Jan 2015 18:01:16 +0100 Subject: [PATCH 02/22] Add RocksDB Env wrapper with threading related options - Low & High priority pools thread count - Thread status - Background compactions and flushes optiopns --- ObjectiveRocks.xcodeproj/project.pbxproj | 26 +++++++ ObjectiveRocks/ObjectiveRocks.h | 3 + ObjectiveRocks/RocksDBDatabaseOptions.h | 5 +- ObjectiveRocks/RocksDBEnv.h | 22 ++++++ ObjectiveRocks/RocksDBEnv.mm | 94 ++++++++++++++++++++++++ ObjectiveRocks/RocksDBThreadStatus.h | 26 +++++++ ObjectiveRocks/RocksDBThreadStatus.mm | 13 ++++ 7 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 ObjectiveRocks/RocksDBEnv.h create mode 100644 ObjectiveRocks/RocksDBEnv.mm create mode 100644 ObjectiveRocks/RocksDBThreadStatus.h create mode 100644 ObjectiveRocks/RocksDBThreadStatus.mm diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index fe37822..bddeea8 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -18,6 +18,9 @@ 621CD71C1A4FB24700853E16 /* RocksDBBackupEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 621CD71B1A4FB24700853E16 /* RocksDBBackupEngine.mm */; }; 62269EDC1A1FF27A005A58D3 /* checkpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62269EDB1A1FF27A005A58D3 /* checkpoint.cc */; }; 62269EE01A1FF2DC005A58D3 /* leveldb_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62269EDF1A1FF2DC005A58D3 /* leveldb_options.cc */; }; + 6231475B1A5AE18A0019D14A /* RocksDBEnv.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6231475A1A5AE18A0019D14A /* RocksDBEnv.mm */; }; + 6231475C1A5AE18A0019D14A /* RocksDBEnv.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6231475A1A5AE18A0019D14A /* RocksDBEnv.mm */; }; + 6231475F1A5AE3E30019D14A /* RocksDBThreadStatus.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6231475E1A5AE3E30019D14A /* RocksDBThreadStatus.mm */; }; 623224AC1A2116A400FB6625 /* RocksDBComparator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 623224AB1A2116A400FB6625 /* RocksDBComparator.mm */; }; 6232B7351A1E80F900B14535 /* RocksDBWriteOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6232B7341A1E80F900B14535 /* RocksDBWriteOptions.mm */; }; 6232B7381A1E860700B14535 /* RocksDBReadOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6232B7371A1E860700B14535 /* RocksDBReadOptions.mm */; }; @@ -526,6 +529,11 @@ 62269EDB1A1FF27A005A58D3 /* checkpoint.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = checkpoint.cc; sourceTree = ""; }; 62269EDD1A1FF2B2005A58D3 /* leveldb_options.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = leveldb_options.h; sourceTree = ""; }; 62269EDF1A1FF2DC005A58D3 /* leveldb_options.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_options.cc; sourceTree = ""; }; + 623147591A5AE18A0019D14A /* RocksDBEnv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBEnv.h; sourceTree = ""; }; + 6231475A1A5AE18A0019D14A /* RocksDBEnv.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBEnv.mm; sourceTree = ""; }; + 6231475D1A5AE3E30019D14A /* RocksDBThreadStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBThreadStatus.h; sourceTree = ""; }; + 6231475E1A5AE3E30019D14A /* RocksDBThreadStatus.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBThreadStatus.mm; sourceTree = ""; }; + 623147601A5AF1190019D14A /* thread_status.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_status.h; sourceTree = ""; }; 623224AA1A2116A400FB6625 /* RocksDBComparator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBComparator.h; sourceTree = ""; }; 623224AB1A2116A400FB6625 /* RocksDBComparator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBComparator.mm; sourceTree = ""; }; 6232B7331A1E80F900B14535 /* RocksDBWriteOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBWriteOptions.h; sourceTree = ""; }; @@ -1158,12 +1166,24 @@ 6232B7341A1E80F900B14535 /* RocksDBWriteOptions.mm */, 6232B7361A1E860700B14535 /* RocksDBReadOptions.h */, 6232B7371A1E860700B14535 /* RocksDBReadOptions.mm */, + 623147581A5AE1720019D14A /* Env */, 62F3ED521A57176200EBFEBF /* Table */, 625F8F261A59D78E007796BA /* Mem Table */, ); name = Options; sourceTree = ""; }; + 623147581A5AE1720019D14A /* Env */ = { + isa = PBXGroup; + children = ( + 623147591A5AE18A0019D14A /* RocksDBEnv.h */, + 6231475A1A5AE18A0019D14A /* RocksDBEnv.mm */, + 6231475D1A5AE3E30019D14A /* RocksDBThreadStatus.h */, + 6231475E1A5AE3E30019D14A /* RocksDBThreadStatus.mm */, + ); + name = Env; + sourceTree = ""; + }; 62376BBC1A20EA4B00C85DFB /* Internal */ = { isa = PBXGroup; children = ( @@ -1551,6 +1571,7 @@ 62EE29CA1A1ABA1F00486C31 /* status.h */, 62EE29CB1A1ABA1F00486C31 /* table.h */, 62EE29CC1A1ABA1F00486C31 /* table_properties.h */, + 623147601A5AF1190019D14A /* thread_status.h */, 62EE29CD1A1ABA1F00486C31 /* transaction_log.h */, 62EE29CE1A1ABA1F00486C31 /* types.h */, 62EE29CF1A1ABA1F00486C31 /* universal_compaction.h */, @@ -2269,6 +2290,7 @@ 62EE2D7E1A1ABA2100486C31 /* document_db.cc in Sources */, 62EEC4BA1A34FF0600624DA2 /* RocksDBCallbackAssociativeMergeOperator.cpp in Sources */, 62EE2C261A1ABA2000486C31 /* transaction_log_impl.cc in Sources */, + 6231475B1A5AE18A0019D14A /* RocksDBEnv.mm in Sources */, 62EE2D0A1A1ABA2000486C31 /* arena.cc in Sources */, 620629661A510056001DEDC4 /* RocksDBDatabaseOptions.mm in Sources */, 62EE2C341A1ABA2000486C31 /* write_batch.cc in Sources */, @@ -2276,6 +2298,7 @@ 62376BBF1A20EDF000C85DFB /* RocksDBCallbackComparator.cpp in Sources */, 62EE2CE61A1ABA2000486C31 /* full_filter_block.cc in Sources */, 62EE2D6A1A1ABA2100486C31 /* status.cc in Sources */, + 6231475F1A5AE3E30019D14A /* RocksDBThreadStatus.mm in Sources */, 62EE2BDA1A1ABA2000486C31 /* c.cc in Sources */, 62EE2D551A1ABA2100486C31 /* options.cc in Sources */, 62EE2BE01A1ABA2000486C31 /* compaction.cc in Sources */, @@ -2490,6 +2513,7 @@ 62A8B0061A58C30E0069B4C8 /* options_helper.cc in Sources */, 62A8B0071A58C30E0069B4C8 /* hash_cuckoo_rep.cc in Sources */, 62A8B0081A58C30E0069B4C8 /* sst_dump_tool.cc in Sources */, + 6231475C1A5AE18A0019D14A /* RocksDBEnv.mm in Sources */, 62A8B0091A58C30E0069B4C8 /* block_hash_index.cc in Sources */, 62A8B00A1A58C30E0069B4C8 /* block_based_table_factory.cc in Sources */, 62A8B00B1A58C30E0069B4C8 /* log_writer.cc in Sources */, @@ -2654,6 +2678,7 @@ "DEBUG=1", "OS_MACOSX=1", "ROCKSDB_PLATFORM_POSIX=1", + "ROCKSDB_USING_THREAD_STATUS=1", ); HEADER_SEARCH_PATHS = ( "$(inherited)", @@ -2681,6 +2706,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "OS_MACOSX=1", "ROCKSDB_PLATFORM_POSIX=1", + "ROCKSDB_USING_THREAD_STATUS=1", ); HEADER_SEARCH_PATHS = ( "$(inherited)", diff --git a/ObjectiveRocks/ObjectiveRocks.h b/ObjectiveRocks/ObjectiveRocks.h index a596b71..7fcde35 100644 --- a/ObjectiveRocks/ObjectiveRocks.h +++ b/ObjectiveRocks/ObjectiveRocks.h @@ -29,6 +29,7 @@ #import "RocksDBCache.h" #import "RocksDBFilterPolicy.h" #import "RocksDBMemTableRepFactory.h" +#import "RocksDBEnv.h" #import "RocksDBSnapshot.h" @@ -42,6 +43,8 @@ #import "RocksDBPlainTableOptions.h" #import "RocksDBCuckooTableOptions.h" +#import "RocksDBThreadStatus.h" + #import "RocksDBCheckpoint.h" #import "RocksDBStatistics.h" diff --git a/ObjectiveRocks/RocksDBDatabaseOptions.h b/ObjectiveRocks/RocksDBDatabaseOptions.h index 6626090..ac34f4d 100644 --- a/ObjectiveRocks/RocksDBDatabaseOptions.h +++ b/ObjectiveRocks/RocksDBDatabaseOptions.h @@ -7,7 +7,7 @@ // #import - +#import "RocksDBEnv.h" #import "RocksDBStatistics.h" typedef NS_ENUM(unsigned char, RocksDBLogLevel) @@ -25,12 +25,15 @@ typedef NS_ENUM(unsigned char, RocksDBLogLevel) @property (nonatomic, assign) BOOL createMissingColumnFamilies; @property (nonatomic, assign) BOOL errorIfExists; @property (nonatomic, assign) BOOL paranoidChecks; +@property (nonatomic, strong) RocksDBEnv *env; @property (nonatomic, assign) RocksDBLogLevel infoLogLevel; @property (nonatomic, assign) int maxOpenFiles; @property (nonatomic, assign) uint64_t maxWriteAheadLogSize; @property (nonatomic, strong) RocksDBStatistics *statistics; @property (nonatomic, assign) BOOL disableDataSync; @property (nonatomic, assign) BOOL useFSync; +@property (nonatomic, assign) int maxBackgroundCompactions; +@property (nonatomic, assign) int maxBackgroundFlushes; @property (nonatomic, assign) size_t maxLogFileSize; @property (nonatomic, assign) size_t logFileTimeToRoll; @property (nonatomic, assign) size_t keepLogFileNum; diff --git a/ObjectiveRocks/RocksDBEnv.h b/ObjectiveRocks/RocksDBEnv.h new file mode 100644 index 0000000..13776ca --- /dev/null +++ b/ObjectiveRocks/RocksDBEnv.h @@ -0,0 +1,22 @@ +// +// RocksDBEnv.h +// ObjectiveRocks +// +// Created by Iska on 05/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import + +@interface RocksDBEnv : NSObject + ++ (instancetype)envWithLowPriorityThreadCount:(int)lowPrio andHighPriorityThreadCount:(int)highPrio; + +- (void)setHighPriorityPoolThreadsCount:(int)numThreads; +- (void)setLowPriorityPoolThreadsCount:(int)numThreads; + +#if ROCKSDB_USING_THREAD_STATUS +- (NSArray *)threadList; +#endif + +@end diff --git a/ObjectiveRocks/RocksDBEnv.mm b/ObjectiveRocks/RocksDBEnv.mm new file mode 100644 index 0000000..47a92b9 --- /dev/null +++ b/ObjectiveRocks/RocksDBEnv.mm @@ -0,0 +1,94 @@ +// +// RocksDBEnv.m +// ObjectiveRocks +// +// Created by Iska on 05/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBEnv.h" + +#if ROCKSDB_USING_THREAD_STATUS +#import "RocksDBThreadStatus.h" +#endif + +#import +#import + +@interface RocksDBEnv () +{ + rocksdb::Env *_env; +} +@property (nonatomic, assign) rocksdb::Env *env; +@end + +@implementation RocksDBEnv +@synthesize env = _env; + +#pragma mark - Lifecycle + ++ (instancetype)envWithLowPriorityThreadCount:(int)lowPrio andHighPriorityThreadCount:(int)highPrio +{ + RocksDBEnv *instance = [RocksDBEnv new]; + [instance setLowPriorityPoolThreadsCount:lowPrio]; + [instance setHighPriorityPoolThreadsCount:highPrio]; + return instance; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _env = rocksdb::Env::Default(); + } + return self; +} + +- (void)dealloc +{ + @synchronized(self) { + if (_env != nullptr) { + delete _env; + _env = nullptr; + } + } +} + +#pragma mark - Threads + +- (void)setHighPriorityPoolThreadsCount:(int)numThreads +{ + if (numThreads <= 0) numThreads = 1; + _env->SetBackgroundThreads(numThreads, rocksdb::Env::HIGH); +} + +- (void)setLowPriorityPoolThreadsCount:(int)numThreads +{ + if (numThreads <= 0) numThreads = 1; + _env->SetBackgroundThreads(numThreads, rocksdb::Env::LOW); +} + +#if ROCKSDB_USING_THREAD_STATUS + +- (NSArray *)threadList +{ + std::vector thread_list; + _env->GetThreadList(&thread_list); + + NSMutableArray *threadList = [NSMutableArray array]; + for (auto it = std::begin(thread_list); it != std::end(thread_list); ++it) { + RocksDBThreadStatus *thread = [RocksDBThreadStatus new]; + thread.threadId = (*it).thread_id; + thread.threadType = (RocksDBThreadType)(*it).thread_type; + thread.databaseName = [NSString stringWithCString:(*it).db_name.c_str() encoding:NSUTF8StringEncoding]; + thread.columnFamilyname = [NSString stringWithCString:(*it).cf_name.c_str() encoding:NSUTF8StringEncoding]; + thread.event = [NSString stringWithCString:(*it).event.c_str() encoding:NSUTF8StringEncoding]; + [threadList addObject:thread]; + } + + return threadList; +} + +#endif + +@end diff --git a/ObjectiveRocks/RocksDBThreadStatus.h b/ObjectiveRocks/RocksDBThreadStatus.h new file mode 100644 index 0000000..cb97780 --- /dev/null +++ b/ObjectiveRocks/RocksDBThreadStatus.h @@ -0,0 +1,26 @@ +// +// RocksDBThreadStatus.h +// ObjectiveRocks +// +// Created by Iska on 05/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import + +typedef NS_ENUM(NSUInteger, RocksDBThreadType) +{ + RocksDBThreadHighPiority = 0x0, + RocksDBThreadLowPiority = 0x1, + RocksDBThreadUser = 0x2, +}; + +@interface RocksDBThreadStatus : NSObject + +@property (nonatomic, assign) uint64_t threadId; +@property (nonatomic, assign) RocksDBThreadType threadType; +@property (nonatomic, strong) NSString *databaseName; +@property (nonatomic, strong) NSString *columnFamilyname; +@property (nonatomic, strong) NSString *event; + +@end diff --git a/ObjectiveRocks/RocksDBThreadStatus.mm b/ObjectiveRocks/RocksDBThreadStatus.mm new file mode 100644 index 0000000..b8c9b4d --- /dev/null +++ b/ObjectiveRocks/RocksDBThreadStatus.mm @@ -0,0 +1,13 @@ +// +// RocksDBThreadStatus.m +// ObjectiveRocks +// +// Created by Iska on 05/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBThreadStatus.h" + +@implementation RocksDBThreadStatus + +@end From 95bcf48aa72a564844438d5310f7dbcba57812e3 Mon Sep 17 00:00:00 2001 From: iska Date: Mon, 5 Jan 2015 18:03:51 +0100 Subject: [PATCH 03/22] Fix backup info method local variable Instead of allocating the vector in the heap and then deleting it, just use a local stack one. --- ObjectiveRocks/RocksDBBackupEngine.mm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/ObjectiveRocks/RocksDBBackupEngine.mm b/ObjectiveRocks/RocksDBBackupEngine.mm index 8b996f7..7a7154d 100644 --- a/ObjectiveRocks/RocksDBBackupEngine.mm +++ b/ObjectiveRocks/RocksDBBackupEngine.mm @@ -128,11 +128,11 @@ - (BOOL)deleteBackupWithId:(uint32_t)backupId error:(NSError *__autoreleasing *) - (NSArray *)backupInfo { - std::vector *backup_info = new std::vector; - _backupEngine->GetBackupInfo(backup_info); + std::vector backup_info; + _backupEngine->GetBackupInfo(&backup_info); NSMutableArray *backupInfo = [NSMutableArray array]; - for (auto it = std::begin(*backup_info); it != std::end(*backup_info); ++it) { + for (auto it = std::begin(backup_info); it != std::end(backup_info); ++it) { RocksDBBackupInfo *info = [RocksDBBackupInfo new]; info.backupId = (*it).backup_id; info.timestamp = (*it).timestamp; @@ -141,9 +141,6 @@ - (NSArray *)backupInfo [backupInfo addObject:info]; } - backup_info->clear(); - delete backup_info; - return backupInfo; } From bd3727767fb0cefa87ee611ce6ec07c6098f46fa Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 8 Jan 2015 19:57:31 +0100 Subject: [PATCH 04/22] Fix method name typo in Filter Policy class --- ObjectiveRocks/RocksDBFilterPolicy.h | 2 +- ObjectiveRocks/RocksDBFilterPolicy.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ObjectiveRocks/RocksDBFilterPolicy.h b/ObjectiveRocks/RocksDBFilterPolicy.h index 5329d84..cc8efbc 100644 --- a/ObjectiveRocks/RocksDBFilterPolicy.h +++ b/ObjectiveRocks/RocksDBFilterPolicy.h @@ -11,6 +11,6 @@ @interface RocksDBFilterPolicy : NSObject + (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey; -+ (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey useBlockBasedBuilde:(BOOL)useBlockBasedBuilder; ++ (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey useBlockBasedBuilder:(BOOL)useBlockBasedBuilder; @end diff --git a/ObjectiveRocks/RocksDBFilterPolicy.mm b/ObjectiveRocks/RocksDBFilterPolicy.mm index 6bb5682..296cbc7 100644 --- a/ObjectiveRocks/RocksDBFilterPolicy.mm +++ b/ObjectiveRocks/RocksDBFilterPolicy.mm @@ -25,7 +25,7 @@ + (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey return [[RocksDBFilterPolicy alloc] initWithNativeFilterPolicy:rocksdb::NewBloomFilterPolicy(bitsPerKey)]; } -+ (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey useBlockBasedBuilde:(BOOL)useBlockBasedBuilder ++ (instancetype)bloomFilterPolicyWithBitsPerKey:(int)bitsPerKey useBlockBasedBuilder:(BOOL)useBlockBasedBuilder { return [[RocksDBFilterPolicy alloc] initWithNativeFilterPolicy:rocksdb::NewBloomFilterPolicy(bitsPerKey, useBlockBasedBuilder)]; } From 195a1bca2993dc32f6f4e7e4bbb88f4370ff7fe2 Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 8 Jan 2015 19:57:54 +0100 Subject: [PATCH 05/22] Add dealloc to Prefix Extractor to delete Slice Transform --- ObjectiveRocks/RocksDBPrefixExtractor.mm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ObjectiveRocks/RocksDBPrefixExtractor.mm b/ObjectiveRocks/RocksDBPrefixExtractor.mm index f363d94..ce1529d 100644 --- a/ObjectiveRocks/RocksDBPrefixExtractor.mm +++ b/ObjectiveRocks/RocksDBPrefixExtractor.mm @@ -34,6 +34,8 @@ @implementation RocksDBPrefixExtractor @synthesize name = _name; @synthesize sliceTransform = _sliceTransform; +#pragma mark - Lifecycle + + (instancetype)prefixExtractorWithType:(RocksDBPrefixType)type length:(size_t)length { switch (type) { @@ -69,6 +71,18 @@ - (instancetype)initWithName:(NSString *)name return self; } +- (void)dealloc +{ + @synchronized(self) { + if (_sliceTransform != nullptr) { + delete _sliceTransform; + _sliceTransform = nullptr; + } + } +} + +#pragma mark - Callbacks + rocksdb::Slice trampolineTransform(void* instance, const rocksdb::Slice& src) { NSData *data = [(__bridge id)instance transformKey:src]; From 171dd76b7892a434aed513d7f4dbf25451ce93e0 Mon Sep 17 00:00:00 2001 From: iska Date: Thu, 8 Jan 2015 19:58:33 +0100 Subject: [PATCH 06/22] Add Iterator methods for key-value enumeration --- ObjectiveRocks/RocksDBIterator.h | 4 + ObjectiveRocks/RocksDBIterator.mm | 33 +++- ObjectiveRocksTests/RocksDBIteratorTests.mm | 182 +++++++++++++++++++- 3 files changed, 210 insertions(+), 9 deletions(-) diff --git a/ObjectiveRocks/RocksDBIterator.h b/ObjectiveRocks/RocksDBIterator.h index 02c98af..cdd1b1a 100644 --- a/ObjectiveRocks/RocksDBIterator.h +++ b/ObjectiveRocks/RocksDBIterator.h @@ -46,6 +46,10 @@ namespace rocksdb { - (void)enumerateKeysInReverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block; - (void)enumerateKeysInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block; +- (void)enumerateKeysAndValuesUsingBlock:(void (^)(id key, id value, BOOL *stop))block; +- (void)enumerateKeysAndValuesInReverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; +- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; + - (void)enumerateKeysWithPrefix:(id)prefix usingBlock:(void (^)(id key, BOOL *stop))block; @end diff --git a/ObjectiveRocks/RocksDBIterator.mm b/ObjectiveRocks/RocksDBIterator.mm index 6994ce4..e0ed0c2 100644 --- a/ObjectiveRocks/RocksDBIterator.mm +++ b/ObjectiveRocks/RocksDBIterator.mm @@ -11,6 +11,8 @@ #import +static RocksDBIteratorKeyRange RocksDBEmptyRange = RocksDBMakeKeyRange(nil, nil); + @interface RocksDBIterator () { rocksdb::Iterator *_iterator; @@ -96,19 +98,42 @@ - (id)value return value; } -#pragma mark - Enumeration +#pragma mark - Enumerate Keys - (void)enumerateKeysUsingBlock:(void (^)(id key, BOOL *stop))block { - [self enumerateKeysInReverse:NO usingBlock:block]; + [self enumerateKeysAndValuesInRange:RocksDBEmptyRange reverse:NO usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; } - (void)enumerateKeysInReverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block { - [self enumerateKeysInRange:RocksDBMakeKeyRange(nil, nil) reverse:reverse usingBlock:block]; + [self enumerateKeysAndValuesInRange:RocksDBEmptyRange reverse:reverse usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; } - (void)enumerateKeysInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block +{ + [self enumerateKeysAndValuesInRange:range reverse:reverse usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; +} + +#pragma mark - Enumerate Keys & Values + +- (void)enumerateKeysAndValuesUsingBlock:(void (^)(id key, id value, BOOL *stop))block +{ + [self enumerateKeysAndValuesInRange:RocksDBEmptyRange reverse:NO usingBlock:block]; +} + +- (void)enumerateKeysAndValuesInReverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block +{ + [self enumerateKeysAndValuesInRange:RocksDBEmptyRange reverse:reverse usingBlock:block]; +} + +- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block { BOOL stop = NO; @@ -136,7 +161,7 @@ - (void)enumerateKeysInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)revers while (_iterator->Valid() && checkLimit(reverse, keySlice)) { keySlice = _iterator->key(); - if (block) block(self.key, &stop); + if (block) block(self.key, self.value, &stop); if (stop == YES) break; reverse ? _iterator->Prev(): _iterator->Next(); diff --git a/ObjectiveRocksTests/RocksDBIteratorTests.mm b/ObjectiveRocksTests/RocksDBIteratorTests.mm index 2cf088e..34843a7 100644 --- a/ObjectiveRocksTests/RocksDBIteratorTests.mm +++ b/ObjectiveRocksTests/RocksDBIteratorTests.mm @@ -80,7 +80,29 @@ - (void)testDB_Iterator_Seek [iterator close]; } -- (void)testDB_Iterator_Reverse +- (void)testDB_Iterator_EnumerateKeys +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysUsingBlock:^(id key, BOOL *stop) { + [actual addObject:Str(key)]; + }]; + + NSArray *expected = @[ @"key 1", @"key 2", @"key 3" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeys_Reverse { _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { options.createIfMissing = YES; @@ -102,7 +124,7 @@ - (void)testDB_Iterator_Reverse [iterator close]; } -- (void)testDB_Iterator_RangeStart +- (void)testDB_Iterator_EnumerateKeys_RangeStart { _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { options.createIfMissing = YES; @@ -125,7 +147,7 @@ - (void)testDB_Iterator_RangeStart [iterator close]; } -- (void)testDB_Iterator_RangeEnd +- (void)testDB_Iterator_EnumerateKeys_RangeEnd { _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { options.createIfMissing = YES; @@ -148,7 +170,7 @@ - (void)testDB_Iterator_RangeEnd [iterator close]; } -- (void)testDB_Iterator_RangeStartEnd +- (void)testDB_Iterator_EnumerateKeys_RangeStartEnd { _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { options.createIfMissing = YES; @@ -171,7 +193,7 @@ - (void)testDB_Iterator_RangeStartEnd [iterator close]; } -- (void)testDB_Iterator_Encoded +- (void)testDB_Iterator_EnumerateKeys_Encoded { _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { options.createIfMissing = YES; @@ -195,4 +217,154 @@ - (void)testDB_Iterator_Encoded [iterator close]; } +- (void)testDB_Iterator_EnumerateKeysAndValues +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesUsingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:Str(key)]; + [actual addObject:Str(value)]; + }]; + + NSArray *expected = @[ @"key 1", @"value 1", @"key 2", @"value 2", @"key 3", @"value 3" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeysAndValues_Reverse +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesInReverse:YES usingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:Str(key)]; + [actual addObject:Str(value)]; + }]; + + NSArray *expected = @[ @"key 3", @"value 3", @"key 2", @"value 2", @"key 1", @"value 1" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeysAndValues_RangeStart +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + [_rocks setData:Data(@"value 4") forKey:Data(@"key 4")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesInRange:RocksDBMakeKeyRange(Data(@"key 2"), nil) + reverse:NO + usingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:Str(key)]; + [actual addObject:Str(value)]; + }]; + + NSArray *expected = @[ @"key 2", @"value 2", @"key 3", @"value 3", @"key 4", @"value 4" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeysAndValues_RangeEnd +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + [_rocks setData:Data(@"value 4") forKey:Data(@"key 4")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesInRange:RocksDBMakeKeyRange(nil, Data(@"key 4")) + reverse:NO + usingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:Str(key)]; + [actual addObject:Str(value)]; + }]; + + NSArray *expected = @[ @"key 1", @"value 1", @"key 2", @"value 2", @"key 3", @"value 3" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeysAndValues_RangeStartEnd +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + }]; + + [_rocks setData:Data(@"value 1") forKey:Data(@"key 1")]; + [_rocks setData:Data(@"value 2") forKey:Data(@"key 2")]; + [_rocks setData:Data(@"value 3") forKey:Data(@"key 3")]; + [_rocks setData:Data(@"value 4") forKey:Data(@"key 4")]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesInRange:RocksDBMakeKeyRange(Data(@"key 2"), Data(@"key 4")) + reverse:NO + usingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:Str(key)]; + [actual addObject:Str(value)]; + }]; + + + NSArray *expected = @[ @"key 2", @"value 2", @"key 3", @"value 3" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + +- (void)testDB_Iterator_EnumerateKeysAndValues_Encoded +{ + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + options.keyType = RocksDBTypeNSString; + options.valueType = RocksDBTypeNSString; + }]; + + [_rocks setObject:@"value 1" forKey:@"Key 1"]; + [_rocks setObject:@"value 2" forKey:@"Key 2"]; + [_rocks setObject:@"value 3" forKey:@"Key 3"]; + + NSMutableArray *actual = [NSMutableArray array]; + RocksDBIterator *iterator = [_rocks iterator]; + [iterator enumerateKeysAndValuesUsingBlock:^(id key, id value, BOOL *stop) { + [actual addObject:key]; + [actual addObject:value]; + }]; + + NSArray *expected = @[ @"Key 1", @"value 1", @"Key 2", @"value 2", @"Key 3", @"value 3" ]; + XCTAssertEqualObjects(actual, expected); + + [iterator close]; +} + @end From beef4f4468372fbdb3c77154d77127a401d68378 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 9 Jan 2015 17:10:14 +0100 Subject: [PATCH 07/22] Add Iterator methods for key-value enumeration with a given prefix When a prefix extractor is defined, an iterator seeks inside the given prefix. RocksDBPrefixExtractor provides a built-in fixed length prefix extractor and a block-based variant to provide own implementation. --- ObjectiveRocks/RocksDBIterator.h | 1 + ObjectiveRocks/RocksDBIterator.mm | 32 ++++----- .../RocksDBPrefixExtractorTests.mm | 67 ++++++++++++++++++- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/ObjectiveRocks/RocksDBIterator.h b/ObjectiveRocks/RocksDBIterator.h index cdd1b1a..9ed7103 100644 --- a/ObjectiveRocks/RocksDBIterator.h +++ b/ObjectiveRocks/RocksDBIterator.h @@ -51,5 +51,6 @@ namespace rocksdb { - (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; - (void)enumerateKeysWithPrefix:(id)prefix usingBlock:(void (^)(id key, BOOL *stop))block; +- (void)enumerateKeysAndValuesWithPrefix:(id)prefix usingBlock:(void (^)(id key, id value, BOOL *stop))block; @end diff --git a/ObjectiveRocks/RocksDBIterator.mm b/ObjectiveRocks/RocksDBIterator.mm index e0ed0c2..32b776f 100644 --- a/ObjectiveRocks/RocksDBIterator.mm +++ b/ObjectiveRocks/RocksDBIterator.mm @@ -148,7 +148,7 @@ - (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BO limitSlice = SliceFromKey(range.end, _options, nil); } - BOOL (^ checkLimit)(BOOL reverse, rocksdb::Slice key) = ^ BOOL (BOOL reverse, rocksdb::Slice key) { + BOOL (^ checkLimit)(BOOL, rocksdb::Slice) = ^ BOOL (BOOL reverse, rocksdb::Slice key) { if (limitSlice.size() == 0) return YES; if (reverse && key.ToString() <= limitSlice.ToString()) return NO; @@ -157,10 +157,7 @@ - (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BO return YES; }; - rocksdb::Slice keySlice; - while (_iterator->Valid() && checkLimit(reverse, keySlice)) { - keySlice = _iterator->key(); - + while (_iterator->Valid() && checkLimit(reverse, _iterator->key())) { if (block) block(self.key, self.value, &stop); if (stop == YES) break; @@ -168,26 +165,25 @@ - (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BO } } +#pragma mark - Enumerate Prefix + - (void)enumerateKeysWithPrefix:(id)prefix usingBlock:(void (^)(id key, BOOL *stop))block +{ + [self enumerateKeysAndValuesWithPrefix:prefix usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; +} + +- (void)enumerateKeysAndValuesWithPrefix:(id)prefix usingBlock:(void (^)(id key, id value, BOOL *stop))block { BOOL stop = NO; rocksdb::Slice prefixSlice = SliceFromKey(prefix, _options, nil); - _iterator->Seek(prefixSlice); - BOOL (^ checkBounds)(rocksdb::Slice key) = ^ BOOL (rocksdb::Slice key) { - return key.starts_with(prefixSlice); - }; - - rocksdb::Slice keySlice = _iterator->key(); - - while (_iterator->Valid() && checkBounds(keySlice)) { - keySlice = _iterator->key(); - - if (block) block(self.key, &stop); + for (_iterator->Seek(prefixSlice); _iterator->Valid(); _iterator->Next()) { + if (_iterator->key().starts_with(prefixSlice) == false) continue; + if (block) block(self.key, self.value, &stop); if (stop == YES) break; - - _iterator->Next(); } } diff --git a/ObjectiveRocksTests/RocksDBPrefixExtractorTests.mm b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.mm index c8d1e01..6ace030 100644 --- a/ObjectiveRocksTests/RocksDBPrefixExtractorTests.mm +++ b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.mm @@ -55,7 +55,7 @@ - (void)testPrefixExtractor_FixedLength expected = @[@"101A", @"101B"]; XCTAssertEqualObjects(keys, expected); - [iterator seekToKey:@"100XYZ"]; + [iterator seekToKey:@"1000"]; XCTAssertTrue(iterator.isValid); XCTAssertEqualObjects(iterator.key, @"100A"); @@ -66,4 +66,69 @@ - (void)testPrefixExtractor_FixedLength XCTAssertEqualObjects(iterator.key, @"100B"); } +- (void)testPrefixExtractor_FixedLength_CustomComparator +{ + // 1001 < 9910 < 2011 < 3412 ... + RocksDBComparator *cmp = [[RocksDBComparator alloc] initWithName:@"cmp" andBlock:^int(id key1, id key2) { + return [[key1 substringFromIndex:2] compare:[key2 substringFromIndex:2]]; + }]; + + _rocks = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + options.comparator = cmp; + options.prefixExtractor = [RocksDBPrefixExtractor prefixExtractorWithType:RocksDBPrefixFixedLength length:2]; + + options.memtablePrefixBloomBits = 100000000; + options.memtablePrefixBloomProbes = 6; + + options.tableFacotry = [RocksDBTableFactory blockBasedTableFactoryWithOptions:^(RocksDBBlockBasedTableOptions *options) { + options.filterPolicy = [RocksDBFilterPolicy bloomFilterPolicyWithBitsPerKey:10 useBlockBasedBuilder:YES]; + }]; + + options.keyType = RocksDBTypeNSString; + options.valueType = RocksDBTypeNSString; + }]; + + [_rocks setObject:@"x" forKey:@"1010"]; + [_rocks setObject:@"x" forKey:@"4211"]; + [_rocks setObject:@"x" forKey:@"1012"]; + [_rocks setObject:@"x" forKey:@"5313"]; + [_rocks setObject:@"x" forKey:@"1020"]; + [_rocks setObject:@"x" forKey:@"4221"]; + [_rocks setObject:@"x" forKey:@"1022"]; + [_rocks setObject:@"x" forKey:@"5323"]; + + RocksDBIterator *iterator = [_rocks iterator]; + + NSMutableArray *keys = [NSMutableArray array]; + [iterator enumerateKeysWithPrefix:@"10" usingBlock:^(id key, BOOL *stop) { + [keys addObject:key]; + }]; + + XCTAssertEqual(keys.count, 4); + + NSArray *expected = @[@"1010", @"1012", @"1020", @"1022"]; + XCTAssertEqualObjects(keys, expected); + + keys = [NSMutableArray array]; + [iterator enumerateKeysWithPrefix:@"42" usingBlock:^(id key, BOOL *stop) { + [keys addObject:key]; + }]; + + XCTAssertEqual(keys.count, 2); + + expected = @[@"4211", @"4221"]; + XCTAssertEqualObjects(keys, expected); + + keys = [NSMutableArray array]; + [iterator enumerateKeysWithPrefix:@"53" usingBlock:^(id key, BOOL *stop) { + [keys addObject:key]; + }]; + + XCTAssertEqual(keys.count, 2); + + expected = @[@"5313", @"5323"]; + XCTAssertEqualObjects(keys, expected); +} + @end From f87025fa9f4ad7b15a44b7a0a3af30611a288e10 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 9 Jan 2015 17:14:44 +0100 Subject: [PATCH 08/22] Fix typo in code sample in the Backup Readme entry --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0bce5d..88fc322 100644 --- a/README.md +++ b/README.md @@ -594,7 +594,7 @@ Backups are incremental and only the new data will be copied to backup directory * Delete specific backups * Purge all backups keeping the last N backups -```objecgtive-c +```objective-c RocksDB *db = ... RocksDBBackupEngine *backupEngine = [[RocksDBBackupEngine alloc] initWithPath:@"path/to/backup"]; From ec54ffc632b7ca9e66621dcb0e5a196b4edd9d03 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 9 Jan 2015 17:34:32 +0100 Subject: [PATCH 09/22] Update RocksDB and Thread Status API --- ObjectiveRocks.xcodeproj/project.pbxproj | 4 ++++ ObjectiveRocks/RocksDBEnv.mm | 3 ++- ObjectiveRocks/RocksDBThreadStatus.h | 23 ++++++++++++++++++----- rocksdb | 2 +- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index bddeea8..a4dab39 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -603,6 +603,8 @@ 6299F8141A17B28200123F56 /* ObjectiveRocksTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjectiveRocksTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6299F81A1A17B28200123F56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBasicTests.mm; sourceTree = ""; }; + 62A74F821A6037F500BAD95B /* thread_operation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_operation.h; sourceTree = ""; }; + 62A74F831A60385D00BAD95B /* memtablerep_bench.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memtablerep_bench.cc; sourceTree = ""; }; 62A8B0431A58C30E0069B4C8 /* libObjectiveRocks.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libObjectiveRocks.a; sourceTree = BUILT_PRODUCTS_DIR; }; 62A8B0571A58C40A0069B4C8 /* ObjectiveRocksTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ObjectiveRocksTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 62A8B05F1A58CC400069B4C8 /* RocksDBBackupInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBBackupInfo.h; sourceTree = ""; }; @@ -1461,6 +1463,7 @@ 6235339F1A47722900D5CD14 /* memtable_allocator.h */, 62EE29641A1ABA1F00486C31 /* memtable_list.cc */, 62EE29651A1ABA1F00486C31 /* memtable_list.h */, + 62A74F831A60385D00BAD95B /* memtablerep_bench.cc */, 62EE29671A1ABA1F00486C31 /* merge_context.h */, 62EE29681A1ABA1F00486C31 /* merge_helper.cc */, 62EE29691A1ABA1F00486C31 /* merge_helper.h */, @@ -1910,6 +1913,7 @@ 62EE2B941A1ABA2000486C31 /* thread_local.cc */, 62EE2B951A1ABA2000486C31 /* thread_local.h */, 62EE2B971A1ABA2000486C31 /* thread_local_test.cc */, + 62A74F821A6037F500BAD95B /* thread_operation.h */, 62451ACC1A4BC85400AF11C8 /* thread_status_updater_debug.cc */, 62451ACD1A4BC85400AF11C8 /* thread_status_updater.cc */, 62451ACE1A4BC85400AF11C8 /* thread_status_updater.h */, diff --git a/ObjectiveRocks/RocksDBEnv.mm b/ObjectiveRocks/RocksDBEnv.mm index 47a92b9..5634eab 100644 --- a/ObjectiveRocks/RocksDBEnv.mm +++ b/ObjectiveRocks/RocksDBEnv.mm @@ -82,7 +82,8 @@ - (NSArray *)threadList thread.threadType = (RocksDBThreadType)(*it).thread_type; thread.databaseName = [NSString stringWithCString:(*it).db_name.c_str() encoding:NSUTF8StringEncoding]; thread.columnFamilyname = [NSString stringWithCString:(*it).cf_name.c_str() encoding:NSUTF8StringEncoding]; - thread.event = [NSString stringWithCString:(*it).event.c_str() encoding:NSUTF8StringEncoding]; + thread.operationType = (RocksDBOperationType)(*it).operation_type; + thread.stateType = (RocksDBStateType)(*it).state_type; [threadList addObject:thread]; } diff --git a/ObjectiveRocks/RocksDBThreadStatus.h b/ObjectiveRocks/RocksDBThreadStatus.h index cb97780..e361a7a 100644 --- a/ObjectiveRocks/RocksDBThreadStatus.h +++ b/ObjectiveRocks/RocksDBThreadStatus.h @@ -8,11 +8,23 @@ #import -typedef NS_ENUM(NSUInteger, RocksDBThreadType) +typedef NS_ENUM(int, RocksDBThreadType) { - RocksDBThreadHighPiority = 0x0, - RocksDBThreadLowPiority = 0x1, - RocksDBThreadUser = 0x2, + RocksDBThreadHighPiority = 0, + RocksDBThreadLowPiority, + RocksDBThreadUser +}; + +typedef NS_ENUM(int, RocksDBOperationType) +{ + RocksDBOperationUnknown = 0, + RocksDBOperationCompaction, + RocksDBOperationFlush +}; + +typedef NS_ENUM(int, RocksDBStateType) +{ + RocksDBStateUnknown = 0, }; @interface RocksDBThreadStatus : NSObject @@ -21,6 +33,7 @@ typedef NS_ENUM(NSUInteger, RocksDBThreadType) @property (nonatomic, assign) RocksDBThreadType threadType; @property (nonatomic, strong) NSString *databaseName; @property (nonatomic, strong) NSString *columnFamilyname; -@property (nonatomic, strong) NSString *event; +@property (nonatomic, assign) RocksDBOperationType operationType; +@property (nonatomic, assign) RocksDBStateType stateType; @end diff --git a/rocksdb b/rocksdb index a801c1f..b89d58d 160000 --- a/rocksdb +++ b/rocksdb @@ -1 +1 @@ -Subproject commit a801c1fb099167cf48a714483163061062e3dcb7 +Subproject commit b89d58dfa3887d561bd772421fb92ef01bd26fc4 From d11325d8cb5cbdf35b7eed9857f0b1ad64336739 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 9 Jan 2015 17:43:42 +0100 Subject: [PATCH 10/22] Add write batch method to append a blob of arbitrary data to the batch Useful to store client specific meta data, like timestamp ..etc. --- ObjectiveRocks/RocksDBWriteBatch.h | 2 ++ ObjectiveRocks/RocksDBWriteBatch.mm | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/ObjectiveRocks/RocksDBWriteBatch.h b/ObjectiveRocks/RocksDBWriteBatch.h index dfb1868..149b50a 100644 --- a/ObjectiveRocks/RocksDBWriteBatch.h +++ b/ObjectiveRocks/RocksDBWriteBatch.h @@ -38,6 +38,8 @@ namespace rocksdb { - (void)deleteObjectForKey:(id)aKey inColumnFamily:(RocksDBColumnFamily *)columnFamily; - (void)deleteDataForKey:(NSData *)aKey inColumnFamily:(RocksDBColumnFamily *)columnFamily; +- (void)putLogData:(NSData *)logData; + - (void)clear; - (int)count; diff --git a/ObjectiveRocks/RocksDBWriteBatch.mm b/ObjectiveRocks/RocksDBWriteBatch.mm index 9340d4a..bdad9a3 100644 --- a/ObjectiveRocks/RocksDBWriteBatch.mm +++ b/ObjectiveRocks/RocksDBWriteBatch.mm @@ -148,6 +148,15 @@ - (void)deleteDataForKey:(NSData *)aKey inColumnFamily:(RocksDBColumnFamily *)co } } +#pragma mark - + +- (void)putLogData:(NSData *)logData; +{ + if (logData != nil) { + _writeBatch.PutLogData(SliceFromData(logData)); + } +} + - (void)clear { _writeBatch.Clear(); From 7ee8ff188bd5f3eae304a2d001a2c88725bba320 Mon Sep 17 00:00:00 2001 From: iska Date: Fri, 9 Jan 2015 18:22:06 +0100 Subject: [PATCH 11/22] Add DB method to retrieve Column Family Metadata --- ObjectiveRocks.xcodeproj/project.pbxproj | 6 ++ ObjectiveRocks/RocksDB.h | 10 ++- ObjectiveRocks/RocksDB.mm | 9 +++ ObjectiveRocks/RocksDBColumnFamilyMetadata.h | 51 +++++++++++++ ObjectiveRocks/RocksDBColumnFamilyMetadata.mm | 73 +++++++++++++++++++ ObjectiveRocks/RocksDBSnapshot.h | 10 +++ 6 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 ObjectiveRocks/RocksDBColumnFamilyMetadata.h create mode 100644 ObjectiveRocks/RocksDBColumnFamilyMetadata.mm diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index a4dab39..da3d834 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -106,6 +106,7 @@ 628B0CEA1A1C104D0099C39B /* RocksDBError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 628B0CE91A1C104D0099C39B /* RocksDBError.mm */; }; 6299F80F1A17B28200123F56 /* RocksDB.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6299F80E1A17B28200123F56 /* RocksDB.mm */; }; 6299F8561A17B7AD00123F56 /* RocksDBBasicTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */; }; + 62A74F861A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62A74F851A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm */; }; 62A8AF981A58C30E0069B4C8 /* memtable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE29611A1ABA1F00486C31 /* memtable.cc */; }; 62A8AF991A58C30E0069B4C8 /* hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE2B3F1A1ABA2000486C31 /* hash.cc */; }; 62A8AF9A1A58C30E0069B4C8 /* RocksDBCallbackMergeOperator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6214FD071A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp */; }; @@ -605,6 +606,8 @@ 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBasicTests.mm; sourceTree = ""; }; 62A74F821A6037F500BAD95B /* thread_operation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_operation.h; sourceTree = ""; }; 62A74F831A60385D00BAD95B /* memtablerep_bench.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memtablerep_bench.cc; sourceTree = ""; }; + 62A74F841A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBColumnFamilyMetadata.h; sourceTree = ""; }; + 62A74F851A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBColumnFamilyMetadata.mm; sourceTree = ""; }; 62A8B0431A58C30E0069B4C8 /* libObjectiveRocks.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libObjectiveRocks.a; sourceTree = BUILT_PRODUCTS_DIR; }; 62A8B0571A58C40A0069B4C8 /* ObjectiveRocksTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ObjectiveRocksTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 62A8B05F1A58CC400069B4C8 /* RocksDBBackupInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBBackupInfo.h; sourceTree = ""; }; @@ -1121,6 +1124,8 @@ 620629691A510D36001DEDC4 /* RocksDBColumnFamily.mm */, 62074F2B1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.h */, 62074F2C1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.mm */, + 62A74F841A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.h */, + 62A74F851A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm */, ); name = "Column Family"; sourceTree = ""; @@ -2369,6 +2374,7 @@ 62EE2D431A1ABA2100486C31 /* iostats_context.cc in Sources */, 6236E25A1A4DD71600A81ED6 /* RocksDBCallbackSliceTransform.cpp in Sources */, 62EE2C021A1ABA2000486C31 /* flush_job.cc in Sources */, + 62A74F861A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm in Sources */, 62EE2CE91A1ABA2000486C31 /* get_context.cc in Sources */, 62EE2CCE1A1ABA2000486C31 /* block_based_table_reader.cc in Sources */, 62EE2D161A1ABA2100486C31 /* bloom.cc in Sources */, diff --git a/ObjectiveRocks/RocksDB.h b/ObjectiveRocks/RocksDB.h index ae5e996..3f610e0 100644 --- a/ObjectiveRocks/RocksDB.h +++ b/ObjectiveRocks/RocksDB.h @@ -8,6 +8,7 @@ #import #import "RocksDBColumnFamilyDescriptor.h" +#import "RocksDBColumnFamilyMetaData.h" #import "RocksDBOptions.h" #import "RocksDBReadOptions.h" #import "RocksDBWriteOptions.h" @@ -19,8 +20,6 @@ @interface RocksDB : NSObject -+ (NSArray *)listColumnFamiliesInDatabaseAtPath:(NSString *)path; - - (instancetype)initWithPath:(NSString *)path; - (instancetype)initWithPath:(NSString *)path andDBOptions:(void (^)(RocksDBOptions *options))options; @@ -33,8 +32,15 @@ - (void)setDefaultReadOptions:(void (^)(RocksDBReadOptions *readOptions))readOptions andWriteOptions:(void (^)(RocksDBWriteOptions *writeOptions))writeOptions; +@end + +@interface RocksDB (ColumnFamilies) + ++ (NSArray *)listColumnFamiliesInDatabaseAtPath:(NSString *)path; + - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions:(void (^)(RocksDBColumnFamilyOptions *options))optionsBlock; +- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData; - (NSArray *)columnFamilies; @end diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index 6f28c5a..cf6925d 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -238,6 +238,15 @@ - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions: return columnFamily; } +- (RocksDBColumnFamilyMetaData *)columnFamilyMetadata +{ + rocksdb::ColumnFamilyMetaData metadata; + _db->GetColumnFamilyMetaData(_columnFamily, &metadata); + + RocksDBColumnFamilyMetaData *columnFamilyMetaData = [[RocksDBColumnFamilyMetaData alloc] initWithMetaData:metadata]; + return columnFamilyMetaData; +} + - (NSArray *)columnFamilies { return _columnFamilies; diff --git a/ObjectiveRocks/RocksDBColumnFamilyMetadata.h b/ObjectiveRocks/RocksDBColumnFamilyMetadata.h new file mode 100644 index 0000000..c93fad8 --- /dev/null +++ b/ObjectiveRocks/RocksDBColumnFamilyMetadata.h @@ -0,0 +1,51 @@ +// +// RocksDBColumnFamilyMetaData.h +// ObjectiveRocks +// +// Created by Iska on 09/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import + +namespace rocksdb { + class ColumnFamilyMetaData; + class LevelMetaData; + class SstFileMetaData; +} + +@interface RocksDBColumnFamilyMetaData : NSObject + +- (instancetype)initWithMetaData:(rocksdb::ColumnFamilyMetaData)metadata; + +@property (nonatomic, assign) uint64_t size; +@property (nonatomic, assign) size_t fileCount; +@property (nonatomic, assign) NSString *name; +@property (nonatomic, strong, readonly) NSArray *levels; + +@end + +@interface RocksDBLevelFileMetaData : NSObject + +- (instancetype)initWithLevelMetaData:(rocksdb::LevelMetaData)metadata; + +@property (nonatomic, assign) const int level; +@property (nonatomic, assign) const uint64_t size; +@property (nonatomic, strong, readonly) NSArray *files; + +@end + +@interface RocksDBSstFileMetaData : NSObject + +- (instancetype)initWithSstFileMetaData:(rocksdb::SstFileMetaData)metadata; + +@property (nonatomic, assign) uint64_t size; +@property (nonatomic, assign) NSString *name; +@property (nonatomic, assign) NSString *dbPath; +@property (nonatomic, assign) uint64_t smallestSeqno; +@property (nonatomic, assign) uint64_t largestSeqno; +@property (nonatomic, assign) NSString *smallestKey; +@property (nonatomic, assign) NSString *largestKey; +@property (nonatomic, assign) bool beingCompacted; + +@end diff --git a/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm b/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm new file mode 100644 index 0000000..cd269dc --- /dev/null +++ b/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm @@ -0,0 +1,73 @@ +// +// RocksDBColumnFamilyMetaData.m +// ObjectiveRocks +// +// Created by Iska on 09/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBColumnFamilyMetaData.h" + +#import + +@implementation RocksDBColumnFamilyMetaData + +- (instancetype)initWithMetaData:(rocksdb::ColumnFamilyMetaData)metadata +{ + self = [super init]; + if (self) { + self.size = metadata.size; + self.fileCount = metadata.file_count; + self.name = [NSString stringWithCString:metadata.name.c_str() encoding:NSUTF8StringEncoding]; + NSMutableArray *levels = [NSMutableArray array]; + for (auto it = std::begin(metadata.levels); it != std::end(metadata.levels); ++it) { + RocksDBLevelFileMetaData *levelMetaData = [[RocksDBLevelFileMetaData alloc] initWithLevelMetaData:*it]; + [levels addObject:levelMetaData]; + } + self->_levels = levels; + } + return self; +} + +@end + +@implementation RocksDBLevelFileMetaData + +- (instancetype)initWithLevelMetaData:(rocksdb::LevelMetaData)metadata +{ + self = [super init]; + if (self) { + self.level = metadata.level; + self.size = metadata.size; + + NSMutableArray *sstFiles = [NSMutableArray array]; + for (auto it = std::begin(metadata.files); it != std::end(metadata.files); ++it) { + RocksDBSstFileMetaData *sstFileMetaData = [[RocksDBSstFileMetaData alloc] initWithSstFileMetaData:*it]; + [sstFiles addObject:sstFileMetaData]; + } + self->_files = sstFiles; + } + return self; +} + +@end + +@implementation RocksDBSstFileMetaData + +- (instancetype)initWithSstFileMetaData:(rocksdb::SstFileMetaData)metadata +{ + self = [super init]; + if (self) { + self.size = metadata.size; + self.name = [NSString stringWithCString:metadata.name.c_str() encoding:NSUTF8StringEncoding]; + self.dbPath = [NSString stringWithCString:metadata.db_path.c_str() encoding:NSUTF8StringEncoding]; + self.smallestSeqno = metadata.smallest_seqno; + self.largestSeqno = metadata.largest_seqno; + self.smallestKey = [NSString stringWithCString:metadata.smallestkey.c_str() encoding:NSUTF8StringEncoding]; + self.largestKey = [NSString stringWithCString:metadata.largestkey.c_str() encoding:NSUTF8StringEncoding]; + self.beingCompacted = metadata.being_compacted; + } + return self; +} + +@end diff --git a/ObjectiveRocks/RocksDBSnapshot.h b/ObjectiveRocks/RocksDBSnapshot.h index c8fb837..4814e1c 100644 --- a/ObjectiveRocks/RocksDBSnapshot.h +++ b/ObjectiveRocks/RocksDBSnapshot.h @@ -29,6 +29,16 @@ namespace rocksdb { - (instancetype)initWithPath:(NSString *)path NA("Create a snapshot via a DB instance"); - (instancetype)initWithPath:(NSString *)path andDBOptions:(void (^)(RocksDBOptions *options))options NA("Create a snapshot via a DB instance"); +- (instancetype)initWithPath:(NSString *)path + columnFamilies:(RocksDBColumnFamilyDescriptor *)descriptor + andDatabaseOptions:(void (^)(RocksDBDatabaseOptions *options))options NA("Create a snapshot via a DB instance"); + ++ (NSArray *)listColumnFamiliesInDatabaseAtPath:(NSString *)path NA("Column Family API not available"); + +- (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name + andOptions:(void (^)(RocksDBColumnFamilyOptions *options))optionsBlock NA("Column Family API not available"); +- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData NA("Column Family API not available"); +- (NSArray *)columnFamilies NA("Column Family API not available"); - (void)setDefaultReadOptions:(void (^)(RocksDBReadOptions *readOptions))readOptions andWriteOptions:(void (^)(RocksDBWriteOptions *writeOptions))writeOptions NA("Specify options when creating snapshot via DB instance"); From 32f10f84914e1ef2b961b81b41de3c753ba144ec Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 10 Jan 2015 16:05:00 +0100 Subject: [PATCH 12/22] Add method for default Column Family in the descriptor class --- ObjectiveRocks/RocksDBColumnFamilyDescriptor.h | 3 +++ ObjectiveRocks/RocksDBColumnFamilyDescriptor.mm | 11 +++++++++++ ObjectiveRocksTests/RocksDBColumnFamilyTests.mm | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ObjectiveRocks/RocksDBColumnFamilyDescriptor.h b/ObjectiveRocks/RocksDBColumnFamilyDescriptor.h index 2641d22..d4b3f4c 100644 --- a/ObjectiveRocks/RocksDBColumnFamilyDescriptor.h +++ b/ObjectiveRocks/RocksDBColumnFamilyDescriptor.h @@ -9,8 +9,11 @@ #import #import "RocksDBColumnFamilyOptions.h" +extern NSString * const RocksDBDefaultColumnFamilyName; + @interface RocksDBColumnFamilyDescriptor : NSObject +- (void)addDefaultColumnFamilyWithOptions:(void (^)(RocksDBColumnFamilyOptions *options))options; - (void)addColumnFamilyWithName:(NSString *)name andOptions:(void (^)(RocksDBColumnFamilyOptions *options))options; @end diff --git a/ObjectiveRocks/RocksDBColumnFamilyDescriptor.mm b/ObjectiveRocks/RocksDBColumnFamilyDescriptor.mm index 6334263..15207ff 100644 --- a/ObjectiveRocks/RocksDBColumnFamilyDescriptor.mm +++ b/ObjectiveRocks/RocksDBColumnFamilyDescriptor.mm @@ -10,6 +10,8 @@ #import +NSString * const RocksDBDefaultColumnFamilyName = @"default"; + @interface RocksDBColumnFamilyOptions () @property (nonatomic, assign) rocksdb::ColumnFamilyOptions options; @end @@ -24,6 +26,8 @@ @interface RocksDBColumnFamilyDescriptor () @implementation RocksDBColumnFamilyDescriptor @synthesize columnFamilies = _columnFamilies; +#pragma mark - Lifecycle + - (instancetype)init { self = [super init]; @@ -44,6 +48,13 @@ - (void)dealloc } } +#pragma mark - Add Column Families + +- (void)addDefaultColumnFamilyWithOptions:(void (^)(RocksDBColumnFamilyOptions *options))options +{ + [self addColumnFamilyWithName:RocksDBDefaultColumnFamilyName andOptions:options]; +} + - (void)addColumnFamilyWithName:(NSString *)name andOptions:(void (^)(RocksDBColumnFamilyOptions *options))optionsBlock { RocksDBColumnFamilyOptions *options = [RocksDBColumnFamilyOptions new]; diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm index 452b5ed..8eab380 100644 --- a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm +++ b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm @@ -162,7 +162,7 @@ - (void)testColumnFamilies_CRUD [_rocks close]; RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; - [descriptor addColumnFamilyWithName:@"default" andOptions:nil]; + [descriptor addDefaultColumnFamilyWithOptions:nil]; [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { @@ -202,7 +202,7 @@ - (void)testColumnFamilies_CRUD - (void)testColumnFamilies_WriteBatch { RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; - [descriptor addColumnFamilyWithName:@"default" andOptions:nil]; + [descriptor addDefaultColumnFamilyWithOptions:nil]; [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { @@ -243,7 +243,7 @@ - (void)testColumnFamilies_WriteBatch - (void)testColumnFamilies_Iterator { RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; - [descriptor addColumnFamilyWithName:@"default" andOptions:nil]; + [descriptor addDefaultColumnFamilyWithOptions:nil]; [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { From 3db763b8b8475225ee4d06039c5b065b1d3183dd Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 10 Jan 2015 16:05:22 +0100 Subject: [PATCH 13/22] Fix typo in method name to retrieve column families --- ObjectiveRocks/RocksDB.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index cf6925d..1eeda37 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -238,7 +238,7 @@ - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions: return columnFamily; } -- (RocksDBColumnFamilyMetaData *)columnFamilyMetadata +- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData { rocksdb::ColumnFamilyMetaData metadata; _db->GetColumnFamilyMetaData(_columnFamily, &metadata); From 9d069d98b20ad69b3e49ae002d2a60b493ae3d9d Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 10 Jan 2015 16:06:02 +0100 Subject: [PATCH 14/22] Consolidate DB open methods into one and lazy load opened Column Families --- ObjectiveRocks/RocksDB.mm | 52 +++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index 1eeda37..12db032 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -99,7 +99,7 @@ - (instancetype)initWithPath:(NSString *)path andDBOptions:(void (^)(RocksDBOpti optionsBlock(_options); } - if ([self open] == NO) { + if ([self openColumnFamilies:nil] == NO) { return nil; } [self setDefaultReadOptions:nil andWriteOptions:nil]; @@ -155,29 +155,21 @@ - (void)close #pragma mark - Open -- (BOOL)open -{ - rocksdb::Status status = rocksdb::DB::Open(_options.options, _path.UTF8String, &_db); - if (!status.ok()) { - NSLog(@"Error opening database: %@", [RocksDBError errorWithRocksStatus:status]); - [self close]; - return NO; - } - _columnFamily = _db->DefaultColumnFamily(); - - return YES; -} - - (BOOL)openColumnFamilies:(RocksDBColumnFamilyDescriptor *)descriptor { - std::vector *columnFamilies = descriptor.columnFamilies; - _columnFamilyHandles = new std::vector; + rocksdb::Status status; + if (descriptor == nil) { + status = rocksdb::DB::Open(_options.options, _path.UTF8String, &_db); + } else { + std::vector *columnFamilies = descriptor.columnFamilies; + _columnFamilyHandles = new std::vector; + status = rocksdb::DB::Open(_options.options, + _path.UTF8String, + *columnFamilies, + _columnFamilyHandles, + &_db); + } - rocksdb::Status status = rocksdb::DB::Open(_options.options, - _path.UTF8String, - *columnFamilies, - _columnFamilyHandles, - &_db); if (!status.ok()) { NSLog(@"Error opening database: %@", [RocksDBError errorWithRocksStatus:status]); @@ -186,14 +178,6 @@ - (BOOL)openColumnFamilies:(RocksDBColumnFamilyDescriptor *)descriptor } _columnFamily = _db->DefaultColumnFamily(); - _columnFamilies = [NSMutableArray new]; - for(auto it = std::begin(*_columnFamilyHandles); it != std::end(*_columnFamilyHandles); ++it) { - RocksDBColumnFamily *columnFamily = [[RocksDBColumnFamily alloc] initWithDBInstance:_db - columnFamily:*it - andOptions:_options]; - [_columnFamilies addObject:columnFamily]; - } - return YES; } @@ -249,6 +233,16 @@ - (RocksDBColumnFamilyMetaData *)columnFamilyMetaData - (NSArray *)columnFamilies { + if (_columnFamilies == nil) { + _columnFamilies = [NSMutableArray new]; + for(auto it = std::begin(*_columnFamilyHandles); it != std::end(*_columnFamilyHandles); ++it) { + RocksDBColumnFamily *columnFamily = [[RocksDBColumnFamily alloc] initWithDBInstance:_db + columnFamily:*it + andOptions:_options]; + [_columnFamilies addObject:columnFamily]; + } + } + return _columnFamilies; } From 897d2d8966d4b8d4068b5c014b9d7b0b061fc057 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 10 Jan 2015 16:06:32 +0100 Subject: [PATCH 15/22] Add test for Column Family Metadata Currently checks that the return is not nil --- .../RocksDBColumnFamilyTests.mm | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm index 8eab380..6715455 100644 --- a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm +++ b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm @@ -290,4 +290,31 @@ - (void)testColumnFamilies_Iterator [newColumnFamily close]; } +- (void)testColumnFamilies_Metadata +{ + RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; + [descriptor addDefaultColumnFamilyWithOptions:nil]; + [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; + + _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { + options.createIfMissing = YES; + options.createMissingColumnFamilies = YES; + }]; + + RocksDBColumnFamily *defaultColumnFamily = _rocks.columnFamilies[0]; + RocksDBColumnFamily *newColumnFamily = _rocks.columnFamilies[1]; + + [defaultColumnFamily setData:Data(@"df_value1") forKey:Data(@"df_key1")]; + [defaultColumnFamily setData:Data(@"df_value2") forKey:Data(@"df_key2")]; + + [newColumnFamily setData:Data(@"cf_value1") forKey:Data(@"cf_key1")]; + [newColumnFamily setData:Data(@"cf_value2") forKey:Data(@"cf_key2")]; + + RocksDBColumnFamilyMetaData *defaultMetadata = defaultColumnFamily.columnFamilyMetaData; + XCTAssertNotNil(defaultMetadata); + + RocksDBColumnFamilyMetaData *newColumnFamilyMetadata = newColumnFamily.columnFamilyMetaData; + XCTAssertNotNil(newColumnFamilyMetadata); +} + @end From e4cea7ede6c5d9db8eb9a2e2629ecb9253666e87 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 11 Jan 2015 00:09:40 +0100 Subject: [PATCH 16/22] Exclude Column Family Metadata methods and tests from iOS target --- ObjectiveRocks.xcodeproj/project.pbxproj | 2 + ObjectiveRocks/ObjectiveRocks.h | 2 + ObjectiveRocks/RocksDB.h | 8 +++- ObjectiveRocks/RocksDB.mm | 22 ++++++---- .../RocksDBColumnFamilyMetadataTests.m | 44 +++++++++++++++++++ .../RocksDBColumnFamilyTests.mm | 27 ------------ 6 files changed, 68 insertions(+), 37 deletions(-) create mode 100644 ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index da3d834..f2ca14a 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -595,6 +595,7 @@ 626A7D521A27EC570098A979 /* rdb.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rdb.cc; sourceTree = ""; }; 626A7D531A27EC570098A979 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 626A7D541A27EC570098A979 /* unit_test.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = unit_test.js; sourceTree = ""; }; + 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RocksDBColumnFamilyMetadataTests.m; sourceTree = ""; }; 628B0CE81A1C104D0099C39B /* RocksDBError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBError.h; sourceTree = ""; }; 628B0CE91A1C104D0099C39B /* RocksDBError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBError.mm; sourceTree = ""; }; 628C51C71A3BD08500B96F8F /* RocksDBSnapshotUnavailable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RocksDBSnapshotUnavailable.h; sourceTree = ""; }; @@ -1314,6 +1315,7 @@ 620A2CAD1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm */, 6236E25B1A4E19A300A81ED6 /* RocksDBPrefixExtractorTests.mm */, 624566C71A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm */, + 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.m */, 62FC8B461A565B19003DF5C6 /* RocksDBBackupTests.mm */, 62A8B06A1A5900540069B4C8 /* RocksDBStatisticsTests.mm */, 625F8F1E1A59C9B3007796BA /* RocksDBPropertiesTests.mm */, diff --git a/ObjectiveRocks/ObjectiveRocks.h b/ObjectiveRocks/ObjectiveRocks.h index 7fcde35..ebc2940 100644 --- a/ObjectiveRocks/ObjectiveRocks.h +++ b/ObjectiveRocks/ObjectiveRocks.h @@ -40,6 +40,8 @@ #ifndef ROCKSDB_LITE +#import "RocksDBColumnFamilyMetadata.h" + #import "RocksDBPlainTableOptions.h" #import "RocksDBCuckooTableOptions.h" diff --git a/ObjectiveRocks/RocksDB.h b/ObjectiveRocks/RocksDB.h index 3f610e0..dd8a574 100644 --- a/ObjectiveRocks/RocksDB.h +++ b/ObjectiveRocks/RocksDB.h @@ -40,9 +40,15 @@ - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions:(void (^)(RocksDBColumnFamilyOptions *options))optionsBlock; -- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData; + - (NSArray *)columnFamilies; +#ifndef ROCKSDB_LITE + +- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData; + +#endif + @end #ifndef ROCKSDB_LITE diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index 12db032..c55001e 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -222,15 +222,6 @@ - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions: return columnFamily; } -- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData -{ - rocksdb::ColumnFamilyMetaData metadata; - _db->GetColumnFamilyMetaData(_columnFamily, &metadata); - - RocksDBColumnFamilyMetaData *columnFamilyMetaData = [[RocksDBColumnFamilyMetaData alloc] initWithMetaData:metadata]; - return columnFamilyMetaData; -} - - (NSArray *)columnFamilies { if (_columnFamilies == nil) { @@ -246,6 +237,19 @@ - (NSArray *)columnFamilies return _columnFamilies; } +#ifndef ROCKSDB_LITE + +- (RocksDBColumnFamilyMetaData *)columnFamilyMetaData +{ + rocksdb::ColumnFamilyMetaData metadata; + _db->GetColumnFamilyMetaData(_columnFamily, &metadata); + + RocksDBColumnFamilyMetaData *columnFamilyMetaData = [[RocksDBColumnFamilyMetaData alloc] initWithMetaData:metadata]; + return columnFamilyMetaData; +} + +#endif + #pragma mark - Read/Write Options - (void)setDefaultReadOptions:(void (^)(RocksDBReadOptions *))readOptionsBlock andWriteOptions:(void (^)(RocksDBWriteOptions *))writeOptionsBlock diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m b/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m new file mode 100644 index 0000000..65f84ea --- /dev/null +++ b/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m @@ -0,0 +1,44 @@ +// +// RocksDBColumnFamilyMetadataTests.m +// ObjectiveRocks +// +// Created by Iska on 10/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBTests.h" + +@interface RocksDBColumnFamilyMetadataTests : RocksDBTests + +@end + +@implementation RocksDBColumnFamilyMetadataTests + +- (void)testColumnFamilies_Metadata +{ + RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; + [descriptor addDefaultColumnFamilyWithOptions:nil]; + [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; + + _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { + options.createIfMissing = YES; + options.createMissingColumnFamilies = YES; + }]; + + RocksDBColumnFamily *defaultColumnFamily = _rocks.columnFamilies[0]; + RocksDBColumnFamily *newColumnFamily = _rocks.columnFamilies[1]; + + [defaultColumnFamily setData:Data(@"df_value1") forKey:Data(@"df_key1")]; + [defaultColumnFamily setData:Data(@"df_value2") forKey:Data(@"df_key2")]; + + [newColumnFamily setData:Data(@"cf_value1") forKey:Data(@"cf_key1")]; + [newColumnFamily setData:Data(@"cf_value2") forKey:Data(@"cf_key2")]; + + RocksDBColumnFamilyMetaData *defaultMetadata = defaultColumnFamily.columnFamilyMetaData; + XCTAssertNotNil(defaultMetadata); + + RocksDBColumnFamilyMetaData *newColumnFamilyMetadata = newColumnFamily.columnFamilyMetaData; + XCTAssertNotNil(newColumnFamilyMetadata); +} + +@end diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm index 6715455..8eab380 100644 --- a/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm +++ b/ObjectiveRocksTests/RocksDBColumnFamilyTests.mm @@ -290,31 +290,4 @@ - (void)testColumnFamilies_Iterator [newColumnFamily close]; } -- (void)testColumnFamilies_Metadata -{ - RocksDBColumnFamilyDescriptor *descriptor = [RocksDBColumnFamilyDescriptor new]; - [descriptor addDefaultColumnFamilyWithOptions:nil]; - [descriptor addColumnFamilyWithName:@"new_cf" andOptions:nil]; - - _rocks = [[RocksDB alloc] initWithPath:_path columnFamilies:descriptor andDatabaseOptions:^(RocksDBDatabaseOptions *options) { - options.createIfMissing = YES; - options.createMissingColumnFamilies = YES; - }]; - - RocksDBColumnFamily *defaultColumnFamily = _rocks.columnFamilies[0]; - RocksDBColumnFamily *newColumnFamily = _rocks.columnFamilies[1]; - - [defaultColumnFamily setData:Data(@"df_value1") forKey:Data(@"df_key1")]; - [defaultColumnFamily setData:Data(@"df_value2") forKey:Data(@"df_key2")]; - - [newColumnFamily setData:Data(@"cf_value1") forKey:Data(@"cf_key1")]; - [newColumnFamily setData:Data(@"cf_value2") forKey:Data(@"cf_key2")]; - - RocksDBColumnFamilyMetaData *defaultMetadata = defaultColumnFamily.columnFamilyMetaData; - XCTAssertNotNil(defaultMetadata); - - RocksDBColumnFamilyMetaData *newColumnFamilyMetadata = newColumnFamily.columnFamilyMetaData; - XCTAssertNotNil(newColumnFamilyMetadata); -} - @end From b0b558309739cba664c629479fba067f59b723ad Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 11 Jan 2015 16:10:31 +0100 Subject: [PATCH 17/22] Refactor code base to provide a pure Objective-C public header interface to support Swift - All C++ types and forward declarations are moved into private categories - Structs converted to Objects for ARC - Bridging header added in test targets along with a dummy swift test file --- ObjectiveRocks.xcodeproj/project.pbxproj | 58 +++++++++++++++++-- ObjectiveRocks/ObjectiveRocks.h | 1 - ObjectiveRocks/RocksDB+Private.h | 24 ++++++++ ObjectiveRocks/RocksDB.mm | 12 ++-- ObjectiveRocks/RocksDBCheckpoint.h | 1 - ObjectiveRocks/RocksDBCheckpoint.mm | 5 +- ObjectiveRocks/RocksDBColumnFamily+Private.h | 24 ++++++++ ObjectiveRocks/RocksDBColumnFamily.h | 9 --- ObjectiveRocks/RocksDBColumnFamily.mm | 9 +-- .../RocksDBColumnFamilyMetaData+Private.h | 33 +++++++++++ ObjectiveRocks/RocksDBColumnFamilyMetadata.h | 12 ---- ObjectiveRocks/RocksDBColumnFamilyMetadata.mm | 1 + ObjectiveRocks/RocksDBIterator+Private.h | 20 +++++++ ObjectiveRocks/RocksDBIterator.h | 33 +++++------ ObjectiveRocks/RocksDBIterator.mm | 14 ++++- ObjectiveRocks/RocksDBSnapshot+Private.h | 22 +++++++ ObjectiveRocks/RocksDBSnapshot.h | 9 --- ObjectiveRocks/RocksDBSnapshot.mm | 9 +-- ObjectiveRocks/RocksDBWriteBatch+Private.h | 23 ++++++++ ObjectiveRocks/RocksDBWriteBatch.h | 7 --- ObjectiveRocks/RocksDBWriteBatch.mm | 5 +- .../ObjectiveRocksTests-Bridging-Header.h | 53 +++++++++++++++++ .../ObjectiveRocksTests-iOS-Bridging-Header.h | 34 +++++++++++ ObjectiveRocksTests/RockDBTests.swift | 32 ++++++++++ 24 files changed, 357 insertions(+), 93 deletions(-) create mode 100644 ObjectiveRocks/RocksDB+Private.h create mode 100644 ObjectiveRocks/RocksDBColumnFamily+Private.h create mode 100644 ObjectiveRocks/RocksDBColumnFamilyMetaData+Private.h create mode 100644 ObjectiveRocks/RocksDBIterator+Private.h create mode 100644 ObjectiveRocks/RocksDBSnapshot+Private.h create mode 100644 ObjectiveRocks/RocksDBWriteBatch+Private.h create mode 100644 ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h create mode 100644 ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h create mode 100644 ObjectiveRocksTests/RockDBTests.swift diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index f2ca14a..3d118f7 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 620A2CAE1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 620A2CAD1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm */; }; 6214FD091A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6214FD071A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp */; }; 621CD71C1A4FB24700853E16 /* RocksDBBackupEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 621CD71B1A4FB24700853E16 /* RocksDBBackupEngine.mm */; }; + 6221B7A71A629E1B00D28BF5 /* RockDBTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */; }; + 6221B7A81A629E2700D28BF5 /* RockDBTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */; }; 62269EDC1A1FF27A005A58D3 /* checkpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62269EDB1A1FF27A005A58D3 /* checkpoint.cc */; }; 62269EE01A1FF2DC005A58D3 /* leveldb_options.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62269EDF1A1FF2DC005A58D3 /* leveldb_options.cc */; }; 6231475B1A5AE18A0019D14A /* RocksDBEnv.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6231475A1A5AE18A0019D14A /* RocksDBEnv.mm */; }; @@ -526,6 +528,15 @@ 6214FD081A3F698300B92E5C /* RocksDBCallbackMergeOperator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBCallbackMergeOperator.h; sourceTree = ""; }; 621CD71A1A4FB24700853E16 /* RocksDBBackupEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBBackupEngine.h; sourceTree = ""; }; 621CD71B1A4FB24700853E16 /* RocksDBBackupEngine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBackupEngine.mm; sourceTree = ""; }; + 6221B78A1A62970800D28BF5 /* RocksDB+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDB+Private.h"; sourceTree = ""; }; + 6221B78E1A62973500D28BF5 /* RocksDBColumnFamily+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDBColumnFamily+Private.h"; sourceTree = ""; }; + 6221B7921A62976F00D28BF5 /* RocksDBColumnFamilyMetaData+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDBColumnFamilyMetaData+Private.h"; sourceTree = ""; }; + 6221B7961A6298AD00D28BF5 /* RocksDBIterator+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDBIterator+Private.h"; sourceTree = ""; }; + 6221B79A1A6298F800D28BF5 /* RocksDBWriteBatch+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDBWriteBatch+Private.h"; sourceTree = ""; }; + 6221B79E1A629A4F00D28BF5 /* RocksDBSnapshot+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDBSnapshot+Private.h"; sourceTree = ""; }; + 6221B7A21A629B3500D28BF5 /* ObjectiveRocksTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjectiveRocksTests-Bridging-Header.h"; sourceTree = ""; }; + 6221B7A31A629B3500D28BF5 /* ObjectiveRocksTests-iOS-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ObjectiveRocksTests-iOS-Bridging-Header.h"; sourceTree = ""; }; + 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RockDBTests.swift; sourceTree = ""; }; 62269ED91A1FF266005A58D3 /* checkpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = checkpoint.h; path = utilities/checkpoint.h; sourceTree = ""; }; 62269EDB1A1FF27A005A58D3 /* checkpoint.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = checkpoint.cc; sourceTree = ""; }; 62269EDD1A1FF2B2005A58D3 /* leveldb_options.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = leveldb_options.h; sourceTree = ""; }; @@ -1142,6 +1153,19 @@ name = Backup; sourceTree = ""; }; + 6221B7851A6295FA00D28BF5 /* Private */ = { + isa = PBXGroup; + children = ( + 6221B78A1A62970800D28BF5 /* RocksDB+Private.h */, + 6221B78E1A62973500D28BF5 /* RocksDBColumnFamily+Private.h */, + 6221B7921A62976F00D28BF5 /* RocksDBColumnFamilyMetaData+Private.h */, + 6221B7961A6298AD00D28BF5 /* RocksDBIterator+Private.h */, + 6221B79A1A6298F800D28BF5 /* RocksDBWriteBatch+Private.h */, + 6221B79E1A629A4F00D28BF5 /* RocksDBSnapshot+Private.h */, + ); + name = Private; + sourceTree = ""; + }; 62269EDA1A1FF27A005A58D3 /* checkpoint */ = { isa = PBXGroup; children = ( @@ -1295,6 +1319,7 @@ 62EEC4B41A34FEC500624DA2 /* Merge Operator */, 62A8B0621A58DD620069B4C8 /* Statistics */, 621CD7191A4FB22C00853E16 /* Backup */, + 6221B7851A6295FA00D28BF5 /* Private */, 62376BBC1A20EA4B00C85DFB /* Internal */, 62EE28FD1A1ABA1F00486C31 /* rocksdb */, ); @@ -1304,8 +1329,11 @@ 6299F8181A17B28200123F56 /* ObjectiveRocksTests */ = { isa = PBXGroup; children = ( + 6221B7A21A629B3500D28BF5 /* ObjectiveRocksTests-Bridging-Header.h */, + 6221B7A31A629B3500D28BF5 /* ObjectiveRocksTests-iOS-Bridging-Header.h */, 6249A3CD1A4A6E4000949B07 /* RocksDBTests.h */, 6249A3CB1A4A43CA00949B07 /* RocksDBTests.mm */, + 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */, 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */, 62685CB81A2E600A009401B1 /* RocksDBWriteBatchTests.mm */, 62385EB31A2FCFB100493F18 /* RocksDBIteratorTests.mm */, @@ -2392,6 +2420,7 @@ files = ( 6299F8561A17B7AD00123F56 /* RocksDBBasicTests.mm in Sources */, 62FC8B471A565B19003DF5C6 /* RocksDBBackupTests.mm in Sources */, + 6221B7A71A629E1B00D28BF5 /* RockDBTests.swift in Sources */, 625F8F251A59D11D007796BA /* RocksDBCheckpointTests.mm in Sources */, 6249A3CC1A4A43CA00949B07 /* RocksDBTests.mm in Sources */, 62A8B06B1A5900540069B4C8 /* RocksDBStatisticsTests.mm in Sources */, @@ -2578,6 +2607,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6221B7A81A629E2700D28BF5 /* RockDBTests.swift in Sources */, 62A8B0481A58C40A0069B4C8 /* RocksDBBasicTests.mm in Sources */, 62A8B0491A58C40A0069B4C8 /* RocksDBTests.mm in Sources */, 62A8B04A1A58C40A0069B4C8 /* RocksDBColumnFamilyTests.mm in Sources */, @@ -2685,6 +2715,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2697,8 +2728,9 @@ "$(SRCROOT)/rocksdb", "$(SRCROOT)/rocksdb/include", ); + LD_RUNPATH_SEARCH_PATHS = ""; LIBRARY_SEARCH_PATHS = ""; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = "-ObjC"; @@ -2714,6 +2746,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_PREPROCESSOR_DEFINITIONS = ( "OS_MACOSX=1", @@ -2725,6 +2758,7 @@ "$(SRCROOT)/rocksdb", "$(SRCROOT)/rocksdb/include", ); + LD_RUNPATH_SEARCH_PATHS = ""; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = ""; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; @@ -2739,26 +2773,35 @@ 6299F8211A17B28200123F56 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = ObjectiveRocksTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_NAME = ObjectiveRocksTests; SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = "ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 6299F8221A17B28200123F56 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = ObjectiveRocksTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_NAME = ObjectiveRocksTests; SDKROOT = macosx; + SWIFT_OBJC_BRIDGING_HEADER = "ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h"; }; name = Release; }; @@ -2782,7 +2825,7 @@ "$(SRCROOT)/rocksdb/include", ); LIBRARY_SEARCH_PATHS = ""; - ONLY_ACTIVE_ARCH = NO; + ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = "-ObjC"; @@ -2823,6 +2866,8 @@ 62A8B0551A58C40A0069B4C8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2831,16 +2876,21 @@ INFOPLIST_FILE = ObjectiveRocksTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "ObjectiveRocksTests-iOS"; + SWIFT_OBJC_BRIDGING_HEADER = "ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 62A8B0561A58C40A0069B4C8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = ObjectiveRocksTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "ObjectiveRocksTests-iOS"; + SWIFT_OBJC_BRIDGING_HEADER = "ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h"; }; name = Release; }; diff --git a/ObjectiveRocks/ObjectiveRocks.h b/ObjectiveRocks/ObjectiveRocks.h index ebc2940..04a74fd 100644 --- a/ObjectiveRocks/ObjectiveRocks.h +++ b/ObjectiveRocks/ObjectiveRocks.h @@ -36,7 +36,6 @@ #import "RocksDBMergeOperator.h" #import "RocksDBTypes.h" -#import "RocksDBError.h" #ifndef ROCKSDB_LITE diff --git a/ObjectiveRocks/RocksDB+Private.h b/ObjectiveRocks/RocksDB+Private.h new file mode 100644 index 0000000..6872dc6 --- /dev/null +++ b/ObjectiveRocks/RocksDB+Private.h @@ -0,0 +1,24 @@ +// +// RocksDB+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDB.h" + +namespace rocksdb { + class DB; + class ColumnFamilyHandle; +} + +@interface RocksDB (Private) + +@property (nonatomic, assign) rocksdb::DB *db; +@property (nonatomic, assign) rocksdb::ColumnFamilyHandle *columnFamily; +@property (nonatomic, retain) RocksDBOptions *options; +@property (nonatomic, retain) RocksDBReadOptions *readOptions; +@property (nonatomic, retain) RocksDBWriteOptions *writeOptions; + +@end diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index c55001e..3d3ca4c 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -9,10 +9,18 @@ #import "RocksDB.h" #import "RocksDBColumnFamily.h" +#import "RocksDBColumnFamily+Private.h" +#import "RocksDBColumnFamilyMetaData+Private.h" + #import "RocksDBOptions.h" #import "RocksDBReadOptions.h" #import "RocksDBWriteOptions.h" + +#import "RocksDBIterator+Private.h" +#import "RocksDBWriteBatch+Private.h" + #import "RocksDBSnapshot.h" +#import "RocksDBSnapshot+Private.h" #import "RocksDBError.h" #import "RocksDBSlice.h" @@ -49,10 +57,6 @@ @interface RocksDBWriteOptions (Private) @property (nonatomic, assign) rocksdb::WriteOptions options; @end -@interface RocksDBWriteBatch (Private) -@property (nonatomic, assign) rocksdb::WriteBatch writeBatch; -@end - @interface RocksDB () { NSString *_path; diff --git a/ObjectiveRocks/RocksDBCheckpoint.h b/ObjectiveRocks/RocksDBCheckpoint.h index 497bdb0..ac6b121 100644 --- a/ObjectiveRocks/RocksDBCheckpoint.h +++ b/ObjectiveRocks/RocksDBCheckpoint.h @@ -7,7 +7,6 @@ // #import - #import "RocksDB.h" @interface RocksDBCheckpoint : NSObject diff --git a/ObjectiveRocks/RocksDBCheckpoint.mm b/ObjectiveRocks/RocksDBCheckpoint.mm index b0d39a6..8321699 100644 --- a/ObjectiveRocks/RocksDBCheckpoint.mm +++ b/ObjectiveRocks/RocksDBCheckpoint.mm @@ -7,14 +7,11 @@ // #import "RocksDBCheckpoint.h" +#import "RocksDB+Private.h" #import "RocksDBError.h" #import -@interface RocksDB (Private) -@property (nonatomic, assign) rocksdb::DB *db; -@end - @interface RocksDBCheckpoint () { rocksdb::Checkpoint *_checkpoint; diff --git a/ObjectiveRocks/RocksDBColumnFamily+Private.h b/ObjectiveRocks/RocksDBColumnFamily+Private.h new file mode 100644 index 0000000..be1352e --- /dev/null +++ b/ObjectiveRocks/RocksDBColumnFamily+Private.h @@ -0,0 +1,24 @@ +// +// RocksDBColumnFamily+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBColumnFamily.h" + +namespace rocksdb { + class DB; + class ColumnFamilyHandle; +} + +@interface RocksDBColumnFamily (Private) + +@property (nonatomic, assign) rocksdb::ColumnFamilyHandle *columnFamily; + +- (instancetype)initWithDBInstance:(rocksdb::DB *)db + columnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily + andOptions:(RocksDBOptions *)options; + +@end diff --git a/ObjectiveRocks/RocksDBColumnFamily.h b/ObjectiveRocks/RocksDBColumnFamily.h index f3e19b8..369cef4 100644 --- a/ObjectiveRocks/RocksDBColumnFamily.h +++ b/ObjectiveRocks/RocksDBColumnFamily.h @@ -9,11 +9,6 @@ #import "RocksDB.h" #import "RocksDBOptions.h" -namespace rocksdb { - class DB; - class ColumnFamilyHandle; -} - @interface RocksDBColumnFamily : RocksDB - (instancetype)initWithPath:(NSString *)path __attribute__((unavailable("Create column family via a RocksDB instance"))); @@ -27,10 +22,6 @@ namespace rocksdb { - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions:(void (^)(RocksDBColumnFamilyOptions *options))optionsBlock __attribute__((unavailable("Use the superclass RocksDB instead"))); -- (instancetype)initWithDBInstance:(rocksdb::DB *)db - columnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily - andOptions:(RocksDBOptions *)options; - - (void)drop; @end diff --git a/ObjectiveRocks/RocksDBColumnFamily.mm b/ObjectiveRocks/RocksDBColumnFamily.mm index dd48ada..c5a3560 100644 --- a/ObjectiveRocks/RocksDBColumnFamily.mm +++ b/ObjectiveRocks/RocksDBColumnFamily.mm @@ -7,17 +7,10 @@ // #import "RocksDBColumnFamily.h" +#import "RocksDB+Private.h" #import -@interface RocksDB (Private) -@property (nonatomic, assign) rocksdb::DB *db; -@property (nonatomic, assign) rocksdb::ColumnFamilyHandle *columnFamily; -@property (nonatomic, retain) RocksDBOptions *options; -@property (nonatomic, retain) RocksDBReadOptions *readOptions; -@property (nonatomic, retain) RocksDBWriteOptions *writeOptions; -@end - @implementation RocksDBColumnFamily - (instancetype)initWithDBInstance:(rocksdb::DB *)db diff --git a/ObjectiveRocks/RocksDBColumnFamilyMetaData+Private.h b/ObjectiveRocks/RocksDBColumnFamilyMetaData+Private.h new file mode 100644 index 0000000..30aa48b --- /dev/null +++ b/ObjectiveRocks/RocksDBColumnFamilyMetaData+Private.h @@ -0,0 +1,33 @@ +// +// RocksDBColumnFamilyMetaData+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBColumnFamilyMetaData.h" + +namespace rocksdb { + class ColumnFamilyMetaData; + class LevelMetaData; + class SstFileMetaData; +} + +@interface RocksDBColumnFamilyMetaData (Private) + +- (instancetype)initWithMetaData:(rocksdb::ColumnFamilyMetaData)metadata; + +@end + +@interface RocksDBLevelFileMetaData (Private) + +- (instancetype)initWithLevelMetaData:(rocksdb::LevelMetaData)metadata; + +@end + +@interface RocksDBSstFileMetaData (Private) + +- (instancetype)initWithSstFileMetaData:(rocksdb::SstFileMetaData)metadata; + +@end diff --git a/ObjectiveRocks/RocksDBColumnFamilyMetadata.h b/ObjectiveRocks/RocksDBColumnFamilyMetadata.h index c93fad8..bba03a0 100644 --- a/ObjectiveRocks/RocksDBColumnFamilyMetadata.h +++ b/ObjectiveRocks/RocksDBColumnFamilyMetadata.h @@ -8,16 +8,8 @@ #import -namespace rocksdb { - class ColumnFamilyMetaData; - class LevelMetaData; - class SstFileMetaData; -} - @interface RocksDBColumnFamilyMetaData : NSObject -- (instancetype)initWithMetaData:(rocksdb::ColumnFamilyMetaData)metadata; - @property (nonatomic, assign) uint64_t size; @property (nonatomic, assign) size_t fileCount; @property (nonatomic, assign) NSString *name; @@ -27,8 +19,6 @@ namespace rocksdb { @interface RocksDBLevelFileMetaData : NSObject -- (instancetype)initWithLevelMetaData:(rocksdb::LevelMetaData)metadata; - @property (nonatomic, assign) const int level; @property (nonatomic, assign) const uint64_t size; @property (nonatomic, strong, readonly) NSArray *files; @@ -37,8 +27,6 @@ namespace rocksdb { @interface RocksDBSstFileMetaData : NSObject -- (instancetype)initWithSstFileMetaData:(rocksdb::SstFileMetaData)metadata; - @property (nonatomic, assign) uint64_t size; @property (nonatomic, assign) NSString *name; @property (nonatomic, assign) NSString *dbPath; diff --git a/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm b/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm index cd269dc..4f72413 100644 --- a/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm +++ b/ObjectiveRocks/RocksDBColumnFamilyMetadata.mm @@ -7,6 +7,7 @@ // #import "RocksDBColumnFamilyMetaData.h" +#import "RocksDBColumnFamilyMetaData+Private.h" #import diff --git a/ObjectiveRocks/RocksDBIterator+Private.h b/ObjectiveRocks/RocksDBIterator+Private.h new file mode 100644 index 0000000..0472f92 --- /dev/null +++ b/ObjectiveRocks/RocksDBIterator+Private.h @@ -0,0 +1,20 @@ +// +// RocksDBIterator+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBIterator.h" + +namespace rocksdb { + class Iterator; +} + +@interface RocksDBIterator (Private) + +- (instancetype)initWithDBIterator:(rocksdb::Iterator *)iterator + andEncodingOptions:(RocksDBEncodingOptions *)options; + +@end diff --git a/ObjectiveRocks/RocksDBIterator.h b/ObjectiveRocks/RocksDBIterator.h index 9ed7103..5bad6a8 100644 --- a/ObjectiveRocks/RocksDBIterator.h +++ b/ObjectiveRocks/RocksDBIterator.h @@ -9,28 +9,23 @@ #import #import "RocksDBEncodingOptions.h" -typedef struct RocksDBIteratorKeyRange -{ - id start; - id end; -} RocksDBIteratorKeyRange; - -NS_INLINE RocksDBIteratorKeyRange RocksDBMakeKeyRange(id start, id end) { - RocksDBIteratorKeyRange range = (RocksDBIteratorKeyRange) { - .start = start, - .end = end - }; - return range; -} +@interface RocksDBIteratorKeyRange : NSObject -namespace rocksdb { - class Iterator; +@property (nonatomic, strong) id start; +@property (nonatomic, strong) id end; + +@end + +NS_INLINE RocksDBIteratorKeyRange * RocksDBMakeKeyRange(id start, id end) { + RocksDBIteratorKeyRange *range = [RocksDBIteratorKeyRange new]; + range.start = start; + range.end = end; + + return range; } @interface RocksDBIterator : NSObject -- (instancetype)initWithDBIterator:(rocksdb::Iterator *)iterator - andEncodingOptions:(RocksDBEncodingOptions *)options; - (void)close; - (BOOL)isValid; @@ -44,11 +39,11 @@ namespace rocksdb { - (void)enumerateKeysUsingBlock:(void (^)(id key, BOOL *stop))block; - (void)enumerateKeysInReverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block; -- (void)enumerateKeysInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block; +- (void)enumerateKeysInRange:(RocksDBIteratorKeyRange *)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block; - (void)enumerateKeysAndValuesUsingBlock:(void (^)(id key, id value, BOOL *stop))block; - (void)enumerateKeysAndValuesInReverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; -- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; +- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange *)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block; - (void)enumerateKeysWithPrefix:(id)prefix usingBlock:(void (^)(id key, BOOL *stop))block; - (void)enumerateKeysAndValuesWithPrefix:(id)prefix usingBlock:(void (^)(id key, id value, BOOL *stop))block; diff --git a/ObjectiveRocks/RocksDBIterator.mm b/ObjectiveRocks/RocksDBIterator.mm index 32b776f..8795e60 100644 --- a/ObjectiveRocks/RocksDBIterator.mm +++ b/ObjectiveRocks/RocksDBIterator.mm @@ -11,7 +11,15 @@ #import -static RocksDBIteratorKeyRange RocksDBEmptyRange = RocksDBMakeKeyRange(nil, nil); +#pragma mark - Iterator Key Range + +static RocksDBIteratorKeyRange *RocksDBEmptyRange = RocksDBMakeKeyRange(nil, nil); + +@implementation RocksDBIteratorKeyRange + +@end + +#pragma mark - Iterator @interface RocksDBIterator () { @@ -114,7 +122,7 @@ - (void)enumerateKeysInReverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL * }]; } -- (void)enumerateKeysInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block +- (void)enumerateKeysInRange:(RocksDBIteratorKeyRange *)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, BOOL *stop))block { [self enumerateKeysAndValuesInRange:range reverse:reverse usingBlock:^(id key, id value, BOOL *stop) { block(key, stop); @@ -133,7 +141,7 @@ - (void)enumerateKeysAndValuesInReverse:(BOOL)reverse usingBlock:(void (^)(id ke [self enumerateKeysAndValuesInRange:RocksDBEmptyRange reverse:reverse usingBlock:block]; } -- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block +- (void)enumerateKeysAndValuesInRange:(RocksDBIteratorKeyRange *)range reverse:(BOOL)reverse usingBlock:(void (^)(id key, id value, BOOL *stop))block { BOOL stop = NO; diff --git a/ObjectiveRocks/RocksDBSnapshot+Private.h b/ObjectiveRocks/RocksDBSnapshot+Private.h new file mode 100644 index 0000000..e292532 --- /dev/null +++ b/ObjectiveRocks/RocksDBSnapshot+Private.h @@ -0,0 +1,22 @@ +// +// RocksDBSnapshot+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBSnapshot.h" + +namespace rocksdb { + class DB; + class ColumnFamilyHandle; +} + +@interface RocksDBSnapshot (Private) + +- (instancetype)initWithDBInstance:(rocksdb::DB *)db + columnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily + andReadOptions:(RocksDBReadOptions *)readOptions; + +@end diff --git a/ObjectiveRocks/RocksDBSnapshot.h b/ObjectiveRocks/RocksDBSnapshot.h index 4814e1c..80fa31a 100644 --- a/ObjectiveRocks/RocksDBSnapshot.h +++ b/ObjectiveRocks/RocksDBSnapshot.h @@ -11,17 +11,8 @@ #import "RocksDBReadOptions.h" #import "RocksDBSnapshotUnavailable.h" -namespace rocksdb { - class DB; - class ColumnFamilyHandle; -} - @interface RocksDBSnapshot : RocksDB -- (instancetype)initWithDBInstance:(rocksdb::DB *)db - columnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily - andReadOptions:(RocksDBReadOptions *)readOptions; - @end @interface RocksDBSnapshot (Unavailable) diff --git a/ObjectiveRocks/RocksDBSnapshot.mm b/ObjectiveRocks/RocksDBSnapshot.mm index 6a0e42d..7a734d6 100644 --- a/ObjectiveRocks/RocksDBSnapshot.mm +++ b/ObjectiveRocks/RocksDBSnapshot.mm @@ -7,17 +7,10 @@ // #import "RocksDBSnapshot.h" +#import "RocksDB+Private.h" #import -@interface RocksDB (Private) -@property (nonatomic, assign) rocksdb::DB *db; -@property (nonatomic, assign) rocksdb::ColumnFamilyHandle *columnFamily; -@property (nonatomic, retain) RocksDBOptions *options; -@property (nonatomic, retain) RocksDBReadOptions *readOptions; -@property (nonatomic, retain) RocksDBWriteOptions *writeOptions; -@end - @interface RocksDBReadOptions (Private) @property (nonatomic, assign) rocksdb::ReadOptions options; @end diff --git a/ObjectiveRocks/RocksDBWriteBatch+Private.h b/ObjectiveRocks/RocksDBWriteBatch+Private.h new file mode 100644 index 0000000..09adbc3 --- /dev/null +++ b/ObjectiveRocks/RocksDBWriteBatch+Private.h @@ -0,0 +1,23 @@ +// +// RocksDBWriteBatch+Private.h +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import "RocksDBWriteBatch.h" + +namespace rocksdb { + class ColumnFamilyHandle; + class WriteBatch; +} + +@interface RocksDBWriteBatch (Private) + +@property (nonatomic, readonly) rocksdb::WriteBatch writeBatch; + +- (instancetype)initWithColumnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily + andEncodingOptions:(RocksDBEncodingOptions *)options; + +@end diff --git a/ObjectiveRocks/RocksDBWriteBatch.h b/ObjectiveRocks/RocksDBWriteBatch.h index 149b50a..ef47c7e 100644 --- a/ObjectiveRocks/RocksDBWriteBatch.h +++ b/ObjectiveRocks/RocksDBWriteBatch.h @@ -11,15 +11,8 @@ @class RocksDBColumnFamily; -namespace rocksdb { - class ColumnFamilyHandle; -} - @interface RocksDBWriteBatch : NSObject -- (instancetype)initWithColumnFamily:(rocksdb::ColumnFamilyHandle *)columnFamily - andEncodingOptions:(RocksDBEncodingOptions *)options; - - (void)setObject:(id)anObject forKey:(id)aKey; - (void)setData:(NSData *)data forKey:(NSData *)aKey; - (void)setObject:(id)anObject forKey:(id)aKey inColumnFamily:(RocksDBColumnFamily *)columnFamily; diff --git a/ObjectiveRocks/RocksDBWriteBatch.mm b/ObjectiveRocks/RocksDBWriteBatch.mm index bdad9a3..688988e 100644 --- a/ObjectiveRocks/RocksDBWriteBatch.mm +++ b/ObjectiveRocks/RocksDBWriteBatch.mm @@ -8,14 +8,11 @@ #import "RocksDBWriteBatch.h" #import "RocksDBColumnFamily.h" +#import "RocksDBColumnFamily+Private.h" #import "RocksDBSlice.h" #import -@interface RocksDBColumnFamily (Private) -@property (nonatomic, assign) rocksdb::ColumnFamilyHandle *columnFamily; -@end - @interface RocksDBWriteBatch () { RocksDBEncodingOptions *_encodingOptions; diff --git a/ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h b/ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h new file mode 100644 index 0000000..7fbf23d --- /dev/null +++ b/ObjectiveRocksTests/ObjectiveRocksTests-Bridging-Header.h @@ -0,0 +1,53 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import + +#import "RocksDB.h" + +#import "RocksDBColumnFamily.h" +#import "RocksDBColumnFamilyDescriptor.h" + +#import "RocksDBIterator.h" +#import "RocksDBPrefixExtractor.h" + +#import "RocksDBWriteBatch.h" + +#import "RocksDBComparator.h" + +#import "RocksDBOptions.h" +#import "RocksDBEncodingOptions.h" +#import "RocksDBDatabaseOptions.h" +#import "RocksDBColumnFamilyOptions.h" +#import "RocksDBWriteOptions.h" +#import "RocksDBReadOptions.h" +#import "RocksDBTableFactory.h" +#import "RocksDBBlockBasedTableOptions.h" +#import "RocksDBCache.h" +#import "RocksDBFilterPolicy.h" +#import "RocksDBMemTableRepFactory.h" +#import "RocksDBEnv.h" + +#import "RocksDBSnapshot.h" + +#import "RocksDBMergeOperator.h" + +#import "RocksDBTypes.h" + +#import "RocksDBColumnFamilyMetadata.h" + +#import "RocksDBPlainTableOptions.h" +#import "RocksDBCuckooTableOptions.h" + +#import "RocksDBThreadStatus.h" + +#import "RocksDBCheckpoint.h" + +#import "RocksDBStatistics.h" +#import "RocksDBStatisticsHistogram.h" + +#import "RocksDBBackupEngine.h" +#import "RocksDBBackupInfo.h" + +#import "RocksDBProperties.h" diff --git a/ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h b/ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h new file mode 100644 index 0000000..bc29ef2 --- /dev/null +++ b/ObjectiveRocksTests/ObjectiveRocksTests-iOS-Bridging-Header.h @@ -0,0 +1,34 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "RocksDB.h" + +#import "RocksDBColumnFamily.h" +#import "RocksDBColumnFamilyDescriptor.h" + +#import "RocksDBIterator.h" +#import "RocksDBPrefixExtractor.h" + +#import "RocksDBWriteBatch.h" + +#import "RocksDBComparator.h" + +#import "RocksDBOptions.h" +#import "RocksDBEncodingOptions.h" +#import "RocksDBDatabaseOptions.h" +#import "RocksDBColumnFamilyOptions.h" +#import "RocksDBWriteOptions.h" +#import "RocksDBReadOptions.h" +#import "RocksDBTableFactory.h" +#import "RocksDBBlockBasedTableOptions.h" +#import "RocksDBCache.h" +#import "RocksDBFilterPolicy.h" +#import "RocksDBMemTableRepFactory.h" +#import "RocksDBEnv.h" + +#import "RocksDBSnapshot.h" + +#import "RocksDBMergeOperator.h" + +#import "RocksDBTypes.h" diff --git a/ObjectiveRocksTests/RockDBTests.swift b/ObjectiveRocksTests/RockDBTests.swift new file mode 100644 index 0000000..a8e3064 --- /dev/null +++ b/ObjectiveRocksTests/RockDBTests.swift @@ -0,0 +1,32 @@ +// +// RockDBTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import Foundation +import XCTest + +class RocksDBTests : XCTestCase { + + var path: String = "" + var rocks: RocksDB? = nil + + override func setUp() { + super.setUp() + let bundle = NSBundle(forClass: self.dynamicType) + path = bundle.bundlePath.stringByAppendingPathComponent("ObjectiveRocks") + cleanupDatabse() + } + + override func tearDown() { + super.tearDown() + cleanupDatabse() + } + + func cleanupDatabse() { + NSFileManager.defaultManager().removeItemAtPath(path, error: nil) + } +} \ No newline at end of file From 56a4e1105da9d4e6e847711dee33f0b6cebd65d1 Mon Sep 17 00:00:00 2001 From: iska Date: Sun, 11 Jan 2015 22:26:45 +0100 Subject: [PATCH 18/22] Add Swift RocksDB tests All previous test cases in Swift --- ObjectiveRocks.xcodeproj/project.pbxproj | 88 ++++- ObjectiveRocksTests/RockDBTests.swift | 57 ++- ObjectiveRocksTests/RocksDBBackupTests.swift | 211 ++++++++++ ObjectiveRocksTests/RocksDBBasicTests.swift | 84 ++++ .../RocksDBCheckpointTests.swift | 46 +++ ....m => RocksDBColumnFamilyMetadataTests.mm} | 0 .../RocksDBColumnFamilyMetadataTests.swift | 38 ++ .../RocksDBColumnFamilyTests.swift | 290 ++++++++++++++ .../RocksDBComparatorTests.swift | 254 ++++++++++++ .../RocksDBIteratorTests.swift | 371 ++++++++++++++++++ .../RocksDBMergeOperatorTests.swift | 167 ++++++++ .../RocksDBPrefixExtractorTests.swift | 140 +++++++ .../RocksDBPropertiesTests.swift | 48 +++ .../RocksDBSnapshotTests.swift | 73 ++++ .../RocksDBStatisticsTests.swift | 65 +++ ObjectiveRocksTests/RocksDBTests.mm | 4 +- .../RocksDBWriteBatchTests.swift | 212 ++++++++++ 17 files changed, 2136 insertions(+), 12 deletions(-) create mode 100644 ObjectiveRocksTests/RocksDBBackupTests.swift create mode 100644 ObjectiveRocksTests/RocksDBBasicTests.swift create mode 100644 ObjectiveRocksTests/RocksDBCheckpointTests.swift rename ObjectiveRocksTests/{RocksDBColumnFamilyMetadataTests.m => RocksDBColumnFamilyMetadataTests.mm} (100%) create mode 100644 ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.swift create mode 100644 ObjectiveRocksTests/RocksDBColumnFamilyTests.swift create mode 100644 ObjectiveRocksTests/RocksDBComparatorTests.swift create mode 100644 ObjectiveRocksTests/RocksDBIteratorTests.swift create mode 100644 ObjectiveRocksTests/RocksDBMergeOperatorTests.swift create mode 100644 ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift create mode 100644 ObjectiveRocksTests/RocksDBPropertiesTests.swift create mode 100644 ObjectiveRocksTests/RocksDBSnapshotTests.swift create mode 100644 ObjectiveRocksTests/RocksDBStatisticsTests.swift create mode 100644 ObjectiveRocksTests/RocksDBWriteBatchTests.swift diff --git a/ObjectiveRocks.xcodeproj/project.pbxproj b/ObjectiveRocks.xcodeproj/project.pbxproj index 3d118f7..3561598 100644 --- a/ObjectiveRocks.xcodeproj/project.pbxproj +++ b/ObjectiveRocks.xcodeproj/project.pbxproj @@ -14,7 +14,18 @@ 6206296A1A510D36001DEDC4 /* RocksDBColumnFamily.mm in Sources */ = {isa = PBXBuildFile; fileRef = 620629691A510D36001DEDC4 /* RocksDBColumnFamily.mm */; }; 62074F2D1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62074F2C1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.mm */; }; 620A2CAE1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 620A2CAD1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm */; }; + 62102D421A643A13007E63F0 /* RocksDBComparatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62102D411A643A13007E63F0 /* RocksDBComparatorTests.swift */; }; + 62102D431A643A13007E63F0 /* RocksDBComparatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62102D411A643A13007E63F0 /* RocksDBComparatorTests.swift */; }; 6214FD091A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6214FD071A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp */; }; + 6216360D1A62C9FB00B132CE /* RocksDBBasicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216360C1A62C9FB00B132CE /* RocksDBBasicTests.swift */; }; + 6216360E1A62C9FB00B132CE /* RocksDBBasicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216360C1A62C9FB00B132CE /* RocksDBBasicTests.swift */; }; + 621636101A62D1BE00B132CE /* RocksDBWriteBatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216360F1A62D1BE00B132CE /* RocksDBWriteBatchTests.swift */; }; + 621636111A62D1BE00B132CE /* RocksDBWriteBatchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216360F1A62D1BE00B132CE /* RocksDBWriteBatchTests.swift */; }; + 621636131A62DF9400B132CE /* RocksDBPropertiesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621636121A62DF9400B132CE /* RocksDBPropertiesTests.swift */; }; + 621636151A62E47A00B132CE /* RocksDBSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621636141A62E47A00B132CE /* RocksDBSnapshotTests.swift */; }; + 621636161A62E47A00B132CE /* RocksDBSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621636141A62E47A00B132CE /* RocksDBSnapshotTests.swift */; }; + 621636181A631CE100B132CE /* RocksDBCheckpointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621636171A631CE100B132CE /* RocksDBCheckpointTests.swift */; }; + 6216361B1A631F2900B132CE /* RocksDBStatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6216361A1A631F2900B132CE /* RocksDBStatisticsTests.swift */; }; 621CD71C1A4FB24700853E16 /* RocksDBBackupEngine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 621CD71B1A4FB24700853E16 /* RocksDBBackupEngine.mm */; }; 6221B7A71A629E1B00D28BF5 /* RockDBTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */; }; 6221B7A81A629E2700D28BF5 /* RockDBTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */; }; @@ -40,6 +51,8 @@ 62451AD21A4BC85400AF11C8 /* thread_status_updater.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62451ACD1A4BC85400AF11C8 /* thread_status_updater.cc */; }; 62451AD31A4BC85400AF11C8 /* thread_status_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62451ACF1A4BC85400AF11C8 /* thread_status_util.cc */; }; 624566C81A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 624566C71A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm */; }; + 62456CBB1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62456CBA1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift */; }; + 62456CBC1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62456CBA1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift */; }; 6249A3CC1A4A43CA00949B07 /* RocksDBTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6249A3CB1A4A43CA00949B07 /* RocksDBTests.mm */; }; 625F8F1C1A59C3EB007796BA /* RocksDBProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 625F8F1B1A59C3EB007796BA /* RocksDBProperties.m */; }; 625F8F1D1A59C3EB007796BA /* RocksDBProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 625F8F1B1A59C3EB007796BA /* RocksDBProperties.m */; }; @@ -106,8 +119,12 @@ 625F8F871A5A229C007796BA /* RocksDBMergeOperator.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 62EEC4B51A34FEE100624DA2 /* RocksDBMergeOperator.h */; }; 62685CB91A2E600A009401B1 /* RocksDBWriteBatchTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62685CB81A2E600A009401B1 /* RocksDBWriteBatchTests.mm */; }; 628B0CEA1A1C104D0099C39B /* RocksDBError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 628B0CE91A1C104D0099C39B /* RocksDBError.mm */; }; + 629416631A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629416621A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift */; }; + 629416641A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 629416621A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift */; }; 6299F80F1A17B28200123F56 /* RocksDB.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6299F80E1A17B28200123F56 /* RocksDB.mm */; }; 6299F8561A17B7AD00123F56 /* RocksDBBasicTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */; }; + 62A37D141A632316003F6095 /* RocksDBIteratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A37D131A632316003F6095 /* RocksDBIteratorTests.swift */; }; + 62A37D151A632316003F6095 /* RocksDBIteratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62A37D131A632316003F6095 /* RocksDBIteratorTests.swift */; }; 62A74F861A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62A74F851A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.mm */; }; 62A8AF981A58C30E0069B4C8 /* memtable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE29611A1ABA1F00486C31 /* memtable.cc */; }; 62A8AF991A58C30E0069B4C8 /* hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE2B3F1A1ABA2000486C31 /* hash.cc */; }; @@ -282,6 +299,7 @@ 62A8B0691A58E4B60069B4C8 /* RocksDBStatisticsHistogram.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62A8B0681A58E4B60069B4C8 /* RocksDBStatisticsHistogram.mm */; }; 62A8B06B1A5900540069B4C8 /* RocksDBStatisticsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62A8B06A1A5900540069B4C8 /* RocksDBStatisticsTests.mm */; }; 62AEF9BB1A1D5DA900E63E89 /* RocksDBOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62AEF9BA1A1D5DA900E63E89 /* RocksDBOptions.mm */; }; + 62E173E61A6AD40E00A00DF3 /* RocksDBBackupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E173E51A6AD40E00A00DF3 /* RocksDBBackupTests.swift */; }; 62EE2BD81A1ABA2000486C31 /* builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE29141A1ABA1F00486C31 /* builder.cc */; }; 62EE2BDA1A1ABA2000486C31 /* c.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE29171A1ABA1F00486C31 /* c.cc */; }; 62EE2BDD1A1ABA2000486C31 /* column_family.cc in Sources */ = {isa = PBXBuildFile; fileRef = 62EE291A1A1ABA1F00486C31 /* column_family.cc */; }; @@ -415,6 +433,10 @@ 62F3ED551A57212800EBFEBF /* RocksDBCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62F3ED541A57212800EBFEBF /* RocksDBCache.mm */; }; 62F3ED581A5727A300EBFEBF /* RocksDBFilterPolicy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62F3ED571A5727A300EBFEBF /* RocksDBFilterPolicy.mm */; }; 62F3ED5B1A574F7500EBFEBF /* RocksDBTableFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62F3ED5A1A574F7500EBFEBF /* RocksDBTableFactory.mm */; }; + 62F4AA7C1A6AAF9A00489D6C /* RocksDBColumnFamilyMetadataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4AA7B1A6AAF9A00489D6C /* RocksDBColumnFamilyMetadataTests.swift */; }; + 62F4AA7E1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4AA7D1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift */; }; + 62F4AA7F1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62F4AA7D1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift */; }; + 62F4AA801A6AAFE500489D6C /* RocksDBColumnFamilyMetadataTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.mm */; }; 62FC8B471A565B19003DF5C6 /* RocksDBBackupTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 62FC8B461A565B19003DF5C6 /* RocksDBBackupTests.mm */; }; /* End PBXBuildFile section */ @@ -524,8 +546,15 @@ 62074F2B1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBColumnFamilyDescriptor.h; sourceTree = ""; }; 62074F2C1A520EC2002B1885 /* RocksDBColumnFamilyDescriptor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBColumnFamilyDescriptor.mm; sourceTree = ""; }; 620A2CAD1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBMergeOperatorTests.mm; sourceTree = ""; }; + 62102D411A643A13007E63F0 /* RocksDBComparatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBComparatorTests.swift; sourceTree = ""; }; 6214FD071A3F698300B92E5C /* RocksDBCallbackMergeOperator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RocksDBCallbackMergeOperator.cpp; sourceTree = ""; }; 6214FD081A3F698300B92E5C /* RocksDBCallbackMergeOperator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBCallbackMergeOperator.h; sourceTree = ""; }; + 6216360C1A62C9FB00B132CE /* RocksDBBasicTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBBasicTests.swift; sourceTree = ""; }; + 6216360F1A62D1BE00B132CE /* RocksDBWriteBatchTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBWriteBatchTests.swift; sourceTree = ""; }; + 621636121A62DF9400B132CE /* RocksDBPropertiesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBPropertiesTests.swift; sourceTree = ""; }; + 621636141A62E47A00B132CE /* RocksDBSnapshotTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBSnapshotTests.swift; sourceTree = ""; }; + 621636171A631CE100B132CE /* RocksDBCheckpointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBCheckpointTests.swift; sourceTree = ""; }; + 6216361A1A631F2900B132CE /* RocksDBStatisticsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBStatisticsTests.swift; sourceTree = ""; }; 621CD71A1A4FB24700853E16 /* RocksDBBackupEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBBackupEngine.h; sourceTree = ""; }; 621CD71B1A4FB24700853E16 /* RocksDBBackupEngine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBackupEngine.mm; sourceTree = ""; }; 6221B78A1A62970800D28BF5 /* RocksDB+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RocksDB+Private.h"; sourceTree = ""; }; @@ -582,6 +611,7 @@ 62451AD41A4BD61700AF11C8 /* sst_dump_tool.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sst_dump_tool.cc; sourceTree = ""; }; 62451AD51A4BD63D00AF11C8 /* sst_dump_test.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sst_dump_test.cc; sourceTree = ""; }; 624566C71A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBColumnFamilyTests.mm; sourceTree = ""; }; + 62456CBA1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBMergeOperatorTests.swift; sourceTree = ""; }; 6249A3CB1A4A43CA00949B07 /* RocksDBTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBTests.mm; sourceTree = ""; }; 6249A3CD1A4A6E4000949B07 /* RocksDBTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RocksDBTests.h; sourceTree = ""; }; 625F8F1A1A59C3EB007796BA /* RocksDBProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBProperties.h; sourceTree = ""; }; @@ -606,16 +636,18 @@ 626A7D521A27EC570098A979 /* rdb.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rdb.cc; sourceTree = ""; }; 626A7D531A27EC570098A979 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 626A7D541A27EC570098A979 /* unit_test.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = unit_test.js; sourceTree = ""; }; - 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RocksDBColumnFamilyMetadataTests.m; sourceTree = ""; }; + 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBColumnFamilyMetadataTests.mm; sourceTree = ""; }; 628B0CE81A1C104D0099C39B /* RocksDBError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBError.h; sourceTree = ""; }; 628B0CE91A1C104D0099C39B /* RocksDBError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBError.mm; sourceTree = ""; }; 628C51C71A3BD08500B96F8F /* RocksDBSnapshotUnavailable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RocksDBSnapshotUnavailable.h; sourceTree = ""; }; + 629416621A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBPrefixExtractorTests.swift; sourceTree = ""; }; 6299F8091A17B28200123F56 /* libObjectiveRocks.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libObjectiveRocks.a; sourceTree = BUILT_PRODUCTS_DIR; }; 6299F80C1A17B28200123F56 /* RocksDB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RocksDB.h; sourceTree = ""; }; 6299F80E1A17B28200123F56 /* RocksDB.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDB.mm; sourceTree = ""; }; 6299F8141A17B28200123F56 /* ObjectiveRocksTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ObjectiveRocksTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6299F81A1A17B28200123F56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBasicTests.mm; sourceTree = ""; }; + 62A37D131A632316003F6095 /* RocksDBIteratorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBIteratorTests.swift; sourceTree = ""; }; 62A74F821A6037F500BAD95B /* thread_operation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = thread_operation.h; sourceTree = ""; }; 62A74F831A60385D00BAD95B /* memtablerep_bench.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memtablerep_bench.cc; sourceTree = ""; }; 62A74F841A603DDB00BAD95B /* RocksDBColumnFamilyMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBColumnFamilyMetadata.h; sourceTree = ""; }; @@ -632,6 +664,7 @@ 62AEF9B81A1D5CF000E63E89 /* ObjectiveRocks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectiveRocks.h; sourceTree = ""; }; 62AEF9B91A1D5DA900E63E89 /* RocksDBOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBOptions.h; sourceTree = ""; }; 62AEF9BA1A1D5DA900E63E89 /* RocksDBOptions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBOptions.mm; sourceTree = ""; }; + 62E173E51A6AD40E00A00DF3 /* RocksDBBackupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBBackupTests.swift; sourceTree = ""; }; 62EE28FE1A1ABA1F00486C31 /* .arcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .arcconfig; sourceTree = ""; }; 62EE28FF1A1ABA1F00486C31 /* .clang-format */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ".clang-format"; sourceTree = ""; }; 62EE29001A1ABA1F00486C31 /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; @@ -1072,6 +1105,8 @@ 62F3ED571A5727A300EBFEBF /* RocksDBFilterPolicy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBFilterPolicy.mm; sourceTree = ""; }; 62F3ED591A574F7500EBFEBF /* RocksDBTableFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RocksDBTableFactory.h; sourceTree = ""; }; 62F3ED5A1A574F7500EBFEBF /* RocksDBTableFactory.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBTableFactory.mm; sourceTree = ""; }; + 62F4AA7B1A6AAF9A00489D6C /* RocksDBColumnFamilyMetadataTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBColumnFamilyMetadataTests.swift; sourceTree = ""; }; + 62F4AA7D1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RocksDBColumnFamilyTests.swift; sourceTree = ""; }; 62FC8B461A565B19003DF5C6 /* RocksDBBackupTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RocksDBBackupTests.mm; sourceTree = ""; }; /* End PBXFileReference section */ @@ -1142,6 +1177,29 @@ name = "Column Family"; sourceTree = ""; }; + 621636191A631E4F00B132CE /* Swift */ = { + isa = PBXGroup; + children = ( + 6221B7A21A629B3500D28BF5 /* ObjectiveRocksTests-Bridging-Header.h */, + 6221B7A31A629B3500D28BF5 /* ObjectiveRocksTests-iOS-Bridging-Header.h */, + 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */, + 6216360C1A62C9FB00B132CE /* RocksDBBasicTests.swift */, + 6216360F1A62D1BE00B132CE /* RocksDBWriteBatchTests.swift */, + 62A37D131A632316003F6095 /* RocksDBIteratorTests.swift */, + 62102D411A643A13007E63F0 /* RocksDBComparatorTests.swift */, + 621636141A62E47A00B132CE /* RocksDBSnapshotTests.swift */, + 621636171A631CE100B132CE /* RocksDBCheckpointTests.swift */, + 62456CBA1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift */, + 629416621A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift */, + 62F4AA7D1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift */, + 62F4AA7B1A6AAF9A00489D6C /* RocksDBColumnFamilyMetadataTests.swift */, + 62E173E51A6AD40E00A00DF3 /* RocksDBBackupTests.swift */, + 6216361A1A631F2900B132CE /* RocksDBStatisticsTests.swift */, + 621636121A62DF9400B132CE /* RocksDBPropertiesTests.swift */, + ); + name = Swift; + sourceTree = ""; + }; 621CD7191A4FB22C00853E16 /* Backup */ = { isa = PBXGroup; children = ( @@ -1329,11 +1387,9 @@ 6299F8181A17B28200123F56 /* ObjectiveRocksTests */ = { isa = PBXGroup; children = ( - 6221B7A21A629B3500D28BF5 /* ObjectiveRocksTests-Bridging-Header.h */, - 6221B7A31A629B3500D28BF5 /* ObjectiveRocksTests-iOS-Bridging-Header.h */, + 621636191A631E4F00B132CE /* Swift */, 6249A3CD1A4A6E4000949B07 /* RocksDBTests.h */, 6249A3CB1A4A43CA00949B07 /* RocksDBTests.mm */, - 6221B7A41A629B3600D28BF5 /* RockDBTests.swift */, 6299F8551A17B7AD00123F56 /* RocksDBBasicTests.mm */, 62685CB81A2E600A009401B1 /* RocksDBWriteBatchTests.mm */, 62385EB31A2FCFB100493F18 /* RocksDBIteratorTests.mm */, @@ -1343,7 +1399,7 @@ 620A2CAD1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm */, 6236E25B1A4E19A300A81ED6 /* RocksDBPrefixExtractorTests.mm */, 624566C71A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm */, - 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.m */, + 627FBE761A61E0AA0038696A /* RocksDBColumnFamilyMetadataTests.mm */, 62FC8B461A565B19003DF5C6 /* RocksDBBackupTests.mm */, 62A8B06A1A5900540069B4C8 /* RocksDBStatisticsTests.mm */, 625F8F1E1A59C9B3007796BA /* RocksDBPropertiesTests.mm */, @@ -2418,20 +2474,34 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62456CBB1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift in Sources */, + 62F4AA801A6AAFE500489D6C /* RocksDBColumnFamilyMetadataTests.mm in Sources */, 6299F8561A17B7AD00123F56 /* RocksDBBasicTests.mm in Sources */, + 62F4AA7E1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift in Sources */, + 62A37D141A632316003F6095 /* RocksDBIteratorTests.swift in Sources */, + 629416631A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift in Sources */, + 6216361B1A631F2900B132CE /* RocksDBStatisticsTests.swift in Sources */, 62FC8B471A565B19003DF5C6 /* RocksDBBackupTests.mm in Sources */, + 62E173E61A6AD40E00A00DF3 /* RocksDBBackupTests.swift in Sources */, + 62102D421A643A13007E63F0 /* RocksDBComparatorTests.swift in Sources */, + 62F4AA7C1A6AAF9A00489D6C /* RocksDBColumnFamilyMetadataTests.swift in Sources */, 6221B7A71A629E1B00D28BF5 /* RockDBTests.swift in Sources */, + 621636181A631CE100B132CE /* RocksDBCheckpointTests.swift in Sources */, 625F8F251A59D11D007796BA /* RocksDBCheckpointTests.mm in Sources */, 6249A3CC1A4A43CA00949B07 /* RocksDBTests.mm in Sources */, 62A8B06B1A5900540069B4C8 /* RocksDBStatisticsTests.mm in Sources */, 624566C81A51DA79009AC3FB /* RocksDBColumnFamilyTests.mm in Sources */, 62385EB41A2FCFB100493F18 /* RocksDBIteratorTests.mm in Sources */, + 621636151A62E47A00B132CE /* RocksDBSnapshotTests.swift in Sources */, 62385EB61A2FD05500493F18 /* RocksDBComparatorTests.mm in Sources */, 625F8F1F1A59C9B3007796BA /* RocksDBPropertiesTests.mm in Sources */, 623DC2561A335BAF00B61B18 /* RocksDBSnapshotTests.mm in Sources */, 6236E25C1A4E19A300A81ED6 /* RocksDBPrefixExtractorTests.mm in Sources */, + 621636131A62DF9400B132CE /* RocksDBPropertiesTests.swift in Sources */, + 6216360D1A62C9FB00B132CE /* RocksDBBasicTests.swift in Sources */, 62685CB91A2E600A009401B1 /* RocksDBWriteBatchTests.mm in Sources */, 620A2CAE1A3654D5007224A4 /* RocksDBMergeOperatorTests.mm in Sources */, + 621636101A62D1BE00B132CE /* RocksDBWriteBatchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2607,14 +2677,22 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 62F4AA7F1A6AAFD700489D6C /* RocksDBColumnFamilyTests.swift in Sources */, 6221B7A81A629E2700D28BF5 /* RockDBTests.swift in Sources */, + 62456CBC1A66FE0500329F11 /* RocksDBMergeOperatorTests.swift in Sources */, 62A8B0481A58C40A0069B4C8 /* RocksDBBasicTests.mm in Sources */, 62A8B0491A58C40A0069B4C8 /* RocksDBTests.mm in Sources */, + 62102D431A643A13007E63F0 /* RocksDBComparatorTests.swift in Sources */, + 621636161A62E47A00B132CE /* RocksDBSnapshotTests.swift in Sources */, + 629416641A69DFB000AA0498 /* RocksDBPrefixExtractorTests.swift in Sources */, + 621636111A62D1BE00B132CE /* RocksDBWriteBatchTests.swift in Sources */, 62A8B04A1A58C40A0069B4C8 /* RocksDBColumnFamilyTests.mm in Sources */, 62A8B04B1A58C40A0069B4C8 /* RocksDBIteratorTests.mm in Sources */, 62A8B04C1A58C40A0069B4C8 /* RocksDBComparatorTests.mm in Sources */, + 62A37D151A632316003F6095 /* RocksDBIteratorTests.swift in Sources */, 62A8B04D1A58C40A0069B4C8 /* RocksDBSnapshotTests.mm in Sources */, 62A8B04E1A58C40A0069B4C8 /* RocksDBPrefixExtractorTests.mm in Sources */, + 6216360E1A62C9FB00B132CE /* RocksDBBasicTests.swift in Sources */, 62A8B04F1A58C40A0069B4C8 /* RocksDBWriteBatchTests.mm in Sources */, 62A8B0501A58C40A0069B4C8 /* RocksDBMergeOperatorTests.mm in Sources */, ); diff --git a/ObjectiveRocksTests/RockDBTests.swift b/ObjectiveRocksTests/RockDBTests.swift index a8e3064..4b6fed1 100644 --- a/ObjectiveRocksTests/RockDBTests.swift +++ b/ObjectiveRocksTests/RockDBTests.swift @@ -9,24 +9,71 @@ import Foundation import XCTest +public func Data(x: String) -> NSData { + return x.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! +} + +public func Str(x: NSData) -> NSString { + return NSString(data: x, encoding: NSUTF8StringEncoding)! +} + +public func NumData(x: UInt64) -> NSData { + var val = x + return NSData(bytes: &val, length: sizeof(UInt64)) +} + +public func NumData(x: Float) -> NSData { + var val = x + return NSData(bytes: &val, length: sizeof(UInt64)) +} + +public func Val(data: NSData) -> UInt64 { + var val: UInt64 = 0 + data.getBytes(&val, length: sizeof(UInt64)) + return val +} + +public func Val(data: NSData) -> Float { + var val: Float = 0 + data.getBytes(&val, length: sizeof(Float)) + return val +} + class RocksDBTests : XCTestCase { - var path: String = "" - var rocks: RocksDB? = nil + var path: String! + var backupPath: String! + var restorePath: String! + var checkpointPath1: String! + var checkpointPath2: String! + + var rocks: RocksDB! override func setUp() { super.setUp() let bundle = NSBundle(forClass: self.dynamicType) path = bundle.bundlePath.stringByAppendingPathComponent("ObjectiveRocks") - cleanupDatabse() + backupPath = path.stringByAppendingString("Backup") + restorePath = path.stringByAppendingString("Restore") + checkpointPath1 = path.stringByAppendingString("Snapshot1") + checkpointPath2 = path.stringByAppendingString("Snapshot2") + + cleanupDatabase() } override func tearDown() { + if (rocks != nil) { + rocks.close() + } + cleanupDatabase() super.tearDown() - cleanupDatabse() } - func cleanupDatabse() { + func cleanupDatabase() { NSFileManager.defaultManager().removeItemAtPath(path, error: nil) + NSFileManager.defaultManager().removeItemAtPath(backupPath, error: nil) + NSFileManager.defaultManager().removeItemAtPath(restorePath, error: nil) + NSFileManager.defaultManager().removeItemAtPath(checkpointPath1, error: nil) + NSFileManager.defaultManager().removeItemAtPath(checkpointPath2, error: nil) } } \ No newline at end of file diff --git a/ObjectiveRocksTests/RocksDBBackupTests.swift b/ObjectiveRocksTests/RocksDBBackupTests.swift new file mode 100644 index 0000000..47574aa --- /dev/null +++ b/ObjectiveRocksTests/RocksDBBackupTests.swift @@ -0,0 +1,211 @@ +// +// RocksDBBackupTests.swift +// ObjectiveRocks +// +// Created by Iska on 17/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBBackupTests : RocksDBTests { + + func testSwift_Backup_Create() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + let exists = NSFileManager.defaultManager().fileExistsAtPath(self.backupPath) + XCTAssertTrue(exists) + } + + func testSwift_Backup_BackupInfo() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + let backupInfo = backupEngine.backupInfo() + + XCTAssertNotNil(backupInfo) + XCTAssertEqual(backupInfo.count, 1); + + let info = backupInfo[0] as RocksDBBackupInfo + + XCTAssertEqual(info.backupId, 1 as UInt32) + } + + func testSwift_Backup_BackupInfo_Multiple() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 2"), forKey: Data("key 2")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 3"), forKey: Data("key 3")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + let backupInfo = backupEngine.backupInfo() + + XCTAssertNotNil(backupInfo) + XCTAssertEqual(backupInfo.count, 3); + + XCTAssertEqual(backupInfo[0].backupId, 1 as UInt32) + XCTAssertEqual(backupInfo[1].backupId, 2 as UInt32) + XCTAssertEqual(backupInfo[2].backupId, 3 as UInt32) + } + + func testSwift_Backup_PurgeBackups() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 2"), forKey: Data("key 2")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 3"), forKey: Data("key 3")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + backupEngine.purgeOldBackupsKeepingLast(2, error: nil) + + let backupInfo = backupEngine.backupInfo() + + XCTAssertNotNil(backupInfo) + XCTAssertEqual(backupInfo.count, 2); + + XCTAssertEqual(backupInfo[0].backupId, 2 as UInt32) + XCTAssertEqual(backupInfo[1].backupId, 3 as UInt32) + } + + func testSwift_Backup_DeleteBackup() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 2"), forKey: Data("key 2")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 3"), forKey: Data("key 3")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + backupEngine.deleteBackupWithId(2, error: nil) + + let backupInfo = backupEngine.backupInfo() + + XCTAssertNotNil(backupInfo) + XCTAssertEqual(backupInfo.count, 2); + + XCTAssertEqual(backupInfo[0].backupId, 1 as UInt32) + XCTAssertEqual(backupInfo[1].backupId, 3 as UInt32) + } + + func testSwift_Backup_Restore() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 10"), forKey: Data("key 1")) + rocks.setData(Data("value 20"), forKey: Data("key 2")) + rocks.setData(Data("value 30"), forKey: Data("key 3")) + + rocks.close() + + backupEngine.restoreBackupToDestinationPath(self.restorePath, error: nil) + + let backupRocks = RocksDB(path: restorePath) + + XCTAssertEqual(backupRocks.dataForKey(Data("key 1")), Data("value 1")) + XCTAssertEqual(backupRocks.dataForKey(Data("key 2")), Data("value 2")) + XCTAssertEqual(backupRocks.dataForKey(Data("key 3")), Data("value 3")) + + backupRocks.close() + } + + func testSwift_Backup_Restore_Specific() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let backupEngine = RocksDBBackupEngine(path: self.backupPath) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 2"), forKey: Data("key 2")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.setData(Data("value 3"), forKey: Data("key 3")) + backupEngine.createBackupForDatabase(rocks, error: nil) + + rocks.close() + + backupEngine.restoreBackupWithId(1, toDestinationPath: self.restorePath, error: nil) + + var backupRocks = RocksDB(path: restorePath) + + XCTAssertEqual(backupRocks.dataForKey(Data("key 1")), Data("value 1")) + XCTAssertNil(backupRocks.dataForKey(Data("key 2"))) + XCTAssertNil(backupRocks.dataForKey(Data("key 3"))) + + backupRocks.close() + + backupEngine.restoreBackupWithId(2, toDestinationPath: self.restorePath, error: nil) + + backupRocks = RocksDB(path: restorePath) + + XCTAssertEqual(backupRocks.dataForKey(Data("key 1")), Data("value 1")) + XCTAssertEqual(backupRocks.dataForKey(Data("key 2")), Data("value 2")) + XCTAssertNil(backupRocks.dataForKey(Data("key 3"))) + + backupRocks.close() + } +} diff --git a/ObjectiveRocksTests/RocksDBBasicTests.swift b/ObjectiveRocksTests/RocksDBBasicTests.swift new file mode 100644 index 0000000..b73a044 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBBasicTests.swift @@ -0,0 +1,84 @@ +// +// RocksDBBasicTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBBasicTests : RocksDBTests { + + func testSwift_DB_Open_ErrorIfExists() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + rocks.close() + + let db = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.errorIfExists = true + }) + + XCTAssertNil(db) + } + + func testSwift_DB_CRUD() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + rocks.setDefaultReadOptions({ (readOptions) -> Void in + readOptions.fillCache = true + readOptions.verifyChecksums = true + }, andWriteOptions: { (writeOptions) -> Void in + writeOptions.syncWrites = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(rocks.dataForKey(Data("key 3")), Data("value 3")); + + rocks.deleteDataForKey(Data("key 2")) + XCTAssertNil(rocks.dataForKey(Data("key 2"))); + + var error: NSError? = nil + var ok = rocks.deleteDataForKey(Data("key 2"), error:&error); + XCTAssertTrue(ok); + XCTAssertNil(error); + } + + func testSwift_DB_CRUD_Encoded() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.keyType = .NSString + options.valueType = .NSString + }) + rocks.setDefaultReadOptions({ (readOptions) -> Void in + readOptions.fillCache = true + readOptions.verifyChecksums = true + }, andWriteOptions: { (writeOptions) -> Void in + writeOptions.syncWrites = true + }) + + rocks.setObject("value 1", forKey: "key 1") + rocks.setObject("value 2", forKey: "key 2") + rocks.setObject("value 3", forKey: "key 3") + + + XCTAssertEqual(rocks.objectForKey("key 1") as NSString, "value 1"); + XCTAssertEqual(rocks.objectForKey("key 2") as NSString, "value 2"); + XCTAssertEqual(rocks.objectForKey("key 3") as NSString, "value 3"); + + rocks.deleteObjectForKey("key 2") + XCTAssertNil(rocks.objectForKey("key 2")); + + var error: NSError? = nil + var ok = rocks.deleteObjectForKey("key 2", error:&error); + XCTAssertTrue(ok); + XCTAssertNil(error); + } +} diff --git a/ObjectiveRocksTests/RocksDBCheckpointTests.swift b/ObjectiveRocksTests/RocksDBCheckpointTests.swift new file mode 100644 index 0000000..dc02dc6 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBCheckpointTests.swift @@ -0,0 +1,46 @@ +// +// RocksDBCheckpointTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBCheckpointTests : RocksDBTests { + + func testSwift_Checkpoint() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + let checkpoint = RocksDBCheckpoint(database: rocks) + + checkpoint.createCheckpointAtPath(checkpointPath1, error: nil) + + rocks.setData(Data("value 2"), forKey: Data("key 2")) + + checkpoint.createCheckpointAtPath(checkpointPath2, error: nil) + + rocks.close() + + rocks = RocksDB(path: self.checkpointPath1, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")) + XCTAssertNil(rocks.dataForKey(Data("key 2"))) + + rocks.close() + + rocks = RocksDB(path: self.checkpointPath2, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")) + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")) + } +} diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m b/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.mm similarity index 100% rename from ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.m rename to ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.mm diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.swift b/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.swift new file mode 100644 index 0000000..4099dda --- /dev/null +++ b/ObjectiveRocksTests/RocksDBColumnFamilyMetadataTests.swift @@ -0,0 +1,38 @@ +// +// RocksDBColumnFamilyMetadataTests.swift +// ObjectiveRocks +// +// Created by Iska on 17/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBColumnFamilyMetadataTests : RocksDBTests { + + func testSwift_ColumnFamilies_Metadata() { + let descriptor = RocksDBColumnFamilyDescriptor() + descriptor.addDefaultColumnFamilyWithOptions(nil) + descriptor.addColumnFamilyWithName("new_cf", andOptions: nil) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + options.createMissingColumnFamilies = true + }) + + let defaultColumnFamily = rocks.columnFamilies()[0] as RocksDBColumnFamily + let newColumnFamily = rocks.columnFamilies()[1] as RocksDBColumnFamily + + defaultColumnFamily.setData(Data("df_value1"), forKey: Data("df_key1")) + defaultColumnFamily.setData(Data("df_value2"), forKey: Data("df_key2")) + + newColumnFamily.setData(Data("cf_value1"), forKey: Data("cf_key1")) + newColumnFamily.setData(Data("cf_value2"), forKey: Data("cf_key2")) + + let defaultMetadata = defaultColumnFamily.columnFamilyMetaData() + XCTAssertNotNil(defaultMetadata); + + let newColumnFamilyMetadata = newColumnFamily.columnFamilyMetaData() + XCTAssertNotNil(newColumnFamilyMetadata); + } +} diff --git a/ObjectiveRocksTests/RocksDBColumnFamilyTests.swift b/ObjectiveRocksTests/RocksDBColumnFamilyTests.swift new file mode 100644 index 0000000..c3a835d --- /dev/null +++ b/ObjectiveRocksTests/RocksDBColumnFamilyTests.swift @@ -0,0 +1,290 @@ +// +// RocksDBColumnFamilyTests.swift +// ObjectiveRocks +// +// Created by Iska on 17/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBColumnFamilyTests : RocksDBTests { + + func testSwift_ColumnFamilies_List() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.close() + + let names = RocksDB.listColumnFamiliesInDatabaseAtPath(self.path) + + XCTAssertTrue(names.count == 1); + XCTAssertEqual(names[0] as NSString, "default") + } + + func testSwift_ColumnFamilies_Create() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let columnFamily = rocks.createColumnFamilyWithName("new_cf", andOptions: nil) + columnFamily.close() + rocks.close() + + let names = RocksDB.listColumnFamiliesInDatabaseAtPath(self.path) + + XCTAssertTrue(names.count == 2); + XCTAssertEqual(names[0] as NSString, "default") + XCTAssertEqual(names[1] as NSString, "new_cf") + } + + func testSwift_ColumnFamilies_Drop() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let columnFamily = rocks.createColumnFamilyWithName("new_cf", andOptions: nil) + columnFamily.drop() + columnFamily.close() + rocks.close() + + let names = RocksDB.listColumnFamiliesInDatabaseAtPath(self.path) + + XCTAssertTrue(names.count == 1); + XCTAssertEqual(names[0] as NSString, "default") + } + + func testSwift_ColumnFamilies_Open() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + }) + + let columnFamily = rocks.createColumnFamilyWithName("new_cf", andOptions: { + (options) in + options.comparator = RocksDBComparator.comaparatorWithType(.BytewiseDescending) + }) + + columnFamily.close() + rocks.close() + + let names = RocksDB.listColumnFamiliesInDatabaseAtPath(self.path) + + XCTAssertTrue(names.count == 2) + XCTAssertEqual(names[0] as NSString, "default") + XCTAssertEqual(names[1] as NSString, "new_cf") + + let descriptor = RocksDBColumnFamilyDescriptor() + + descriptor.addDefaultColumnFamilyWithOptions { (options) -> Void in + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + } + descriptor.addColumnFamilyWithName("new_cf", andOptions: { (options) -> Void in + options.comparator = RocksDBComparator.comaparatorWithType(.BytewiseDescending) + }) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + }) + + XCTAssertNotNil(rocks); + + XCTAssertTrue(rocks.columnFamilies().count == 2) + + let defaultColumnFamily = rocks.columnFamilies()[0] as RocksDBColumnFamily + let newColumnFamily = rocks.columnFamilies()[1] as RocksDBColumnFamily + + XCTAssertNotNil(defaultColumnFamily) + XCTAssertNotNil(newColumnFamily) + + defaultColumnFamily.close() + newColumnFamily.close() + } + + func testSwift_ColumnFamilies_Open_ComparatorMismatch() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + }) + + let columnFamily = rocks.createColumnFamilyWithName("new_cf", andOptions: { + (options) in + options.comparator = RocksDBComparator.comaparatorWithType(.BytewiseDescending) + }) + + columnFamily.close() + rocks.close() + + let names = RocksDB.listColumnFamiliesInDatabaseAtPath(self.path) + + XCTAssertTrue(names.count == 2) + XCTAssertEqual(names[0] as NSString, "default") + XCTAssertEqual(names[1] as NSString, "new_cf") + + let descriptor = RocksDBColumnFamilyDescriptor() + + descriptor.addDefaultColumnFamilyWithOptions { (options) -> Void in + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + } + descriptor.addColumnFamilyWithName("new_cf", andOptions: { (options) -> Void in + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + }) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + }) + + XCTAssertNil(rocks) + } + + func testSwift_ColumnFamilies_CRUD() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("df_value"), forKey: Data("df_key1")) + rocks.setData(Data("df_value"), forKey: Data("df_key2")) + + let columnFamily = rocks.createColumnFamilyWithName("new_cf", andOptions:nil) + + columnFamily.setData(Data("cf_value"), forKey: Data("cf_key1")) + columnFamily.setData(Data("cf_value"), forKey: Data("cf_key2")) + + + columnFamily.close() + rocks.close() + + let descriptor = RocksDBColumnFamilyDescriptor() + + descriptor.addDefaultColumnFamilyWithOptions(nil) + descriptor.addColumnFamilyWithName("new_cf", andOptions: nil) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + options.createMissingColumnFamilies = true + }) + + let defaultColumnFamily = rocks.columnFamilies()[0] as RocksDBColumnFamily + let newColumnFamily = rocks.columnFamilies()[1] as RocksDBColumnFamily + + XCTAssertEqual(rocks.dataForKey(Data("df_key1")), Data("df_value")) + XCTAssertEqual(rocks.dataForKey(Data("df_key2")), Data("df_value")) + XCTAssertNil(rocks.dataForKey(Data("cf_key1"))) + XCTAssertNil(rocks.dataForKey(Data("cf_key2"))) + + XCTAssertEqual(defaultColumnFamily.dataForKey(Data("df_key1")), Data("df_value")) + XCTAssertEqual(defaultColumnFamily.dataForKey(Data("df_key2")), Data("df_value")) + + XCTAssertNil(defaultColumnFamily.dataForKey(Data("cf_key1"))) + XCTAssertNil(defaultColumnFamily.dataForKey(Data("cf_key2"))) + + XCTAssertEqual(newColumnFamily.dataForKey(Data("cf_key1")), Data("cf_value")) + XCTAssertEqual(newColumnFamily.dataForKey(Data("cf_key2")), Data("cf_value")) + + XCTAssertNil(newColumnFamily.dataForKey(Data("df_key1"))) + XCTAssertNil(newColumnFamily.dataForKey(Data("df_key2"))) + + newColumnFamily.deleteDataForKey(Data("cf_key1")) + XCTAssertNil(newColumnFamily.dataForKey(Data("cf_key1"))) + + newColumnFamily.deleteDataForKey(Data("cf_key1")) + XCTAssertNil(newColumnFamily.dataForKey(Data("cf_key1"))) + + defaultColumnFamily.close() + newColumnFamily.close() + } + + func testSwift_ColumnFamilies_WriteBatch() { + let descriptor = RocksDBColumnFamilyDescriptor() + + descriptor.addDefaultColumnFamilyWithOptions(nil) + descriptor.addColumnFamilyWithName("new_cf", andOptions: nil) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + options.createMissingColumnFamilies = true + }) + + let defaultColumnFamily = rocks.columnFamilies()[0] as RocksDBColumnFamily + let newColumnFamily = rocks.columnFamilies()[1] as RocksDBColumnFamily + + newColumnFamily.setData(Data("xyz_value"), forKey: Data("xyz")) + + let batch = newColumnFamily.writeBatch() + + batch.setData(Data("cf_value1"), forKey:Data("cf_key1")) + batch.setData(Data("df_value"), forKey:Data("df_key"), inColumnFamily:defaultColumnFamily) + batch.setData(Data("cf_value2"), forKey:Data("cf_key2")) + batch.deleteDataForKey(Data("xyz"), inColumnFamily:defaultColumnFamily) + batch.deleteDataForKey(Data("xyz")) + + rocks.applyWriteBatch(batch, withWriteOptions:nil) + + XCTAssertEqual(defaultColumnFamily.dataForKey(Data("df_key")), Data("df_value")) + XCTAssertNil(defaultColumnFamily.dataForKey(Data("df_key1"))) + XCTAssertNil(defaultColumnFamily.dataForKey(Data("df_key2"))) + + XCTAssertEqual(newColumnFamily.dataForKey(Data("cf_key1")), Data("cf_value1")) + XCTAssertEqual(newColumnFamily.dataForKey(Data("cf_key2")), Data("cf_value2")) + XCTAssertNil(newColumnFamily.dataForKey(Data("df_key"))) + + XCTAssertNil(defaultColumnFamily.dataForKey(Data("xyz"))) + XCTAssertNil(newColumnFamily.dataForKey(Data("xyz"))) + + defaultColumnFamily.close() + newColumnFamily.close() + } + + func testSwift_ColumnFamilies_Iterator() { + let descriptor = RocksDBColumnFamilyDescriptor() + + descriptor.addDefaultColumnFamilyWithOptions(nil) + descriptor.addColumnFamilyWithName("new_cf", andOptions: nil) + + rocks = RocksDB(path: self.path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + options.createMissingColumnFamilies = true + }) + + let defaultColumnFamily = rocks.columnFamilies()[0] as RocksDBColumnFamily + let newColumnFamily = rocks.columnFamilies()[1] as RocksDBColumnFamily + + defaultColumnFamily.setData(Data("df_value1"), forKey: Data("df_key1")) + defaultColumnFamily.setData(Data("df_value2"), forKey: Data("df_key2")) + + newColumnFamily.setData(Data("cf_value1"), forKey: Data("cf_key1")) + newColumnFamily.setData(Data("cf_value2"), forKey: Data("cf_key2")) + + let dfIterator = defaultColumnFamily.iterator() + + let actual = NSMutableArray() + + for dfIterator.seekToFirst(); dfIterator.isValid(); dfIterator.next() { + actual.addObject(Str(dfIterator.key() as NSData)) + actual.addObject(Str(dfIterator.value() as NSData)) + } + + var expected = [ "df_key1", "df_value1", "df_key2", "df_value2" ] + XCTAssertEqual(actual, expected); + + dfIterator.close() + + let cfIterator = newColumnFamily.iterator() + + actual.removeAllObjects() + + for cfIterator.seekToFirst(); cfIterator.isValid(); cfIterator.next() { + actual.addObject(Str(cfIterator.key() as NSData)) + actual.addObject(Str(cfIterator.value() as NSData)) + } + + expected = [ "cf_key1", "cf_value1", "cf_key2", "cf_value2" ] + XCTAssertEqual(actual, expected) + + cfIterator.close() + + defaultColumnFamily.close() + newColumnFamily.close() + } +} diff --git a/ObjectiveRocksTests/RocksDBComparatorTests.swift b/ObjectiveRocksTests/RocksDBComparatorTests.swift new file mode 100644 index 0000000..af6e4b5 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBComparatorTests.swift @@ -0,0 +1,254 @@ +// +// RocksDBComparatorTests.swift +// ObjectiveRocks +// +// Created by Iska on 12/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBComparatorTests : RocksDBTests { + + func testSwift_Comparator_Native_Bytewise_Ascending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.BytewiseAscending) + }) + + rocks.setData(Data("abc1"), forKey: Data("abc1")) + rocks.setData(Data("abc2"), forKey: Data("abc2")) + rocks.setData(Data("abc3"), forKey: Data("abc3")) + + let iterator = rocks.iterator() + + iterator.seekToFirst() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc1")) + XCTAssertEqual(iterator.value() as NSData, Data("abc1")) + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc2")) + XCTAssertEqual(iterator.value() as NSData, Data("abc2")) + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc3")) + XCTAssertEqual(iterator.value() as NSData, Data("abc3")) + + iterator.next() + + XCTAssertFalse(iterator.isValid()) + + iterator.seekToLast() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc3")) + XCTAssertEqual(iterator.value() as NSData, Data("abc3")) + + iterator.seekToKey(Data("abc")) + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc1")) + XCTAssertEqual(iterator.value() as NSData, Data("abc1")) + + iterator.close() + } + + func testSwift_Comparator_Native_Bytewise_Descending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.BytewiseDescending) + }) + + rocks.setData(Data("abc1"), forKey: Data("abc1")) + rocks.setData(Data("abc2"), forKey: Data("abc2")) + rocks.setData(Data("abc3"), forKey: Data("abc3")) + + let iterator = rocks.iterator() + + iterator.seekToFirst() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc3")) + XCTAssertEqual(iterator.value() as NSData, Data("abc3")) + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc2")) + XCTAssertEqual(iterator.value() as NSData, Data("abc2")) + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc1")) + XCTAssertEqual(iterator.value() as NSData, Data("abc1")) + + iterator.next() + + XCTAssertFalse(iterator.isValid()) + + iterator.seekToLast() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc1")) + XCTAssertEqual(iterator.value() as NSData, Data("abc1")) + + iterator.seekToKey(Data("abc")) + + XCTAssertFalse(iterator.isValid()) + + iterator.seekToKey(Data("abc999")) + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("abc3")) + XCTAssertEqual(iterator.value() as NSData, Data("abc3")) + + iterator.close() + } + + func testSwift_Comparator_StringCompare_Ascending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareAscending) + options.keyType = .NSString + }) + + let expected = NSMutableArray() + + for i in 0...10000 { + let str = NSString(format: "a%d", i) + expected.addObject(str) + rocks.setObject(str, forKey: str) + } + + /* Expected Array: [A0, A1, A10, A100, A1000, A1001, A1019, A102, A1020, ...] */ + expected.sortUsingSelector(Selector("compare:")) + + let iterator = rocks.iterator() + var idx = 0 + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + XCTAssertEqual(key as NSString, expected[idx] as NSString) + idx++ + } + } + + func testSwift_Comparator_StringCompare_Descending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.StringCompareDescending) + options.keyType = .NSString + }) + + let expected = NSMutableArray() + + for i in 0...10000 { + let str = NSString(format: "a%d", i) + expected.addObject(str) + rocks.setObject(str, forKey: str) + } + + /* Expected Array: [A9999, A9998 .. A9990, A999, A9989, ...] */ + expected.sortUsingSelector(Selector("compare:")) + + let iterator = rocks.iterator() + var idx = 9999 + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + XCTAssertEqual(key as NSString, expected[idx] as NSString) + idx-- + } + } + + func testSwift_Comparator_Number_Ascending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.NumberAscending) + options.keyEncoder = { + (number) -> NSData in + var r: NSInteger = number.unsignedIntegerValue + return NSData(bytes: &r, length: sizeof(NSInteger)) + } + options.keyDecoder = { + (data) -> AnyObject in + if (data == nil) { + return Optional.None! + } + var r: NSInteger = 0 + data.getBytes(&r, length: sizeof(NSInteger)) + return NSNumber(unsignedInteger: r) + } + }) + + var i = 0 + while i < 10000 { + let r = arc4random_uniform(UINT32_MAX); + if (rocks.objectForKey(NSNumber(unsignedInt: r)) == nil) { + rocks.setObject(Data("value"), forKey: NSNumber(unsignedInt: r)) + i++ + } + } + + var count = 0 + var lastKey: NSNumber = NSNumber(unsignedInteger: 0) + + let iterator = rocks.iterator() + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + XCTAssertTrue(lastKey.compare(key as NSNumber) == .OrderedAscending) + lastKey = key as NSNumber + count++ + } + + XCTAssertEqual(count, 10000); + } + + func testSwift_Comparator_Number_Decending() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = RocksDBComparator.comaparatorWithType(.NumberDescending) + options.keyEncoder = { + (number) -> NSData in + var r: NSInteger = number.unsignedIntegerValue + return NSData(bytes: &r, length: sizeof(NSInteger)) + } + options.keyDecoder = { + (data) -> AnyObject in + if (data == nil) { + return Optional.None! + } + var r: NSInteger = 0 + data.getBytes(&r, length: sizeof(NSInteger)) + return NSNumber(unsignedInteger: r) + } + }) + + var i = 0 + while i < 10000 { + let r = arc4random_uniform(UINT32_MAX); + if (rocks.objectForKey(NSNumber(unsignedInt: r)) == nil) { + rocks.setObject(Data("value"), forKey: NSNumber(unsignedInt: r)) + i++ + } + } + + var count = 0 + var lastKey: NSNumber = NSNumber(unsignedInt: UINT32_MAX) + + let iterator = rocks.iterator() + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + XCTAssertTrue(lastKey.compare(key as NSNumber) == .OrderedDescending) + lastKey = key as NSNumber + count++ + } + + XCTAssertEqual(count, 10000); + } +} diff --git a/ObjectiveRocksTests/RocksDBIteratorTests.swift b/ObjectiveRocksTests/RocksDBIteratorTests.swift new file mode 100644 index 0000000..e5cc85f --- /dev/null +++ b/ObjectiveRocksTests/RocksDBIteratorTests.swift @@ -0,0 +1,371 @@ +// +// RocksDBIteratorTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBIteratorTests : RocksDBTests { + + func testSwift_DB_Iterator() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + for iterator.seekToFirst(); iterator.isValid(); iterator.next() { + actual.addObject(Str(iterator.key() as NSData)) + } + + let expected = [ "key 1", "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_Seek() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + + let iterator = rocks.iterator() + + iterator.seekToFirst() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("key 1")) + XCTAssertEqual(iterator.value() as NSData, Data("value 1")) + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("key 2")) + XCTAssertEqual(iterator.value() as NSData, Data("value 2")) + + iterator.next() + + XCTAssertFalse(iterator.isValid()) + + iterator.seekToLast() + iterator.previous() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("key 1")) + XCTAssertEqual(iterator.value() as NSData, Data("value 1")) + + iterator.seekToFirst() + iterator.seekToLast() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSData, Data("key 2")) + XCTAssertEqual(iterator.value() as NSData, Data("value 2")) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + + let expected = [ "key 1", "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys_Reverse() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysInReverse(true, usingBlock: { (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + }) + + let expected = [ "key 3", "key 2", "key 1" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys_RangeStart() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysInRange(RocksDBMakeKeyRange(Data("key 2"), nil), reverse: false) + { + (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + let expected = [ "key 2", "key 3", "key 4" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys_RangeEnd() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysInRange(RocksDBMakeKeyRange(nil, Data("key 4")), reverse: false) + { + (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + let expected = [ "key 1", "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys_RangeStartEnd() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysInRange(RocksDBMakeKeyRange(Data("key 2"), Data("key 4")), reverse: false) + { + (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + let expected = [ "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeys_Encoded() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.keyType = .NSString + options.valueType = .NSString + }) + + rocks.setObject("value 1", forKey: "key 1") + rocks.setObject("value 2", forKey: "key 2") + rocks.setObject("value 3", forKey: "key 3") + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + actual.addObject(key) + } + + let expected = [ "key 1", "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesUsingBlock { (key, value, stop) -> Void in + actual.addObject(Str(key as NSData)) + actual.addObject(Str(value as NSData)) + } + + let expected = [ "key 1", "value 1", "key 2", "value 2", "key 3", "value 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues_Reverse() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesInReverse(true, usingBlock: { (key, value, stop) -> Void in + actual.addObject(Str(key as NSData)) + actual.addObject(Str(value as NSData)) + }) + + let expected = [ "key 3", "value 3", "key 2", "value 2", "key 1", "value 1" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues_RangeStart() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesInRange(RocksDBMakeKeyRange(Data("key 2"), nil), reverse: false) + { + (key, value, stop) -> Void in + actual.addObject(Str(key as NSData)) + actual.addObject(Str(value as NSData)) + } + + let expected = [ "key 2", "value 2", "key 3", "value 3", "key 4", "value 4" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues_RangeEnd() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesInRange(RocksDBMakeKeyRange(nil, Data("key 4")), reverse: false) + { + (key, value, stop) -> Void in + actual.addObject(Str(key as NSData)) + actual.addObject(Str(value as NSData)) + } + + let expected = [ "key 1", "value 1", "key 2", "value 2", "key 3", "value 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues_RangeStartEnd() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesInRange(RocksDBMakeKeyRange(Data("key 2"), Data("key 4")), reverse: false) + { + (key, value, stop) -> Void in + actual.addObject(Str(key as NSData)) + actual.addObject(Str(value as NSData)) + } + + let expected = [ "key 2", "value 2", "key 3", "value 3" ] + XCTAssertEqual(actual, expected) + + iterator.close() + } + + func testSwift_DB_Iterator_EnumerateKeysAndValues_Encoded() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.keyType = .NSString + options.valueType = .NSString + }) + + rocks.setObject("value 1", forKey: "key 1") + rocks.setObject("value 2", forKey: "key 2") + rocks.setObject("value 3", forKey: "key 3") + + let actual = NSMutableArray() + let iterator = rocks.iterator() + + iterator.enumerateKeysAndValuesUsingBlock { (key, value, stop) -> Void in + actual.addObject(key) + actual.addObject(value) + } + + let expected = [ "key 1", "value 1", "key 2", "value 2", "key 3", "value 3" ]; + XCTAssertEqual(actual, expected) + + iterator.close() + } +} + diff --git a/ObjectiveRocksTests/RocksDBMergeOperatorTests.swift b/ObjectiveRocksTests/RocksDBMergeOperatorTests.swift new file mode 100644 index 0000000..4a02a54 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBMergeOperatorTests.swift @@ -0,0 +1,167 @@ +// +// RocksDBMergeOperatorTests.swift +// ObjectiveRocks +// +// Created by Iska on 14/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBMergeOperatorTests : RocksDBTests { + + func testSwift_AssociativeMergeOperator() { + let mergeOp = RocksDBMergeOperator(name: "operator") { (key, existing, value) -> AnyObject! in + var prev: UInt64 = 0 + if (existing != nil) { + existing.getBytes(&prev, length: sizeof(UInt64)) + } + var plus: UInt64 = 0 + value.getBytes(&plus, length: sizeof(UInt64)) + + var result: UInt64 = prev + plus + return NSData(bytes: &result, length: sizeof(UInt64)) + } + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.mergeOperator = mergeOp + }) + + var value: UInt64 = 1 + rocks.mergeData(NumData(value), forKey: Data("key 1")) + + value = 5 + rocks.mergeData(NumData(value), forKey: Data("key 1")) + + var res: UInt64 = Val(rocks.dataForKey(Data("key 1"))) + + XCTAssertTrue(res == 6); + } + + func testSwift_AssociativeMergeOperator_NumberAdd_Encoded() { + let mergeOp = RocksDBMergeOperator(name: "operator") { (key, existing, value) -> AnyObject! in + var val = value.floatValue + if (existing != nil) { + val = val + existing.floatValue + } + let result: NSNumber = NSNumber(float: val) + return result + } + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.mergeOperator = mergeOp + options.keyType = .NSString + + options.valueEncoder = { + (key, value) -> NSData in + let val = value.floatValue + let data = NumData(val) + return data + } + + options.valueDecoder = { + (key, data) -> NSNumber in + if (data == nil) { + return Optional.None! + } + + var value: Float = Val(data) + return NSNumber(float: value) + } + }) + + rocks.mergeObject(NSNumber(float: 100.541), forKey: "key 1") + rocks.mergeObject(NSNumber(float: 200.125), forKey: "key 1") + + let result: Float = rocks.objectForKey("key 1").floatValue + XCTAssertEqualWithAccuracy(result, Float(300.666), Float(0.0001)) + } + + func testSwift_AssociativeMergeOperator_DictionaryPut_Encoded() { + let mergeOp = RocksDBMergeOperator(name: "operator") { (key, existing, value) -> AnyObject! in + if (existing != nil) { + existing.addEntriesFromDictionary(value as NSDictionary) + return existing + } else { + return value + } + } + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.mergeOperator = mergeOp + options.keyType = .NSString + options.valueType = .NSJSONSerializable + }) + + rocks.setObject(["key 1": "value 1"], forKey: "dict key") + rocks.mergeObject(["key 1": "value 1 new"], forKey: "dict key") + rocks.mergeObject(["key 2": "value 2"], forKey: "dict key") + rocks.mergeObject(["key 3": "value 3"], forKey: "dict key") + rocks.mergeObject(["key 4": "value 4"], forKey: "dict key") + rocks.mergeObject(["key 5": "value 5"], forKey: "dict key") + + let expected: NSDictionary = ["key 1" : "value 1 new", + "key 2" : "value 2", + "key 3" : "value 3", + "key 4" : "value 4", + "key 5" : "value 5"] + + XCTAssertEqual(rocks.objectForKey("dict key") as NSDictionary, expected) + } + + func testSwift_MergeOperator_DictionaryUpdate_Encoded() { + let mergeOp = RocksDBMergeOperator(name: "operator", partialMergeBlock: + { + (key, leftOperand, rightOperand) -> String! in + let left: NSString = leftOperand.componentsSeparatedByString(":")[0] + let right: NSString = rightOperand.componentsSeparatedByString(":")[0] + if left.isEqualToString(right) { + return rightOperand + } + return Optional.None! + + }, + { + (key, existing, operands) -> NSMutableDictionary! in + + var dict: NSMutableDictionary = existing as NSMutableDictionary + for op in operands as NSArray { + let comp: NSArray = op.componentsSeparatedByString(":") + let action: NSString = comp[1] as NSString + if action.isEqualToString("DELETE") { + dict.removeObjectForKey(comp[0]) + } else { + dict.setObject(comp[2], forKey: comp[0] as NSString) + } + } + return existing as NSMutableDictionary + }) + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.mergeOperator = mergeOp + options.keyType = .NSString + options.valueType = .NSJSONSerializable + }) + + let object = ["key 1" : "value 1", + "key 2" : "value 2", + "key 3" : "value 3"] + + rocks.setObject(object, forKey: "dict key") + + rocks.mergeOperation("key 1:UPDATE:value X", forKey: "dict key") + rocks.mergeOperation("key 4:INSERT:value 4", forKey: "dict key") + rocks.mergeOperation("key 2:DELETE", forKey: "dict key") + rocks.mergeOperation("key 1:UPDATE:value 1 new", forKey: "dict key") + + let expected = ["key 1" : "value 1 new", + "key 3" : "value 3", + "key 4" : "value 4"]; + + XCTAssertEqual(rocks.objectForKey("dict key") as NSDictionary, expected) + } +} diff --git a/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift new file mode 100644 index 0000000..bf09ef6 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift @@ -0,0 +1,140 @@ +// +// RocksDBPrefixExtractorTests.swift +// ObjectiveRocks +// +// Created by Iska on 17/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBPrefixExtractorTests : RocksDBTests { + + func testSwift_PrefixExtractor_FixedLength() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.prefixExtractor = RocksDBPrefixExtractor(type: .FixedLength, length: 3) + options.keyType = .NSString; + options.valueType = .NSString; + }) + + rocks.setObject("x", forKey: "100A") + rocks.setObject("x", forKey: "100B") + + rocks.setObject("x", forKey: "101A") + rocks.setObject("x", forKey: "101B") + + let iterator = rocks.iterator() + let keys = NSMutableArray() + + iterator.enumerateKeysWithPrefix("100", usingBlock: { (key, stop) -> Void in + keys.addObject(key) + }) + + XCTAssertEqual(keys.count, 2); + + var expected = ["100A", "100B"] + + XCTAssertEqual(keys, expected); + + keys.removeAllObjects() + + iterator.enumerateKeysWithPrefix("101", usingBlock: { (key, stop) -> Void in + keys.addObject(key) + }) + + XCTAssertEqual(keys.count, 2); + + expected = ["101A", "101B"] + XCTAssertEqual(keys, expected); + + iterator.seekToKey("1000") + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSString, "100A") + + iterator.next() + + XCTAssertTrue(iterator.isValid()) + XCTAssertEqual(iterator.key() as NSString, "100B") + } + + func testSwift_PrefixExtractor_FixedLength_CustomComparator() { + // 1001 < 9910 < 2011 < 3412 ... + let cmp = RocksDBComparator(name: "cmp") { (key1, key2) -> Int32 in + var sub1: NSString = key1.substringFromIndex(2) as NSString + var sub2: NSString = key2.substringFromIndex(2) as NSString + + let res = sub1.compare(sub2) + switch res { + case .OrderedAscending: + return 1 + case .OrderedDescending: + return -1 + case .OrderedSame: + return 0 + } + } + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.comparator = cmp + options.prefixExtractor = RocksDBPrefixExtractor(type: .FixedLength, length: 2) + options.keyType = .NSString; + options.valueType = .NSString; + + options.memtablePrefixBloomBits = 100000000; + options.memtablePrefixBloomProbes = 6; + + options.tableFacotry = RocksDBTableFactory.blockBasedTableFactoryWithOptions({ + (options) -> Void in + options.filterPolicy = RocksDBFilterPolicy.bloomFilterPolicyWithBitsPerKey(10, useBlockBasedBuilder: true) + }) + }) + + rocks.setObject("x", forKey: "1010") + rocks.setObject("x", forKey: "4211") + rocks.setObject("x", forKey: "1012") + rocks.setObject("x", forKey: "5313") + rocks.setObject("x", forKey: "1020") + rocks.setObject("x", forKey: "4221") + rocks.setObject("x", forKey: "1022") + rocks.setObject("x", forKey: "5323") + + let iterator = rocks.iterator() + let keys = NSMutableArray() + + iterator.enumerateKeysWithPrefix("100", usingBlock: { (key, stop) -> Void in + keys.addObject(key) + }) + + XCTAssertEqual(keys.count, 4); + + var expected = ["1010", "1012", "1020", "1022"] + + XCTAssertEqual(keys, expected); + + keys.removeAllObjects() + + iterator.enumerateKeysWithPrefix("101", usingBlock: { (key, stop) -> Void in + keys.addObject(key) + }) + + XCTAssertEqual(keys.count, 2); + + expected = ["4211", "4221"] + XCTAssertEqual(keys, expected); + + + keys.removeAllObjects() + + iterator.enumerateKeysWithPrefix("101", usingBlock: { (key, stop) -> Void in + keys.addObject(key) + }) + + XCTAssertEqual(keys.count, 2); + + expected = ["5313", "5323"] + XCTAssertEqual(keys, expected); + } +} diff --git a/ObjectiveRocksTests/RocksDBPropertiesTests.swift b/ObjectiveRocksTests/RocksDBPropertiesTests.swift new file mode 100644 index 0000000..a29a0aa --- /dev/null +++ b/ObjectiveRocksTests/RocksDBPropertiesTests.swift @@ -0,0 +1,48 @@ +// +// RocksDBPropertiesTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import Foundation +import XCTest + +class RocksDBPropertiesTests : RocksDBTests { + + func testSwift_Properties() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.maxWriteBufferNumber = 10; + options.minWriteBufferNumberToMerge = 10; + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + XCTAssertGreaterThan(rocks.valueForIntProperty(String(RocksDBIntPropertyNumEntriesInMutableMemtable)), 0 as UInt64); + XCTAssertGreaterThan(rocks.valueForIntProperty(String(RocksDBIntPropertyCurSizeActiveMemTable)), 0 as UInt64); + } + + func testSwift_Properties_ColumnFamily() { + + let descriptor = RocksDBColumnFamilyDescriptor() + descriptor.addDefaultColumnFamilyWithOptions(nil) + descriptor.addColumnFamilyWithName("new_cf", andOptions: nil) + + rocks = RocksDB(path: path, columnFamilies: descriptor, andDatabaseOptions: { (options) -> Void in + options.createIfMissing = true + options.createMissingColumnFamilies = true + }) + + XCTAssertGreaterThanOrEqual(rocks.columnFamilies()[0].valueForIntProperty(String(RocksDBIntPropertyEstimatedNumKeys)), 0 as UInt64); + XCTAssertNotNil(rocks.columnFamilies()[0].valueForProperty(String(RocksDBPropertyStats))); + XCTAssertNotNil(rocks.columnFamilies()[0].valueForProperty(String(RocksDBPropertySsTables))); + + XCTAssertGreaterThanOrEqual(rocks.columnFamilies()[1].valueForIntProperty(String(RocksDBIntPropertyEstimatedNumKeys)), 0 as UInt64); + XCTAssertNotNil(rocks.columnFamilies()[1].valueForProperty(String(RocksDBPropertyStats))); + XCTAssertNotNil(rocks.columnFamilies()[1].valueForProperty(String(RocksDBPropertySsTables))); + } +} diff --git a/ObjectiveRocksTests/RocksDBSnapshotTests.swift b/ObjectiveRocksTests/RocksDBSnapshotTests.swift new file mode 100644 index 0000000..d9b8c4b --- /dev/null +++ b/ObjectiveRocksTests/RocksDBSnapshotTests.swift @@ -0,0 +1,73 @@ +// +// RocksDBSnapshotTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBSnapshotTests : RocksDBTests { + + func testSwift_Snapshot() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let snapshot = rocks.snapshot() + + rocks.deleteDataForKey(Data("key 1")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + XCTAssertEqual(snapshot.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertEqual(snapshot.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(snapshot.dataForKey(Data("key 3")), Data("value 3")); + XCTAssertNil(snapshot.dataForKey(Data("Key 4"))) + + snapshot.close() + + XCTAssertNil(snapshot.dataForKey(Data("Key 1"))) + XCTAssertEqual(snapshot.dataForKey(Data("key 4")), Data("value 4")); + } + + func testSwift_Snapshot_Iterator() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + rocks.setData(Data("value 2"), forKey: Data("key 2")) + rocks.setData(Data("value 3"), forKey: Data("key 3")) + + let snapshot = rocks.snapshot() + + rocks.deleteDataForKey(Data("key 1")) + rocks.setData(Data("value 4"), forKey: Data("key 4")) + + var actual: NSMutableArray = [] + var iterator = snapshot.iterator() + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + var expected = [ "key 1", "key 2", "key 3" ] + XCTAssertEqual(actual, expected) + + snapshot.close() + + actual.removeAllObjects() + + iterator = snapshot.iterator() + iterator.enumerateKeysUsingBlock { (key, stop) -> Void in + actual.addObject(Str(key as NSData)) + } + + expected = [ "key 2", "key 3", "key 4" ] + XCTAssertEqual(actual, expected) + } +} diff --git a/ObjectiveRocksTests/RocksDBStatisticsTests.swift b/ObjectiveRocksTests/RocksDBStatisticsTests.swift new file mode 100644 index 0000000..6d65d3c --- /dev/null +++ b/ObjectiveRocksTests/RocksDBStatisticsTests.swift @@ -0,0 +1,65 @@ +// +// RocksDBStatisticsTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBStatisticsTests : RocksDBTests { + + func testSwift_Statistics() { + let statistics = RocksDBStatistics() + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.statistics = statistics; + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + XCTAssertNotNil(statistics.description); + } + + func testSwift_Statistics_Ticker() { + let statistics = RocksDBStatistics() + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.statistics = statistics; + }) + + rocks.setData(Data("abcd"), forKey: Data("abcd")) + + XCTAssertEqual(statistics.countForTicker(RocksDBTickerType.BytesRead), 0 as UInt64); + XCTAssertGreaterThan(statistics.countForTicker(RocksDBTickerType.BytesWritten), 0 as UInt64); + + rocks.dataForKey(Data("abcd")) + + XCTAssertGreaterThan(statistics.countForTicker(RocksDBTickerType.BytesRead), 0 as UInt64); + } + + func testSwift_Statistics_Histogram() { + let statistics = RocksDBStatistics() + + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.statistics = statistics; + }) + + for i in 0...10000 { + let str = NSString(format: "a%d", i) + rocks.setData(Data(str), forKey: Data(str)) + } + + rocks.dataForKey(Data("a42")) + + let dbGetHistogram = statistics.histogramDataForType(RocksDBHistogramType.DBGet) + + XCTAssertNotNil(dbGetHistogram); + XCTAssertGreaterThan(dbGetHistogram.median, 0.0); + } +} + diff --git a/ObjectiveRocksTests/RocksDBTests.mm b/ObjectiveRocksTests/RocksDBTests.mm index 2decae2..93f2b40 100644 --- a/ObjectiveRocksTests/RocksDBTests.mm +++ b/ObjectiveRocksTests/RocksDBTests.mm @@ -18,8 +18,8 @@ - (void)setUp _path = [_path stringByAppendingPathComponent:@"ObjectiveRocks"]; _backupPath = [_path stringByAppendingString:@"Backup"]; _restorePath = [_path stringByAppendingString:@"Restore"]; - _chekpointPath_1 = [_path stringByAppendingPathComponent:@"Snapshot1"]; - _chekpointPath_2 = [_path stringByAppendingPathComponent:@"Snapshot2"]; + _chekpointPath_1 = [_path stringByAppendingString:@"Snapshot1"]; + _chekpointPath_2 = [_path stringByAppendingString:@"Snapshot2"]; [self cleanupDB]; } diff --git a/ObjectiveRocksTests/RocksDBWriteBatchTests.swift b/ObjectiveRocksTests/RocksDBWriteBatchTests.swift new file mode 100644 index 0000000..c739c27 --- /dev/null +++ b/ObjectiveRocksTests/RocksDBWriteBatchTests.swift @@ -0,0 +1,212 @@ +// +// RocksDBWriteBatchTests.swift +// ObjectiveRocks +// +// Created by Iska on 11/01/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +import XCTest + +class RocksDBWriteBatchTests : RocksDBTests { + + func testSwift_WriteBatch_Perform() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.performWriteBatch { (batch, options) -> Void in + batch.setData(Data("value 1"), forKey: Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + } + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(rocks.dataForKey(Data("key 3")), Data("value 3")); + XCTAssertNil(rocks.dataForKey(Data("Key 4"))) + } + + func testSwift_WriteBatch_Perform_DeleteOps() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + rocks.performWriteBatch { (batch, options) -> Void in + batch.deleteDataForKey(Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + } + + XCTAssertNil(rocks.dataForKey(Data("Key 1"))) + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(rocks.dataForKey(Data("key 3")), Data("value 3")); + XCTAssertNil(rocks.dataForKey(Data("Key 4"))) + } + + func testSwift_WriteBatch_Perform_ClearOps() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + rocks.performWriteBatch { (batch, options) -> Void in + batch.deleteDataForKey(Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + batch.clear() + batch.setData(Data("value 4"), forKey: Data("key 4")) + } + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertNil(rocks.dataForKey(Data("Key 2"))) + XCTAssertNil(rocks.dataForKey(Data("Key 3"))) + XCTAssertEqual(rocks.dataForKey(Data("key 4")), Data("value 4")); + } + + func testSwift_WriteBatch_Apply() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + let batch = rocks.writeBatch() + + batch.setData(Data("value 1"), forKey: Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + + rocks.applyWriteBatch(batch, error: nil, writeOptions: nil) + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(rocks.dataForKey(Data("key 3")), Data("value 3")); + XCTAssertNil(rocks.dataForKey(Data("Key 4"))) + } + + func testSwift_WriteBatch_Apply_DeleteOps() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + let batch = rocks.writeBatch() + + batch.deleteDataForKey(Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + + rocks.applyWriteBatch(batch, error: nil, writeOptions: nil) + + XCTAssertNil(rocks.dataForKey(Data("Key 1"))) + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2")); + XCTAssertEqual(rocks.dataForKey(Data("key 3")), Data("value 3")); + XCTAssertNil(rocks.dataForKey(Data("Key 4"))) + } + + func testSwift_WriteBatch_Apply_MergeOps() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.mergeOperator = RocksDBMergeOperator(name: "merge", andBlock: { (key, existing, value) -> AnyObject! in + var result: NSMutableString = "" + if let existingValue = existing as? NSData { + result.setString(Str(existingValue)) + } + result.appendString(",") + result.appendString(Str(value as NSData)) + return Data(result) + }) + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + let batch = rocks.writeBatch() + + batch.deleteDataForKey(Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + batch.mergeData(Data("value 2 new"), forKey: Data("key 2")) + + rocks.applyWriteBatch(batch, error: nil, writeOptions: nil) + + XCTAssertEqual(rocks.dataForKey(Data("key 2")), Data("value 2,value 2 new")); + } + + func testSwift_WriteBatch_Apply_ClearOps() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + let batch = rocks.writeBatch() + + batch.deleteDataForKey(Data("key 1")) + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + batch.clear() + batch.setData(Data("value 4"), forKey: Data("key 4")) + + rocks.applyWriteBatch(batch, error: nil, writeOptions: nil) + + XCTAssertEqual(rocks.dataForKey(Data("key 1")), Data("value 1")); + XCTAssertNil(rocks.dataForKey(Data("Key 2"))) + XCTAssertNil(rocks.dataForKey(Data("Key 3"))) + XCTAssertEqual(rocks.dataForKey(Data("key 4")), Data("value 4")); + } + + func testSwift_WriteBatch_Count() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + let batch = rocks.writeBatch() + + batch.deleteDataForKey(Data("key 1")) + + XCTAssertEqual(batch.count(), 1 as Int32); + + batch.setData(Data("value 2"), forKey: Data("key 2")) + batch.setData(Data("value 3"), forKey: Data("key 3")) + + XCTAssertEqual(batch.count(), 3 as Int32); + + batch.clear() + + XCTAssertEqual(batch.count(), 0 as Int32); + + batch.setData(Data("value 4"), forKey: Data("key 3")) + batch.setData(Data("value 5"), forKey: Data("key 4")) + + XCTAssertEqual(batch.count(), 2 as Int32); + + batch.deleteDataForKey(Data("key 4")) + + XCTAssertEqual(batch.count(), 3 as Int32); + } + + func testSwift_WriteBatch_Encoded() { + rocks = RocksDB(path: self.path, andDBOptions: { (options) -> Void in + options.createIfMissing = true + options.keyType = .NSString + options.valueType = .NSString + }) + + rocks.setData(Data("value 1"), forKey: Data("key 1")) + + rocks.performWriteBatch { (batch, options) -> Void in + batch.setObject("value 2", forKey: "key 2") + batch.setObject("value 3", forKey: "key 3") + batch.deleteObjectForKey("value 1") + } + + XCTAssertNil(rocks.objectForKey("Key 1")) + XCTAssertEqual(rocks.objectForKey("key 2") as NSString, "value 2"); + XCTAssertEqual(rocks.objectForKey("key 3") as NSString, "value 3"); + } +} From 596f3990c9a01be62d9554eebe0ffc27e2c31253 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 17 Jan 2015 18:47:41 +0100 Subject: [PATCH 19/22] Add missing null pointer check for Column Family Handles in main DB class --- ObjectiveRocks/RocksDB.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ObjectiveRocks/RocksDB.mm b/ObjectiveRocks/RocksDB.mm index 3d3ca4c..40f3044 100644 --- a/ObjectiveRocks/RocksDB.mm +++ b/ObjectiveRocks/RocksDB.mm @@ -228,6 +228,10 @@ - (RocksDBColumnFamily *)createColumnFamilyWithName:(NSString *)name andOptions: - (NSArray *)columnFamilies { + if (_columnFamilyHandles == nullptr) { + return nil; + } + if (_columnFamilies == nil) { _columnFamilies = [NSMutableArray new]; for(auto it = std::begin(*_columnFamilyHandles); it != std::end(*_columnFamilyHandles); ++it) { From f00877f2dc4ec17712f365838d0a1266ca9b6442 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 17 Jan 2015 18:54:58 +0100 Subject: [PATCH 20/22] Add strong reference to the options object in the Table factory to prevent deallocation --- ObjectiveRocks/RocksDBTableFactory.mm | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ObjectiveRocks/RocksDBTableFactory.mm b/ObjectiveRocks/RocksDBTableFactory.mm index 7144c67..e8a101c 100644 --- a/ObjectiveRocks/RocksDBTableFactory.mm +++ b/ObjectiveRocks/RocksDBTableFactory.mm @@ -28,6 +28,7 @@ @interface RocksDBCuckooTableOptions () @interface RocksDBTableFactory () { + id _tableOptions; rocksdb::TableFactory *_tableFactory; } @property (nonatomic, assign) rocksdb::TableFactory *tableFactory; @@ -43,7 +44,8 @@ + (instancetype)blockBasedTableFactoryWithOptions:(void (^)(RocksDBBlockBasedTab optionsBlock(options); } - RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewBlockBasedTableFactory(options.options)]; + RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewBlockBasedTableFactory(options.options) + andOptions:options]; return instance; } @@ -56,7 +58,8 @@ + (instancetype)plainTableFactoryWithOptions:(void (^)(RocksDBPlainTableOptions optionsBlock(options); } - RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewPlainTableFactory(options.options)]; + RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewPlainTableFactory(options.options) + andOptions:options]; return instance; } @@ -67,16 +70,18 @@ + (instancetype)cuckooTableFactoryWithOptions:(void (^)(RocksDBCuckooTableOption optionsBlock(options); } - RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewCuckooTableFactory(options.options)]; + RocksDBTableFactory *instance = [[RocksDBTableFactory alloc] initWithNativeTableFacotry:rocksdb::NewCuckooTableFactory(options.options) + andOptions:options]; return instance; } #endif -- (instancetype)initWithNativeTableFacotry:(rocksdb::TableFactory *)tableFactory +- (instancetype)initWithNativeTableFacotry:(rocksdb::TableFactory *)tableFactory andOptions:(id)options { self = [super init]; if (self) { + _tableOptions = options; _tableFactory = tableFactory; } return self; From fd013fb523ca7475f033b6a735de1234a591a0f9 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 17 Jan 2015 18:58:52 +0100 Subject: [PATCH 21/22] Fix key comparator and prefixes in Prefix Extractor Swift tests --- ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift index bf09ef6..9e7be88 100644 --- a/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift +++ b/ObjectiveRocksTests/RocksDBPrefixExtractorTests.swift @@ -68,9 +68,9 @@ class RocksDBPrefixExtractorTests : RocksDBTests { let res = sub1.compare(sub2) switch res { case .OrderedAscending: - return 1 - case .OrderedDescending: return -1 + case .OrderedDescending: + return 1 case .OrderedSame: return 0 } @@ -104,7 +104,7 @@ class RocksDBPrefixExtractorTests : RocksDBTests { let iterator = rocks.iterator() let keys = NSMutableArray() - iterator.enumerateKeysWithPrefix("100", usingBlock: { (key, stop) -> Void in + iterator.enumerateKeysWithPrefix("10", usingBlock: { (key, stop) -> Void in keys.addObject(key) }) @@ -116,7 +116,7 @@ class RocksDBPrefixExtractorTests : RocksDBTests { keys.removeAllObjects() - iterator.enumerateKeysWithPrefix("101", usingBlock: { (key, stop) -> Void in + iterator.enumerateKeysWithPrefix("42", usingBlock: { (key, stop) -> Void in keys.addObject(key) }) @@ -128,7 +128,7 @@ class RocksDBPrefixExtractorTests : RocksDBTests { keys.removeAllObjects() - iterator.enumerateKeysWithPrefix("101", usingBlock: { (key, stop) -> Void in + iterator.enumerateKeysWithPrefix("53", usingBlock: { (key, stop) -> Void in keys.addObject(key) }) From f585af6a369a1995ac727246c8d30c42b4508bd5 Mon Sep 17 00:00:00 2001 From: iska Date: Sat, 17 Jan 2015 20:55:06 +0100 Subject: [PATCH 22/22] Update Readme for version 0.4.0 - Swift support - RocksDB Env & Thread Status - Prefix Seek - Column Family Metadata --- README.md | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 88fc322..1ab0d30 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ ObjectiveRocks provides an easy interface to RocksDB and an Objective-C friendly If you are interested in the internals of RocksDB, please refer to the [RocksDB Wiki](https://github.com/facebook/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 @@ -45,6 +49,7 @@ These features are only available in OSX: * Database Backups * Database Statistics * Database Properties +* Thread Status ## Installation @@ -355,29 +360,107 @@ or use one of the provided enumeration-blocks: RocksDBIterator *iterator = [db iterator]; +/* Keys Enumeration */ [db enumerateKeysUsingBlock:^(id key, BOOL *stop) { - NSLog(@"%@: %@", key, [db objectForKey:key]); + NSLog(@"%@", key); // A, B, C, D }]; // reverse enumeration [db enumerateKeysInReverse:YES usingBlock:^(id key, BOOL *stop) { - NSLog(@"%@: %@", key, [db objectForKey:key]); + NSLog(@"%@", key); // D, C, B, A }]; // Enumeration in a given key-range [start, end) -RocksDBIteratorKeyRange range = RocksDBMakeKeyRange(@"C", @"A"); +RocksDBIteratorKeyRange range = RocksDBMakeKeyRange(@"A", @"C"); + +[db enumerateKeysInRange:range reverse:NO usingBlock:^(id key, BOOL *stop) { + NSLog(@"%@", key, [db objectForKey:key]); + // B, C +}]; -[db enumerateKeysInRange:range reverse:YES usingBlock:^(id key, BOOL *stop) { +/* Key-Value Enumeration */ +[db enumerateKeysAndValuesUsingBlock:^(id key, id value BOOL *stop) { + NSLog(@"%@:%@", key, value); + // A:1, B:2, C:3, D:4 +}]; + +[db enumerateKeysAndValuesInReverse:YES usingBlock:^(id key, BOOL *stop) { NSLog(@"%@: %@", key, [db objectForKey:key]); - // C, B + // D:4, C:3, B:2, A:1 +}]; + +// Enumeration in a given key-range [start, end) +RocksDBIteratorKeyRange range = RocksDBMakeKeyRange(@"A", @"C"); + +[db enumerateKeysAndValuesInRange:range reverse:YES usingBlock:^(id key, BOOL *stop) { + NSLog(@"%@:%@", key, [db objectForKey:key]); + // B:2, C:3 }]; ``` ## Prefix-Seek Iteration -TBD +`RocksDBIterator` supports iterating inside a key-prefix by providing a `RocksDBPrefixExtractor`. One such extractor is built-in and it extracts a fixed-length prefix for each key: + +```objective-c +RocksDB *db = [[RocksDB alloc] initWithPath:_path andDBOptions:^(RocksDBOptions *options) { + options.createIfMissing = YES; + options.prefixExtractor = [RocksDBPrefixExtractor prefixExtractorWithType:RocksDBPrefixFixedLength length:2]; + + options.keyType = RocksDBTypeNSString; + options.valueType = RocksDBTypeNSString; +}]; + +[db setObject:@"a" forKey:@"10.1"]; +[db setObject:@"b" forKey:@"10.2"]; +[db setObject:@"b" forKey:@"10.3"]; +[db setObject:@"c" forKey:@"11.1"]; +[db setObject:@"d" forKey:@"11.2"]; +[db setObject:@"d" forKey:@"11.3"]; + +RocksDBIterator *iterator = [db iterator]; + +// Enumeration starts with the key that is Greater-Than-Or-Equal to a key +// with the given "prefix" parameter +[iterator enumerateKeysWithPrefix:@"10" usingBlock:^(id key, BOOL *stop) { + NSLog(@"%@", key); + // 10.1, 10.2, 10.3 +}]; + +// .. so in this case the enumeration starts at key "10.2", even if "10.1" +// has the same prefix +[iterator enumerateKeysWithPrefix:@"10.2" usingBlock:^(id key, BOOL *stop) { + NSLog(@"%@", key); + // 10.2, 10.3 +}]; +``` + +You can also define your own Prefix Extractor: + +```objective-c +RocksDBPrefixExtractor *extractor = [[RocksDBPrefixExtractor alloc] initWithName:@"custom_prefix" + transformBlock:^id (id key) { + // Apply your key transformation to extract the prefix part + id prefix = extractPrefixFromKey(key); + return prefix; + } + prefixCandidateBlock:^BOOL (id key) { + // You can filter out keys that are not viable candidates for + // your custom prefix format, e.g. key length is smaller than + // the target prefix length + BOOL isCandidate = canExtractPrefixFromKey(key); + return isCandidate; + } + validPrefixBlock:^BOOL (id prefix) { + // After a prefix is extracted you can perform extra + // checks here to verify that the prefix is valid + BOOL isValid = isExtractedPrefixValid(prefix); + return isValid; + } +]; +``` ## Snapshot @@ -561,6 +644,25 @@ result = @{@"Key 1" : @"Value 1 New", */ ``` +## Env & Thread Status + +The `RocksDBEnv` allows for modifying the thread pool for backgrond jobs. RocksDB uses this thread pool for compactions and memtable flushes. + +```objective-c +RocksDBEnv *dbEnv = [RocksDBEnv envWithLowPriorityThreadCount:12 andHighPriorityThreadCount:4]; +RocksDB *db = [[RocksDB alloc] initWithPath:@"path/to/db" andDBOptions:^(RocksDBOptions *options) { + options.env = dbEnv; +}]; + +// To get a list of all threads +NSArray *threads = dbEnv.threadList; + +// "threads" array contains objects of type RocksDBThreadStatus +RocksDBThreadStatus *status = threads[0]; +``` + +> Thread Status API is currently a WIP. + ## Backup & Restore To backup a database use the `RocksDBBackupEngine`: