diff --git a/Jenkinsfile b/Jenkinsfile index c0c866030..88b5ce5c7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -15,7 +15,7 @@ pipeline { stage("Validate C") { agent { label 's61113u16 (litecore)' } steps { - sh 'jenkins/c_build.sh 3.2.4' + sh 'jenkins/c_build.sh 4.0.0' } } stage("Validate iOS") { diff --git a/modules/c/examples/code_snippets/CMakeLists.txt b/modules/c/examples/code_snippets/CMakeLists.txt index 6df289af4..69a60beee 100644 --- a/modules/c/examples/code_snippets/CMakeLists.txt +++ b/modules/c/examples/code_snippets/CMakeLists.txt @@ -14,7 +14,7 @@ if(DEFINED CBL_MACOS_ARCH) endif() if(NOT DEFINED CBL_VERSION) - set(CBL_VERSION 3.2.3) + set(CBL_VERSION 4.0.0) endif() project(code-snippets) diff --git a/modules/c/examples/code_snippets/main.cpp b/modules/c/examples/code_snippets/main.cpp index 9726e238a..4e2f5cbec 100644 --- a/modules/c/examples/code_snippets/main.cpp +++ b/modules/c/examples/code_snippets/main.cpp @@ -119,9 +119,8 @@ static void getting_started() { return; } - // All CRUD operations must be carried out via a collection (for backwards compatibility - // the old CBLDatabase_ API will automatically use the default collection). This is a quick - // API to explicitly get the default collection. + // All CRUD operations must be carried out via a collection. + // Remember to release the collection using CBLCollection_Release() when done. CBLCollection* collection = CBLDatabase_DefaultCollection(database, &err); // The lack of 'const' indicates this document is mutable @@ -178,7 +177,10 @@ static void getting_started() { // tag::query-syntax-n1ql[] // Create a query to fetch documents of type SDK int errorPos; - CBLQuery* query = CBLDatabase_CreateQuery(database, kCBLN1QLLanguage, FLSTR("SELECT * FROM _ WHERE type = \"SDK\""), &errorPos, &err); + CBLQuery* query = CBLDatabase_CreateQuery( + database, + kCBLN1QLLanguage, + FLSTR("SELECT * FROM _ WHERE type = \"SDK\""), &errorPos, &err); if(!query) { // Failed to create query, do error handling as above // Note that errorPos will contain the position in the N1QL string @@ -197,17 +199,21 @@ static void getting_started() { CBLQuery_Release(query); // Create replicator to push and pull changes to and from the cloud + CBLCollectionConfiguration collectionConfig = {0}; + collectionConfig.collection = collection; + CBLEndpoint* targetEndpoint = CBLEndpoint_CreateWithURL(FLSTR("ws://localhost:4984/getting-started-db"), &err); if(!targetEndpoint) { // Failed to create endpoint, do error handling as above return; } - CBLReplicatorConfiguration replConfig; - CBLAuthenticator* basicAuth = CBLAuth_CreatePassword(FLSTR("john"), FLSTR("pass")); - memset(&replConfig, 0, sizeof(replConfig)); - replConfig.database = database; + CBLReplicatorConfiguration replConfig = {0}; + replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = targetEndpoint; + + CBLAuthenticator* basicAuth = CBLAuth_CreatePassword(FLSTR("john"), FLSTR("pass")); replConfig.authenticator = basicAuth; CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err); @@ -218,7 +224,7 @@ static void getting_started() { return; } - // Assume a function like the simple following + // Assume a function like the following sample // // static void getting_started_change_listener(void* context, CBLReplicator* repl, const CBLReplicatorStatus* status) { // if(status->error.code != 0) { @@ -231,12 +237,15 @@ static void getting_started() { CBLReplicator_Start(replicator, false); // Later, stop and release the replicator - // end::getting-started[] // When finished release resources ... eg CBLListener_Remove(token); stop_replicator(replicator); + + CBLCollection_Release(collection); + CBLDatabase_Release(database); + // end::getting-started[] } @@ -300,15 +309,13 @@ static void test_replicator_conflict_resolve() { CBLError err{}; CBLEndpoint* target = CBLEndpoint_CreateWithURL(FLSTR("ws://localhost:4984/mydatabase"), &err); - CBLReplicationCollection collectionConfig; - memset(&collection, 0, sizeof(collectionConfig)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; collectionConfig.conflictResolver = local_win_conflict_resolver; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(replConfig)); - replConfig.collectionCount = 1; + CBLReplicatorConfiguration replConfig = {0}; replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err); @@ -345,11 +352,11 @@ static bool custom_conflict_handler(void* context, } static void test_save_with_conflict_handler() { - // tag::update-document-with-conflict-handler[] CBLDatabase* database = kDatabase; - CBLCollection* collection = CBLDatabase_DefaultCollection(database, NULL); + + // tag::update-document-with-conflict-handler[] CBLError err{}; - + CBLCollection* collection = CBLDatabase_DefaultCollection(database, &err); CBLDocument* mutableDoc = CBLCollection_GetMutableDocument(collection, FLSTR("xyz"), &err); FLMutableDict properties = CBLDocument_MutableProperties(mutableDoc); FLMutableDict_SetString(properties, FLSTR("name"), FLSTR("apples")); @@ -378,12 +385,14 @@ static void test_save_with_conflict_handler() { */ CBLCollection_SaveDocumentWithConflictHandler(collection, mutableDoc, custom_conflict_handler, NULL, &err); + // Release when done: + CBLDocument_Release(mutableDoc); + CBLCollection_Release(collection); // end::update-document-with-conflict-handler[] } static void use_encryption() { #ifdef COUCHBASE_ENTERPRISE - // tag::database-encryption[] // NOTE: No error handling, for brevity (see getting started) @@ -403,16 +412,20 @@ static void use_encryption() { // Remove encryption CBLDatabase_ChangeEncryptionKey(db, NULL, &err); // end::database-encryption[] - #endif } static void reset_replicator_checkpoint() { + CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); + CBLCollectionConfiguration collectionConfig = {0}; + collectionConfig.collection = collection; + CBLEndpoint* target = CBLEndpoint_CreateWithURL(FLSTR("ws://localhost:4984/db"), NULL); - CBLReplicatorConfiguration config; - memset(&config, 0, sizeof(CBLReplicatorConfiguration)); - config.database = kDatabase; + CBLReplicatorConfiguration config = {0}; + config.collections = &collectionConfig; + config.collectionCount = 1; config.endpoint = target; + CBLReplicator* replicator = CBLReplicator_Create(&config, NULL); CBLEndpoint_Free(target); @@ -447,7 +460,6 @@ static void create_new_database() { CBLError err{}; CBLDatabase* db = CBLDatabase_Open(FLSTR("my-database"), NULL, &err); // end::new-database[] - kDatabase = db; } @@ -505,16 +517,6 @@ static void list_scopes_and_collections(){ // end::scopes-manage-list[] } -static void change_logging() { - // tag::logging[] - // For output to stdout - CBLLog_SetConsoleLevel(kCBLLogVerbose); - - // For output to custom logging - CBLLog_SetCallbackLevel(kCBLLogVerbose); - // end::logging[] -} - static void load_prebuilt() { CBL_DeleteDatabase(FLSTR("travel-sample.cblite2"), kFLSliceNull, NULL); @@ -793,8 +795,7 @@ static void blob_json() { // end::tojson-blob[] } -static void datatype_dictionary() -{ +static void datatype_dictionary() { CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::datatype_dictionary[] @@ -833,8 +834,7 @@ static void datatype_dictionary() // end::datatype_dictionary[] } -static void datatype_mutable_dictionary() -{ +static void datatype_mutable_dictionary() { CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::datatype_mutable_dictionary[] @@ -860,8 +860,7 @@ static void datatype_mutable_dictionary() // end::datatype_mutable_dictionary[] } -static void datatype_array() -{ +static void datatype_array() { CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::datatype_array[] @@ -905,8 +904,7 @@ static void datatype_array() FLMutableArray_Release(mutableArray); } -static void datatype_mutable_array() -{ +static void datatype_mutable_array() { CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::datatype_mutable_array[] @@ -934,14 +932,13 @@ static void datatype_mutable_array() static void datatype_usage() { - // tag::datatype_usage[] // tag::datatype_usage_createdb[] // Open or create DB if it doesn't exist CBLError err{}; CBLDatabase* database = CBLDatabase_Open(FLSTR("mydb"), NULL, &err); - if(!database) { + if (!database) { return; } @@ -1005,10 +1002,11 @@ static void datatype_usage() { } // tag::datatype_usage_release[] - CBLDatabase_Release(database); CBLDocument_Release(mutableDoc); FLMutableDict_Release(address); FLMutableArray_Release(phones); + CBLCollection_Release(collection); + CBLDatabase_Release(database); // end::datatype_usage_release[] // end::datatype_usage[] @@ -1017,7 +1015,6 @@ static void datatype_usage() { static void create_index() { - CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::query-index[] @@ -1060,7 +1057,6 @@ static void create_array_index_single() { } static void create_array_index_nested() { - CBLDatabase *database = kDatabase; CBLCollection *collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::array-index-nested[] @@ -1075,7 +1071,6 @@ static void create_array_index_nested() { } static void create_partial_value_index() { - CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::partial-value-index[] @@ -1090,7 +1085,6 @@ static void create_partial_value_index() { } static void create_partial_full_text_index() { - CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::partial-full-text-index[] @@ -1106,7 +1100,6 @@ static void create_partial_full_text_index() { static void select_meta() { CBLDatabase* database = kDatabase; - // tag::query-select-meta[] // NOTE: No error handling, for brevity (see getting started) @@ -1157,7 +1150,6 @@ static void query_change_listener(void* context, CBLQuery* query, CBLListenerTok static void select_all() { CBLDatabase* database = kDatabase; - { // tag::query-select-all[] // NOTE: No error handling, for brevity (see getting started) @@ -1678,12 +1670,10 @@ static void start_replication() { FLString url = FLSTR("ws://localhost:4984/db"); CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); + CBLReplicatorConfiguration replConfig = {0}; replConfig.collectionCount = 1; replConfig.collections = &collectionConfig; replConfig.endpoint = target; @@ -1697,41 +1687,6 @@ static void start_replication() { stop_replicator(replicator); } -static void console_logging() { - // tag::console-logging[] - CBLLog_SetConsoleLevel(kCBLLogVerbose); - // end::console-logging[] -} - -static void file_logging() { - // tag::file-logging[] - // NOTE: No error handling, for brevity (see getting started) - // NOTE: You will need to use a platform appropriate method for finding - // a temporary directory - CBLLogFileConfiguration config {}; // Don't bother zeroing, since we set all properties - config.level = kCBLLogInfo; - config.directory = FLSTR("/tmp/logs");; - config.maxRotateCount = 12; - config.maxSize = 1048576; - config.usePlaintext = false; - - CBLError err{}; - CBLLog_SetFileConfig(config, &err); - // end::file-logging[] -} - -// tag::custom-logging[] -static void custom_log_callback(CBLLogDomain domain, CBLLogLevel level, FLString message) { - // handle the message, for example piping it to a third party framework -} -// end::custom-logging[] - -static void enable_custom_logging() { - // tag::set-custom-logging[] - CBLLog_SetCallback(custom_log_callback); - // end::set-custom-logging[] -} - static void console_log_sink() { // tag::new-console-logging[] CBLConsoleLogSink logSink {}; @@ -1780,12 +1735,10 @@ static void enable_basic_auth() { CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); CBLAuthenticator* basicAuth = CBLAuth_CreatePassword(FLSTR("john"), FLSTR("pass")); - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); + CBLReplicatorConfiguration replConfig = {0}; replConfig.collectionCount = 1; replConfig.collections = &collectionConfig; replConfig.endpoint = target; @@ -1801,8 +1754,7 @@ static void enable_basic_auth() { stop_replicator(replicator); } -static void docsonly_N1QL_Params(CBLDatabase* argDb) -{ +static void docsonly_N1QL_Params(CBLDatabase* argDb) { CBLDatabase* database = argDb; // tag::query-syntax-n1ql-params[] @@ -1847,7 +1799,7 @@ static void docsonly_N1QL_Params(CBLDatabase* argDb) // end::query-syntax-n1ql-params[] } -static void date_getter(){ +static void date_getter() { CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); CBLError err{}; @@ -1931,14 +1883,12 @@ static void docs_act_replication(CBLDatabase* argDb) FLString url = FLSTR("ws://localhost:4984/db"); CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); // <.> - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); - replConfig.collectionCount = 1; + CBLReplicatorConfiguration replConfig = {0}; replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; // <.> // tag::p2p-act-rep-config-cont[] @@ -1997,7 +1947,6 @@ static void docs_act_replication(CBLDatabase* argDb) // static void docs_act_replication_config_section_snippets() { - CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); bool docs_example_ShowBasicAuth = false; bool docs_example_ShowSessionAuth = false; @@ -2028,14 +1977,12 @@ static void docs_act_replication_config_section_snippets() CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); // <.> - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); - replConfig.collectionCount = 1; + CBLReplicatorConfiguration replConfig = {0}; replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; // <.> // end::sgw-act-rep-initialize[] @@ -2258,23 +2205,22 @@ static void docs_act_replication_Stop( // END replication.html >> Stop section static void replication_error_handling() { - CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); CBLError err{}; + CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, &err); FLString url = FLSTR("ws://localhost:4984/db"); CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); + CBLCollectionConfiguration collectionConfig = {0}; collectionConfig.collection = collection; - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); - replConfig.collectionCount = 1; + CBLReplicatorConfiguration replConfig = {0}; replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err); CBLEndpoint_Free(target); + CBLCollection_Release(collection); stop_replicator(replicator); } @@ -2344,8 +2290,6 @@ static void release_encryptable() { static void use_encryptable() { #ifdef COUCHBASE_ENTERPRISE - - CBLDatabase* database = kDatabase; CBLCollection* collection = CBLDatabase_DefaultCollection(kDatabase, NULL); // tag::use_encryptable[] @@ -2411,16 +2355,32 @@ static FLSliceResult my_cipher_function(FLSlice input) { return result; } - -static FLSliceResult property_encryptor(void* context, FLString docID, FLDict props, FLString path, - FLSlice input, FLStringResult* algorithm, FLStringResult* keyID, CBLError* error) { +static FLSliceResult property_encryptor( + void* context, + FLString scope, + FLString collection, + FLString docID, + FLDict props, + FLString path, + FLSlice input, + FLStringResult* algorithm, + FLStringResult* keyID, + CBLError* error) { *algorithm = FLSlice_Copy(FLSTR("MyEnc")); return my_cipher_function(input); } - -static FLSliceResult property_decryptor(void* context, FLString documentID, FLDict properties, FLString keyPath, - FLSlice input, FLString algorithm, FLString keyID, CBLError* error) { +static FLSliceResult property_decryptor( + void* context, + FLString scope, + FLString collection, + FLString documentID, + FLDict properties, + FLString keyPath, + FLSlice input, + FLString algorithm, + FLString keyID, + CBLError* error) { return my_cipher_function(input); } @@ -2441,22 +2401,19 @@ static void replicator_property_encryption() { // tag::replicator_property_encryption[] // Purpose: Show how to declare en(de)cryptors in replicator config // NOTE: No error handling, for brevity (see getting started) + CBLCollectionConfiguration collectionConfig = {0}; + collectionConfig.collection = collection; CBLError err{}; FLString url = FLSTR("ws://localhost:4984/db"); CBLEndpoint* target = CBLEndpoint_CreateWithURL(url, &err); - CBLReplicationCollection collectionConfig; - memset(&collectionConfig, 0, sizeof(CBLReplicationCollection)); - collectionConfig.collection = collection; - - CBLReplicatorConfiguration replConfig; - memset(&replConfig, 0, sizeof(CBLReplicatorConfiguration)); - replConfig.collectionCount = 1; + CBLReplicatorConfiguration replConfig = {0}; replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; - replConfig.propertyEncryptor = property_encryptor; // <.> - replConfig.propertyDecryptor = property_decryptor; // <.> + replConfig.documentPropertyEncryptor = property_encryptor; // <.> + replConfig.documentPropertyDecryptor = property_decryptor; // <.> CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err); CBLEndpoint_Free(target); @@ -2472,19 +2429,25 @@ static void replicator_property_encryption() { static void database_replica(){ #ifdef COUCHBASE_ENTERPRISE - CBLError err{}; - CBLReplicatorConfiguration replConfig; CBLDatabase* database1 = kDatabase; - CBLDatabase* database2 = CBLDatabase_Open(FLSTR("mydb"), NULL, &err); + CBLDatabase* database2 = CBLDatabase_Open(FLSTR("mydb"), NULL, NULL); // tag::database-replica[] + CBLError err{}; + CBLCollection* collection = CBLDatabase_DefaultCollection(database1, &err); + CBLCollectionConfiguration collectionConfig = {0}; + collectionConfig.collection = collection; + CBLEndpoint* target = CBLEndpoint_CreateWithLocalDB(database2); - replConfig.database = database1; + CBLReplicatorConfiguration replConfig = {0}; + replConfig.collections = &collectionConfig; + replConfig.collectionCount = 1; replConfig.endpoint = target; CBLReplicator* replicator = CBLReplicator_Create(&replConfig, &err); CBLEndpoint_Free(target); + CBLCollection_Release(collection); CBLReplicator_Start(replicator, false); // end::database-replica[] @@ -2547,6 +2510,14 @@ static void simpleReplicatorForListener() { CBLReplicatorConfiguration replConfig; memset(&replConfig, 0, sizeof(replConfig)); + // Set up the collections for replication: + CBLCollectionConfiguration collectionConfig; + memset(&collectionConfig, 0, sizeof(collectionConfig)); + + collectionConfig.collection = collection; + replConfig.collectionCount = 1; + replConfig.collections = &collectionConfig; + // Create a URL endpoint to the listener and set to the replicator config: // Note: You can safely free `endpoint` using CBLEndpoint_Free() after the replicator is created. CBLError error; @@ -2554,13 +2525,6 @@ static void simpleReplicatorForListener() { CBLEndpoint* endpoint = CBLEndpoint_CreateWithURL(FLSTR("wss://:/"), &error); replConfig.endpoint = endpoint; - // Set up the collections for replication: - CBLReplicationCollection collectionConfig; - memset(&collection, 0, sizeof(collectionConfig)); - collectionConfig.collection = collection; - replConfig.collectionCount = 1; - replConfig.collections = &collectionConfig; - // tag::p2p-act-rep-config-self-cert[] // Accept self-signed certificates, for testing purposes only: replConfig.acceptOnlySelfSignedServerCertificate = true; diff --git a/modules/c/nav-c.adoc b/modules/c/nav-c.adoc index 7b3b36dc2..03e37de59 100644 --- a/modules/c/nav-c.adoc +++ b/modules/c/nav-c.adoc @@ -43,6 +43,8 @@ include::partial$_set_page_context_for_c.adoc[] * xref:c:conflict.adoc[] + * xref:c:new-logging-api.adoc[] + * xref:c:upgrade.adoc[] * https://docs.couchbase.com/mobile/{version-maintenance}/couchbase-lite-c/C/html/modules.html[API Reference]