Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11e1defc8f | |||
| 3d56d59adc | |||
| 7154803d4c | |||
| df9b488799 | |||
| 15e05eab32 | |||
| 9d3047bd0d | |||
| 2b30518804 | |||
| 33f0a3ed13 | |||
| 762946b236 | |||
| 8550e4a9f8 |
+2
-9
@@ -702,23 +702,16 @@ dbhash$(TEXE): $(TOP)/tool/dbhash.c sqlite3.lo sqlite3.h
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)/tool/sqlite3-rsync.c \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
sqlite3.c
|
||||
|
||||
RSYNC_OPT = \
|
||||
-I$(TOP)/ext/consio \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-USQLITE_THREADSAFE \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DCONSIO_SET_ERROR_STREAM
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
RSYNC_DEP = \
|
||||
$(TOP)/ext/consio/console_io.h \
|
||||
$(TOP)/ext/consio/console_io.c
|
||||
|
||||
sqlite3-rsync$(TEXE): $(RSYNC_DEP) $(RSYNC_SRC)
|
||||
sqlite3-rsync$(TEXE): $(RSYNC_SRC)
|
||||
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
|
||||
|
||||
scrub$(TEXE): $(TOP)/ext/misc/scrub.c sqlite3.lo
|
||||
|
||||
+2
-5
@@ -1869,18 +1869,15 @@ dbhash.exe: $(TOP)\tool\dbhash.c $(SQLITE3C) $(SQLITE3H)
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)\tool\sqlite3-rsync.c \
|
||||
$(TOP)\ext\consio\console_io.c \
|
||||
$(SQLITE3C)
|
||||
|
||||
RSYNC_OPT = \
|
||||
-I$(TOP)/ext/consio \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DCONSIO_SET_ERROR_STREAM
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync.exe: $(RSYNC_SRC) $(RSYNC_DEP) $(LIBRESOBJS)
|
||||
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)
|
||||
|
||||
@@ -154,7 +154,7 @@ static ConsoleInfo consoleInfo = {
|
||||
SAC_NoConsole /* sacSetup */
|
||||
};
|
||||
|
||||
FILE* invalidFileStream = (FILE *)~0;
|
||||
SQLITE_INTERNAL_LINKAGE FILE* invalidFileStream = (FILE *)~0;
|
||||
|
||||
# if CIO_WIN_WC_XLATE
|
||||
static void maybeSetupAsConsole(PerStreamTags *ppst, short odir){
|
||||
|
||||
@@ -120,7 +120,7 @@ SQLITE_INTERNAL_LINKAGE void SQLITE_CDECL consoleRestore( void );
|
||||
** It is error to close a stream so designated, then, without
|
||||
** designating another, use the corresponding {o,e}Emit(...).
|
||||
*/
|
||||
extern FILE *invalidFileStream;
|
||||
SQLITE_INTERNAL_LINKAGE FILE *invalidFileStream;
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setOutputStream(FILE *pf);
|
||||
# ifdef CONSIO_SET_ERROR_STREAM
|
||||
SQLITE_INTERNAL_LINKAGE FILE *setErrorStream(FILE *pf);
|
||||
|
||||
@@ -570,21 +570,15 @@ dbhash$(EXE): $(TOP)/tool/dbhash.c sqlite3.c sqlite3.h
|
||||
|
||||
RSYNC_SRC = \
|
||||
$(TOP)/tool/sqlite3-rsync.c \
|
||||
$(TOP)/ext/consio/console_io.c \
|
||||
sqlite3.c
|
||||
|
||||
RSYNC_DEP = \
|
||||
$(TOP)/ext/consio/console_io.h
|
||||
|
||||
RSYNC_OPT = \
|
||||
-I$(TOP)/ext/consio \
|
||||
-DSQLITE_ENABLE_DBPAGE_VTAB \
|
||||
-DSQLITE_THREADSAFE=0 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION \
|
||||
-DSQLITE_OMIT_DEPRECATED \
|
||||
-DCONSIO_SET_ERROR_STREAM
|
||||
-DSQLITE_OMIT_DEPRECATED
|
||||
|
||||
sqlite3-rsync$(EXE): $(RSYNC_SRC) $(RSYNC_DEP)
|
||||
sqlite3-rsync$(EXE): $(RSYNC_SRC)
|
||||
$(TCC) -o $@ $(RSYNC_OPT) $(RSYNC_SRC) $(TLIBS)
|
||||
|
||||
scrub$(EXE): $(TOP)/ext/misc/scrub.c sqlite3.o
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
C Fix\sthe\shanging\sproblem.
|
||||
D 2024-09-13T16:15:07.770
|
||||
C CLI\sarg\shandling\srobustness\simprovements.
|
||||
D 2024-09-14T16:30:01.739
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
F Makefile.in 53f65164355c90793e6df88c5770ac04d02c1690e8a175e7cf5e703ca497cc4c
|
||||
F Makefile.in 31368ad3e1800bb5f311adede543ee456ca7d2595403c7f131797ae65a7d415c
|
||||
F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
|
||||
F Makefile.msc 8732e98919b1b2b072fb52d46b5d200741b210b9f46bc17c355f9dcfc4844b4a
|
||||
F Makefile.msc 62ace0005c53b52f189c20c1d6d8fa4dbd2a37c90d9c1362b60f4fb4c841fa15
|
||||
F README.md c3c0f19532ce28f6297a71870f3c7b424729f0e6d9ab889616d3587dd2332159
|
||||
F VERSION 0db40f92c04378404eb45bff93e9e42c148c7e54fd3da99469ed21e22411f5a6
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -53,8 +53,8 @@ F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad1aff3294f94
|
||||
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
|
||||
F ext/consio/console_io.c 5f8d6b832faa9db9f7442d6e02cf7e62409282c31fe68efa67da312db88c4fab x
|
||||
F ext/consio/console_io.h 6212909529c4ab3deeeee29db2d0b2b9cd5c881cc9dd51dede079273ce91db3d
|
||||
F ext/consio/console_io.c d2b74afae8d301de2e8447b1045fcd33eb59df13bf581d906d99c74fe5d2b13f x
|
||||
F ext/consio/console_io.h b5ebe34aa15b357621ebbea3d3f2e2b24750d4280b5802516409e23947fd9ee5
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test 661f873fd451127edf822ef0d520088faa319135f6a15bd10be6801ac284ac9b
|
||||
@@ -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 27b50c79c995968403b7b2b5726069abb5c99d429c9949302049fed8a769671e
|
||||
F main.mk 8b9c0252aef57b5b2a10f34b8b46e89f9ed06bdccef1df98673a12f34e9b3e79
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
@@ -714,7 +714,7 @@ F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d49
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c b224d3db0f28c4a5f1407c50107a0a8133bd244ff3c7f6f8cedeb896a8cf1b64
|
||||
F src/date.c 89ce1ff20512a7fa5070ba6e7dd5c171148ca7d580955795bf97c79c2456144a
|
||||
F src/dbpage.c 3c437630c2933b9eefca915d191f8dea9da135195593bb17f553be58ffcd3634
|
||||
F src/dbpage.c 12e49515d67d4a59625d71f9aa42499556cfdc2e4f1ea49086e674a7f47f46e5
|
||||
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
|
||||
F src/delete.c 444c4d1eaac40103461e3b6f0881846dd3aafc1cec1dd169d3482fa331667da7
|
||||
F src/expr.c 6d5f2c38fe3ec06a7eac599dac822788b36064124e20112a844e9cd5156cb239
|
||||
@@ -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 780f48e6de46308546e1e4382f36ce85a4ab2085b75daa9c660e6d74fb1ea14c
|
||||
F tool/sqlite3-rsync.c 00c9b4483851ca0337dff4b544ee39dffa8cdbe9dc55cd51d391590fd1f03763
|
||||
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 b4eff1fd6eb5f373f0b4ca2709fcab735aed426cdfd8a88ed3f08fd10afcd534
|
||||
R cd42a019762d0f5cd5c8b6435be44826
|
||||
U drh
|
||||
Z ce55e767fb46264cb3e1a3b4cf6e579f
|
||||
P 9961334c8007e7cb6ae55885075b74acddc4fa701b359cf67e0f3c237d7eba4a
|
||||
R 88be3363ce7bdb6c2bdb93ef027d46e9
|
||||
U stephan
|
||||
Z 5b00ba151c4dd893eaaa646fc9f450ae
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d57903f7fdb5abbda70f049bb0b4e229deefc39b8a4a4c48203d4c4e7be3782c
|
||||
129aca54f6b791c222b51f3eb01569e1e569269860e153b005140eb65af378b9
|
||||
|
||||
+4
-1
@@ -360,7 +360,7 @@ static int dbpageUpdate(
|
||||
iDb = 0;
|
||||
}else{
|
||||
const char *zSchema = (const char*)sqlite3_value_text(argv[4]);
|
||||
iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
|
||||
iDb = sqlite3FindDbName(pTab->db, zSchema);
|
||||
if( iDb<0 ){
|
||||
zErr = "no such schema";
|
||||
goto update_fail;
|
||||
@@ -377,8 +377,11 @@ static int dbpageUpdate(
|
||||
){
|
||||
if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){
|
||||
if( iDb>=pTab->nTrunc ){
|
||||
testcase( pTab->aTrunc!=0 );
|
||||
pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno));
|
||||
if( pTab->aTrunc ){
|
||||
int j;
|
||||
for(j=pTab->nTrunc; j<iDb; j++) pTab->aTrunc[j] = 0;
|
||||
pTab->nTrunc = iDb+1;
|
||||
}else{
|
||||
return SQLITE_NOMEM;
|
||||
|
||||
+190
-96
@@ -20,7 +20,7 @@
|
||||
#include <stdarg.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
static const char zUsage[] =
|
||||
static const char zUsage[] =
|
||||
"sqlite3-rsync ORIGIN REPLICA ?OPTIONS?\n"
|
||||
"\n"
|
||||
"One of ORIGIN or REPLICA is a pathname to a database on the local\n"
|
||||
@@ -34,6 +34,7 @@ static const char zUsage[] =
|
||||
" --help Show this help screen\n"
|
||||
" --ssh PATH Name of the SSH program used to reach the remote side\n"
|
||||
" -v Verbose. Multiple v's for increasing output\n"
|
||||
" --version Show detailed version information\n"
|
||||
;
|
||||
|
||||
typedef unsigned char u8;
|
||||
@@ -43,8 +44,10 @@ typedef struct SQLiteRsync SQLiteRsync;
|
||||
struct SQLiteRsync {
|
||||
const char *zOrigin; /* Name of the origin */
|
||||
const char *zReplica; /* Name of the replica */
|
||||
const char *zErrFile; /* Append error messages to this file */
|
||||
FILE *pOut; /* Transmit to the other side */
|
||||
FILE *pIn; /* Receive from the other side */
|
||||
FILE *pLog; /* Duplicate output here if not NULL */
|
||||
sqlite3 *db; /* Database connection */
|
||||
int nErr; /* Number of errors encountered */
|
||||
u8 eVerbose; /* Bigger for more output. 0 means none. */
|
||||
@@ -82,34 +85,6 @@ struct SQLiteRsync {
|
||||
#define REPLICA_READY 0x65 /* Read to receive page content */
|
||||
#define REPLICA_MSG 0x66 /* Informational message */
|
||||
|
||||
#include "console_io.h"
|
||||
/* From here onward, fgets() is redirected to the console_io library. */
|
||||
# define fgets(b,n,f) fGetsUtf8(b,n,f)
|
||||
/*
|
||||
* Define macros for emitting output text in various ways:
|
||||
* sputz(s, z) => emit 0-terminated string z to given stream s
|
||||
* sputf(s, f, ...) => emit varargs per format f to given stream s
|
||||
* oputz(z) => emit 0-terminated string z to default stream
|
||||
* oputf(f, ...) => emit varargs per format f to default stream
|
||||
* eputz(z) => emit 0-terminated string z to error stream
|
||||
* eputf(f, ...) => emit varargs per format f to error stream
|
||||
* oputb(b, n) => emit char buffer b[0..n-1] to default stream
|
||||
*
|
||||
* Note that the default stream is whatever has been last set via:
|
||||
* setOutputStream(FILE *pf)
|
||||
* This is normally the stream that CLI normal output goes to.
|
||||
* For the stand-alone CLI, it is stdout with no .output redirect.
|
||||
*
|
||||
* The ?putz(z) forms are for unformatted strings.
|
||||
*/
|
||||
# define sputz(s,z) fPutsUtf8(z,s)
|
||||
# define sputf fPrintfUtf8
|
||||
# define oputz(z) oPutsUtf8(z)
|
||||
# define oputf oPrintfUtf8
|
||||
# define eputz(z) ePutsUtf8(z)
|
||||
# define eputf ePrintfUtf8
|
||||
# define oputb(buf,na) oPutbUtf8(buf,na)
|
||||
/*# define fflush(s) fFlushBuffer(s)*/
|
||||
|
||||
/****************************************************************************
|
||||
** Beginning of the popen2() implementation copied from Fossil *************
|
||||
@@ -121,7 +96,7 @@ struct SQLiteRsync {
|
||||
** Print a fatal error and quit.
|
||||
*/
|
||||
static void win32_fatal_error(const char *zMsg){
|
||||
eputf("%s\n", zMsg);
|
||||
fprintf(stderr, "%s", zMsg);
|
||||
exit(1);
|
||||
}
|
||||
extern int _open_osfhandle(intptr_t,int);
|
||||
@@ -299,7 +274,7 @@ static int popen2(
|
||||
close(0);
|
||||
fd = dup(pout[0]);
|
||||
if( fd!=0 ) {
|
||||
eputz("popen2() failed to open file descriptor 0\n");
|
||||
fprintf(stderr,"popen2() failed to open file descriptor 0");
|
||||
exit(1);
|
||||
}
|
||||
close(pout[0]);
|
||||
@@ -307,7 +282,7 @@ static int popen2(
|
||||
close(1);
|
||||
fd = dup(pin[1]);
|
||||
if( fd!=1 ){
|
||||
eputz("popen() failed to open file descriptor 1\n");
|
||||
fprintf(stderr,"popen() failed to open file descriptor 1");
|
||||
exit(1);
|
||||
}
|
||||
close(pin[0]);
|
||||
@@ -840,6 +815,24 @@ const char *file_tail(const char *z){
|
||||
return zTail;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append error message text to the error file, if an error file is
|
||||
** specified. In any case, increment the error count.
|
||||
*/
|
||||
static void logError(SQLiteRsync *p, const char *zFormat, ...){
|
||||
if( p->zErrFile ){
|
||||
FILE *pErr = fopen(p->zErrFile, "a");
|
||||
if( pErr ){
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
vfprintf(pErr, zFormat, ap);
|
||||
va_end(ap);
|
||||
fclose(pErr);
|
||||
}
|
||||
}
|
||||
p->nErr++;
|
||||
}
|
||||
|
||||
|
||||
/* Read a single big-endian 32-bit unsigned integer from the input
|
||||
** stream. Return 0 on success and 1 if there are any errors.
|
||||
@@ -868,8 +861,9 @@ static int writeUint32(SQLiteRsync *p, unsigned int x){
|
||||
buf[1] = x & 0xff;
|
||||
x >>= 8;
|
||||
buf[0] = x;
|
||||
if( p->pLog ) fwrite(buf, sizeof(buf), 1, p->pLog);
|
||||
if( fwrite(buf, sizeof(buf), 1, p->pOut)!=1 ){
|
||||
p->nErr++;
|
||||
logError(p, "failed to write 32-bit integer 0x%x", x);
|
||||
return 1;
|
||||
}
|
||||
p->nOut += 4;
|
||||
@@ -887,6 +881,7 @@ int readByte(SQLiteRsync *p){
|
||||
/* Write a single byte into the wire.
|
||||
*/
|
||||
void writeByte(SQLiteRsync *p, int c){
|
||||
if( p->pLog ) fputc(c, p->pLog);
|
||||
fputc(c, p->pOut);
|
||||
p->nOut++;
|
||||
}
|
||||
@@ -896,7 +891,7 @@ void writeByte(SQLiteRsync *p, int c){
|
||||
int readPow2(SQLiteRsync *p){
|
||||
int x = readByte(p);
|
||||
if( x>=32 ){
|
||||
p->nErr++;
|
||||
logError(p, "read invalid page size %d\n", x);
|
||||
return 0;
|
||||
}
|
||||
return 1<<x;
|
||||
@@ -907,7 +902,7 @@ int readPow2(SQLiteRsync *p){
|
||||
void writePow2(SQLiteRsync *p, int c){
|
||||
int n;
|
||||
if( c<0 || (c&(c-1))!=0 ){
|
||||
p->nErr++;
|
||||
logError(p, "trying to read invalid page size %d\n", c);
|
||||
}
|
||||
for(n=0; c>1; n++){ c /= 2; }
|
||||
writeByte(p, n);
|
||||
@@ -919,17 +914,18 @@ void readBytes(SQLiteRsync *p, int nByte, void *pData){
|
||||
if( fread(pData, 1, nByte, p->pIn)==nByte ){
|
||||
p->nIn += nByte;
|
||||
}else{
|
||||
p->nErr++;
|
||||
logError(p, "failed to read %d bytes", nByte);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write an array of bytes onto the wire.
|
||||
*/
|
||||
void writeBytes(SQLiteRsync *p, int nByte, const void *pData){
|
||||
if( p->pLog ) fwrite(pData, 1, nByte, p->pLog);
|
||||
if( fwrite(pData, 1, nByte, p->pOut)==nByte ){
|
||||
p->nOut += nByte;
|
||||
}else{
|
||||
p->nErr++;
|
||||
logError(p, "failed to write %d bytes", nByte);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -956,15 +952,15 @@ static void reportError(SQLiteRsync *p, const char *zFormat, ...){
|
||||
writeBytes(p, nMsg, zMsg);
|
||||
fflush(p->pOut);
|
||||
}else{
|
||||
eputf("%s\n", zMsg);
|
||||
fprintf(stderr, "%s\n", zMsg);
|
||||
}
|
||||
logError(p, "%s\n", zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
p->nErr++;
|
||||
}
|
||||
|
||||
/* Send an informational message.
|
||||
**
|
||||
** If this happens on the remote side, we send back a *_MSG
|
||||
** If this happens on the remote side, we send back a *_MSG
|
||||
** message. On the local side, the message goes to stdout.
|
||||
*/
|
||||
static void infoMsg(SQLiteRsync *p, const char *zFormat, ...){
|
||||
@@ -985,7 +981,7 @@ static void infoMsg(SQLiteRsync *p, const char *zFormat, ...){
|
||||
writeBytes(p, nMsg, zMsg);
|
||||
fflush(p->pOut);
|
||||
}else{
|
||||
oputf("%s\n", zMsg);
|
||||
printf("%s\n", zMsg);
|
||||
}
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
@@ -998,22 +994,22 @@ static void readAndDisplayMessage(SQLiteRsync *p, int c){
|
||||
const char *zPrefix;
|
||||
if( c==ORIGIN_ERROR || c==REPLICA_ERROR ){
|
||||
zPrefix = "ERROR: ";
|
||||
p->nErr++;
|
||||
}else{
|
||||
zPrefix = "";
|
||||
}
|
||||
readUint32(p, &n);
|
||||
if( n==0 ){
|
||||
eputz("ERROR: unknown (possibly out-of-memory)\n");
|
||||
fprintf(stderr,"ERROR: unknown (possibly out-of-memory)\n");
|
||||
}else{
|
||||
zMsg = sqlite3_malloc64( n+1 );
|
||||
if( zMsg==0 ){
|
||||
eputz("ERROR: out-of-memory\n");
|
||||
fprintf(stderr, "ERROR: out-of-memory\n");
|
||||
return;
|
||||
}
|
||||
memset(zMsg, 0, n+1);
|
||||
readBytes(p, n, zMsg);
|
||||
eputf("%s%s\n", zPrefix, zMsg);
|
||||
fprintf(stderr,"%s%s\n", zPrefix, zMsg);
|
||||
if( zPrefix[0] ) logError(p, "%s%s\n", zPrefix, zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
}
|
||||
@@ -1212,8 +1208,8 @@ static void originSide(SQLiteRsync *p){
|
||||
/* Open the ORIGIN database. */
|
||||
rc = sqlite3_open_v2(p->zOrigin, &p->db, SQLITE_OPEN_READWRITE, 0);
|
||||
if( rc ){
|
||||
reportError(p, "unable to open origin database file \"%s\": %s",
|
||||
sqlite3_errmsg(p->db));
|
||||
reportError(p, "cannot open origin \"%s\": %s",
|
||||
p->zOrigin, sqlite3_errmsg(p->db));
|
||||
closeDb(p);
|
||||
return;
|
||||
}
|
||||
@@ -1225,7 +1221,7 @@ static void originSide(SQLiteRsync *p){
|
||||
}
|
||||
runSqlReturnUInt(p, &nPage, "PRAGMA page_count");
|
||||
runSqlReturnUInt(p, &szPg, "PRAGMA page_size");
|
||||
|
||||
|
||||
if( p->nErr==0 ){
|
||||
/* Send the ORIGIN_BEGIN message */
|
||||
writeByte(p, ORIGIN_BEGIN);
|
||||
@@ -1238,7 +1234,7 @@ static void originSide(SQLiteRsync *p){
|
||||
p->iProtocol = PROTOCOL_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Respond to message from the replica */
|
||||
while( p->nErr==0 && (c = readByte(p))!=EOF && c!=REPLICA_END ){
|
||||
switch( c ){
|
||||
@@ -1283,32 +1279,56 @@ static void originSide(SQLiteRsync *p){
|
||||
}
|
||||
case REPLICA_READY: {
|
||||
sqlite3_stmt *pStmt;
|
||||
int needPageOne = 0;
|
||||
sqlite3_finalize(pCkHash);
|
||||
pCkHash = 0;
|
||||
if( iPage+1<p->nPage ){
|
||||
runSql(p, "WITH RECURSIVE c(n) AS"
|
||||
" (VALUES(%d) UNION ALL SELECT n+1 FROM c WHERE n<%d)"
|
||||
" INSERT INTO badHash SELECT n FROM c",
|
||||
iPage+1, p->nPage);
|
||||
}
|
||||
pStmt = prepareStmt(p,
|
||||
"SELECT pgno, data"
|
||||
" FROM badHash JOIN sqlite_dbpage('main') USING(pgno) "
|
||||
"UNION ALL "
|
||||
"SELECT pgno, data"
|
||||
" FROM sqlite_dbpage('main')"
|
||||
" WHERE pgno>%d",
|
||||
iPage);
|
||||
" FROM badHash JOIN sqlite_dbpage('main') USING(pgno)");
|
||||
if( pStmt==0 ) break;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW && p->nErr==0 ){
|
||||
unsigned int pgno = (unsigned int)sqlite3_column_int64(pStmt,0);
|
||||
const void *pContent = sqlite3_column_blob(pStmt, 1);
|
||||
writeByte(p, ORIGIN_PAGE);
|
||||
writeUint32(p, (unsigned int)sqlite3_column_int64(pStmt, 0));
|
||||
writeBytes(p, szPg, pContent);
|
||||
p->nPageSent++;
|
||||
if( pgno==1 ){
|
||||
needPageOne = 1;
|
||||
}else{
|
||||
writeByte(p, ORIGIN_PAGE);
|
||||
writeUint32(p, (unsigned int)sqlite3_column_int64(pStmt, 0));
|
||||
writeBytes(p, szPg, pContent);
|
||||
p->nPageSent++;
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
if( needPageOne ){
|
||||
pStmt = prepareStmt(p,
|
||||
"SELECT data"
|
||||
" FROM sqlite_dbpage('main')"
|
||||
" WHERE pgno=1"
|
||||
);
|
||||
if( pStmt==0 ) break;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW && p->nErr==0 ){
|
||||
const void *pContent = sqlite3_column_blob(pStmt, 0);
|
||||
writeByte(p, ORIGIN_PAGE);
|
||||
writeUint32(p, 1);
|
||||
writeBytes(p, szPg, pContent);
|
||||
p->nPageSent++;
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
writeByte(p, ORIGIN_TXN);
|
||||
writeUint32(p, nPage);
|
||||
writeByte(p, ORIGIN_END);
|
||||
goto origin_end;
|
||||
}
|
||||
default: {
|
||||
reportError(p, "Origin side received unknown message: 0x%02x", c);
|
||||
reportError(p, "Unknown message 0x%02x %lld bytes into conversation",
|
||||
c, p->nIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1396,7 +1416,7 @@ static void replicaSide(SQLiteRsync *p){
|
||||
p->szPage = szOPage;
|
||||
rc = sqlite3_open(p->zReplica, &p->db);
|
||||
if( rc ){
|
||||
reportError(p, "cannot open replica database \"%s\": %s",
|
||||
reportError(p, "cannot open replica \"%s\": %s",
|
||||
p->zReplica, sqlite3_errmsg(p->db));
|
||||
closeDb(p);
|
||||
break;
|
||||
@@ -1458,6 +1478,7 @@ static void replicaSide(SQLiteRsync *p){
|
||||
sqlite3_sql(pIns), sqlite3_errmsg(p->db));
|
||||
}
|
||||
sqlite3_reset(pIns);
|
||||
p->nPage = nOPage;
|
||||
runSql(p, "COMMIT");
|
||||
}
|
||||
break;
|
||||
@@ -1469,7 +1490,7 @@ static void replicaSide(SQLiteRsync *p){
|
||||
if( p->nErr ) break;
|
||||
if( pIns==0 ){
|
||||
pIns = prepareStmt(p,
|
||||
"INSERT INTO sqlite_dbpage(pgno,data,schema) VALUES(?1,?2,'main')"
|
||||
"INSERT INTO sqlite_dbpage(pgno,data) VALUES(?1,?2)"
|
||||
);
|
||||
if( pIns==0 ) break;
|
||||
}
|
||||
@@ -1480,14 +1501,15 @@ static void replicaSide(SQLiteRsync *p){
|
||||
sqlite3_bind_blob(pIns, 2, buf, szOPage, SQLITE_STATIC);
|
||||
rc = sqlite3_step(pIns);
|
||||
if( rc!=SQLITE_DONE ){
|
||||
reportError(p, "SQL statement [%s] failed: %s",
|
||||
sqlite3_sql(pIns), sqlite3_errmsg(p->db));
|
||||
reportError(p, "SQL statement [%s] failed (pgno=%u): %s",
|
||||
sqlite3_sql(pIns), pgno, sqlite3_errmsg(p->db));
|
||||
}
|
||||
sqlite3_reset(pIns);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
reportError(p, "Replica side received unknown message: 0x%02x", c);
|
||||
reportError(p, "Unknown message 0x%02x %lld bytes into conversation",
|
||||
c, p->nIn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1518,13 +1540,24 @@ static int numVs(const char *z){
|
||||
static const char *cmdline_option_value(int argc, const char * const*argv,
|
||||
int i){
|
||||
if( i==argc ){
|
||||
eputf("%s: Error: missing argument to %s\n",
|
||||
argv[0], argv[argc-1]);
|
||||
fprintf(stderr,"%s: Error: missing argument to %s\n",
|
||||
argv[0], argv[argc-1]);
|
||||
exit(1);
|
||||
}
|
||||
return argv[i];
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time in milliseconds since the Julian epoch.
|
||||
*/
|
||||
sqlite3_int64 currentTime(void){
|
||||
sqlite3_int64 now = 0;
|
||||
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
||||
if( pVfs && pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64!=0 ){
|
||||
pVfs->xCurrentTimeInt64(pVfs, &now);
|
||||
}
|
||||
return now;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse command-line arguments. Dispatch subroutines to do the
|
||||
@@ -1564,11 +1597,13 @@ int main(int argc, char const * const *argv){
|
||||
const char *zSsh = "ssh";
|
||||
const char *zExe = "sqlite3-rsync";
|
||||
char *zCmd = 0;
|
||||
sqlite3_int64 tmStart;
|
||||
sqlite3_int64 tmEnd;
|
||||
sqlite3_int64 tmElapse;
|
||||
const char *zRemoteErrFile = 0;
|
||||
|
||||
#define cli_opt_val cmdline_option_value(argc, argv, ++i)
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
setOutputStream(stdout);
|
||||
setErrorStream(stderr);
|
||||
for(i=1; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( strcmp(z,"--origin")==0 ){
|
||||
@@ -1591,10 +1626,39 @@ int main(int argc, char const * const *argv){
|
||||
zExe = cli_opt_val;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "--logfile")==0 ){
|
||||
/* DEBUG OPTION: --logfile FILENAME
|
||||
** Cause all local output traffic to be duplicated in FILENAME */
|
||||
const char *zLog = cli_opt_val;
|
||||
if( ctx.pLog ) fclose(ctx.pLog);
|
||||
ctx.pLog = fopen(zLog, "wb");
|
||||
if( ctx.pLog==0 ){
|
||||
fprintf(stderr, "cannot open \"%s\" for writing\n", argv[i]);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "--errorfile")==0 ){
|
||||
/* DEBUG OPTION: --errorfile FILENAME
|
||||
** Error messages on the local side are written into FILENAME */
|
||||
ctx.zErrFile = cli_opt_val;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "--remote-errorfile")==0 ){
|
||||
/* DEBUG OPTION: --remote-errorfile FILENAME
|
||||
** Error messages on the remote side are written into FILENAME on
|
||||
** the remote side. */
|
||||
zRemoteErrFile = cli_opt_val;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-help")==0 || strcmp(z, "--help")==0
|
||||
|| strcmp(z, "-?")==0
|
||||
){
|
||||
oputf("%s", zUsage);
|
||||
printf("%s", zUsage);
|
||||
return 0;
|
||||
}
|
||||
if( strcmp(z, "--version")==0 ){
|
||||
printf("%s\n", sqlite3_sourceid());
|
||||
return 0;
|
||||
}
|
||||
if( z[0]=='-' ){
|
||||
@@ -1613,10 +1677,11 @@ int main(int argc, char const * const *argv){
|
||||
for(k=0; k<argc; k++){
|
||||
append_escaped_arg(pStr, argv[k], i!=k);
|
||||
}
|
||||
oputf("%s\n", sqlite3_str_value(pStr));
|
||||
printf("%s\n", sqlite3_str_value(pStr));
|
||||
return 0;
|
||||
}
|
||||
eputf("unknown option: \"%s\". Use --help for more detail.\n", z);
|
||||
fprintf(stderr,
|
||||
"unknown option: \"%s\". Use --help for more detail.\n", z);
|
||||
return 1;
|
||||
}
|
||||
if( ctx.zOrigin==0 ){
|
||||
@@ -1624,20 +1689,20 @@ int main(int argc, char const * const *argv){
|
||||
}else if( ctx.zReplica==0 ){
|
||||
ctx.zReplica = z;
|
||||
}else{
|
||||
eputf("Unknown argument: \"%s\"\n", z);
|
||||
fprintf(stderr, "Unknown argument: \"%s\"\n", z);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( ctx.zOrigin==0 ){
|
||||
eputz("missing ORIGIN database filename\n");
|
||||
fprintf(stderr, "missing ORIGIN database filename\n");
|
||||
return 1;
|
||||
}
|
||||
if( ctx.zReplica==0 ){
|
||||
eputz("missing REPLICA database filename\n");
|
||||
fprintf(stderr, "missing REPLICA database filename\n");
|
||||
return 1;
|
||||
}
|
||||
if( isOrigin && isReplica ){
|
||||
eputz("bad option combination\n");
|
||||
fprintf(stderr, "bad option combination\n");
|
||||
return 1;
|
||||
}
|
||||
if( isOrigin ){
|
||||
@@ -1655,13 +1720,14 @@ int main(int argc, char const * const *argv){
|
||||
return 0;
|
||||
}
|
||||
if( ctx.zReplica==0 ){
|
||||
eputz("missing REPLICA database filename\n");
|
||||
fprintf(stderr, "missing REPLICA database filename\n");
|
||||
return 1;
|
||||
}
|
||||
tmStart = currentTime();
|
||||
zDiv = strchr(ctx.zOrigin,':');
|
||||
if( zDiv ){
|
||||
if( strchr(ctx.zReplica,':')!=0 ){
|
||||
eputz(
|
||||
fprintf(stderr,
|
||||
"At least one of ORIGIN and REPLICA must be a local database\n"
|
||||
"You provided two remote databases.\n");
|
||||
return 1;
|
||||
@@ -1678,12 +1744,16 @@ int main(int argc, char const * const *argv){
|
||||
append_escaped_arg(pStr, "--commcheck", 0);
|
||||
if( ctx.eVerbose==0 ) ctx.eVerbose = 1;
|
||||
}
|
||||
if( zRemoteErrFile ){
|
||||
append_escaped_arg(pStr, "--errorfile", 0);
|
||||
append_escaped_arg(pStr, zRemoteErrFile, 1);
|
||||
}
|
||||
append_escaped_arg(pStr, zDiv, 1);
|
||||
append_escaped_arg(pStr, file_tail(ctx.zReplica), 1);
|
||||
zCmd = sqlite3_str_finish(pStr);
|
||||
if( ctx.eVerbose ) oputf("%s\n", zCmd);
|
||||
if( ctx.eVerbose>=2 ) printf("%s\n", zCmd);
|
||||
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
|
||||
eputf("Could not start auxiliary process: %s\n", zCmd);
|
||||
fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
|
||||
return 1;
|
||||
}
|
||||
replicaSide(&ctx);
|
||||
@@ -1700,12 +1770,16 @@ int main(int argc, char const * const *argv){
|
||||
append_escaped_arg(pStr, "--commcheck", 0);
|
||||
if( ctx.eVerbose==0 ) ctx.eVerbose = 1;
|
||||
}
|
||||
if( zRemoteErrFile ){
|
||||
append_escaped_arg(pStr, "--errorfile", 0);
|
||||
append_escaped_arg(pStr, zRemoteErrFile, 1);
|
||||
}
|
||||
append_escaped_arg(pStr, file_tail(ctx.zOrigin), 1);
|
||||
append_escaped_arg(pStr, zDiv, 1);
|
||||
zCmd = sqlite3_str_finish(pStr);
|
||||
if( ctx.eVerbose ) oputf("%s\n", zCmd);
|
||||
if( ctx.eVerbose>=2 ) printf("%s\n", zCmd);
|
||||
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
|
||||
eputf("Could not start auxiliary process: %s\n", zCmd);
|
||||
fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
|
||||
return 1;
|
||||
}
|
||||
originSide(&ctx);
|
||||
@@ -1717,31 +1791,51 @@ int main(int argc, char const * const *argv){
|
||||
if( ctx.bCommCheck ){
|
||||
append_escaped_arg(pStr, "--commcheck", 0);
|
||||
}
|
||||
if( zRemoteErrFile ){
|
||||
append_escaped_arg(pStr, "--errorfile", 0);
|
||||
append_escaped_arg(pStr, zRemoteErrFile, 1);
|
||||
}
|
||||
append_escaped_arg(pStr, ctx.zOrigin, 1);
|
||||
append_escaped_arg(pStr, ctx.zReplica, 1);
|
||||
zCmd = sqlite3_str_finish(pStr);
|
||||
if( ctx.eVerbose ) oputf("%s\n", zCmd);
|
||||
if( ctx.eVerbose>=2 ) printf("%s\n", zCmd);
|
||||
if( popen2(zCmd, &ctx.pIn, &ctx.pOut, &childPid, 0) ){
|
||||
eputf("Could not start auxiliary process: %s\n", zCmd);
|
||||
fprintf(stderr, "Could not start auxiliary process: %s\n", zCmd);
|
||||
return 1;
|
||||
}
|
||||
originSide(&ctx);
|
||||
}
|
||||
if( ctx.pLog ) fclose(ctx.pLog);
|
||||
tmEnd = currentTime();
|
||||
tmElapse = tmEnd - tmStart; /* Elapse time in milliseconds */
|
||||
if( ctx.nErr ){
|
||||
printf("Databases where not synced due to errors\n");
|
||||
}
|
||||
if( ctx.eVerbose==1 ){
|
||||
printf("Network traffic is %.1f%% of database size\n",
|
||||
(100.0*(double)(ctx.nIn+ctx.nOut))/(ctx.szPage*(double)ctx.nPage));
|
||||
}
|
||||
if( ctx.eVerbose>=2 ){
|
||||
if( ctx.nErr ) oputf("%d errors, ", ctx.nErr);
|
||||
oputf("%lld bytes sent, %lld bytes received\n", ctx.nOut, ctx.nIn);
|
||||
if( ctx.eVerbose>=2 ){
|
||||
oputf("Database is %u pages of %u bytes each.\n",
|
||||
ctx.nPage, ctx.szPage);
|
||||
oputf("Sent %u hashes, %u page contents\n",
|
||||
ctx.nHashSent, ctx.nPageSent);
|
||||
if( ctx.eVerbose>=1 ){
|
||||
char *zMsg;
|
||||
sqlite3_int64 szTotal = (sqlite3_int64)ctx.nPage*(sqlite3_int64)ctx.szPage;
|
||||
sqlite3_int64 nIO = ctx.nOut +ctx.nIn;
|
||||
zMsg = sqlite3_mprintf("sent %,lld bytes, received %,lld bytes",
|
||||
ctx.nOut, ctx.nIn);
|
||||
printf("%s", zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
if( tmElapse>0 ){
|
||||
zMsg = sqlite3_mprintf(", %,.2f bytes/sec",
|
||||
1000.0*(double)nIO/(double)tmElapse);
|
||||
printf("%s\n", zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
}else{
|
||||
printf("\n");
|
||||
}
|
||||
if( ctx.nErr==0 ){
|
||||
if( nIO<=szTotal && nIO>0 ){
|
||||
zMsg = sqlite3_mprintf("total size %,lld speedup is %.2f",
|
||||
szTotal, (double)szTotal/(double)nIO);
|
||||
}else{
|
||||
zMsg = sqlite3_mprintf("total size %,lld", szTotal);
|
||||
}
|
||||
printf("%s\n", zMsg);
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zCmd);
|
||||
|
||||
Reference in New Issue
Block a user