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>