xref: /sqlite-3.40.0/src/test_thread.c (revision 65a2ea11)
1 /*
2 ** 2007 September 9
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 the implementation of some Tcl commands used to
14 ** test that sqlite3 database handles may be concurrently accessed by
15 ** multiple threads. Right now this only works on unix.
16 **
17 ** $Id: test_thread.c,v 1.12 2009/03/19 07:58:31 danielk1977 Exp $
18 */
19 
20 #include "sqliteInt.h"
21 #include <tcl.h>
22 
23 #if SQLITE_THREADSAFE
24 
25 #include <errno.h>
26 
27 #if !defined(_MSC_VER)
28 #include <unistd.h>
29 #endif
30 
31 /*
32 ** One of these is allocated for each thread created by [sqlthread spawn].
33 */
34 typedef struct SqlThread SqlThread;
35 struct SqlThread {
36   Tcl_ThreadId parent;     /* Thread id of parent thread */
37   Tcl_Interp *interp;      /* Parent interpreter */
38   char *zScript;           /* The script to execute. */
39   char *zVarname;          /* Varname in parent script */
40 };
41 
42 /*
43 ** A custom Tcl_Event type used by this module. When the event is
44 ** handled, script zScript is evaluated in interpreter interp. If
45 ** the evaluation throws an exception (returns TCL_ERROR), then the
46 ** error is handled by Tcl_BackgroundError(). If no error occurs,
47 ** the result is simply discarded.
48 */
49 typedef struct EvalEvent EvalEvent;
50 struct EvalEvent {
51   Tcl_Event base;          /* Base class of type Tcl_Event */
52   char *zScript;           /* The script to execute. */
53   Tcl_Interp *interp;      /* The interpreter to execute it in. */
54 };
55 
56 static Tcl_ObjCmdProc sqlthread_proc;
57 static Tcl_ObjCmdProc clock_seconds_proc;
58 static Tcl_ObjCmdProc blocking_step_proc;
59 static Tcl_ObjCmdProc blocking_prepare_v2_proc;
60 int Sqlitetest1_Init(Tcl_Interp *);
61 
62 /* Functions from test1.c */
63 void *sqlite3TestTextToPtr(const char *);
64 const char *sqlite3TestErrorName(int);
65 int getDbPointer(Tcl_Interp *, const char *, sqlite3 **);
66 int sqlite3TestMakePointerStr(Tcl_Interp *, char *, void *);
67 int sqlite3TestErrCode(Tcl_Interp *, sqlite3 *, int);
68 
69 /*
70 ** Handler for events of type EvalEvent.
71 */
72 static int tclScriptEvent(Tcl_Event *evPtr, int flags){
73   int rc;
74   EvalEvent *p = (EvalEvent *)evPtr;
75   rc = Tcl_Eval(p->interp, p->zScript);
76   if( rc!=TCL_OK ){
77     Tcl_BackgroundError(p->interp);
78   }
79   UNUSED_PARAMETER(flags);
80   return 1;
81 }
82 
83 /*
84 ** Register an EvalEvent to evaluate the script pScript in the
85 ** parent interpreter/thread of SqlThread p.
86 */
87 static void postToParent(SqlThread *p, Tcl_Obj *pScript){
88   EvalEvent *pEvent;
89   char *zMsg;
90   int nMsg;
91 
92   zMsg = Tcl_GetStringFromObj(pScript, &nMsg);
93   pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1);
94   pEvent->base.nextPtr = 0;
95   pEvent->base.proc = tclScriptEvent;
96   pEvent->zScript = (char *)&pEvent[1];
97   memcpy(pEvent->zScript, zMsg, nMsg+1);
98   pEvent->interp = p->interp;
99 
100   Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL);
101   Tcl_ThreadAlert(p->parent);
102 }
103 
104 /*
105 ** The main function for threads created with [sqlthread spawn].
106 */
107 static Tcl_ThreadCreateType tclScriptThread(ClientData pSqlThread){
108   Tcl_Interp *interp;
109   Tcl_Obj *pRes;
110   Tcl_Obj *pList;
111   int rc;
112   SqlThread *p = (SqlThread *)pSqlThread;
113   extern int Sqlitetest_mutex_Init(Tcl_Interp*);
114 
115   interp = Tcl_CreateInterp();
116   Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0);
117   Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, pSqlThread, 0);
118 #if defined(OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
119   Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0);
120   Tcl_CreateObjCommand(
121       interp, "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc,0,0);
122 #endif
123   Sqlitetest1_Init(interp);
124   Sqlitetest_mutex_Init(interp);
125 
126   rc = Tcl_Eval(interp, p->zScript);
127   pRes = Tcl_GetObjResult(interp);
128   pList = Tcl_NewObj();
129   Tcl_IncrRefCount(pList);
130   Tcl_IncrRefCount(pRes);
131 
132   if( rc!=TCL_OK ){
133     Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("error", -1));
134     Tcl_ListObjAppendElement(interp, pList, pRes);
135     postToParent(p, pList);
136     Tcl_DecrRefCount(pList);
137     pList = Tcl_NewObj();
138   }
139 
140   Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj("set", -1));
141   Tcl_ListObjAppendElement(interp, pList, Tcl_NewStringObj(p->zVarname, -1));
142   Tcl_ListObjAppendElement(interp, pList, pRes);
143   postToParent(p, pList);
144 
145   ckfree((void *)p);
146   Tcl_DecrRefCount(pList);
147   Tcl_DecrRefCount(pRes);
148   Tcl_DeleteInterp(interp);
149   TCL_THREAD_CREATE_RETURN;
150 }
151 
152 /*
153 ** sqlthread spawn VARNAME SCRIPT
154 **
155 **     Spawn a new thread with its own Tcl interpreter and run the
156 **     specified SCRIPT(s) in it. The thread terminates after running
157 **     the script. The result of the script is stored in the variable
158 **     VARNAME.
159 **
160 **     The caller can wait for the script to terminate using [vwait VARNAME].
161 */
162 static int sqlthread_spawn(
163   ClientData clientData,
164   Tcl_Interp *interp,
165   int objc,
166   Tcl_Obj *CONST objv[]
167 ){
168   Tcl_ThreadId x;
169   SqlThread *pNew;
170   int rc;
171 
172   int nVarname; char *zVarname;
173   int nScript; char *zScript;
174 
175   /* Parameters for thread creation */
176   const int nStack = TCL_THREAD_STACK_DEFAULT;
177   const int flags = TCL_THREAD_NOFLAGS;
178 
179   assert(objc==4);
180   UNUSED_PARAMETER(clientData);
181   UNUSED_PARAMETER(objc);
182 
183   zVarname = Tcl_GetStringFromObj(objv[2], &nVarname);
184   zScript = Tcl_GetStringFromObj(objv[3], &nScript);
185 
186   pNew = (SqlThread *)ckalloc(sizeof(SqlThread)+nVarname+nScript+2);
187   pNew->zVarname = (char *)&pNew[1];
188   pNew->zScript = (char *)&pNew->zVarname[nVarname+1];
189   memcpy(pNew->zVarname, zVarname, nVarname+1);
190   memcpy(pNew->zScript, zScript, nScript+1);
191   pNew->parent = Tcl_GetCurrentThread();
192   pNew->interp = interp;
193 
194   rc = Tcl_CreateThread(&x, tclScriptThread, (void *)pNew, nStack, flags);
195   if( rc!=TCL_OK ){
196     Tcl_AppendResult(interp, "Error in Tcl_CreateThread()", 0);
197     ckfree((char *)pNew);
198     return TCL_ERROR;
199   }
200 
201   return TCL_OK;
202 }
203 
204 /*
205 ** sqlthread parent SCRIPT
206 **
207 **     This can be called by spawned threads only. It sends the specified
208 **     script back to the parent thread for execution. The result of
209 **     evaluating the SCRIPT is returned. The parent thread must enter
210 **     the event loop for this to work - otherwise the caller will
211 **     block indefinitely.
212 **
213 **     NOTE: At the moment, this doesn't work. FIXME.
214 */
215 static int sqlthread_parent(
216   ClientData clientData,
217   Tcl_Interp *interp,
218   int objc,
219   Tcl_Obj *CONST objv[]
220 ){
221   EvalEvent *pEvent;
222   char *zMsg;
223   int nMsg;
224   SqlThread *p = (SqlThread *)clientData;
225 
226   assert(objc==3);
227   UNUSED_PARAMETER(objc);
228 
229   if( p==0 ){
230     Tcl_AppendResult(interp, "no parent thread", 0);
231     return TCL_ERROR;
232   }
233 
234   zMsg = Tcl_GetStringFromObj(objv[2], &nMsg);
235   pEvent = (EvalEvent *)ckalloc(sizeof(EvalEvent)+nMsg+1);
236   pEvent->base.nextPtr = 0;
237   pEvent->base.proc = tclScriptEvent;
238   pEvent->zScript = (char *)&pEvent[1];
239   memcpy(pEvent->zScript, zMsg, nMsg+1);
240   pEvent->interp = p->interp;
241   Tcl_ThreadQueueEvent(p->parent, (Tcl_Event *)pEvent, TCL_QUEUE_TAIL);
242   Tcl_ThreadAlert(p->parent);
243 
244   return TCL_OK;
245 }
246 
247 static int xBusy(void *pArg, int nBusy){
248   UNUSED_PARAMETER(pArg);
249   UNUSED_PARAMETER(nBusy);
250   sqlite3_sleep(50);
251   return 1;             /* Try again... */
252 }
253 
254 /*
255 ** sqlthread open
256 **
257 **     Open a database handle and return the string representation of
258 **     the pointer value.
259 */
260 static int sqlthread_open(
261   ClientData clientData,
262   Tcl_Interp *interp,
263   int objc,
264   Tcl_Obj *CONST objv[]
265 ){
266   int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p);
267 
268   const char *zFilename;
269   sqlite3 *db;
270   int rc;
271   char zBuf[100];
272   extern void Md5_Register(sqlite3*);
273 
274   UNUSED_PARAMETER(clientData);
275   UNUSED_PARAMETER(objc);
276 
277   zFilename = Tcl_GetString(objv[2]);
278   rc = sqlite3_open(zFilename, &db);
279   Md5_Register(db);
280   sqlite3_busy_handler(db, xBusy, 0);
281 
282   if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
283   Tcl_AppendResult(interp, zBuf, 0);
284 
285   return TCL_OK;
286 }
287 
288 
289 /*
290 ** sqlthread open
291 **
292 **     Return the current thread-id (Tcl_GetCurrentThread()) cast to
293 **     an integer.
294 */
295 static int sqlthread_id(
296   ClientData clientData,
297   Tcl_Interp *interp,
298   int objc,
299   Tcl_Obj *CONST objv[]
300 ){
301   Tcl_ThreadId id = Tcl_GetCurrentThread();
302   Tcl_SetObjResult(interp, Tcl_NewIntObj((int)id));
303   UNUSED_PARAMETER(clientData);
304   UNUSED_PARAMETER(objc);
305   UNUSED_PARAMETER(objv);
306   return TCL_OK;
307 }
308 
309 
310 /*
311 ** Dispatch routine for the sub-commands of [sqlthread].
312 */
313 static int sqlthread_proc(
314   ClientData clientData,
315   Tcl_Interp *interp,
316   int objc,
317   Tcl_Obj *CONST objv[]
318 ){
319   struct SubCommand {
320     char *zName;
321     Tcl_ObjCmdProc *xProc;
322     int nArg;
323     char *zUsage;
324   } aSub[] = {
325     {"parent", sqlthread_parent, 1, "SCRIPT"},
326     {"spawn",  sqlthread_spawn,  2, "VARNAME SCRIPT"},
327     {"open",   sqlthread_open,   1, "DBNAME"},
328     {"id",     sqlthread_id,     0, ""},
329     {0, 0, 0}
330   };
331   struct SubCommand *pSub;
332   int rc;
333   int iIndex;
334 
335   if( objc<2 ){
336     Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND");
337     return TCL_ERROR;
338   }
339 
340   rc = Tcl_GetIndexFromObjStruct(
341       interp, objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iIndex
342   );
343   if( rc!=TCL_OK ) return rc;
344   pSub = &aSub[iIndex];
345 
346   if( objc!=(pSub->nArg+2) ){
347     Tcl_WrongNumArgs(interp, 2, objv, pSub->zUsage);
348     return TCL_ERROR;
349   }
350 
351   return pSub->xProc(clientData, interp, objc, objv);
352 }
353 
354 /*
355 ** The [clock_seconds] command. This is more or less the same as the
356 ** regular tcl [clock seconds], except that it is available in testfixture
357 ** when linked against both Tcl 8.4 and 8.5. Because [clock seconds] is
358 ** implemented as a script in Tcl 8.5, it is not usually available to
359 ** testfixture.
360 */
361 static int clock_seconds_proc(
362   ClientData clientData,
363   Tcl_Interp *interp,
364   int objc,
365   Tcl_Obj *CONST objv[]
366 ){
367   Tcl_Time now;
368   Tcl_GetTime(&now);
369   Tcl_SetObjResult(interp, Tcl_NewIntObj(now.sec));
370   UNUSED_PARAMETER(clientData);
371   UNUSED_PARAMETER(objc);
372   UNUSED_PARAMETER(objv);
373   return TCL_OK;
374 }
375 
376 /*************************************************************************
377 ** This block contains the implementation of the [sqlite3_blocking_step]
378 ** command available to threads created by [sqlthread spawn] commands. It
379 ** is only available on UNIX for now. This is because pthread condition
380 ** variables are used.
381 **
382 ** The source code for the C functions sqlite3_blocking_step(),
383 ** blocking_step_notify() and the structure UnlockNotification is
384 ** automatically extracted from this file and used as part of the
385 ** documentation for the sqlite3_unlock_notify() API function. This
386 ** should be considered if these functions are to be extended (i.e. to
387 ** support windows) in the future.
388 */
389 #if defined(OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
390 
391 /* BEGIN_SQLITE_BLOCKING_STEP */
392 /* This example uses the pthreads API */
393 #include <pthread.h>
394 
395 /*
396 ** A pointer to an instance of this structure is passed as the user-context
397 ** pointer when registering for an unlock-notify callback.
398 */
399 typedef struct UnlockNotification UnlockNotification;
400 struct UnlockNotification {
401   int fired;                           /* True after unlock event has occured */
402   pthread_cond_t cond;                 /* Condition variable to wait on */
403   pthread_mutex_t mutex;               /* Mutex to protect structure */
404 };
405 
406 /*
407 ** This function is an unlock-notify callback registered with SQLite.
408 */
409 static void unlock_notify_cb(void **apArg, int nArg){
410   int i;
411   for(i=0; i<nArg; i++){
412     UnlockNotification *p = (UnlockNotification *)apArg[i];
413     pthread_mutex_lock(&p->mutex);
414     p->fired = 1;
415     pthread_cond_signal(&p->cond);
416     pthread_mutex_unlock(&p->mutex);
417   }
418 }
419 
420 /*
421 ** This function assumes that an SQLite API call (either sqlite3_prepare_v2()
422 ** or sqlite3_step()) has just returned SQLITE_LOCKED. The argument is the
423 ** associated database connection.
424 **
425 ** This function calls sqlite3_unlock_notify() to register for an
426 ** unlock-notify callback, then blocks until that callback is delivered
427 ** and returns SQLITE_OK. The caller should then retry the failed operation.
428 **
429 ** Or, if sqlite3_unlock_notify() indicates that to block would deadlock
430 ** the system, then this function returns SQLITE_LOCKED immediately. In
431 ** this case the caller should not retry the operation and should roll
432 ** back the current transaction (if any).
433 */
434 static int wait_for_unlock_notify(sqlite3 *db){
435   int rc;
436   UnlockNotification un;
437 
438   /* Initialize the UnlockNotification structure. */
439   un.fired = 0;
440   pthread_mutex_init(&un.mutex, 0);
441   pthread_cond_init(&un.cond, 0);
442 
443   /* Register for an unlock-notify callback. */
444   rc = sqlite3_unlock_notify(db, unlock_notify_cb, (void *)&un);
445   assert( rc==SQLITE_LOCKED || rc==SQLITE_OK );
446 
447   /* The call to sqlite3_unlock_notify() always returns either SQLITE_LOCKED
448   ** or SQLITE_OK.
449   **
450   ** If SQLITE_LOCKED was returned, then the system is deadlocked. In this
451   ** case this function needs to return SQLITE_LOCKED to the caller so
452   ** that the current transaction can be rolled back. Otherwise, block
453   ** until the unlock-notify callback is invoked, then return SQLITE_OK.
454   */
455   if( rc==SQLITE_OK ){
456     pthread_mutex_lock(&un.mutex);
457     if( !un.fired ){
458       pthread_cond_wait(&un.cond, &un.mutex);
459     }
460     pthread_mutex_unlock(&un.mutex);
461   }
462 
463   /* Destroy the mutex and condition variables. */
464   pthread_cond_destroy(&un.cond);
465   pthread_mutex_destroy(&un.mutex);
466 
467   return rc;
468 }
469 
470 /*
471 ** This function is a wrapper around the SQLite function sqlite3_step().
472 ** It functions in the same way as step(), except that if a required
473 ** shared-cache lock cannot be obtained, this function may block waiting for
474 ** the lock to become available. In this scenario the normal API step()
475 ** function always returns SQLITE_LOCKED.
476 **
477 ** If this function returns SQLITE_LOCKED, the caller should rollback
478 ** the current transaction (if any) and try again later. Otherwise, the
479 ** system may become deadlocked.
480 */
481 int sqlite3_blocking_step(sqlite3_stmt *pStmt){
482   int rc;
483   while( SQLITE_LOCKED==(rc = sqlite3_step(pStmt)) ){
484     rc = wait_for_unlock_notify(sqlite3_db_handle(pStmt));
485     if( rc!=SQLITE_OK ) break;
486     sqlite3_reset(pStmt);
487   }
488   return rc;
489 }
490 
491 /*
492 ** This function is a wrapper around the SQLite function sqlite3_prepare_v2().
493 ** It functions in the same way as prepare_v2(), except that if a required
494 ** shared-cache lock cannot be obtained, this function may block waiting for
495 ** the lock to become available. In this scenario the normal API prepare_v2()
496 ** function always returns SQLITE_LOCKED.
497 **
498 ** If this function returns SQLITE_LOCKED, the caller should rollback
499 ** the current transaction (if any) and try again later. Otherwise, the
500 ** system may become deadlocked.
501 */
502 int sqlite3_blocking_prepare_v2(
503   sqlite3 *db,              /* Database handle. */
504   const char *zSql,         /* UTF-8 encoded SQL statement. */
505   int nSql,                 /* Length of zSql in bytes. */
506   sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
507   const char **pz           /* OUT: End of parsed string */
508 ){
509   int rc;
510   while( SQLITE_LOCKED==(rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, pz)) ){
511     rc = wait_for_unlock_notify(db);
512     if( rc!=SQLITE_OK ) break;
513   }
514   return rc;
515 }
516 /* END_SQLITE_BLOCKING_STEP */
517 
518 /*
519 ** Usage: sqlite3_blocking_step STMT
520 **
521 ** Advance the statement to the next row.
522 */
523 static int blocking_step_proc(
524   void * clientData,
525   Tcl_Interp *interp,
526   int objc,
527   Tcl_Obj *CONST objv[]
528 ){
529 
530   sqlite3_stmt *pStmt;
531   int rc;
532 
533   if( objc!=2 ){
534     Tcl_WrongNumArgs(interp, 1, objv, "STMT");
535     return TCL_ERROR;
536   }
537 
538   pStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
539   rc = sqlite3_blocking_step(pStmt);
540 
541   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), 0);
542   return TCL_OK;
543 }
544 
545 /*
546 ** Usage: sqlite3_blocking_prepare_v2 DB sql bytes ?tailvar?
547 */
548 static int blocking_prepare_v2_proc(
549   void * clientData,
550   Tcl_Interp *interp,
551   int objc,
552   Tcl_Obj *CONST objv[]
553 ){
554   sqlite3 *db;
555   const char *zSql;
556   int bytes;
557   const char *zTail = 0;
558   sqlite3_stmt *pStmt = 0;
559   char zBuf[50];
560   int rc;
561 
562   if( objc!=5 && objc!=4 ){
563     Tcl_AppendResult(interp, "wrong # args: should be \"",
564        Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
565     return TCL_ERROR;
566   }
567   if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
568   zSql = Tcl_GetString(objv[2]);
569   if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
570 
571   rc = sqlite3_blocking_prepare_v2(db, zSql, bytes, &pStmt, objc>=5?&zTail : 0);
572   assert(rc==SQLITE_OK || pStmt==0);
573   if( zTail && objc>=5 ){
574     if( bytes>=0 ){
575       bytes = bytes - (zTail-zSql);
576     }
577     Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
578   }
579   if( rc!=SQLITE_OK ){
580     assert( pStmt==0 );
581     sprintf(zBuf, "%s ", (char *)sqlite3TestErrorName(rc));
582     Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
583     return TCL_ERROR;
584   }
585 
586   if( pStmt ){
587     if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
588     Tcl_AppendResult(interp, zBuf, 0);
589   }
590   return TCL_OK;
591 }
592 
593 #endif
594 /*
595 ** End of implementation of [sqlite3_blocking_step].
596 ************************************************************************/
597 
598 /*
599 ** Register commands with the TCL interpreter.
600 */
601 int SqlitetestThread_Init(Tcl_Interp *interp){
602   Tcl_CreateObjCommand(interp, "sqlthread", sqlthread_proc, 0, 0);
603   Tcl_CreateObjCommand(interp, "clock_seconds", clock_seconds_proc, 0, 0);
604 #if defined(OS_UNIX) && defined(SQLITE_ENABLE_UNLOCK_NOTIFY)
605   Tcl_CreateObjCommand(interp, "sqlite3_blocking_step", blocking_step_proc,0,0);
606   Tcl_CreateObjCommand(
607       interp, "sqlite3_blocking_prepare_v2", blocking_prepare_v2_proc,0,0);
608 #endif
609   return TCL_OK;
610 }
611 #else
612 int SqlitetestThread_Init(Tcl_Interp *interp){
613   return TCL_OK;
614 }
615 #endif
616