From: drh <> Date: Mon, 6 Feb 2023 15:46:34 +0000 (+0000) Subject: Remove the long obsolete "client/server" mode tests. X-Git-Tag: version-3.41.0~40^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da3d655fd80a67667590d4b4aeb53f9f6ee84016;p=thirdparty%2Fsqlite.git Remove the long obsolete "client/server" mode tests. FossilOrigin-Name: 08e3114caec0633fc54f8febb7f4732b46a1f47508bbca0a6a2bff02591254d5 --- diff --git a/Makefile.in b/Makefile.in index 8e6d3f97f0..750c3ac157 100644 --- a/Makefile.in +++ b/Makefile.in @@ -373,7 +373,6 @@ TESTSRC = \ $(TOP)/src/test4.c \ $(TOP)/src/test5.c \ $(TOP)/src/test6.c \ - $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ @@ -402,7 +401,6 @@ TESTSRC = \ $(TOP)/src/test_quota.c \ $(TOP)/src/test_rtree.c \ $(TOP)/src/test_schema.c \ - $(TOP)/src/test_server.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclsh.c \ diff --git a/Makefile.msc b/Makefile.msc index 622fae4455..884bb10654 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1485,7 +1485,6 @@ TESTSRC = \ $(TOP)\src\test4.c \ $(TOP)\src\test5.c \ $(TOP)\src\test6.c \ - $(TOP)\src\test7.c \ $(TOP)\src\test8.c \ $(TOP)\src\test9.c \ $(TOP)\src\test_autoext.c \ @@ -1514,7 +1513,6 @@ TESTSRC = \ $(TOP)\src\test_quota.c \ $(TOP)\src\test_rtree.c \ $(TOP)\src\test_schema.c \ - $(TOP)\src\test_server.c \ $(TOP)\src\test_superlock.c \ $(TOP)\src\test_syscall.c \ $(TOP)\src\test_tclsh.c \ diff --git a/main.mk b/main.mk index 56a707ae5c..628f3d1621 100644 --- a/main.mk +++ b/main.mk @@ -298,7 +298,6 @@ TESTSRC = \ $(TOP)/src/test4.c \ $(TOP)/src/test5.c \ $(TOP)/src/test6.c \ - $(TOP)/src/test7.c \ $(TOP)/src/test8.c \ $(TOP)/src/test9.c \ $(TOP)/src/test_autoext.c \ @@ -327,7 +326,6 @@ TESTSRC = \ $(TOP)/src/test_quota.c \ $(TOP)/src/test_rtree.c \ $(TOP)/src/test_schema.c \ - $(TOP)/src/test_server.c \ $(TOP)/src/test_sqllog.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ diff --git a/manifest b/manifest index 9629aeb782..d35bf3664f 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Update\stest\sscripts\sspeed1.test\sand\sspeed1p.test\sso\sthey\smay\sbe\srun\sby\stestrunner.tcl. -D 2023-02-06T15:46:01.294 +C Remove\sthe\slong\sobsolete\s"client/server"\smode\stests. +D 2023-02-06T15:46:34.433 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in 3c7df00360783e20db13c928cbd2f3561aea14b29da2b78f6ce57393c0643ef3 +F Makefile.in 03ae384c9efbd8827cbcdce1d2fa57c6c0df264cb408d4e10dc4c57534214d36 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 9e0147a280fde917aa4a3337b96da43fab2ed2235b0a0a62b3aa6bd5b8b1774f +F Makefile.msc 26e2fa6144907df27487b7c25767a87dbc5c4a312ccc382dbf44648f40073623 F README.md 8b8df9ca852aeac4864eb1e400002633ee6db84065bd01b78c33817f97d31f5e F VERSION 413ec94920a487ae32c9a2a8819544d690662d6f7c7ce025c0d0b8a1e74fa9db F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -540,7 +540,7 @@ F ext/wasm/wasmfs.make cf9a68162d92ca2bcb0b9528b244cb36d5cc2d84ccc9c2d398461927d F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0 -F main.mk c8af6b90044e4675a1b2c4000c76429fe6bc0dc0a5b3092d7e036f059a58c030 +F main.mk ac6b13f8ecc43f377e9912380ea4cf366051d7f784cf61c8886e03e1cf0fbefa F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -637,7 +637,6 @@ F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664 F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce -F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010 F src/test8.c 0c856d6ff6b0d2ff6696addc467a15ed17c6910f14475302cd5b3b4e54406161 F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5 F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a @@ -670,7 +669,6 @@ F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99 F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b -F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939 @@ -1464,7 +1462,6 @@ F test/selectD.test 6d1909b49970bf92f45ce657505befcef5fc7cbc13544e18103a316d3218 F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3 F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840 -F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d785dc4 F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb F test/sessionfuzz.c 5eef09af01eeff6f20250ae4c0112c2e576e4d2f2026cc9a49dc5be6886fa6ee @@ -2048,8 +2045,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b760a7307c453d95cf3b302c9867c84a9c899956c16c2ce1ea6cce8f025db425 -R 307214cb20044df19132161114770393 -U dan -Z cf0e7b089ab074de1ca2ba831e6ee97f +P e761d4b9c8dcacccc927d23f20fdf779a0ae5304281b5bd6aa998bade56f0a37 +R 011e0ef815119f8bbf074c0e4c1fc189 +U drh +Z 2cf846d6f5b78b2c3d26ce53dcad23b7 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3c53fe128b..155117783e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e761d4b9c8dcacccc927d23f20fdf779a0ae5304281b5bd6aa998bade56f0a37 \ No newline at end of file +08e3114caec0633fc54f8febb7f4732b46a1f47508bbca0a6a2bff02591254d5 \ No newline at end of file diff --git a/src/test7.c b/src/test7.c deleted file mode 100644 index d57e4b826b..0000000000 --- a/src/test7.c +++ /dev/null @@ -1,718 +0,0 @@ -/* -** 2006 January 09 -** -** The author disclaims copyright to this source code. In place of -** a legal notice, here is a blessing: -** -** May you do good and not evil. -** May you find forgiveness for yourself and forgive others. -** May you share freely, never taking more than you give. -** -************************************************************************* -** Code for testing the client/server version of the SQLite library. -** Derived from test4.c. -*/ -#include "sqliteInt.h" -#if defined(INCLUDE_SQLITE_TCL_H) -# include "sqlite_tcl.h" -#else -# include "tcl.h" -#endif - -/* -** This test only works on UNIX with a SQLITE_THREADSAFE build that includes -** the SQLITE_SERVER option. -*/ -#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE) && \ - SQLITE_OS_UNIX && SQLITE_THREADSAFE - -#include -#include -#include -#include -#include - -/* -** Interfaces defined in server.c -*/ -int sqlite3_client_open(const char*, sqlite3**); -int sqlite3_client_prepare(sqlite3*,const char*,int, - sqlite3_stmt**,const char**); -int sqlite3_client_step(sqlite3_stmt*); -int sqlite3_client_reset(sqlite3_stmt*); -int sqlite3_client_finalize(sqlite3_stmt*); -int sqlite3_client_close(sqlite3*); -int sqlite3_server_start(void); -int sqlite3_server_stop(void); -void sqlite3_server_start2(int *pnDecr); - -/* -** Each thread is controlled by an instance of the following -** structure. -*/ -typedef struct Thread Thread; -struct Thread { - /* The first group of fields are writable by the supervisor thread - ** and read-only to the client threads - */ - char *zFilename; /* Name of database file */ - void (*xOp)(Thread*); /* next operation to do */ - char *zArg; /* argument usable by xOp */ - volatile int opnum; /* Operation number */ - volatile int busy; /* True if this thread is in use */ - - /* The next group of fields are writable by the client threads - ** but read-only to the superviser thread. - */ - volatile int completed; /* Number of operations completed */ - sqlite3 *db; /* Open database */ - sqlite3_stmt *pStmt; /* Pending operation */ - char *zErr; /* operation error */ - char *zStaticErr; /* Static error message */ - int rc; /* operation return code */ - int argc; /* number of columns in result */ - const char *argv[100]; /* result columns */ - const char *colv[100]; /* result column names */ - - /* Initialized to 1 by the supervisor thread when the client is - ** created, and then deemed read-only to the supervisor thread. - ** Is set to 0 by the server thread belonging to this client - ** just before it exits. - */ - int nServer; /* Number of server threads running */ -}; - -/* -** There can be as many as 26 threads running at once. Each is named -** by a capital letter: A, B, C, ..., Y, Z. -*/ -#define N_THREAD 26 -static Thread threadset[N_THREAD]; - -/* -** The main loop for a thread. Threads use busy waiting. -*/ -static void *client_main(void *pArg){ - Thread *p = (Thread*)pArg; - if( p->db ){ - sqlite3_client_close(p->db); - } - sqlite3_client_open(p->zFilename, &p->db); - if( SQLITE_OK!=sqlite3_errcode(p->db) ){ - p->zErr = strdup(sqlite3_errmsg(p->db)); - sqlite3_client_close(p->db); - p->db = 0; - } - p->pStmt = 0; - p->completed = 1; - while( p->opnum<=p->completed ) sched_yield(); - while( p->xOp ){ - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - (*p->xOp)(p); - p->completed++; - while( p->opnum<=p->completed ) sched_yield(); - } - if( p->pStmt ){ - sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; - } - if( p->db ){ - sqlite3_client_close(p->db); - p->db = 0; - } - if( p->zErr && p->zErr!=p->zStaticErr ){ - sqlite3_free(p->zErr); - p->zErr = 0; - } - p->completed++; -#ifndef SQLITE_OMIT_DEPRECATED - sqlite3_thread_cleanup(); -#endif - return 0; -} - -/* -** Get a thread ID which is an upper case letter. Return the index. -** If the argument is not a valid thread ID put an error message in -** the interpreter and return -1. -*/ -static int parse_client_id(Tcl_Interp *interp, const char *zArg){ - if( zArg==0 || zArg[0]==0 || zArg[1]!=0 || !isupper((unsigned char)zArg[0]) ){ - Tcl_AppendResult(interp, "thread ID must be an upper case letter", 0); - return -1; - } - return zArg[0] - 'A'; -} - -/* -** Usage: client_create NAME FILENAME -** -** NAME should be an upper case letter. Start the thread running with -** an open connection to the given database. -*/ -static int SQLITE_TCLAPI tcl_client_create( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - pthread_t x; - int rc; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID FILENAME", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( threadset[i].busy ){ - Tcl_AppendResult(interp, "thread ", argv[1], " is already running", 0); - return TCL_ERROR; - } - threadset[i].busy = 1; - sqlite3_free(threadset[i].zFilename); - threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum = 1; - threadset[i].completed = 0; - rc = pthread_create(&x, 0, client_main, &threadset[i]); - if( rc ){ - Tcl_AppendResult(interp, "failed to create the thread", 0); - sqlite3_free(threadset[i].zFilename); - threadset[i].busy = 0; - return TCL_ERROR; - } - pthread_detach(x); - if( threadset[i].nServer==0 ){ - threadset[i].nServer = 1; - sqlite3_server_start2(&threadset[i].nServer); - } - return TCL_OK; -} - -/* -** Wait for a thread to reach its idle state. -*/ -static void client_wait(Thread *p){ - while( p->opnum>p->completed ) sched_yield(); -} - -/* -** Usage: client_wait ID -** -** Wait on thread ID to reach its idle state. -*/ -static int SQLITE_TCLAPI tcl_client_wait( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - return TCL_OK; -} - -/* -** Stop a thread. -*/ -static void stop_thread(Thread *p){ - client_wait(p); - p->xOp = 0; - p->opnum++; - client_wait(p); - sqlite3_free(p->zArg); - p->zArg = 0; - sqlite3_free(p->zFilename); - p->zFilename = 0; - p->busy = 0; -} - -/* -** Usage: client_halt ID -** -** Cause a client thread to shut itself down. Wait for the shutdown to be -** completed. If ID is "*" then stop all client threads. -*/ -static int SQLITE_TCLAPI tcl_client_halt( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - if( argv[1][0]=='*' && argv[1][1]==0 ){ - for(i=0; i=N_THREAD ){ - sqlite3_server_stop(); - while( 1 ){ - for(i=0; i=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].argv[n], 0); - return TCL_OK; -} - -/* -** Usage: client_colname ID N -** -** Wait on the most recent client_step to complete, then return the -** name of the N-th columns in the result set. -*/ -static int SQLITE_TCLAPI tcl_client_colname( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - int n; - - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID N", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR; - client_wait(&threadset[i]); - if( n<0 || n>=threadset[i].argc ){ - Tcl_AppendResult(interp, "column number out of range", 0); - return TCL_ERROR; - } - Tcl_AppendResult(interp, threadset[i].colv[n], 0); - return TCL_OK; -} - -extern const char *sqlite3ErrName(int); - -/* -** Usage: client_result ID -** -** Wait on the most recent operation to complete, then return the -** result code from that operation. -*/ -static int SQLITE_TCLAPI tcl_client_result( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - const char *zName; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - zName = sqlite3ErrName(threadset[i].rc); - Tcl_AppendResult(interp, zName, 0); - return TCL_OK; -} - -/* -** Usage: client_error ID -** -** Wait on the most recent operation to complete, then return the -** error string. -*/ -static int SQLITE_TCLAPI tcl_client_error( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - Tcl_AppendResult(interp, threadset[i].zErr, 0); - return TCL_OK; -} - -/* -** This procedure runs in the thread to compile an SQL statement. -*/ -static void do_compile(Thread *p){ - if( p->db==0 ){ - p->zErr = p->zStaticErr = "no database is open"; - p->rc = SQLITE_ERROR; - return; - } - if( p->pStmt ){ - sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; - } - p->rc = sqlite3_client_prepare(p->db, p->zArg, -1, &p->pStmt, 0); -} - -/* -** Usage: client_compile ID SQL -** -** Compile a new virtual machine. -*/ -static int SQLITE_TCLAPI tcl_client_compile( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID SQL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_compile; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = sqlite3_mprintf("%s", argv[2]); - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to step the virtual machine. -*/ -static void do_step(Thread *p){ - int i; - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_step(p->pStmt); - if( p->rc==SQLITE_ROW ){ - p->argc = sqlite3_column_count(p->pStmt); - for(i=0; ipStmt); i++){ - p->argv[i] = (char*)sqlite3_column_text(p->pStmt, i); - } - for(i=0; iargc; i++){ - p->colv[i] = sqlite3_column_name(p->pStmt, i); - } - } -} - -/* -** Usage: client_step ID -** -** Advance the virtual machine by one step -*/ -static int SQLITE_TCLAPI tcl_client_step( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_step; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to finalize a virtual machine. -*/ -static void do_finalize(Thread *p){ - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_finalize(p->pStmt); - p->pStmt = 0; -} - -/* -** Usage: client_finalize ID -** -** Finalize the virtual machine. -*/ -static int SQLITE_TCLAPI tcl_client_finalize( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_finalize; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = 0; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** This procedure runs in the thread to reset a virtual machine. -*/ -static void do_reset(Thread *p){ - if( p->pStmt==0 ){ - p->zErr = p->zStaticErr = "no virtual machine available"; - p->rc = SQLITE_ERROR; - return; - } - p->rc = sqlite3_client_reset(p->pStmt); - p->pStmt = 0; -} - -/* -** Usage: client_reset ID -** -** Finalize the virtual machine. -*/ -static int SQLITE_TCLAPI tcl_client_reset( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " IDL", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - threadset[i].xOp = do_reset; - sqlite3_free(threadset[i].zArg); - threadset[i].zArg = 0; - threadset[i].opnum++; - return TCL_OK; -} - -/* -** Usage: client_swap ID ID -** -** Interchange the sqlite* pointer between two threads. -*/ -static int SQLITE_TCLAPI tcl_client_swap( - void *NotUsed, - Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ - int argc, /* Number of arguments */ - const char **argv /* Text of each argument */ -){ - int i, j; - sqlite3 *temp; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ID1 ID2", 0); - return TCL_ERROR; - } - i = parse_client_id(interp, argv[1]); - if( i<0 ) return TCL_ERROR; - if( !threadset[i].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[i]); - j = parse_client_id(interp, argv[2]); - if( j<0 ) return TCL_ERROR; - if( !threadset[j].busy ){ - Tcl_AppendResult(interp, "no such thread", 0); - return TCL_ERROR; - } - client_wait(&threadset[j]); - temp = threadset[i].db; - threadset[i].db = threadset[j].db; - threadset[j].db = temp; - return TCL_OK; -} - -/* -** Register commands with the TCL interpreter. -*/ -int Sqlitetest7_Init(Tcl_Interp *interp){ - static struct { - char *zName; - Tcl_CmdProc *xProc; - } aCmd[] = { - { "client_create", (Tcl_CmdProc*)tcl_client_create }, - { "client_wait", (Tcl_CmdProc*)tcl_client_wait }, - { "client_halt", (Tcl_CmdProc*)tcl_client_halt }, - { "client_argc", (Tcl_CmdProc*)tcl_client_argc }, - { "client_argv", (Tcl_CmdProc*)tcl_client_argv }, - { "client_colname", (Tcl_CmdProc*)tcl_client_colname }, - { "client_result", (Tcl_CmdProc*)tcl_client_result }, - { "client_error", (Tcl_CmdProc*)tcl_client_error }, - { "client_compile", (Tcl_CmdProc*)tcl_client_compile }, - { "client_step", (Tcl_CmdProc*)tcl_client_step }, - { "client_reset", (Tcl_CmdProc*)tcl_client_reset }, - { "client_finalize", (Tcl_CmdProc*)tcl_client_finalize }, - { "client_swap", (Tcl_CmdProc*)tcl_client_swap }, - }; - int i; - - for(i=0; i -#include "sqlite3.h" - -/* -** Messages are passed from client to server and back again as -** instances of the following structure. -*/ -typedef struct SqlMessage SqlMessage; -struct SqlMessage { - int op; /* Opcode for the message */ - sqlite3 *pDb; /* The SQLite connection */ - sqlite3_stmt *pStmt; /* A specific statement */ - int errCode; /* Error code returned */ - const char *zIn; /* Input filename or SQL statement */ - int nByte; /* Size of the zIn parameter for prepare() */ - const char *zOut; /* Tail of the SQL statement */ - SqlMessage *pNext; /* Next message in the queue */ - SqlMessage *pPrev; /* Previous message in the queue */ - pthread_mutex_t clientMutex; /* Hold this mutex to access the message */ - pthread_cond_t clientWakeup; /* Signal to wake up the client */ -}; - -/* -** Legal values for SqlMessage.op -*/ -#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */ -#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */ -#define MSG_Step 3 /* sqlite3_step(pStmt) */ -#define MSG_Reset 4 /* sqlite3_reset(pStmt) */ -#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */ -#define MSG_Close 6 /* sqlite3_close(pDb) */ -#define MSG_Done 7 /* Server has finished with this message */ - - -/* -** State information about the server is stored in a static variable -** named "g" as follows: -*/ -static struct ServerState { - pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */ - pthread_mutex_t serverMutex; /* Held by the server while it is running */ - pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */ - volatile int serverHalt; /* Server halts itself when true */ - SqlMessage *pQueueHead; /* Head of the message queue */ - SqlMessage *pQueueTail; /* Tail of the message queue */ -} g = { - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, -}; - -/* -** Send a message to the server. Block until we get a reply. -** -** The mutex and condition variable in the message are uninitialized -** when this routine is called. This routine takes care of -** initializing them and destroying them when it has finished. -*/ -static void sendToServer(SqlMessage *pMsg){ - /* Initialize the mutex and condition variable on the message - */ - pthread_mutex_init(&pMsg->clientMutex, 0); - pthread_cond_init(&pMsg->clientWakeup, 0); - - /* Add the message to the head of the server's message queue. - */ - pthread_mutex_lock(&g.queueMutex); - pMsg->pNext = g.pQueueHead; - if( g.pQueueHead==0 ){ - g.pQueueTail = pMsg; - }else{ - g.pQueueHead->pPrev = pMsg; - } - pMsg->pPrev = 0; - g.pQueueHead = pMsg; - pthread_mutex_unlock(&g.queueMutex); - - /* Signal the server that the new message has be queued, then - ** block waiting for the server to process the message. - */ - pthread_mutex_lock(&pMsg->clientMutex); - pthread_cond_signal(&g.serverWakeup); - while( pMsg->op!=MSG_Done ){ - pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex); - } - pthread_mutex_unlock(&pMsg->clientMutex); - - /* Destroy the mutex and condition variable of the message. - */ - pthread_mutex_destroy(&pMsg->clientMutex); - pthread_cond_destroy(&pMsg->clientWakeup); -} - -/* -** The following 6 routines are client-side implementations of the -** core SQLite interfaces: -** -** sqlite3_open -** sqlite3_prepare -** sqlite3_step -** sqlite3_reset -** sqlite3_finalize -** sqlite3_close -** -** Clients should use the following client-side routines instead of -** the core routines above. -** -** sqlite3_client_open -** sqlite3_client_prepare -** sqlite3_client_step -** sqlite3_client_reset -** sqlite3_client_finalize -** sqlite3_client_close -** -** Each of these routines creates a message for the desired operation, -** sends that message to the server, waits for the server to process -** then message and return a response. -*/ -int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){ - SqlMessage msg; - msg.op = MSG_Open; - msg.zIn = zDatabaseName; - sendToServer(&msg); - *ppDb = msg.pDb; - return msg.errCode; -} -int sqlite3_client_prepare( - sqlite3 *pDb, - const char *zSql, - int nByte, - sqlite3_stmt **ppStmt, - const char **pzTail -){ - SqlMessage msg; - msg.op = MSG_Prepare; - msg.pDb = pDb; - msg.zIn = zSql; - msg.nByte = nByte; - sendToServer(&msg); - *ppStmt = msg.pStmt; - if( pzTail ) *pzTail = msg.zOut; - return msg.errCode; -} -int sqlite3_client_step(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Step; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_reset(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Reset; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_finalize(sqlite3_stmt *pStmt){ - SqlMessage msg; - msg.op = MSG_Finalize; - msg.pStmt = pStmt; - sendToServer(&msg); - return msg.errCode; -} -int sqlite3_client_close(sqlite3 *pDb){ - SqlMessage msg; - msg.op = MSG_Close; - msg.pDb = pDb; - sendToServer(&msg); - return msg.errCode; -} - -/* -** This routine implements the server. To start the server, first -** make sure g.serverHalt is false, then create a new detached thread -** on this procedure. See the sqlite3_server_start() routine below -** for an example. This procedure loops until g.serverHalt becomes -** true. -*/ -void *sqlite3_server(void *NotUsed){ - if( pthread_mutex_trylock(&g.serverMutex) ){ - return 0; /* Another server is already running */ - } - sqlite3_enable_shared_cache(1); - while( !g.serverHalt ){ - SqlMessage *pMsg; - - /* Remove the last message from the message queue. - */ - pthread_mutex_lock(&g.queueMutex); - while( g.pQueueTail==0 && g.serverHalt==0 ){ - pthread_cond_wait(&g.serverWakeup, &g.queueMutex); - } - pMsg = g.pQueueTail; - if( pMsg ){ - if( pMsg->pPrev ){ - pMsg->pPrev->pNext = 0; - }else{ - g.pQueueHead = 0; - } - g.pQueueTail = pMsg->pPrev; - } - pthread_mutex_unlock(&g.queueMutex); - if( pMsg==0 ) break; - - /* Process the message just removed - */ - pthread_mutex_lock(&pMsg->clientMutex); - switch( pMsg->op ){ - case MSG_Open: { - pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb); - break; - } - case MSG_Prepare: { - pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte, - &pMsg->pStmt, &pMsg->zOut); - break; - } - case MSG_Step: { - pMsg->errCode = sqlite3_step(pMsg->pStmt); - break; - } - case MSG_Reset: { - pMsg->errCode = sqlite3_reset(pMsg->pStmt); - break; - } - case MSG_Finalize: { - pMsg->errCode = sqlite3_finalize(pMsg->pStmt); - break; - } - case MSG_Close: { - pMsg->errCode = sqlite3_close(pMsg->pDb); - break; - } - } - - /* Signal the client that the message has been processed. - */ - pMsg->op = MSG_Done; - pthread_mutex_unlock(&pMsg->clientMutex); - pthread_cond_signal(&pMsg->clientWakeup); - } - pthread_mutex_unlock(&g.serverMutex); - return 0; -} - -/* -** Start a server thread if one is not already running. If there -** is aleady a server thread running, the new thread will quickly -** die and this routine is effectively a no-op. -*/ -void sqlite3_server_start(void){ - pthread_t x; - int rc; - g.serverHalt = 0; - rc = pthread_create(&x, 0, sqlite3_server, 0); - if( rc==0 ){ - pthread_detach(x); - } -} - -/* -** A wrapper around sqlite3_server() that decrements the int variable -** pointed to by the first argument after the sqlite3_server() call -** returns. -*/ -static void *serverWrapper(void *pnDecr){ - void *p = sqlite3_server(0); - (*(int*)pnDecr)--; - return p; -} - -/* -** This function is the similar to sqlite3_server_start(), except that -** the integer pointed to by the first argument is decremented when -** the server thread exits. -*/ -void sqlite3_server_start2(int *pnDecr){ - pthread_t x; - int rc; - g.serverHalt = 0; - rc = pthread_create(&x, 0, serverWrapper, (void*)pnDecr); - if( rc==0 ){ - pthread_detach(x); - } -} - -/* -** If a server thread is running, then stop it. If no server is -** running, this routine is effectively a no-op. -** -** This routine waits until the server has actually stopped before -** returning. -*/ -void sqlite3_server_stop(void){ - g.serverHalt = 1; - pthread_cond_broadcast(&g.serverWakeup); - pthread_mutex_lock(&g.serverMutex); - pthread_mutex_unlock(&g.serverMutex); -} - -#endif /* SQLITE_OS_UNIX && SQLITE_THREADSAFE */ -#endif /* defined(SQLITE_SERVER) */ diff --git a/test/server1.test b/test/server1.test deleted file mode 100644 index c809217094..0000000000 --- a/test/server1.test +++ /dev/null @@ -1,180 +0,0 @@ -# 2006 January 09 -# -# The author disclaims copyright to this source code. In place of -# a legal notice, here is a blessing: -# -# May you do good and not evil. -# May you find forgiveness for yourself and forgive others. -# May you share freely, never taking more than you give. -# -#*********************************************************************** -# This file implements regression tests for SQLite library. The -# focus of this script is testing the server mode of SQLite. -# -# This file is derived from thread1.test -# -# $Id: server1.test,v 1.5 2007/08/29 18:20:17 drh Exp $ - - -set testdir [file dirname $argv0] -source $testdir/tester.tcl - -# Skip this whole file if the server testing code is not enabled -# -if {[llength [info command client_step]]==0 || [sqlite3 -has-codec]} { - finish_test - return -} - -# This test does not work on older PPC Macs due to problems in the -# pthreads library. So skip it. -# -if {$tcl_platform(machine)=="Power Macintosh" && - $tcl_platform(byteOrder)=="bigEndian"} { - finish_test - return -} - -# The sample server implementation does not work right when memory -# management is enabled. -# -ifcapable (memorymanage||mutex_noop) { - finish_test - return -} - -# Create some data to work with -# -do_test server1-1.1 { - execsql { - CREATE TABLE t1(a,b); - INSERT INTO t1 VALUES(1,'abcdefgh'); - INSERT INTO t1 SELECT a+1, b||b FROM t1; - INSERT INTO t1 SELECT a+2, b||b FROM t1; - INSERT INTO t1 SELECT a+4, b||b FROM t1; - SELECT count(*), max(length(b)) FROM t1; - } -} {8 64} - -# Interleave two threads on read access. Then make sure a third -# thread can write the database. In other words: -# -# read-lock A -# read-lock B -# unlock A -# unlock B -# write-lock C -# -do_test server1-1.2 { - client_create A test.db - client_create B test.db - client_create C test.db - client_compile A {SELECT a FROM t1} - client_step A - client_result A -} SQLITE_ROW -do_test server1-1.3 { - client_argc A -} 1 -do_test server1-1.4 { - client_argv A 0 -} 1 -do_test server1-1.5 { - client_compile B {SELECT b FROM t1} - client_step B - client_result B -} SQLITE_ROW -do_test server1-1.6 { - client_argc B -} 1 -do_test server1-1.7 { - client_argv B 0 -} abcdefgh -do_test server1-1.8 { - client_finalize A - client_result A -} SQLITE_OK -do_test server1-1.9 { - client_finalize B - client_result B -} SQLITE_OK -do_test server1-1.10 { - client_compile C {CREATE TABLE t2(x,y)} - client_step C - client_result C -} SQLITE_DONE -do_test server1-1.11 { - client_finalize C - client_result C -} SQLITE_OK -do_test server1-1.12 { - catchsql {SELECT name FROM sqlite_master} - execsql {SELECT name FROM sqlite_master} -} {t1 t2} - - -# Read from table t1. Do not finalize the statement. This -# will leave the lock pending. -# -do_test server1-2.1 { - client_halt * - client_create A test.db - client_compile A {SELECT a FROM t1} - client_step A - client_result A -} SQLITE_ROW - -# Read from the same table from another thread. This is allows. -# -do_test server1-2.2 { - client_create B test.db - client_compile B {SELECT b FROM t1} - client_step B - client_result B -} SQLITE_ROW - -# Write to a different table from another thread. This is allowed -# because in server mode with a shared cache we have table-level locking. -# -do_test server1-2.3 { - client_create C test.db - client_compile C {INSERT INTO t2 VALUES(98,99)} - client_step C - client_result C - client_finalize C - client_result C -} SQLITE_OK - -# But we cannot insert into table t1 because threads A and B have it locked. -# -do_test server1-2.4 { - client_compile C {INSERT INTO t1 VALUES(98,99)} - client_step C - client_result C - client_finalize C - client_result C -} SQLITE_LOCKED -do_test server1-2.5 { - client_finalize B - client_wait B - client_compile C {INSERT INTO t1 VALUES(98,99)} - client_step C - client_result C - client_finalize C - client_result C -} SQLITE_LOCKED - -# Insert into t1 is successful after finishing the other two threads. -do_test server1-2.6 { - client_finalize A - client_wait A - client_compile C {INSERT INTO t1 VALUES(98,99)} - client_step C - client_result C - client_finalize C - client_result C -} SQLITE_OK - -client_halt * -sqlite3_enable_shared_cache 0 -finish_test