1
1
#include <sqlite3.h>
2
2
#include <stdio.h>
3
+ #include <stdlib.h>
4
+ #include <stdint.h>
3
5
#include <string.h>
4
6
#include <assert.h>
5
7
8
+ #define eprintf (...) fprintf(stderr, __VA_ARGS__)
9
+ #define ensure (condition , ...) { if (!(condition)) { eprintf(__VA_ARGS__); exit(1); } }
10
+
6
11
#if 0
7
12
static void dump_frame (unsigned char * frame , size_t size ){
8
13
for (int addr = 0 ; addr < size ; addr += 16 ){
@@ -26,140 +31,100 @@ static void dump_frame(unsigned char *frame, size_t size){
26
31
}
27
32
#endif
28
33
29
- static int cmp_data (sqlite3 * db1 , sqlite3 * db2 ){
34
+ static void cmp_data (sqlite3 * db1 , sqlite3 * db2 ){
30
35
sqlite3_stmt * stmt1 , * stmt2 ;
31
- int rc ;
32
-
33
- rc = sqlite3_prepare_v2 (db1 , "SELECT HEX(x) FROM t" , -1 , & stmt1 , 0 );
34
- if ( rc != SQLITE_OK ){
35
- fprintf (stderr , "Can't prepare statement: %s\n" , sqlite3_errmsg (db1 ));
36
- return 1 ;
37
- }
38
-
39
- rc = sqlite3_prepare_v2 (db2 , "SELECT HEX(x) FROM t" , -1 , & stmt2 , 0 );
40
- if ( rc != SQLITE_OK ){
41
- fprintf (stderr , "Can't prepare statement: %s\n" , sqlite3_errmsg (db2 ));
42
- return 1 ;
43
- }
36
+ ensure (sqlite3_prepare_v2 (db1 , "SELECT HEX(x) FROM t" , -1 , & stmt1 , 0 ) == SQLITE_OK , "can't prepare statement: %s\n" , sqlite3_errmsg (db1 ));
37
+ ensure (sqlite3_prepare_v2 (db2 , "SELECT HEX(x) FROM t" , -1 , & stmt2 , 0 ) == SQLITE_OK , "can't prepare statement: %s\n" , sqlite3_errmsg (db2 ));
44
38
45
39
for (;;){
46
40
int step1 = sqlite3_step (stmt1 );
47
41
int step2 = sqlite3_step (stmt2 );
48
- if ( step1 != step2 ){
49
- fprintf (stderr , "Step mismatch: %d != %d\n" , step1 , step2 );
50
- return 1 ;
51
- }
42
+ ensure (step1 == step2 , "step mismatch: %d != %d\n" , step1 , step2 );
52
43
if ( step1 != SQLITE_ROW ){
53
44
break ;
54
45
}
55
46
const unsigned char * text1 = sqlite3_column_text (stmt1 , 0 );
56
47
const unsigned char * text2 = sqlite3_column_text (stmt2 , 0 );
57
- if ( strncmp ((const char * )text1 , (const char * )text2 , 4096 )!= 0 ){
58
- fprintf (stderr , "Data mismatch\n" );
59
- return 1 ;
60
- }
48
+ ensure (strncmp ((const char * )text1 , (const char * )text2 , 4096 ) == 0 , "data mismatch" );
61
49
}
62
- return 0 ;
63
50
}
64
51
65
- static int sync_db (sqlite3 * db_primary , sqlite3 * db_backup ){
52
+ static void sync_db (sqlite3 * db_primary , sqlite3 * db_backup ){
66
53
unsigned int max_frame ;
67
- int rc ;
68
-
69
- rc = libsql_wal_frame_count (db_primary , & max_frame );
70
- if ( rc != SQLITE_OK ){
71
- fprintf (stderr , "Can't get frame count: %s\n" , sqlite3_errmsg (db_primary ));
72
- return 1 ;
73
- }
74
- rc = libsql_wal_insert_begin (db_backup );
75
- if ( rc != SQLITE_OK ){
76
- fprintf (stderr , "Can't begin commit: %s\n" , sqlite3_errmsg (db_backup ));
77
- return 1 ;
78
- }
54
+ ensure (libsql_wal_frame_count (db_primary , & max_frame ) == SQLITE_OK , "can't get frame count: %s\n" , sqlite3_errmsg (db_primary ));
55
+ ensure (libsql_wal_insert_begin (db_backup ) == SQLITE_OK , "can't begin commit: %s\n" , sqlite3_errmsg (db_backup ));
79
56
for (int i = 1 ; i <=max_frame ; i ++ ){
80
57
char frame [4096 + 24 ];
81
- rc = libsql_wal_get_frame (db_primary , i , frame , sizeof (frame ));
82
- if ( rc != SQLITE_OK ){
83
- fprintf (stderr , "Can't get frame: %s\n" , sqlite3_errmsg (db_primary ));
84
- return 1 ;
85
- }
86
- rc = libsql_wal_insert_frame (db_backup , i , frame , sizeof (frame ));
87
- if ( rc != SQLITE_OK ){
88
- fprintf (stderr , "Can't inject frame %d: %s\n" , rc , sqlite3_errmsg (db_backup ));
89
- return 1 ;
90
- }
91
- }
92
- rc = libsql_wal_insert_end (db_backup );
93
- if ( rc != SQLITE_OK ){
94
- fprintf (stderr , "Can't end commit: %s\n" , sqlite3_errmsg (db_backup ));
95
- return 1 ;
58
+ ensure (libsql_wal_get_frame (db_primary , i , frame , sizeof (frame )) == SQLITE_OK , "can't get frame: %s\n" , sqlite3_errmsg (db_primary ));
59
+ ensure (libsql_wal_insert_frame (db_backup , i , frame , sizeof (frame )) == SQLITE_OK , "can't inject frame: %s\n" , sqlite3_errmsg (db_backup ));
96
60
}
97
- return 0 ;
98
- }
99
-
100
- static void gen_data (sqlite3 * db ){
101
- sqlite3_exec (db , "CREATE TABLE t (x)" , 0 , 0 , 0 );
102
- sqlite3_exec (db , "INSERT INTO t VALUES (randomblob(4 * 1024))" , 0 , 0 , 0 );
103
- sqlite3_exec (db , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 );
104
- sqlite3_exec (db , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 );
61
+ ensure (libsql_wal_insert_end (db_backup ) == SQLITE_OK , "can't end commit: %s\n" , sqlite3_errmsg (db_backup ));
105
62
}
106
63
107
- int open_db (const char * path , sqlite3 * * db ) {
108
- int rc ;
109
-
110
- rc = sqlite3_open (path , db );
111
- if (rc != SQLITE_OK ) {
112
- fprintf (stderr , "Can't open database %s: %s\n" , path , sqlite3_errmsg (* db ));
113
- return rc ;
114
- }
115
- rc = sqlite3_exec (* db , "PRAGMA journal_mode=WAL" , NULL , NULL , NULL );
116
- if (rc != SQLITE_OK ) {
117
- fprintf (stderr , "Can't set journal mode for %s: %s\n" , path , sqlite3_errmsg (* db ));
118
- return rc ;
119
- }
120
- rc = sqlite3_wal_autocheckpoint (* db , 0 );
121
- if (rc != SQLITE_OK ) {
122
- fprintf (stderr , "Can't disable checkpointing for %s: %s\n" , path , sqlite3_errmsg (* db ));
123
- return rc ;
124
- }
125
- return rc ;
64
+ void open_db (const char * path , sqlite3 * * db ) {
65
+ ensure (sqlite3_open (path , db ) == SQLITE_OK , "can't open database %s: %s\n" , path , sqlite3_errmsg (* db ));
66
+ ensure (sqlite3_exec (* db , "PRAGMA journal_mode=WAL" , NULL , NULL , NULL ) == SQLITE_OK , "can't set journal mode for %s: %s\n" , path , sqlite3_errmsg (* db ));
67
+ ensure (sqlite3_wal_autocheckpoint (* db , 0 ) == SQLITE_OK , "can't disable checkpointing for %s: %s\n" , path , sqlite3_errmsg (* db ));
126
68
}
127
69
128
- int main (int argc , char * argv [])
129
- {
70
+ void test_huge_payload () {
130
71
sqlite3 * db_primary , * db_backup ;
131
72
unsigned int max_frame ;
132
- int rc ;
133
-
134
- rc = open_db ("primary.db" , & db_primary );
135
- if (rc != SQLITE_OK ) {
136
- return 1 ;
137
- }
138
- gen_data (db_primary );
139
-
140
- rc = open_db ("backup.db" , & db_backup );
141
- if (rc != SQLITE_OK ) {
142
- return 1 ;
143
- }
144
- rc = libsql_wal_frame_count (db_backup , & max_frame );
145
- if (rc != SQLITE_OK ) {
146
- fprintf (stderr , "Can't get frame count for backup: %s\n" , sqlite3_errmsg (db_backup ));
147
- return 1 ;
148
- }
73
+ open_db ("primary_test_huge_payload.db" , & db_primary );
74
+ ensure (sqlite3_exec (db_primary , "CREATE TABLE t (x)" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
75
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(4 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
76
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
77
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
78
+
79
+ open_db ("backup_test_huge_payload.db" , & db_backup );
80
+ ensure (libsql_wal_frame_count (db_backup , & max_frame ) == SQLITE_OK , "failed to get frames count: %s\n" , sqlite3_errmsg (db_backup ));
149
81
assert (max_frame == 0 );
150
82
83
+ eprintf ("start full sync\n" );
151
84
sync_db (db_primary , db_backup );
152
-
153
- if (cmp_data (db_primary , db_backup )) {
154
- return 1 ;
155
- }
156
-
85
+ cmp_data (db_primary , db_backup );
157
86
sync_db (db_primary , db_backup );
158
- if (cmp_data (db_primary , db_backup )) {
159
- return 1 ;
87
+ cmp_data (db_primary , db_backup );
88
+ }
89
+
90
+ void test_sync_by_parts () {
91
+ sqlite3 * db_primary , * db_backup ;
92
+ unsigned int max_frame ;
93
+ uint32_t in_commit = 0 ;
94
+ open_db ("primary_test_sync_by_parts.db" , & db_primary );
95
+ ensure (sqlite3_exec (db_primary , "CREATE TABLE t (x)" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
96
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(4 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
97
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
98
+ ensure (sqlite3_exec (db_primary , "INSERT INTO t VALUES (randomblob(1 * 1024))" , 0 , 0 , 0 ) == SQLITE_OK , "failed to insert data\n" );
99
+
100
+ open_db ("backup_test_sync_by_parts.db" , & db_backup );
101
+
102
+ ensure (libsql_wal_frame_count (db_primary , & max_frame ) == SQLITE_OK , "can't get frame count: %s\n" , sqlite3_errmsg (db_primary ));
103
+ eprintf ("start sync by parts\n" );
104
+ for (int i = 1 ; i <=max_frame ; i ++ ){
105
+ char frame [4096 + 24 ];
106
+ uint32_t is_commit ;
107
+ ensure (libsql_wal_get_frame (db_primary , i , frame , sizeof (frame )) == SQLITE_OK , "can't get frame: %s\n" , sqlite3_errmsg (db_primary ));
108
+ is_commit = ((uint32_t )frame [4 ] << 24 ) + ((uint32_t )frame [5 ] << 16 ) + ((uint32_t )frame [6 ] << 8 ) + ((uint32_t )frame [7 ] << 0 );
109
+ if (!in_commit ) {
110
+ in_commit = 1 ;
111
+ ensure (libsql_wal_insert_begin (db_backup ) == SQLITE_OK , "can't begin commit: %s\n" , sqlite3_errmsg (db_backup ));
112
+ }
113
+ ensure (libsql_wal_insert_frame (db_backup , i , frame , sizeof (frame )) == SQLITE_OK , "can't inject frame: %s\n" , sqlite3_errmsg (db_backup ));
114
+ if (is_commit ) {
115
+ ensure (libsql_wal_insert_end (db_backup ) == SQLITE_OK , "can't end commit: %s\n" , sqlite3_errmsg (db_backup ));
116
+ in_commit = 0 ;
117
+ }
160
118
}
119
+ cmp_data (db_primary , db_backup );
120
+ }
161
121
162
- printf ("OK\n" );
122
+ int main (int argc , char * argv [])
123
+ {
124
+ test_huge_payload ();
125
+ printf ("============= OK test_huge_payload\n" );
163
126
127
+ test_sync_by_parts ();
128
+ printf ("============= OK test_sync_by_parts\n" );
164
129
return 0 ;
165
130
}
0 commit comments