wasCSharpSQLite – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System.Diagnostics;
2  
3 namespace Community.CsharpSqlite
4 {
5 #if TCLSH
6 using tcl.lang;
7 using Tcl_Interp = tcl.lang.Interp;
8 using Tcl_Obj = tcl.lang.TclObject;
9 using System.Text;
10  
11  
12 public partial class Sqlite3
13 {
14 /*
15 ** 2008 June 18
16 **
17 ** The author disclaims copyright to this source code. In place of
18 ** a legal notice, here is a blessing:
19 **
20 ** May you do good and not evil.
21 ** May you find forgiveness for yourself and forgive others.
22 ** May you share freely, never taking more than you give.
23 **
24 *************************************************************************
25 ** This file contains test logic for the sqlite3_mutex interfaces.
26 *************************************************************************
27 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
28 ** C#-SQLite is an independent reimplementation of the SQLite software library
29 **
30 ** SQLITE_SOURCE_ID: 2011-01-28 17:03:50 ed759d5a9edb3bba5f48f243df47be29e3fe8cd7
31 **
32 *************************************************************************
33 */
34  
35 //#include "tcl.h"
36 //#include "sqlite3.h"
37 //#include "sqliteInt.h"
38 //#include <stdlib.h>
39 //#include <assert.h>
40 //#include <string.h>
41  
42 /* defined in test1.c */
43 //string sqlite3TestErrorName(int);
44  
45 /* A countable mutex */
46 public partial class sqlite3_mutex
47 {
48 public sqlite3_mutex pReal;
49 public int eType;
50 };
51  
52 static Var.SQLITE3_GETSET disableInit = new Var.SQLITE3_GETSET( "disable_mutex_init" );
53 static Var.SQLITE3_GETSET disableTry = new Var.SQLITE3_GETSET( "disable_mutex_try" );
54  
55 /* State variables */
56 public class test_mutex_globals
57 {
58 public bool isInstalled; /* True if installed */
59 public bool disableInit; /* True to cause sqlite3_initalize() to fail */
60 public bool disableTry; /* True to force sqlite3_mutex_try() to fail */
61 public bool isInit; /* True if initialized */
62 public sqlite3_mutex_methods m = new sqlite3_mutex_methods(); /* Interface to "real" mutex system */
63 public int[] aCounter = new int[8]; /* Number of grabs of each type of mutex */
64 public sqlite3_mutex[] aStatic = new sqlite3_mutex[6]; /* The six static mutexes */
65  
66 public test_mutex_globals()
67 {
68 for ( int i = 0; i < aStatic.Length; i++ )
69 aStatic[i] = new sqlite3_mutex();
70 }
71 }
72  
73 static test_mutex_globals g = new test_mutex_globals();
74  
75 /* Return true if the countable mutex is currently held */
76 static bool counterMutexHeld( sqlite3_mutex p )
77 {
78 return g.m.xMutexHeld( p.pReal );
79 }
80  
81 /* Return true if the countable mutex is not currently held */
82 static bool counterMutexNotheld( sqlite3_mutex p )
83 {
84 return g.m.xMutexNotheld( p.pReal );
85 }
86  
87 /* Initialize the countable mutex interface
88 ** Or, if g.disableInit is non-zero, then do not initialize but instead
89 ** return the value of g.disableInit as the result code. This can be used
90 ** to simulate an initialization failure.
91 */
92 static int counterMutexInit()
93 {
94 int rc;
95 if ( g.disableInit )
96 return g.disableInit ? 1 : 0;
97 rc = g.m.xMutexInit();
98 g.isInit = true;
99 return rc;
100 }
101  
102 /*
103 ** Uninitialize the mutex subsystem
104 */
105 static int counterMutexEnd()
106 {
107 g.isInit = false;
108 return g.m.xMutexEnd();
109 }
110  
111 /*
112 ** Allocate a countable mutex
113 */
114 static sqlite3_mutex counterMutexAlloc( int eType )
115 {
116 sqlite3_mutex pReal;
117 sqlite3_mutex pRet = null;
118  
119 Debug.Assert( g.isInit );
120 Debug.Assert( eType < 8 && eType >= 0 );
121  
122 pReal = g.m.xMutexAlloc( eType );
123 if ( null == pReal )
124 return null;
125  
126 if ( eType == SQLITE_MUTEX_FAST || eType == SQLITE_MUTEX_RECURSIVE )
127 {
128 pRet = new sqlite3_mutex();
129 ;//(sqlite3_mutex)malloc( sizeof( sqlite3_mutex ) );
130 }
131 else
132 {
133 pRet = g.aStatic[eType - 2];
134 }
135  
136 pRet.eType = eType;
137 pRet.pReal = pReal;
138 return pRet;
139 }
140  
141 /*
142 ** Free a countable mutex
143 */
144 static void counterMutexFree( sqlite3_mutex p )
145 {
146 Debug.Assert( g.isInit );
147 g.m.xMutexFree( p.pReal );
148 if ( p.eType == SQLITE_MUTEX_FAST || p.eType == SQLITE_MUTEX_RECURSIVE )
149 {
150 p = null;//free(p);
151 }
152 }
153  
154 /*
155 ** Enter a countable mutex. Block until entry is safe.
156 */
157 static void counterMutexEnter( sqlite3_mutex p )
158 {
159 Debug.Assert( g.isInit );
160 g.aCounter[p.eType]++;
161 g.m.xMutexEnter( p.pReal );
162 }
163  
164 /*
165 ** Try to enter a mutex. Return true on success.
166 */
167 static int counterMutexTry( sqlite3_mutex p )
168 {
169 Debug.Assert( g.isInit );
170 g.aCounter[p.eType]++;
171 if ( g.disableTry )
172 return SQLITE_BUSY;
173 return g.m.xMutexTry( p.pReal );
174 }
175  
176 /* Leave a mutex
177 */
178 static void counterMutexLeave( sqlite3_mutex p )
179 {
180 Debug.Assert( g.isInit );
181 g.m.xMutexLeave( p.pReal );
182 }
183  
184 /*
185 ** sqlite3_shutdown
186 */
187 static int test_shutdown(
188 object clientdata,
189 Tcl_Interp interp,
190 int objc,
191 Tcl_Obj[] objv
192 )
193 {
194 int rc;
195  
196 if ( objc != 1 )
197 {
198 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
199 return TCL.TCL_ERROR;
200 }
201  
202 rc = sqlite3_shutdown();
203 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
204 return TCL.TCL_OK;
205 }
206  
207 /*
208 ** sqlite3_initialize
209 */
210 static int test_initialize(
211 object clientdata,
212 Tcl_Interp interp,
213 int objc,
214 Tcl_Obj[] objv )
215 {
216 int rc;
217  
218 if ( objc != 1 )
219 {
220 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
221 return TCL.TCL_ERROR;
222 }
223  
224 rc = sqlite3_initialize();
225 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
226 return TCL.TCL_OK;
227 }
228  
229 /*
230 ** install_mutex_counters BOOLEAN
231 */
232 static int test_install_mutex_counters(
233 object clientdata,
234 Tcl_Interp interp,
235 int objc,
236 Tcl_Obj[] objv
237 )
238 {
239 int rc = SQLITE_OK;
240 bool isInstall = false;
241  
242 sqlite3_mutex_methods counter_methods = new sqlite3_mutex_methods(
243 (dxMutexInit)counterMutexInit,
244 (dxMutexEnd)counterMutexEnd,
245 (dxMutexAlloc)counterMutexAlloc,
246 (dxMutexFree)counterMutexFree,
247 (dxMutexEnter)counterMutexEnter,
248 (dxMutexTry)counterMutexTry,
249 (dxMutexLeave)counterMutexLeave,
250 (dxMutexHeld)counterMutexHeld,
251 (dxMutexNotheld)counterMutexNotheld
252 );
253  
254 if ( objc != 2 )
255 {
256 TCL.Tcl_WrongNumArgs( interp, 1, objv, "BOOLEAN" );
257 return TCL.TCL_ERROR;
258 }
259 if ( TCL.Tcl_GetBoolean( interp, objv[1], out isInstall ))
260 {
261 return TCL.TCL_ERROR;
262 }
263  
264 Debug.Assert( isInstall == false || isInstall == true );
265 Debug.Assert( g.isInstalled == false || g.isInstalled == true );
266 if ( isInstall == g.isInstalled )
267 {
268 TCL.Tcl_AppendResult( interp, "mutex counters are " );
269 TCL.Tcl_AppendResult( interp, isInstall ? "already installed" : "not installed" );
270 return TCL.TCL_ERROR;
271 }
272  
273 if ( isInstall )
274 {
275 Debug.Assert( g.m.xMutexAlloc == null );
276 rc = sqlite3_config( SQLITE_CONFIG_GETMUTEX, ref g.m );
277 if ( rc == SQLITE_OK )
278 {
279 sqlite3_config( SQLITE_CONFIG_MUTEX, counter_methods );
280 }
281 g.disableTry = false;
282 }
283 else
284 {
285 Debug.Assert( g.m.xMutexAlloc != null );
286 rc = sqlite3_config( SQLITE_CONFIG_MUTEX, g.m );
287 g.m = new sqlite3_mutex_methods();// memset( &g.m, 0, sizeof( sqlite3_mutex_methods ) );
288 }
289  
290 if ( rc == SQLITE_OK )
291 {
292 g.isInstalled = isInstall;
293 }
294  
295 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
296 return TCL.TCL_OK;
297 }
298  
299 /*
300 ** read_mutex_counters
301 */
302 static int test_read_mutex_counters(
303 object clientdata,
304 Tcl_Interp interp,
305 int objc,
306 Tcl_Obj[] objv
307 )
308 {
309 Tcl_Obj pRet;
310 int ii;
311 string[] aName = new string[] {
312 "fast", "recursive", "static_master", "static_mem",
313 "static_open", "static_prng", "static_lru", "static_pmem"
314 };
315  
316 if ( objc != 1 )
317 {
318 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
319 return TCL.TCL_ERROR;
320 }
321  
322 pRet = TCL.Tcl_NewObj();
323 TCL.Tcl_IncrRefCount( pRet );
324 for ( ii = 0; ii < 8; ii++ )
325 {
326 TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewStringObj( aName[ii], -1 ) );
327 TCL.Tcl_ListObjAppendElement( interp, pRet, TCL.Tcl_NewIntObj( g.aCounter[ii] ) );
328 }
329 TCL.Tcl_SetObjResult( interp, pRet );
330 TCL.Tcl_DecrRefCount( ref pRet );
331  
332 return TCL.TCL_OK;
333 }
334  
335 /*
336 ** clear_mutex_counters
337 */
338 static int test_clear_mutex_counters(
339 object clientdata,
340 Tcl_Interp interp,
341 int objc,
342 Tcl_Obj[] objv
343 )
344 {
345 int ii;
346  
347 if ( objc != 1 )
348 {
349 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
350 return TCL.TCL_ERROR;
351 }
352  
353 for ( ii = 0; ii < 8; ii++ )
354 {
355 g.aCounter[ii] = 0;
356 }
357 return TCL.TCL_OK;
358 }
359  
360 /*
361 ** Create and free a mutex. Return the mutex pointer. The pointer
362 ** will be invalid since the mutex has already been freed. The
363 ** return pointer just checks to see if the mutex really was allocated.
364 */
365 static int test_alloc_mutex(
366 object clientdata,
367 Tcl_Interp interp,
368 int objc,
369 Tcl_Obj[] objv )
370 {
371 #if SQLITE_THREADSAFE
372 sqlite3_mutex p = sqlite3_mutex_alloc( SQLITE_MUTEX_FAST );
373 StringBuilder zBuf = new StringBuilder( 100 );
374 sqlite3_mutex_free( p );
375 sqlite3_snprintf( 100, zBuf, "->%p", p );
376 TCL.Tcl_AppendResult( interp, zBuf );
377 #endif
378 return TCL.TCL_OK;
379 }
380  
381 /*
382 ** sqlite3_config OPTION
383 **
384 ** OPTION can be either one of the keywords:
385 **
386 ** SQLITE_CONFIG_SINGLETHREAD
387 ** SQLITE_CONFIG_MULTITHREAD
388 ** SQLITE_CONFIG_SERIALIZED
389 **
390 ** Or OPTION can be an raw integer.
391 */
392 struct ConfigOption
393 {
394 public string zName;
395 public int iValue;
396 public ConfigOption( string zName, int iValue )
397 {
398 this.zName = zName;
399 this.iValue = iValue;
400 }
401 }
402 static bool Tcl_GetIndexFromObjStruct( Interp interp, TclObject to, ConfigOption[] table, int s, string msg, int flags, out int index )
403 {
404 try
405 {
406 for ( index = 0; index < table.Length; index++ )
407 {
408 if ( table[index].zName == msg )
409 return false;
410 }
411 return true;
412 }
413 catch
414 {
415 index = 0;
416 return true;
417 }
418 }
419  
420  
421 static int test_config(
422 object clientdata,
423 Tcl_Interp interp,
424 int objc,
425 Tcl_Obj[] objv
426 )
427 {
428 ConfigOption[] aOpt = new ConfigOption[] {
429 new ConfigOption("singlethread", SQLITE_CONFIG_SINGLETHREAD),
430 new ConfigOption("multithread", SQLITE_CONFIG_MULTITHREAD),
431 new ConfigOption("serialized", SQLITE_CONFIG_SERIALIZED),
432 new ConfigOption(null,0)
433 };
434 int s = aOpt.Length;//sizeof(struct ConfigOption);
435 int i = 0;
436 int rc;
437  
438 if ( objc != 2 )
439 {
440 TCL.Tcl_WrongNumArgs( interp, 1, objv, "" );
441 return TCL.TCL_ERROR;
442 }
443  
444 if ( Tcl_GetIndexFromObjStruct( interp, objv[1], aOpt, s, "flag", 0, out i ) )
445 {
446 if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[1], out i ) )
447 {
448 return TCL.TCL_ERROR;
449 }
450 }
451 else
452 {
453 i = aOpt[i].iValue;
454 }
455  
456 rc = sqlite3_config( i );
457 TCL.Tcl_SetResult( interp, sqlite3TestErrorName( rc ), TCL.TCL_VOLATILE );
458 return TCL.TCL_OK;
459 }
460  
461 //static sqlite3 *getDbPointer(Tcl_Interp *pInterp, TCL.TCL_Obj *pObj){
462 //sqlite3 db;
463 //Tcl_CmdInfo info;
464 //string zCmd = TCL.Tcl_GetString(pObj);
465 //if( TCL.Tcl_GetCommandInfo(pInterp, zCmd, &info) ){
466 // db = *((sqlite3 *)info.objClientData);
467 //}else{
468 // db = (sqlite3)sqlite3TestTextToPtr(zCmd);
469 //}
470 //Debug.Assert( db );
471 //return db;
472  
473 static int test_enter_db_mutex(
474 object clientdata,
475 Tcl_Interp interp,
476 int objc,
477 Tcl_Obj[] objv
478 )
479 {
480 sqlite3 db = null;
481 if ( objc != 2 )
482 {
483 TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB" );
484 return TCL.TCL_ERROR;
485 }
486 getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db );
487 if ( null == db )
488 {
489 return TCL.TCL_ERROR;
490 }
491 sqlite3_mutex_enter( sqlite3_db_mutex( db ) );
492 return TCL.TCL_OK;
493 }
494  
495 static int test_leave_db_mutex(
496 object clientdata,
497 Tcl_Interp interp,
498 int objc,
499 Tcl_Obj[] objv
500 )
501 {
502 sqlite3 db = null;
503 if ( objc != 2 )
504 {
505 TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB" );
506 return TCL.TCL_ERROR;
507 }
508 getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db );
509 if ( null == db )
510 {
511 return TCL.TCL_ERROR;
512 }
513 sqlite3_mutex_leave( sqlite3_db_mutex( db ) );
514 return TCL.TCL_OK;
515 }
516  
517 static public int Sqlitetest_mutex_Init( Tcl_Interp interp )
518 {
519 //static struct {
520 // string zName;
521 // Tcl_ObjCmdProc *xProc;
522 //}
523 _aObjCmd[] aCmd = new _aObjCmd[]{
524 new _aObjCmd( "sqlite3_shutdown", test_shutdown ),
525 new _aObjCmd( "sqlite3_initialize", test_initialize ),
526 new _aObjCmd( "sqlite3_config", test_config ),
527  
528 new _aObjCmd("enter_db_mutex", test_enter_db_mutex ),
529 new _aObjCmd( "leave_db_mutex", test_leave_db_mutex ),
530  
531 new _aObjCmd( "alloc_dealloc_mutex", test_alloc_mutex ),
532 new _aObjCmd( "install_mutex_counters", test_install_mutex_counters ),
533 new _aObjCmd( "read_mutex_counters", test_read_mutex_counters ),
534 new _aObjCmd( "clear_mutex_counters", test_clear_mutex_counters ),
535 };
536 int i;
537 for ( i = 0; i < aCmd.Length; i++ )
538 {//sizeof(aCmd)/sizeof(aCmd[0]); i++){
539 TCL.Tcl_CreateObjCommand( interp, aCmd[i].zName, aCmd[i].xProc, null, null );
540 }
541  
542 TCL.Tcl_LinkVar(interp, "disable_mutex_init",disableInit, VarFlags.SQLITE3_LINK_INT );
543 //g.disableInit, VarFlags.SQLITE3_LINK_INT );
544 TCL.Tcl_LinkVar( interp, "disable_mutex_try",disableTry, VarFlags.SQLITE3_LINK_INT );
545 //g.disableTry, VarFlags.SQLITE3_LINK_INT );
546 return SQLITE_OK;
547 }
548 }
549 #endif
550 }