Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / sqlite / sqlite-src-3080704 / src / test_async.c
blobb0b943185bfc23c17fd08f55768cac12a9f56951
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.
11 *************************************************************************
13 ** This file contains a binding of the asynchronous IO extension interface
14 ** (defined in ext/async/sqlite3async.h) to Tcl.
17 #define TCL_THREADS
18 #include <tcl.h>
20 #ifdef SQLITE_ENABLE_ASYNCIO
22 #include "sqlite3async.h"
23 #include "sqlite3.h"
24 #include <assert.h>
26 /* From main.c */
27 extern const char *sqlite3ErrName(int);
30 struct TestAsyncGlobal {
31 int isInstalled; /* True when async VFS is installed */
32 } testasync_g = { 0 };
34 TCL_DECLARE_MUTEX(testasync_g_writerMutex);
37 ** sqlite3async_initialize PARENT-VFS ISDEFAULT
39 static int testAsyncInit(
40 void * clientData,
41 Tcl_Interp *interp,
42 int objc,
43 Tcl_Obj *CONST objv[]
45 const char *zParent;
46 int isDefault;
47 int rc;
49 if( objc!=3 ){
50 Tcl_WrongNumArgs(interp, 1, objv, "PARENT-VFS ISDEFAULT");
51 return TCL_ERROR;
53 zParent = Tcl_GetString(objv[1]);
54 if( !*zParent ) {
55 zParent = 0;
57 if( Tcl_GetBooleanFromObj(interp, objv[2], &isDefault) ){
58 return TCL_ERROR;
61 rc = sqlite3async_initialize(zParent, isDefault);
62 if( rc!=SQLITE_OK ){
63 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
64 return TCL_ERROR;
66 return TCL_OK;
70 ** sqlite3async_shutdown
72 static int testAsyncShutdown(
73 void * clientData,
74 Tcl_Interp *interp,
75 int objc,
76 Tcl_Obj *CONST objv[]
78 sqlite3async_shutdown();
79 return TCL_OK;
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;
92 ** sqlite3async_start
94 ** Start a new writer thread.
96 static int testAsyncStart(
97 void * clientData,
98 Tcl_Interp *interp,
99 int objc,
100 Tcl_Obj *CONST objv[]
102 volatile int isStarted = 0;
103 ClientData threadData = (ClientData)&isStarted;
105 Tcl_ThreadId x;
106 const int nStack = TCL_THREAD_STACK_DEFAULT;
107 const int flags = TCL_THREAD_NOFLAGS;
108 int rc;
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;
116 while( isStarted==0 ) { /* Busy loop */ }
117 return TCL_OK;
121 ** sqlite3async_wait
123 ** Wait for the current writer thread to terminate.
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.
128 static int testAsyncWait(
129 void * clientData,
130 Tcl_Interp *interp,
131 int objc,
132 Tcl_Obj *CONST objv[]
134 int eCond;
135 if( objc!=1 ){
136 Tcl_WrongNumArgs(interp, 1, objv, "");
137 return TCL_ERROR;
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;
146 Tcl_MutexLock(&testasync_g_writerMutex);
147 Tcl_MutexUnlock(&testasync_g_writerMutex);
148 return TCL_OK;
152 ** sqlite3async_control OPTION ?VALUE?
154 static int testAsyncControl(
155 void * clientData,
156 Tcl_Interp *interp,
157 int objc,
158 Tcl_Obj *CONST objv[]
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;
167 if( objc!=2 && objc!=3 ){
168 Tcl_WrongNumArgs(interp, 1, objv, "OPTION ?VALUE?");
169 return TCL_ERROR;
171 if( Tcl_GetIndexFromObj(interp, objv[1], azOpt, "option", 0, &eOpt) ){
172 return TCL_ERROR;
174 eOpt = aeOpt[eOpt];
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;
185 break;
187 case SQLITEASYNC_DELAY:
188 if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ){
189 return TCL_ERROR;
191 break;
193 case SQLITEASYNC_LOCKFILES:
194 if( Tcl_GetBooleanFromObj(interp, objv[2], &iVal) ){
195 return TCL_ERROR;
197 break;
200 rc = sqlite3async_control(eOpt, iVal);
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);
210 if( rc!=SQLITE_OK ){
211 Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
212 return TCL_ERROR;
215 if( eOpt==SQLITEASYNC_HALT ){
216 Tcl_SetObjResult(interp, Tcl_NewStringObj(az[iVal], -1));
217 }else{
218 Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
221 return TCL_OK;
224 #endif /* SQLITE_ENABLE_ASYNCIO */
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.
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);
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;