Skip to content

Commit

Permalink
CBL-6066: Implement Database Full-Sync Option (#3317)
Browse files Browse the repository at this point in the history
- Implemented FullSync DatabaseConfiguration property.
- Only Obj-C tests do check for c4db_config2 kC4DB_DiskSyncFull flag
  • Loading branch information
velicuvlad committed Aug 2, 2024
1 parent 0085ed3 commit 2187e49
Show file tree
Hide file tree
Showing 12 changed files with 184 additions and 5 deletions.
8 changes: 8 additions & 0 deletions Objective-C/CBLDatabase.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,8 @@ static BOOL setupDatabaseDirectory(NSString *dir, NSError **outError)
static C4DatabaseConfig2 c4DatabaseConfig2 (CBLDatabaseConfiguration *config) {
C4DatabaseConfig2 c4config = kDBConfig;

if (config.fullSync)
c4config.flags |= kC4DB_DiskSyncFull;
#ifdef COUCHBASE_ENTERPRISE
if (config.encryptionKey)
c4config.encryptionKey = [CBLDatabase c4EncryptionKey: config.encryptionKey];
Expand Down Expand Up @@ -1139,4 +1141,10 @@ - (uint64_t) activeStoppableCount {
}
}

#pragma mark - Private for test

- (const C4DatabaseConfig2*) getC4DBConfig {
return c4db_getConfig2(_c4db);
}

@end
13 changes: 13 additions & 0 deletions Objective-C/CBLDatabaseConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy) NSString* directory;

/**
As Couchbase Lite normally configures its databases, there is a very
small (though non-zero) chance that a power failure at just the wrong
time could cause the most recently committed transaction's changes to
be lost. This would cause the database to appear as it did immediately
before that transaction.
Setting this mode true ensures that an operating system crash or
power failure will not cause the loss of any data. FULL synchronous
is very safe but it is also dramatically slower.
*/
@property (nonatomic) BOOL fullSync;

/**
Initializes the CBLDatabaseConfiguration object.
*/
Expand Down
8 changes: 6 additions & 2 deletions Objective-C/CBLDatabaseConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@

#import "CBLDatabaseConfiguration.h"
#import "CBLDatabase+Internal.h"
#import "CBLDefaults.h"

@implementation CBLDatabaseConfiguration {
BOOL _readonly;
}

@synthesize directory=_directory;
@synthesize directory=_directory, fullSync=_fullSync;

#ifdef COUCHBASE_ENTERPRISE
@synthesize encryptionKey=_encryptionKey;
Expand All @@ -47,11 +48,14 @@ - (instancetype) initWithConfig: (nullable CBLDatabaseConfiguration*)config

if (config) {
_directory = config.directory;
_fullSync = config.fullSync;
#ifdef COUCHBASE_ENTERPRISE
_encryptionKey = config.encryptionKey;
#endif
} else
} else {
_directory = [CBLDatabaseConfiguration defaultDirectory];
_fullSync = kCBLDefaultDatabaseFullSync;
}
}
return self;
}
Expand Down
5 changes: 5 additions & 0 deletions Objective-C/CBLDefaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@

#endif

#pragma mark - CBLDatabaseConfiguration

/** [NO] Full sync is off by default because the performance hit is seldom worth the benefit */
extern const BOOL kCBLDefaultDatabaseFullSync;

#pragma mark - CBLLogFileConfiguration

/** [NO] Plaintext is not used, and instead binary encoding is used in log files */
Expand Down
4 changes: 4 additions & 0 deletions Objective-C/CBLDefaults.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

#import "CBLDefaults.h"

#pragma mark - CBLDatabaseConfiguration

const BOOL kCBLDefaultDatabaseFullSync = NO;

#pragma mark - CBLLogFileConfiguration

const BOOL kCBLDefaultLogFileUsePlaintext = NO;
Expand Down
1 change: 1 addition & 0 deletions Objective-C/Exports/CBL.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ _kCBLBlobContentTypeProperty
_kCBLBlobDigestProperty
_kCBLBlobLengthProperty
_kCBLBlobType
_kCBLDefaultDatabaseFullSync
_kCBLDefaultCollectionName
_kCBLDefaultFullTextIndexIgnoreAccents
_kCBLDefaultLogFileMaxRotateCount
Expand Down
1 change: 1 addition & 0 deletions Objective-C/Exports/Generated/CBL.exp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ _kCBLBlobDigestProperty
_kCBLBlobLengthProperty
_kCBLBlobType
_kCBLDefaultCollectionName
_kCBLDefaultDatabaseFullSync
_kCBLDefaultFullTextIndexIgnoreAccents
_kCBLDefaultLogFileMaxRotateCount
_kCBLDefaultLogFileMaxSize
Expand Down
1 change: 1 addition & 0 deletions Objective-C/Exports/Generated/CBL_EE.exp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ _kCBLCertAttrStateOrProvince
_kCBLCertAttrSurname
_kCBLCertAttrURL
_kCBLDefaultCollectionName
_kCBLDefaultDatabaseFullSync
_kCBLDefaultFullTextIndexIgnoreAccents
_kCBLDefaultListenerDisableTls
_kCBLDefaultListenerEnableDeltaSync
Expand Down
5 changes: 4 additions & 1 deletion Objective-C/Internal/CBLDatabase+Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ NS_ASSUME_NONNULL_BEGIN

/// CBLDatabase:


@interface CBLDatabase () <CBLLockable, CBLRemovableListenerToken>

@property (readonly, nonatomic, nullable) C4Database* c4db;
Expand Down Expand Up @@ -80,6 +79,10 @@ NS_ASSUME_NONNULL_BEGIN

- (id) mutex;

#pragma mark - Private for test

- (const C4DatabaseConfig2*) getC4DBConfig;

@end

/// CBLDatabaseConfiguration:
Expand Down
73 changes: 73 additions & 0 deletions Objective-C/Tests/DatabaseTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -2818,6 +2818,79 @@ - (void) testDBEventTrigged {
[token remove];
}

#pragma mark - Full Sync Option

/**
Test Spec for Database Full Sync Option https://github.com/couchbaselabs/couchbase-lite-api/blob/master/spec/tests/T0003-SQLite-Options.md
*/

/**
1. TestSQLiteFullSyncConfig
Description
Test that the FullSync default is as expected and that it's setter and getter work.
Steps
1. Create a DatabaseConfiguration object.
2. Get and check the value of the FullSync property: it should be false.
3. Set the FullSync property true.
4. Get the config FullSync property and verify that it is true.
5. Set the FullSync property false.
6. Get the config FullSync property and verify that it is false.
*/
- (void) testSQLiteFullSyncConfig {
CBLDatabaseConfiguration* config = [[CBLDatabaseConfiguration alloc] init];
AssertFalse(config.fullSync);

config.fullSync = true;
Assert(config.fullSync);

config.fullSync = false;
AssertFalse(config.fullSync);
}

/**
2. TestDBWithFullSync
Description
Test that a Database respects the FullSync property.
Steps
1. Create a DatabaseConfiguration object and set Full Sync false.
2. Create a database with the config.
3. Get the configuration object from the Database and verify that FullSync is false.
4. Use c4db_config2 (perhaps necessary only for this test) to confirm that its config does not contain the kC4DB_DiskSyncFull flag.
5. Set the config's FullSync property true.
6. Create a database with the config.
7. Get the configuration object from the Database and verify that FullSync is true.
8. Use c4db_config2 to confirm that its config contains the kC4DB_DiskSyncFull flag.
*/
- (void) testDBWithFullSync {
NSString* dbName = @"fullsyncdb";
[CBLDatabase deleteDatabase: dbName inDirectory: self.directory error: nil];
AssertFalse([CBLDatabase databaseExists: dbName inDirectory: self.directory]);

CBLDatabaseConfiguration* config = [[CBLDatabaseConfiguration alloc] init];
config.directory = self.directory;
NSError* error;
CBLDatabase* db = [[CBLDatabase alloc] initWithName: dbName
config: config
error: &error];
AssertNil(error);
AssertNotNil(db, @"Couldn't open db: %@", error);
AssertFalse([db config].fullSync);
AssertFalse(([db getC4DBConfig]->flags & kC4DB_DiskSyncFull) == kC4DB_DiskSyncFull);

[self closeDatabase: db];

config.fullSync = true;
db = [[CBLDatabase alloc] initWithName: dbName
config: config
error: &error];
AssertNil(error);
AssertNotNil(db, @"Couldn't open db: %@", error);
Assert([db config].fullSync);
Assert(([db getC4DBConfig]->flags & kC4DB_DiskSyncFull) == kC4DB_DiskSyncFull);

[self closeDatabase: db];
}

#pragma clang diagnostic pop

@end
15 changes: 14 additions & 1 deletion Swift/DatabaseConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// DatabaseConfiguration.swift
// CouchbaseLite
//
// Copyright (c) 2017 Couchbase, Inc All rights reserved.
// Copyright (c) 2024 Couchbase, Inc All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -27,6 +27,17 @@ public struct DatabaseConfiguration {
/// Path to the directory to store the database in.
public var directory: String = CBLDatabaseConfiguration().directory

/// As Couchbase Lite normally configures its databases, There is a very
/// small (though non-zero) chance that a power failure at just the wrong
/// time could cause the most recently committed transaction's changes to
/// be lost. This would cause the database to appear as it did immediately
/// before that transaction.
///
/// Setting this mode true ensures that an operating system crash or
/// power failure will not cause the loss of any data. FULL synchronous
/// is very safe but it is also dramatically slower.
public var fullSync: Bool = defaultFullSync

#if COUCHBASE_ENTERPRISE
/// The key to encrypt the database with.
public var encryptionKey: EncryptionKey?
Expand All @@ -41,6 +52,7 @@ public struct DatabaseConfiguration {
public init(config: DatabaseConfiguration?) {
if let c = config {
self.directory = c.directory
self.fullSync = c.fullSync
#if COUCHBASE_ENTERPRISE
self.encryptionKey = c.encryptionKey
#endif
Expand All @@ -52,6 +64,7 @@ public struct DatabaseConfiguration {
func toImpl() -> CBLDatabaseConfiguration {
let config = CBLDatabaseConfiguration()
config.directory = self.directory
config.fullSync = self.fullSync
#if COUCHBASE_ENTERPRISE
config.encryptionKey = self.encryptionKey?.impl
#endif
Expand Down
55 changes: 54 additions & 1 deletion Swift/Tests/DatabaseTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// DatabaseTest.swift
// CouchbaseLite
//
// Copyright (c) 2017 Couchbase, Inc All rights reserved.
// Copyright (c) 2024 Couchbase, Inc All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -1529,4 +1529,57 @@ class DatabaseTest: CBLTestCase {
XCTAssertNotNil(db.config.encryptionKey)
#endif
}

// MARK: Full Sync Option
/// Test Spec for Database Full Sync Option
/// https://github.com/couchbaselabs/couchbase-lite-api/blob/master/spec/tests/T0003-SQLite-Options.md

/// 1. TestSQLiteFullSyncConfig
/// Description:
/// Test that the FullSync default is as expected and that it's setter and getter work.
/// Steps
/// 1. Create a DatabaseConfiguration object.
/// 2. Get and check the value of the FullSync property: it should be false.
/// 3. Set the FullSync property true.
/// 4. Get the config FullSync property and verify that it is true.
/// 5. Set the FullSync property false.
/// 6. Get the config FullSync property and verify that it is false.
func testSQLiteFullSyncConfig() {
var config = DatabaseConfiguration()
XCTAssertFalse(config.fullSync)

config.fullSync = true
XCTAssert(config.fullSync)

config.fullSync = false
XCTAssertFalse(config.fullSync)
}

/// 2. TestDBWithFullSync
/// Description:
/// Test that the FullSync default is as expected and that it's setter and getter work.
/// Steps
/// 1. Create a DatabaseConfiguration object and set Full Sync false.
/// 2. Create a database with the config.
/// 3. Get the configuration object from the Database and verify that FullSync is false.
/// 4. Use c4db_config2 (perhaps necessary only for this test) to confirm that its config does not contain the kC4DB_DiskSyncFull flag. - done in Obj-C
/// 5. Set the config's FullSync property true.
/// 6. Create a database with the config.
/// 7. Get the configuration object from the Database and verify that FullSync is true.
/// 8. Use c4db_config2 to confirm that its config contains the kC4DB_DiskSyncFull flag. - done in Obj-C
func testDBWithFullSync() throws {
let dbName = "fullsyncdb"
try deleteDB(name: dbName)
XCTAssertFalse(Database.exists(withName: dbName, inDirectory: self.directory))

var config = DatabaseConfiguration()
config.directory = self.directory
db = try Database(name: dbName, config: config)
XCTAssertFalse(DatabaseConfiguration(config: config).fullSync)

db = nil
config.fullSync = true
db = try Database(name: dbName, config: config)
XCTAssert(DatabaseConfiguration(config: config).fullSync)
}
}

0 comments on commit 2187e49

Please sign in to comment.