diff options
author | Hans-Christoph Steiner <hans@eds.org> | 2012-03-30 20:42:12 -0400 |
---|---|---|
committer | Hans-Christoph Steiner <hans@eds.org> | 2012-03-30 20:42:12 -0400 |
commit | 7bb481fda9ecb134804b49c2ce77ca28f7eea583 (patch) | |
tree | 31b520b9914d3e2453968abe375f2c102772c3dc /src/test_async.c |
Imported Upstream version 2.0.3
Diffstat (limited to 'src/test_async.c')
-rw-r--r-- | src/test_async.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/test_async.c b/src/test_async.c new file mode 100644 index 0000000..c760eea --- /dev/null +++ b/src/test_async.c @@ -0,0 +1,241 @@ +/* +** 2005 December 14 +** +** 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 a binding of the asynchronous IO extension interface +** (defined in ext/async/sqlite3async.h) to Tcl. +*/ + +#define TCL_THREADS +#include <tcl.h> + +#ifdef SQLITE_ENABLE_ASYNCIO + +#include "sqlite3async.h" +#include "sqlite3.h" +#include <assert.h> + +/* From test1.c */ +const char *sqlite3TestErrorName(int); + + +struct TestAsyncGlobal { + int isInstalled; /* True when async VFS is installed */ +} testasync_g = { 0 }; + +TCL_DECLARE_MUTEX(testasync_g_writerMutex); + +/* +** sqlite3async_initialize PARENT-VFS ISDEFAULT +*/ +static int testAsyncInit( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + const char *zParent; + int isDefault; + int rc; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "PARENT-VFS ISDEFAULT"); + return TCL_ERROR; + } + zParent = Tcl_GetString(objv[1]); + if( !*zParent ) { + zParent = 0; + } + if( Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){ + return TCL_ERROR; + } + + rc = sqlite3async_initialize(zParent, isDefault); + if( rc!=SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3TestErrorName(rc), -1)); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** sqlite3async_shutdown +*/ +static int testAsyncShutdown( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3async_shutdown(); + return TCL_OK; +} + +static Tcl_ThreadCreateType tclWriterThread(ClientData pIsStarted){ + Tcl_MutexLock(&testasync_g_writerMutex); + *((int *)pIsStarted) = 1; + sqlite3async_run(); + Tcl_MutexUnlock(&testasync_g_writerMutex); + Tcl_ExitThread(0); + TCL_THREAD_CREATE_RETURN; +} + +/* +** sqlite3async_start +** +** Start a new writer thread. +*/ +static int testAsyncStart( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + volatile int isStarted = 0; + ClientData threadData = (ClientData)&isStarted; + + Tcl_ThreadId x; + const int nStack = TCL_THREAD_STACK_DEFAULT; + const int flags = TCL_THREAD_NOFLAGS; + int rc; + + rc = Tcl_CreateThread(&x, tclWriterThread, threadData, nStack, flags); + if( rc!=TCL_OK ){ + Tcl_AppendResult(interp, "Tcl_CreateThread() failed", 0); + return TCL_ERROR; + } + + while( isStarted==0 ) { /* Busy loop */ } + return TCL_OK; +} + +/* +** sqlite3async_wait +** +** Wait for the current writer thread to terminate. +** +** If the current writer thread is set to run forever then this +** command would block forever. To prevent that, an error is returned. +*/ +static int testAsyncWait( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int eCond; + if( objc!=1 ){ + Tcl_WrongNumArgs(interp, 1, objv, ""); + return TCL_ERROR; + } + + sqlite3async_control(SQLITEASYNC_GET_HALT, &eCond); + if( eCond==SQLITEASYNC_HALT_NEVER ){ + Tcl_AppendResult(interp, "would block forever", (char*)0); + return TCL_ERROR; + } + + Tcl_MutexLock(&testasync_g_writerMutex); + Tcl_MutexUnlock(&testasync_g_writerMutex); + return TCL_OK; +} + +/* +** sqlite3async_control OPTION ?VALUE? +*/ +static int testAsyncControl( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int rc = SQLITE_OK; + int aeOpt[] = { SQLITEASYNC_HALT, SQLITEASYNC_DELAY, SQLITEASYNC_LOCKFILES }; + const char *azOpt[] = { "halt", "delay", "lockfiles", 0 }; + const char *az[] = { "never", "now", "idle", 0 }; + int iVal; + int eOpt; + + if( objc!=2 && objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "OPTION ?VALUE?"); + return TCL_ERROR; + } + if( Tcl_GetIndexFromObj(interp, objv[1], azOpt, "option", 0, &eOpt) ){ + return TCL_ERROR; + } + eOpt = aeOpt[eOpt]; + + if( objc==3 ){ + switch( eOpt ){ + case SQLITEASYNC_HALT: { + assert( SQLITEASYNC_HALT_NEVER==0 ); + assert( SQLITEASYNC_HALT_NOW==1 ); + assert( SQLITEASYNC_HALT_IDLE==2 ); + if( Tcl_GetIndexFromObj(interp, objv[2], az, "value", 0, &iVal) ){ + return TCL_ERROR; + } + break; + } + case SQLITEASYNC_DELAY: + if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ){ + return TCL_ERROR; + } + break; + + case SQLITEASYNC_LOCKFILES: + if( Tcl_GetBooleanFromObj(interp, objv[2], &iVal) ){ + return TCL_ERROR; + } + break; + } + + rc = sqlite3async_control(eOpt, iVal); + } + + if( rc==SQLITE_OK ){ + rc = sqlite3async_control( + eOpt==SQLITEASYNC_HALT ? SQLITEASYNC_GET_HALT : + eOpt==SQLITEASYNC_DELAY ? SQLITEASYNC_GET_DELAY : + SQLITEASYNC_GET_LOCKFILES, &iVal); + } + + if( rc!=SQLITE_OK ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3TestErrorName(rc), -1)); + return TCL_ERROR; + } + + if( eOpt==SQLITEASYNC_HALT ){ + Tcl_SetObjResult(interp, Tcl_NewStringObj(az[iVal], -1)); + }else{ + Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); + } + + return TCL_OK; +} + +#endif /* SQLITE_ENABLE_ASYNCIO */ + +/* +** This routine registers the custom TCL commands defined in this +** module. This should be the only procedure visible from outside +** of this module. +*/ +int Sqlitetestasync_Init(Tcl_Interp *interp){ +#ifdef SQLITE_ENABLE_ASYNCIO + Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0); + + Tcl_CreateObjCommand(interp,"sqlite3async_control",testAsyncControl,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_initialize",testAsyncInit,0,0); + Tcl_CreateObjCommand(interp,"sqlite3async_shutdown",testAsyncShutdown,0,0); +#endif /* SQLITE_ENABLE_ASYNCIO */ + return TCL_OK; +} |