Progress on the sqlite3-rsync utility. This is an incremental check-in. It

does compile, but it does not work.

FossilOrigin-Name: fa06977b6db7fa745720561ec0b10570cf7e71598dc7a7c5ee650640e5bdf6f5
This commit is contained in:
drh 2024-09-11 17:02:44 +00:00
parent 79254dc363
commit dc3bec34a6
7 changed files with 448 additions and 23 deletions

View File

@ -700,8 +700,18 @@ sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
dbhash$(TEXE): $(TOP)/tool/dbhash.c sqlite3.lo sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/dbhash.c sqlite3.lo $(TLIBS)
sqlite3-rsync$(TEXE): $(TOP)/tool/sqlite3-rsync.c sqlite3.lo sqlite3.h
$(LTLINK) -o $@ $(TOP)/tool/sqlite3-rsync.c sqlite3.lo $(TLIBS)
RSYNC_SRC = \
$(TOP)/tool/sqlite3-rsync.c \
$(TOP)/ext/misc/sha1.c \
sqlite3.c
RSYNC_OPT = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
sqlite3-rsync$(TEXE): $(RSYNC_SRC)
$(TCC) -o $@ $(RSYNC_SRC) $(TLIBS)
scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
$(LTLINK) -o $@ -I. -DSCRUB_STANDALONE \

View File

@ -1867,8 +1867,18 @@ sqldiff.exe: $(TOP)\tool\sqldiff.c $(TOP)\ext\consio\console_io.h $(TOP)\ext\con
dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbhash.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
sqlite3-rsync.exe: $(TOP)\tool\sqlite3-rsync.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) $(TOP)\tool\sqlite3-rsync.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
RSYNC_SRC = \
$(TOP)\tool\sqlite3-rsync.c \
$(TOP)\ext\misc\sha1.c \
$(SQLITE3C)
RSYNC_OPT = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
sqlite3-rsync.exe: $(RSYNC_SRC) $(LIBRESOBJS)
$(LTLINK) $(RSYNC_OPT) $(NO_WARN) $(RSYNC_SRC) /link $(LDFLAGS) $(LTLINKOPTS) $(LIBRESOBJS)
scrub.exe: $(TOP)\ext\misc\scrub.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSCRUB_STANDALONE=1 $(TOP)\ext\misc\scrub.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)

View File

@ -196,7 +196,8 @@ static void hash_step_vformat(
** zOut[]. zOut[] must be at least 41 bytes long. */
static void hash_finish(
SHA1Context *p, /* The SHA1 context to finish and render */
char *zOut /* Store hexadecimal hash here */
char *zOut, /* Store hex or binary hash here */
int bAsBinary /* 1 for binary hash, 0 for hex hash */
){
unsigned int i;
unsigned char finalcount[8];
@ -251,7 +252,7 @@ static void sha1Func(
}else{
hash_step(&cx, sqlite3_value_text(argv[0]), nByte);
}
hash_finish(&cx, zOut);
hash_finish(&cx, zOut, sqlite3_user_data(context)!=0);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
@ -365,7 +366,7 @@ static void sha1QueryFunc(
}
sqlite3_finalize(pStmt);
}
hash_finish(&cx, zOut);
hash_finish(&cx, zOut, 0);
sqlite3_result_text(context, zOut, 40, SQLITE_TRANSIENT);
}
@ -379,11 +380,17 @@ int sqlite3_sha_init(
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
static int one = 1;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "sha1", 1,
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
0, sha1Func, 0, 0);
0, sha1Func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha1b", 1,
SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
(void*)&one, sha1Func, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "sha1_query", 1,
SQLITE_UTF8|SQLITE_DIRECTONLY, 0,

15
main.mk
View File

@ -568,9 +568,18 @@ dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
$(TCCX) -o dbhash$(EXE) -DSQLITE_THREADSAFE=0 \
$(TOP)/tool/dbhash.c sqlite3.c $(TLIBS) $(THREADLIB)
sqlite3-rsync$(EXE): $(TOP)/tool/sqlite3-rsync.c sqlite3.o
$(TCCX) -o sqlite3-rsync$(EXE) -DSQLITE_THREADSAFE=0 \
$(TOP)/tool/sqlite3-rsync.c sqlite3.o $(TLIBS) $(THREADLIB)
RSYNC_SRC = \
$(TOP)/tool/sqlite3-rsync.c \
$(TOP)/ext/misc/sha1.c \
sqlite3.c
RSYNC_OPT = \
-DSQLITE_THREADSAFE=0 \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_OMIT_DEPRECATED
sqlite3-rsync$(EXE): $(RSYNC_SRC)
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
$(TCC) -I. -DSCRUB_STANDALONE -o scrub$(EXE) $(TOP)/ext/misc/scrub.c sqlite3.o $(THREADLIB)

View File

@ -1,11 +1,11 @@
C Improved\sSSH\sinfrastructure.\s\sThe\sfoundation\sis\snow\sin\splace\sto\sbegin\sworking\non\sthe\sactual\ssync\sprotocol.\s\sStill\sexperimental.\s\sStill\sa\swork\sin\sprogress.
D 2024-09-10T22:14:18.799
C Progress\son\sthe\ssqlite3-rsync\sutility.\s\sThis\sis\san\sincremental\scheck-in.\s\sIt\ndoes\scompile,\sbut\sit\sdoes\snot\swork.
D 2024-09-11T17:02:44.010
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F Makefile.in c9a51ee844a471c950881748f21699fdbf42ef540bf5e78d269f99003f510256
F Makefile.in 54e80b016b0e58db383c0f08d340ef795b8b709ffb6f53a51a8ba7bf0c5e288f
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
F Makefile.msc 4ecdd8ec6bb3264cc2f6c4b154cf9ddd2647e4c6fcb2a294c9725a1483cb2862
F Makefile.msc a86e0f3fe5f807daa82d44b5056e3dbc311e569bd4748646a776a994124ec58b
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@ -420,7 +420,7 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
F ext/misc/series.c a6089b5e8e3002bd1e5d9877cee6aead0b9a6426e406c09a399817db9e9ae823
F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
F ext/misc/sha1.c dfd26eb3437a88fe7349d1fe080b761549c456ae17cb11242441bf66031942bf
F ext/misc/shathree.c 1821d90a0040c9accdbe3e3527d378d30569475d758aa70f6848924c0b430e8c
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd397dbea
@ -687,7 +687,7 @@ F ext/wasm/wasmfs.make 8a4955882aaa0783b3f60a9484a1f0f3d8b6f775c0fcd17c082f31966
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
F main.mk 936f535d99e70cf7c1f51c485a3fad7c7c858abad34d41ce100729befc2b2afe
F main.mk 9ffe4a14bdb4a0b856217a5465ca6b1ef4bef66a3c45e2da3fdb6d9bfc8d583e
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@ -2174,7 +2174,7 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
F tool/sqldiff.c 847fc8fcfddf5ce4797b7394cad6372f2f5dc17d8186e2ef8fb44d50fae4f44a
F tool/sqlite3-rsync.c d9fd25997c34d9a63e7afdd99b467aaa69440e3ce4d4f85cf47da3e182f4c7e9
F tool/sqlite3-rsync.c eb75a24e3a47fe7b5a4d5cbd2eadd4f4b6b6d6038ec7c94eb98a879ccd1bf8c5
F tool/sqlite3_analyzer.c.in 8da2b08f56eeac331a715036cf707cc20f879f231362be0c22efd682e2b89b4f
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@ -2213,8 +2213,8 @@ F vsixtest/vsixtest.tcl 6195aba1f12a5e10efc2b8c0009532167be5e301abe5b31385638080
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 397b2d37b7a6619b0c1eee201065585d03496f94786b21540f613e4716d56612
R 721e909ab77c2cd7295ba63619aaa44c
P 9a1a95f523a96303aad57e2422c2b51ea7e125f5490f32f7a2929d49b6c69ef8
R f1d49deccd29ff432816ec80f04a6271
U drh
Z 2e6a3a2b31db87fda5c83fa80a99e1a6
Z f5a21c2123f254d15ff8790517b1651d
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
9a1a95f523a96303aad57e2422c2b51ea7e125f5490f32f7a2929d49b6c69ef8
fa06977b6db7fa745720561ec0b10570cf7e71598dc7a7c5ee650640e5bdf6f5

View File

@ -17,6 +17,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include "sqlite3.h"
static const char zUsage[] =
@ -37,10 +38,29 @@ struct SQLiteRsync {
FILE *pIn; /* Receive from the other side */
sqlite3_uint64 nOut; /* Bytes transmitted */
sqlite3_uint64 nIn; /* Bytes received */
sqlite3 *db; /* Database connection */
int nErr; /* Number of errors encountered */
int eVerbose; /* Bigger for more output. 0 means none. */
int bCommCheck; /* True to debug the communication protocol */
int isRemote; /* On the remote side of a connection */
};
/* Magic numbers to identify particular messages sent over the wire.
*/
#define ORIGIN_BEGIN 0x41 /* Initial message */
#define ORIGIN_END 0x42 /* Time to quit */
#define ORIGIN_ERROR 0x43 /* Error message from the remote */
#define ORIGIN_PAGE 0x44 /* New page data */
#define ORIGIN_TXN 0x45 /* Transaction commit */
#define REPLICA_BEGIN 0x61 /* Welcome message */
#define REPLICA_ERROR 0x62 /* Error. Report and quit. */
#define REPLICA_END 0x63 /* Replica wants to stop */
#define REPLICA_HASH 0x64 /* One or more pages hashes to report */
#define REPLICA_READY 0x65 /* Read to receive page content */
/****************************************************************************
** Beginning of the popen2() implementation copied from Fossil *************
****************************************************************************/
@ -87,6 +107,12 @@ static void win32_fatal_error(const char *zMsg){
# define PTR_TO_INT(X) ((int)(X))
#endif
/* Register SQL functions provided by ext/misc/sha1.c */
extern int sqlite3_sha_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
);
#ifdef _WIN32
/*
@ -471,6 +497,238 @@ static void echoOneLine(SQLiteRsync *p){
}
}
/* Read a single big-endian 32-bit unsigned integer from the input
** stream. Return 0 on success and 1 if there are any errors.
*/
static int readUint32(SQLiteRsync *p, unsigned int *pU){
unsigned char buf[4];
if( fread(buf, sizeof(buf), 1, p->pIn)==1 ){
*pU = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
return 0;
}else{
p->nErr++;
return 1;
}
}
/* Write a single big-endian 32-bit unsigned integer to the output stream.
** Return 0 on success and 1 if there are any errors.
*/
static int writeUint32(SQLiteRsync *p, unsigned int x){
unsigned char buf[4];
buf[3] = x & 0xff;
x >>= 8;
buf[2] = x & 0xff;
x >>= 8;
buf[1] = x & 0xff;
x >>= 8;
buf[0] = x;
if( fwrite(buf, sizeof(buf), 1, p->pOut)!=1 ){
p->nErr++;
return 1;
}
return 0;
}
/* Report an error.
**
** If this happens on the remote side, we send back a REMOTE_ERROR
** message. On the local side, the error message goes to stderr.
*/
static void reportError(SQLiteRsync *p, const char *zFormat, ...){
va_list ap;
char *zMsg;
unsigned int nMsg;
va_start(ap, zFormat);
zMsg = sqlite3_vmprintf(zFormat, ap);
va_end(ap);
nMsg = zMsg ? (unsigned int)strlen(zMsg) : 0;
if( p->isRemote ){
if( p->zReplica ){
putc(REPLICA_ERROR, p->pOut);
}else{
putc(ORIGIN_ERROR, p->pOut);
}
writeUint32(p, nMsg);
fwrite(zMsg, nMsg, 1, p->pOut);
fflush(p->pOut);
}else{
fprintf(stderr, "%s\n", zMsg);
}
sqlite3_free(zMsg);
p->nErr++;
}
/* Receive and report an error message coming from the other side.
*/
static void readAndDisplayError(SQLiteRsync *p){
unsigned int n = 0;
char *zMsg;
(void)readUint32(p, &n);
if( n==0 ){
fprintf(stderr,"ERROR: unknown (possibly out-of-memory)\n");
}else{
zMsg = sqlite3_malloc64( n+1 );
if( zMsg==0 ){
fprintf(stderr, "ERROR: out-of-memory\n");
return;
}
memset(zMsg, 0, n+1);
fread(zMsg, 1, n, p->pIn);
fprintf(stderr,"ERROR: %s\n", zMsg);
sqlite3_free(zMsg);
}
p->nErr++;
}
/* Construct a new prepared statement. Report an error and return NULL
** if anything goes wrong.
*/
static sqlite3_stmt *prepareStmtVA(
SQLiteRsync *p,
char *zFormat,
va_list ap
){
sqlite3_stmt *pStmt = 0;
char *zSql;
char *zToFree = 0;
int rc;
if( strchr(zFormat,'%') ){
zSql = sqlite3_vmprintf(zFormat, ap);
if( zSql==0 ){
reportError(p, "out-of-memory");
return 0;
}else{
zToFree = zSql;
}
}else{
zSql = zFormat;
}
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc || pStmt==0 ){
reportError(p, "unable to prepare SQL [%s]: %s", zSql,
sqlite3_errmsg(p->db));
sqlite3_finalize(pStmt);
pStmt = 0;
}
if( zToFree ) sqlite3_free(zToFree);
return pStmt;
}
static sqlite3_stmt *prepareStmt(
SQLiteRsync *p,
char *zFormat,
...
){
sqlite3_stmt *pStmt;
va_list ap;
va_start(ap, zFormat);
pStmt = prepareStmtVA(p, zFormat, ap);
va_end(ap);
return pStmt;
}
/* Run a single SQL statement
*/
static void runSql(SQLiteRsync *p, char *zSql, ...){
sqlite3_stmt *pStmt;
va_list ap;
va_start(ap, zSql);
pStmt = prepareStmtVA(p, zSql, ap);
va_end(ap);
if( pStmt ){
int rc = sqlite3_step(pStmt);
if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){
reportError(p, "SQL statement [%s] failed: %s", zSql,
sqlite3_errmsg(p->db));
}
sqlite3_finalize(pStmt);
}
}
/* Run an SQL statement that returns a single unsigned 32-bit integer result
*/
static int runSqlReturnUInt(
SQLiteRsync *p,
unsigned int *pRes,
char *zSql,
...
){
sqlite3_stmt *pStmt;
int res = 0;
va_list ap;
va_start(ap, zSql);
pStmt = prepareStmtVA(p, zSql, ap);
va_end(ap);
if( pStmt==0 ){
res = 1;
}else{
int rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
*pRes = (unsigned int)(sqlite3_column_int64(pStmt, 0)&0xffffffff);
}else{
reportError(p, "SQL statement [%s] failed: %s", zSql,
sqlite3_errmsg(p->db));
res = 1;
}
sqlite3_finalize(pStmt);
}
return res;
}
/* Run an SQL statement that returns a single TEXT value that is no more
** than 99 bytes in length.
*/
static int runSqlReturnText(
SQLiteRsync *p,
char *pRes,
char *zSql,
...
){
sqlite3_stmt *pStmt;
int res = 0;
va_list ap;
va_start(ap, zSql);
pStmt = prepareStmtVA(p, zSql, ap);
va_end(ap);
pRes[0] = 0;
if( pStmt==0 ){
res = 1;
}else{
int rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
const unsigned char *a = sqlite3_column_text(pStmt, 0);
int n;
if( a==0 ){
pRes[0] = 0;
}else{
n = sqlite3_column_bytes(pStmt, 0);
if( n>99 ) n = 99;
memcpy(pRes, a, n);
pRes[n] = 0;
}
}else{
reportError(p, "SQL statement [%s] failed: %s", zSql,
sqlite3_errmsg(p->db));
res = 1;
}
sqlite3_finalize(pStmt);
}
return res;
}
/* Close the database connection associated with p
*/
static void closeDb(SQLiteRsync *p){
if( p->db ){
sqlite3_close(p->db);
p->db = 0;
}
}
/*
** Run the origin-side protocol.
**
@ -484,6 +742,12 @@ static void echoOneLine(SQLiteRsync *p){
** 7. Send origin-end message
*/
static void originSide(SQLiteRsync *p){
int rc = 0;
int c = 0;
unsigned int nPage = 0;
unsigned int szPg = 0;
char buf[100];
if( p->bCommCheck ){
fprintf(p->pOut, "sqlite3-rsync origin-begin %s\n", p->zOrigin);
fflush(p->pOut);
@ -493,6 +757,59 @@ static void originSide(SQLiteRsync *p){
echoOneLine(p);
return;
}
/* Open the ORIGIN database. */
rc = sqlite3_open_v2(p->zOrigin, &p->db, SQLITE_OPEN_READONLY, 0);
if( rc ){
reportError(p, "unable to open origin database file \"%s\": %s",
sqlite3_errmsg(p->db));
closeDb(p);
return;
}
sqlite3_sha_init(p->db, 0, 0);
runSql(p, "BEGIN");
runSqlReturnText(p, buf, "PRAGMA journal_mode");
if( sqlite3_stricmp(buf,"wal")!=0 ){
reportError(p, "Origin database is not in WAL mode");
}
runSqlReturnUInt(p, &nPage, "PRAGMA page_count");
runSqlReturnUInt(p, &szPg, "PRAGMA page_size");
if( p->nErr==0 ){
/* Send the ORIGIN_BEGIN message */
fputc(ORIGIN_BEGIN, p->pOut);
writeUint32(p, nPage);
writeUint32(p, szPg);
fflush(p->pOut);
}
/* Respond to message from the replica */
while( p->nErr==0 && (c = fgetc(p->pIn))!=EOF ){
switch( c ){
case REPLICA_ERROR: {
readAndDisplayError(p);
break;
}
case REPLICA_BEGIN: {
break;
}
case REPLICA_END: {
break;
}
case REPLICA_HASH: {
break;
}
case REPLICA_READY: {
break;
}
default: {
reportError(p, "Origin side received unknown message: 0x%02x", c);
break;
}
}
}
closeDb(p);
}
/*
@ -508,6 +825,8 @@ static void originSide(SQLiteRsync *p){
** 7. COMMIT
*/
static void replicaSide(SQLiteRsync *p){
int c;
char buf[100];
if( p->bCommCheck ){
echoOneLine(p);
fprintf(p->pOut, "replica-begin %s\n", p->zReplica);
@ -517,6 +836,74 @@ static void replicaSide(SQLiteRsync *p){
fflush(p->pOut);
return;
}
/* Respond to message from the origin. The origin will initiate the
** the conversation with an ORIGIN_BEGIN message.
*/
while( p->nErr==0 && (c = fgetc(p->pIn))!=EOF ){
switch( c ){
case ORIGIN_ERROR: {
readAndDisplayError(p);
break;
}
case ORIGIN_BEGIN: {
unsigned int nOPage = 0, szOPage = 0;
unsigned int nRPage = 0, szRPage = 0;
int rc = 0;
sqlite3_stmt *pStmt = 0;
closeDb(p);
readUint32(p, &nOPage);
readUint32(p, &szOPage);
if( p->nErr ) break;
rc = sqlite3_open(p->zReplica, &p->db);
if( rc ){
reportError(p, "cannot open replica database \"%s\": %s",
p->zReplica, sqlite3_errmsg(p->db));
closeDb(p);
break;
}
sqlite3_sha_init(p->db, 0, 0);
if( runSqlReturnUInt(p, &nRPage, "PRAGMA page_count") ){
break;
}
if( nRPage==0 ){
runSql(p, "PRAGMA page_size=%u", szOPage);
runSql(p, "PRAGMA journal_mode=WAL");
}
runSql(p, "BEGIN IMMEDIATE");
runSqlReturnText(p, buf, "PRAGMA journal_mode");
if( strcmp(buf, "wal")!=0 ){
reportError(p, "replica is not in WAL mode");
break;
}
runSqlReturnUInt(p, &nRPage, "PRAGMA page_count");
runSqlReturnUInt(p, &szRPage, "PRAGMA page_size");
if( szRPage!=szOPage ){
reportError(p, "page size mismatch; origin is %d bytes and "
"replica is %d bytes", szOPage, szRPage);
break;
}
pStmt = prepareStmt(p,
"SELECT pgno, sha1(data) FROM sqlite_dbpage"
" WHERE pgno<=min(%d,%d)", nRPage, nOPage);
sqlite3_finalize(pStmt);
break;
}
case ORIGIN_END: {
break;
}
case ORIGIN_PAGE: {
break;
}
default: {
reportError(p, "Replica side received unknown message: 0x%02x", c);
break;
}
}
}
closeDb(p);
}
@ -544,7 +931,7 @@ static void replicaSide(SQLiteRsync *p){
**
** If (3) is seen, call originSide() on stdin and stdout.
**
** If (4) is seen, call replicaSide() on stdin and stdout.
q** If (4) is seen, call replicaSide() on stdin and stdout.
*/
int main(int argc, char **argv){
int isOrigin = 0;
@ -635,6 +1022,7 @@ int main(int argc, char **argv){
if( isOrigin ){
ctx.pIn = stdin;
ctx.pOut = stdout;
ctx.isRemote = 1;
originSide(&ctx);
return 0;
}
@ -643,6 +1031,7 @@ int main(int argc, char **argv){
ctx.zOrigin = 0;
ctx.pIn = stdin;
ctx.pOut = stdout;
ctx.isRemote = 1;
replicaSide(&ctx);
return 0;
}