1
1
#include <assert.h>
2
2
#include <stdio.h>
3
+ #include <stdlib.h>
3
4
#include <string.h>
5
+ #include <unistd.h>
4
6
5
7
#include <cbl/CBLCollection.h>
6
8
#include <cbl/CBLDatabase.h>
7
9
#include <cbl/CBLDocument.h>
8
10
#include <cbl/CBLLog.h>
9
11
#include <cbl/CBLQuery.h>
12
+ #include <cbl/CBLReplicator.h>
10
13
11
14
const char * DOMAINS [] = { "Database" , "Query" , "Replicator" , "Network" };
12
15
const char * LEVEL_PREFIX [] = { "((" , "_" , "" , "WARNING: " , "***ERROR: " };
@@ -22,125 +25,223 @@ void log_callback(CBLLogDomain domain, CBLLogLevel level, FLString message) {
22
25
);
23
26
}
24
27
25
- int main (void ) {
26
- CBLConsoleLogSink log_sink = {};
27
- log_sink .level = kCBLLogDebug ;
28
- log_sink .domains = kCBLLogDomainMaskAll ;
29
-
30
- CBLLogSinks_SetConsole (log_sink );
31
-
32
- // Open database
28
+ void startReplication (CBLDatabase * db , bool writer , bool deleter ) {
33
29
CBLError error ;
34
- CBLDatabaseConfiguration config = {FLSTR ("/tmp" )};
35
- CBLDatabase * db = CBLDatabase_Open (FLSTR ("my_db" ), & config , & error );
36
- assert (db );
37
-
38
- CBLCollection * default_collection = CBLDatabase_DefaultCollection (db , & error );
39
- assert (default_collection );
40
-
41
- // Create a document
42
- CBLDocument * doc = CBLDocument_Create ();
30
+ CBLEndpoint * endpoint = CBLEndpoint_CreateWithURL (FLSTR ("wss://sync-gateway-staging.doctolib.com:443/billeo-db" ), & error );
31
+ assert (endpoint );
32
+
33
+ char * token = writer ? "0febaaafc5368d7e2f8663e0ee08b024a47278c1"
34
+ : (deleter ? "61b8b461214c7d6c6c7365dbc4e824111bc4167a"
35
+ : "49230c1a31db39e1d5e96e5fbdf1bf93099b53b5"
36
+ );
37
+ char cookie [64 ];
38
+ snprintf (cookie , sizeof cookie , "SyncGatewaySession=%s" , token );
39
+
40
+ FLMutableDict headers = FLMutableDict_New ();
41
+ FLMutableDict_SetString (headers , FLSTR ("Cookie" ), FLStr (cookie ));
42
+
43
+ FLMutableArray emptyArray = FLMutableArray_New ();
44
+ FLArray array = FLMutableArray_GetSource (emptyArray );
45
+
46
+ CBLReplicatorConfiguration config = {
47
+ .database = db ,
48
+ .endpoint = endpoint ,
49
+ .replicatorType = kCBLReplicatorTypePushAndPull ,
50
+ .continuous = true,
51
+ .disableAutoPurge = true,
52
+ .maxAttempts = 1 ,
53
+ .maxAttemptWaitTime = 0 ,
54
+ .heartbeat = 55 ,
55
+ .authenticator = NULL ,
56
+ .proxy = NULL ,
57
+ .headers = headers ,
58
+ .pinnedServerCertificate = FLStr (NULL ),
59
+ .trustedRootCertificates = FLStr (NULL ),
60
+ .channels = array ,
61
+ .documentIDs = array ,
62
+ .pushFilter = NULL ,
63
+ .pullFilter = NULL ,
64
+ .conflictResolver = NULL ,
65
+ .context = NULL ,
66
+ .collections = NULL ,
67
+ .collectionCount = 0 ,
68
+ .acceptParentDomainCookies = false,
69
+ };
70
+
71
+ CBLReplicator * replicator = CBLReplicator_Create (& config , & error );
72
+ assert (replicator );
73
+
74
+ CBLReplicator_Start (replicator , false);
75
+ }
43
76
44
- FILE * fp = fopen ("doc.json" , "r" );
77
+ void createDocuments (CBLDatabase * db ) {
78
+ CBLError error ;
45
79
46
- char json_format [4096 ];
47
- int len = fread (json_format , 1 , 4096 , fp );
80
+ FILE * fp = fopen ("replication_issue.json" , "r" );
81
+ if (!fp ) {
82
+ printf ("Failed to open replication_issue.json\n" );
83
+ return ;
84
+ }
85
+
86
+ fseek (fp , 0 , SEEK_END );
87
+ long file_size = ftell (fp );
88
+ fseek (fp , 0 , SEEK_SET );
89
+
90
+ char * json_format = malloc (file_size + 1 );
91
+ if (!json_format ) {
92
+ printf ("Failed to allocate memory for JSON\n" );
93
+ fclose (fp );
94
+ return ;
95
+ }
96
+
97
+ size_t len = fread (json_format , 1 , file_size , fp );
98
+ json_format [len ] = '\0' ;
48
99
49
100
fclose (fp );
50
101
51
102
FLString json = {};
52
- json .buf = & json_format ;
103
+ json .buf = json_format ;
53
104
json .size = len ;
54
- bool set_doc_content = CBLDocument_SetJSON (doc , json , & error );
55
105
56
106
// Save the document
57
- bool saved = CBLDatabase_SaveDocument (db , doc , & error );
58
- assert (saved );
59
-
60
- CBLDocument_Release (doc );
61
-
62
- // Simple array index
63
- CBLArrayIndexConfiguration array_index_config = {};
64
- array_index_config .expressionLanguage = kCBLN1QLLanguage ;
65
- array_index_config .path = FLSTR ("likes" );
66
- array_index_config .expressions = FLSTR ("" );
107
+ const int idOffset = 100 ;
108
+ for (int i = 0 ; i < 100 ; ++ i ) {
109
+ char id [64 ];
110
+ snprintf (id , sizeof id , "replication_issue_%d" , idOffset + i );
111
+
112
+ CBLDocument * doc = CBLDocument_CreateWithID (FLStr (id ));
113
+ bool set_doc_content = CBLDocument_SetJSON (doc , json , & error );
114
+ assert (set_doc_content );
115
+
116
+ FLMutableDict properties = CBLDocument_MutableProperties (doc );
117
+ FLMutableDict_SetString (properties , FLSTR ("owner" ), FLSTR ("00102204" ));
118
+
119
+ bool saved = CBLDatabase_SaveDocument (db , doc , & error );
120
+ assert (saved );
121
+
122
+ CBLDocument_Release (doc );
123
+ }
124
+
125
+ free (json_format );
126
+ }
67
127
68
- bool array_index_created = CBLCollection_CreateArrayIndex (
69
- default_collection ,
70
- FLSTR ("one_level" ),
71
- array_index_config ,
128
+ void getRemainingDocuments (CBLDatabase * db , FLString * result , int * count ) {
129
+ CBLError error ;
130
+ int errorPos = 0 ;
131
+ CBLQuery * query = CBLDatabase_CreateQuery (
132
+ db ,
133
+ kCBLN1QLLanguage ,
134
+ FLSTR ("SELECT meta().id FROM _ WHERE _.type='ReplicationIssue' LIMIT 10" ),
135
+ & errorPos ,
72
136
& error
73
137
);
74
- assert (array_index_created );
138
+ assert (query );
139
+
140
+ CBLResultSet * queryResult = CBLQuery_Execute (query , & error );
141
+ assert (queryResult );
142
+
143
+ int i = 0 ;
144
+ while (CBLResultSet_Next (queryResult ) && i < 10 ) {
145
+ FLValue id = CBLResultSet_ValueAtIndex (queryResult , 0 );
146
+ result [i ++ ] = FLSliceResult_AsSlice (FLSlice_Copy (FLValue_AsString (id )));
147
+ }
148
+ * count = i ;
149
+
150
+ CBLResultSet_Release (queryResult );
151
+ CBLQuery_Release (query );
152
+ }
75
153
76
- int error_pos = 0 ;
154
+ int getDocumentCount (CBLDatabase * db ) {
155
+ CBLError error ;
156
+ int errorPos = 0 ;
77
157
CBLQuery * query = CBLDatabase_CreateQuery (
78
158
db ,
79
159
kCBLN1QLLanguage ,
80
- FLSTR ("SELECT _.name, _like FROM _ UNNEST _.likes as _like WHERE _like = 'travel '" ),
81
- & error_pos ,
160
+ FLSTR ("SELECT COUNT(*) FROM _ WHERE _.type='ReplicationIssue '" ),
161
+ & errorPos ,
82
162
& error
83
163
);
84
164
assert (query );
85
165
86
- FLSliceResult explain_result = CBLQuery_Explain (query );
87
- assert (strstr ( explain_result . buf , "USING INDEX one_level" ) );
166
+ CBLResultSet * queryResult = CBLQuery_Execute (query , & error );
167
+ assert (queryResult );
88
168
89
- CBLResultSet * query_result = CBLQuery_Execute ( query , & error );
90
- assert ( query_result );
169
+ assert ( CBLResultSet_Next ( queryResult ) );
170
+ FLValue count = CBLResultSet_ValueAtIndex ( queryResult , 0 );
91
171
92
- assert ( CBLResultSet_Next ( query_result ) );
172
+ int result = FLValue_AsInt ( count );
93
173
94
- FLArray row = CBLResultSet_ResultArray (query_result );
95
- FLValue name = FLArray_Get (row , 0 );
96
- assert (strcmp (FLValue_AsString (name ).buf , "Sam" ) == 0 );
174
+ CBLResultSet_Release (queryResult );
175
+ CBLQuery_Release (query );
97
176
98
- assert (!CBLResultSet_Next (query_result ));
177
+ return result ;
178
+ }
99
179
100
- CBLResultSet_Release (query_result );
101
- CBLQuery_Release (query );
180
+ void deleteDocuments (CBLDatabase * db ) {
181
+ bool remaining = true;
182
+ CBLError error ;
102
183
103
- // Complex array index
104
- array_index_config .expressionLanguage = kCBLN1QLLanguage ;
105
- array_index_config .path = FLSTR ("contacts[].phones" );
106
- array_index_config .expressions = FLSTR ("type" );
184
+ while (remaining ) {
185
+ sleep (1 );
107
186
108
- array_index_created = CBLCollection_CreateArrayIndex (
109
- default_collection ,
110
- FLSTR ("two_level" ),
111
- array_index_config ,
112
- & error
113
- );
114
- assert (array_index_created );
187
+ FLString documents [10 ];
188
+ int count = 0 ;
189
+ getRemainingDocuments (db , documents , & count );
115
190
116
- query = CBLDatabase_CreateQuery (
117
- db ,
118
- kCBLN1QLLanguage ,
119
- FLSTR ("SELECT _.name, contact.type, phone.number FROM _ UNNEST _.contacts as contact UNNEST contact.phones as phone WHERE phone.type = 'mobile'" ),
120
- & error_pos ,
121
- & error
122
- );
123
- assert (query );
191
+ remaining = (count > 0 );
124
192
125
- explain_result = CBLQuery_Explain (query );
126
- assert (strstr (explain_result .buf , "USING INDEX two_level" ));
193
+ for (int i = 0 ; i < count ; i ++ ) {
194
+ const CBLDocument * doc = CBLDatabase_GetDocument (db , documents [i ], & error );
195
+ if (doc ) {
196
+ bool deleted = CBLDatabase_DeleteDocument (db , doc , & error );
197
+ assert (deleted );
198
+ CBLDocument_Release (doc );
199
+ }
200
+ }
201
+ }
202
+ }
127
203
128
- query_result = CBLQuery_Execute (query , & error );
129
- assert (query_result );
204
+ int main (void ) {
205
+ CBLConsoleLogSink log_sink = {};
206
+ log_sink .level = kCBLLogDebug ;
207
+ log_sink .domains = kCBLLogDomainMaskAll ;
130
208
131
- assert ( CBLResultSet_Next ( query_result ) );
209
+ CBLLogSinks_SetConsole ( log_sink );
132
210
133
- row = CBLResultSet_ResultArray ( query_result );
134
- name = FLArray_Get ( row , 0 ) ;
135
- assert ( strcmp ( FLValue_AsString ( name ). buf , "Sam" ) == 0 ) ;
211
+ // Step configuration
212
+ bool writer = false ;
213
+ bool deleter = false ;
136
214
137
- assert (CBLResultSet_Next (query_result ));
138
- assert (!CBLResultSet_Next (query_result ));
215
+ FLSlice databaseName = writer || deleter ? FLSTR ("writer" ) : FLSTR ("observer" );
139
216
140
- CBLResultSet_Release (query_result );
141
- CBLQuery_Release (query );
217
+ // Open database
218
+ CBLError error ;
219
+ CBLDatabaseConfiguration config = {FLSTR ("/Users/antoinemenciere/Documents" )};
220
+ CBLDatabase * db = CBLDatabase_Open (databaseName , & config , & error );
221
+ assert (db );
142
222
143
- // Cleanup
144
- bool closed = CBLDatabase_Delete (db , & error );
145
- assert (closed );
223
+ // Start a replication
224
+ startReplication (db , writer , deleter );
225
+
226
+ // Create 100 documents if the 'writer' variable is on
227
+ if (writer ) {
228
+ printf ("\nStart creating documents\n\n" );
229
+ createDocuments (db );
230
+ printf ("\nFinish creating documents\n\n" );
231
+ }
232
+
233
+ // Delete all documents if the 'deleter' variable is on
234
+ if (deleter ) {
235
+ printf ("\nStart deleting documents\n\n" );
236
+ deleteDocuments (db );
237
+ printf ("\nFinish deleting documents\n\n" );
238
+ }
239
+
240
+ // Always end by an infinite loop, to let the replication run as long as needed
241
+ while (true) {
242
+ sleep (1 );
243
+
244
+ int count = getDocumentCount (db );
245
+ printf ("\nThere is %d document(s) in database\n\n" , count );
246
+ }
146
247
}
0 commit comments