Annotation of embedaddon/sqlite3/src/test_async.c, revision 1.1.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>