| Index: third_party/sqlite/src/src/test_server.c
|
| diff --git a/third_party/sqlite/src/src/test_server.c b/third_party/sqlite/src/src/test_server.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ed0818e6f65f27282dc7b1c190ec188c8933002b
|
| --- /dev/null
|
| +++ b/third_party/sqlite/src/src/test_server.c
|
| @@ -0,0 +1,490 @@
|
| +/*
|
| +** 2006 January 07
|
| +**
|
| +** 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 contains demonstration code. Nothing in this file gets compiled
|
| +** or linked into the SQLite library unless you use a non-standard option:
|
| +**
|
| +** -DSQLITE_SERVER=1
|
| +**
|
| +** The configure script will never generate a Makefile with the option
|
| +** above. You will need to manually modify the Makefile if you want to
|
| +** include any of the code from this file in your project. Or, at your
|
| +** option, you may copy and paste the code from this file and
|
| +** thereby avoiding a recompile of SQLite.
|
| +**
|
| +**
|
| +** This source file demonstrates how to use SQLite to create an SQL database
|
| +** server thread in a multiple-threaded program. One or more client threads
|
| +** send messages to the server thread and the server thread processes those
|
| +** messages in the order received and returns the results to the client.
|
| +**
|
| +** One might ask: "Why bother? Why not just let each thread connect
|
| +** to the database directly?" There are a several of reasons to
|
| +** prefer the client/server approach.
|
| +**
|
| +** (1) Some systems (ex: Redhat9) have broken threading implementations
|
| +** that prevent SQLite database connections from being used in
|
| +** a thread different from the one where they were created. With
|
| +** the client/server approach, all database connections are created
|
| +** and used within the server thread. Client calls to the database
|
| +** can be made from multiple threads (though not at the same time!)
|
| +**
|
| +** (2) Beginning with SQLite version 3.3.0, when two or more
|
| +** connections to the same database occur within the same thread,
|
| +** they can optionally share their database cache. This reduces
|
| +** I/O and memory requirements. Cache shared is controlled using
|
| +** the sqlite3_enable_shared_cache() API.
|
| +**
|
| +** (3) Database connections on a shared cache use table-level locking
|
| +** instead of file-level locking for improved concurrency.
|
| +**
|
| +** (4) Database connections on a shared cache can by optionally
|
| +** set to READ UNCOMMITTED isolation. (The default isolation for
|
| +** SQLite is SERIALIZABLE.) When this occurs, readers will
|
| +** never be blocked by a writer and writers will not be
|
| +** blocked by readers. There can still only be a single writer
|
| +** at a time, but multiple readers can simultaneously exist with
|
| +** that writer. This is a huge increase in concurrency.
|
| +**
|
| +** To summarize the rational for using a client/server approach: prior
|
| +** to SQLite version 3.3.0 it probably was not worth the trouble. But
|
| +** with SQLite version 3.3.0 and beyond you can get significant performance
|
| +** and concurrency improvements and memory usage reductions by going
|
| +** client/server.
|
| +**
|
| +** Note: The extra features of version 3.3.0 described by points (2)
|
| +** through (4) above are only available if you compile without the
|
| +** option -DSQLITE_OMIT_SHARED_CACHE.
|
| +**
|
| +** Here is how the client/server approach works: The database server
|
| +** thread is started on this procedure:
|
| +**
|
| +** void *sqlite3_server(void *NotUsed);
|
| +**
|
| +** The sqlite_server procedure runs as long as the g.serverHalt variable
|
| +** is false. A mutex is used to make sure no more than one server runs
|
| +** at a time. The server waits for messages to arrive on a message
|
| +** queue and processes the messages in order.
|
| +**
|
| +** Two convenience routines are provided for starting and stopping the
|
| +** server thread:
|
| +**
|
| +** void sqlite3_server_start(void);
|
| +** void sqlite3_server_stop(void);
|
| +**
|
| +** Both of the convenience routines return immediately. Neither will
|
| +** ever give an error. If a server is already started or already halted,
|
| +** then the routines are effectively no-ops.
|
| +**
|
| +** Clients use the following interfaces:
|
| +**
|
| +** sqlite3_client_open
|
| +** sqlite3_client_prepare
|
| +** sqlite3_client_step
|
| +** sqlite3_client_reset
|
| +** sqlite3_client_finalize
|
| +** sqlite3_client_close
|
| +**
|
| +** These interfaces work exactly like the standard core SQLite interfaces
|
| +** having the same names without the "_client_" infix. Many other SQLite
|
| +** interfaces can be used directly without having to send messages to the
|
| +** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined.
|
| +** The following interfaces fall into this second category:
|
| +**
|
| +** sqlite3_bind_*
|
| +** sqlite3_changes
|
| +** sqlite3_clear_bindings
|
| +** sqlite3_column_*
|
| +** sqlite3_complete
|
| +** sqlite3_create_collation
|
| +** sqlite3_create_function
|
| +** sqlite3_data_count
|
| +** sqlite3_db_handle
|
| +** sqlite3_errcode
|
| +** sqlite3_errmsg
|
| +** sqlite3_last_insert_rowid
|
| +** sqlite3_total_changes
|
| +** sqlite3_transfer_bindings
|
| +**
|
| +** A single SQLite connection (an sqlite3* object) or an SQLite statement
|
| +** (an sqlite3_stmt* object) should only be passed to a single interface
|
| +** function at a time. The connections and statements can be passed from
|
| +** any thread to any of the functions listed in the second group above as
|
| +** long as the same connection is not in use by two threads at once and
|
| +** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional
|
| +** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is
|
| +** below.
|
| +**
|
| +** The busy handler for all database connections should remain turned
|
| +** off. That means that any lock contention will cause the associated
|
| +** sqlite3_client_step() call to return immediately with an SQLITE_BUSY
|
| +** error code. If a busy handler is enabled and lock contention occurs,
|
| +** then the entire server thread will block. This will cause not only
|
| +** the requesting client to block but every other database client as
|
| +** well. It is possible to enhance the code below so that lock
|
| +** contention will cause the message to be placed back on the top of
|
| +** the queue to be tried again later. But such enhanced processing is
|
| +** not included here, in order to keep the example simple.
|
| +**
|
| +** This example code assumes the use of pthreads. Pthreads
|
| +** implementations are available for windows. (See, for example
|
| +** http://sourceware.org/pthreads-win32/announcement.html.) Or, you
|
| +** can translate the locking and thread synchronization code to use
|
| +** windows primitives easily enough. The details are left as an
|
| +** exercise to the reader.
|
| +**
|
| +**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT ****
|
| +**
|
| +** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then
|
| +** SQLite includes code that tracks how much memory is being used by
|
| +** each thread. These memory counts can become confused if memory
|
| +** is allocated by one thread and then freed by another. For that
|
| +** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations
|
| +** that might allocate or free memory should be performanced in the same
|
| +** thread that originally created the database connection. In that case,
|
| +** many of the operations that are listed above as safe to be performed
|
| +** in separate threads would need to be sent over to the server to be
|
| +** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then
|
| +** the following functions can be used safely from different threads
|
| +** without messing up the allocation counts:
|
| +**
|
| +** sqlite3_bind_parameter_name
|
| +** sqlite3_bind_parameter_index
|
| +** sqlite3_changes
|
| +** sqlite3_column_blob
|
| +** sqlite3_column_count
|
| +** sqlite3_complete
|
| +** sqlite3_data_count
|
| +** sqlite3_db_handle
|
| +** sqlite3_errcode
|
| +** sqlite3_errmsg
|
| +** sqlite3_last_insert_rowid
|
| +** sqlite3_total_changes
|
| +**
|
| +** The remaining functions are not thread-safe when memory management
|
| +** is enabled. So one would have to define some new interface routines
|
| +** along the following lines:
|
| +**
|
| +** sqlite3_client_bind_*
|
| +** sqlite3_client_clear_bindings
|
| +** sqlite3_client_column_*
|
| +** sqlite3_client_create_collation
|
| +** sqlite3_client_create_function
|
| +** sqlite3_client_transfer_bindings
|
| +**
|
| +** The example code in this file is intended for use with memory
|
| +** management turned off. So the implementation of these additional
|
| +** client interfaces is left as an exercise to the reader.
|
| +**
|
| +** It may seem surprising to the reader that the list of safe functions
|
| +** above does not include things like sqlite3_bind_int() or
|
| +** sqlite3_column_int(). But those routines might, in fact, allocate
|
| +** or deallocate memory. In the case of sqlite3_bind_int(), if the
|
| +** parameter was previously bound to a string that string might need
|
| +** to be deallocated before the new integer value is inserted. In
|
| +** the case of sqlite3_column_int(), the value of the column might be
|
| +** a UTF-16 string which will need to be converted to UTF-8 then into
|
| +** an integer.
|
| +*/
|
| +
|
| +/* Include this to get the definition of SQLITE_THREADSAFE, in the
|
| +** case that default values are used.
|
| +*/
|
| +#include "sqliteInt.h"
|
| +
|
| +/*
|
| +** Only compile the code in this file on UNIX with a SQLITE_THREADSAFE build
|
| +** and only if the SQLITE_SERVER macro is defined.
|
| +*/
|
| +#if defined(SQLITE_SERVER) && !defined(SQLITE_OMIT_SHARED_CACHE)
|
| +#if SQLITE_OS_UNIX && SQLITE_THREADSAFE
|
| +
|
| +/*
|
| +** We require only pthreads and the public interface of SQLite.
|
| +*/
|
| +#include <pthread.h>
|
| +#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);
|
| + }
|
| +}
|
| +
|
| +/*
|
| +** 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) */
|
|
|