Annotation of embedaddon/sqlite3/src/test_async.c, revision 1.1
1.1 ! misho 1: /*
! 2: ** 2005 December 14
! 3: **
! 4: ** The author disclaims copyright to this source code. In place of
! 5: ** a legal notice, here is a blessing:
! 6: **
! 7: ** May you do good and not evil.
! 8: ** May you find forgiveness for yourself and forgive others.
! 9: ** May you share freely, never taking more than you give.
! 10: **
! 11: *************************************************************************
! 12: **
! 13: ** This file contains a binding of the asynchronous IO extension interface
! 14: ** (defined in ext/async/sqlite3async.h) to Tcl.
! 15: */
! 16:
! 17: #define TCL_THREADS
! 18: #include <tcl.h>
! 19:
! 20: #ifdef SQLITE_ENABLE_ASYNCIO
! 21:
! 22: #include "sqlite3async.h"
! 23: #include "sqlite3.h"
! 24: #include <assert.h>
! 25:
! 26: /* From test1.c */
! 27: const char *sqlite3TestErrorName(int);
! 28:
! 29:
! 30: struct TestAsyncGlobal {
! 31: int isInstalled; /* True when async VFS is installed */
! 32: } testasync_g = { 0 };
! 33:
! 34: TCL_DECLARE_MUTEX(testasync_g_writerMutex);
! 35:
! 36: /*
! 37: ** sqlite3async_initialize PARENT-VFS ISDEFAULT
! 38: */
! 39: static int testAsyncInit(
! 40: void * clientData,
! 41: Tcl_Interp *interp,
! 42: int objc,
! 43: Tcl_Obj *CONST objv[]
! 44: ){
! 45: const char *zParent;
! 46: int isDefault;
! 47: int rc;
! 48:
! 49: if( objc!=3 ){
! 50: Tcl_WrongNumArgs(interp, 1, objv, "PARENT-VFS ISDEFAULT");
! 51: return TCL_ERROR;
! 52: }
! 53: zParent = Tcl_GetString(objv[1]);
! 54: if( !*zParent ) {
! 55: zParent = 0;
! 56: }
! 57: if( Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){
! 58: return TCL_ERROR;
! 59: }
! 60:
! 61: rc = sqlite3async_initialize(zParent, isDefault);
! 62: if( rc!=SQLITE_OK ){
! 63: Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3TestErrorName(rc), -1));
! 64: return TCL_ERROR;
! 65: }
! 66: return TCL_OK;
! 67: }
! 68:
! 69: /*
! 70: ** sqlite3async_shutdown
! 71: */
! 72: static int testAsyncShutdown(
! 73: void * clientData,
! 74: Tcl_Interp *interp,
! 75: int objc,
! 76: Tcl_Obj *CONST objv[]
! 77: ){
! 78: sqlite3async_shutdown();
! 79: return TCL_OK;
! 80: }
! 81:
! 82: static Tcl_ThreadCreateType tclWriterThread(ClientData pIsStarted){
! 83: Tcl_MutexLock(&testasync_g_writerMutex);
! 84: *((int *)pIsStarted) = 1;
! 85: sqlite3async_run();
! 86: Tcl_MutexUnlock(&testasync_g_writerMutex);
! 87: Tcl_ExitThread(0);
! 88: TCL_THREAD_CREATE_RETURN;
! 89: }
! 90:
! 91: /*
! 92: ** sqlite3async_start
! 93: **
! 94: ** Start a new writer thread.
! 95: */
! 96: static int testAsyncStart(
! 97: void * clientData,
! 98: Tcl_Interp *interp,
! 99: int objc,
! 100: Tcl_Obj *CONST objv[]
! 101: ){
! 102: volatile int isStarted = 0;
! 103: ClientData threadData = (ClientData)&isStarted;
! 104:
! 105: Tcl_ThreadId x;
! 106: const int nStack = TCL_THREAD_STACK_DEFAULT;
! 107: const int flags = TCL_THREAD_NOFLAGS;
! 108: int rc;
! 109:
! 110: rc = Tcl_CreateThread(&x, tclWriterThread, threadData, nStack, flags);
! 111: if( rc!=TCL_OK ){
! 112: Tcl_AppendResult(interp, "Tcl_CreateThread() failed", 0);
! 113: return TCL_ERROR;
! 114: }
! 115:
! 116: while( isStarted==0 ) { /* Busy loop */ }
! 117: return TCL_OK;
! 118: }
! 119:
! 120: /*
! 121: ** sqlite3async_wait
! 122: **
! 123: ** Wait for the current writer thread to terminate.
! 124: **
! 125: ** If the current writer thread is set to run forever then this
! 126: ** command would block forever. To prevent that, an error is returned.
! 127: */
! 128: static int testAsyncWait(
! 129: void * clientData,
! 130: Tcl_Interp *interp,
! 131: int objc,
! 132: Tcl_Obj *CONST objv[]
! 133: ){
! 134: int eCond;
! 135: if( objc!=1 ){
! 136: Tcl_WrongNumArgs(interp, 1, objv, "");
! 137: return TCL_ERROR;
! 138: }
! 139:
! 140: sqlite3async_control(SQLITEASYNC_GET_HALT, &eCond);
! 141: if( eCond==SQLITEASYNC_HALT_NEVER ){
! 142: Tcl_AppendResult(interp, "would block forever", (char*)0);
! 143: return TCL_ERROR;
! 144: }
! 145:
! 146: Tcl_MutexLock(&testasync_g_writerMutex);
! 147: Tcl_MutexUnlock(&testasync_g_writerMutex);
! 148: return TCL_OK;
! 149: }
! 150:
! 151: /*
! 152: ** sqlite3async_control OPTION ?VALUE?
! 153: */
! 154: static int testAsyncControl(
! 155: void * clientData,
! 156: Tcl_Interp *interp,
! 157: int objc,
! 158: Tcl_Obj *CONST objv[]
! 159: ){
! 160: int rc = SQLITE_OK;
! 161: int aeOpt[] = { SQLITEASYNC_HALT, SQLITEASYNC_DELAY, SQLITEASYNC_LOCKFILES };
! 162: const char *azOpt[] = { "halt", "delay", "lockfiles", 0 };
! 163: const char *az[] = { "never", "now", "idle", 0 };
! 164: int iVal;
! 165: int eOpt;
! 166:
! 167: if( objc!=2 && objc!=3 ){
! 168: Tcl_WrongNumArgs(interp, 1, objv, "OPTION ?VALUE?");
! 169: return TCL_ERROR;
! 170: }
! 171: if( Tcl_GetIndexFromObj(interp, objv[1], azOpt, "option", 0, &eOpt) ){
! 172: return TCL_ERROR;
! 173: }
! 174: eOpt = aeOpt[eOpt];
! 175:
! 176: if( objc==3 ){
! 177: switch( eOpt ){
! 178: case SQLITEASYNC_HALT: {
! 179: assert( SQLITEASYNC_HALT_NEVER==0 );
! 180: assert( SQLITEASYNC_HALT_NOW==1 );
! 181: assert( SQLITEASYNC_HALT_IDLE==2 );
! 182: if( Tcl_GetIndexFromObj(interp, objv[2], az, "value", 0, &iVal) ){
! 183: return TCL_ERROR;
! 184: }
! 185: break;
! 186: }
! 187: case SQLITEASYNC_DELAY:
! 188: if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ){
! 189: return TCL_ERROR;
! 190: }
! 191: break;
! 192:
! 193: case SQLITEASYNC_LOCKFILES:
! 194: if( Tcl_GetBooleanFromObj(interp, objv[2], &iVal) ){
! 195: return TCL_ERROR;
! 196: }
! 197: break;
! 198: }
! 199:
! 200: rc = sqlite3async_control(eOpt, iVal);
! 201: }
! 202:
! 203: if( rc==SQLITE_OK ){
! 204: rc = sqlite3async_control(
! 205: eOpt==SQLITEASYNC_HALT ? SQLITEASYNC_GET_HALT :
! 206: eOpt==SQLITEASYNC_DELAY ? SQLITEASYNC_GET_DELAY :
! 207: SQLITEASYNC_GET_LOCKFILES, &iVal);
! 208: }
! 209:
! 210: if( rc!=SQLITE_OK ){
! 211: Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3TestErrorName(rc), -1));
! 212: return TCL_ERROR;
! 213: }
! 214:
! 215: if( eOpt==SQLITEASYNC_HALT ){
! 216: Tcl_SetObjResult(interp, Tcl_NewStringObj(az[iVal], -1));
! 217: }else{
! 218: Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
! 219: }
! 220:
! 221: return TCL_OK;
! 222: }
! 223:
! 224: #endif /* SQLITE_ENABLE_ASYNCIO */
! 225:
! 226: /*
! 227: ** This routine registers the custom TCL commands defined in this
! 228: ** module. This should be the only procedure visible from outside
! 229: ** of this module.
! 230: */
! 231: int Sqlitetestasync_Init(Tcl_Interp *interp){
! 232: #ifdef SQLITE_ENABLE_ASYNCIO
! 233: Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);
! 234: Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);
! 235:
! 236: Tcl_CreateObjCommand(interp,"sqlite3async_control",testAsyncControl,0,0);
! 237: Tcl_CreateObjCommand(interp,"sqlite3async_initialize",testAsyncInit,0,0);
! 238: Tcl_CreateObjCommand(interp,"sqlite3async_shutdown",testAsyncShutdown,0,0);
! 239: #endif /* SQLITE_ENABLE_ASYNCIO */
! 240: return TCL_OK;
! 241: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>