wasCSharpSQLite – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | using u8 = System.Byte; |
||
6 | using u32 = System.UInt32; |
||
7 | |||
8 | namespace Community.CsharpSqlite |
||
9 | { |
||
10 | #if TCLSH |
||
11 | using tcl.lang; |
||
12 | using sqlite_int64 = System.Int64; |
||
13 | using sqlite3_int64 = System.Int64; |
||
14 | using sqlite3_stmt = Community.CsharpSqlite.Sqlite3.Vdbe; |
||
15 | using Tcl_Interp = tcl.lang.Interp; |
||
16 | using Tcl_Obj = tcl.lang.TclObject; |
||
17 | using ClientData = System.Object; |
||
18 | |||
19 | public partial class Sqlite3 |
||
20 | { |
||
21 | /* |
||
22 | ** 2010 May 05 |
||
23 | ** |
||
24 | ** The author disclaims copyright to this source code. In place of |
||
25 | ** a legal notice, here is a blessing: |
||
26 | ** |
||
27 | ** May you do good and not evil. |
||
28 | ** May you find forgiveness for yourself and forgive others. |
||
29 | ** May you share freely, never taking more than you give. |
||
30 | ** |
||
31 | ****************************************************************************** |
||
32 | ** |
||
33 | ** This file contains the implementation of the Tcl [testvfs] command, |
||
34 | ** used to create SQLite VFS implementations with various properties and |
||
35 | ** instrumentation to support testing SQLite. |
||
36 | ** |
||
37 | ** testvfs VFSNAME ?OPTIONS? |
||
38 | ** |
||
39 | ** Available options are: |
||
40 | ** |
||
41 | ** -noshm BOOLEAN (True to omit shm methods. Default false) |
||
42 | ** -default BOOLEAN (True to make the vfs default. Default false) |
||
43 | ** -szosfile INTEGER (Value for sqlite3_vfs.szOsFile) |
||
44 | ** -mxpathname INTEGER (Value for sqlite3_vfs.mxPathname) |
||
45 | ** -iversion INTEGER (Value for sqlite3_vfs.iVersion) |
||
46 | */ |
||
47 | #if SQLITE_TEST //* This file is used for testing only */ |
||
48 | |||
49 | //#include "sqlite3.h" |
||
50 | //#include "sqliteInt.h" |
||
51 | |||
52 | //typedef struct Testvfs Testvfs; |
||
53 | //typedef struct TestvfsShm TestvfsShm; |
||
54 | //typedef struct TestvfsBuffer TestvfsBuffer; |
||
55 | //typedef struct TestvfsFile TestvfsFile; |
||
56 | //typedef struct TestvfsFd TestvfsFd; |
||
57 | |||
58 | /* |
||
59 | ** An open file handle. |
||
60 | */ |
||
61 | class TestvfsFile : sqlite3_file |
||
62 | { |
||
63 | //public sqlite3_file base; /* Base class. Must be first */ |
||
64 | public TestvfsFd pFd; /* File data */ |
||
65 | }; |
||
66 | //#define tvfsGetFd(pFile) (((TestvfsFile )pFile)->pFd) |
||
67 | static TestvfsFd tvfsGetFd( sqlite3_file pFile ) |
||
68 | { |
||
69 | return ((TestvfsFile)pFile).pFd; |
||
70 | } |
||
71 | |||
72 | class TestvfsFd { |
||
73 | public sqlite3_vfs pVfs; /* The VFS */ |
||
74 | public string zFilename; /* Filename as passed to xOpen() */ |
||
75 | public sqlite3_file pReal; /* The real, underlying file descriptor */ |
||
76 | public Tcl_Obj pShmId; /* Shared memory id for Tcl callbacks */ |
||
77 | |||
78 | public TestvfsBuffer pShm; /* Shared memory buffer */ |
||
79 | public u32 excllock; /* Mask of exclusive locks */ |
||
80 | public u32 sharedlock; /* Mask of shared locks */ |
||
81 | public TestvfsFd pNext; /* Next handle opened on the same file */ |
||
82 | }; |
||
83 | |||
84 | |||
85 | //#define FAULT_INJECT_NONE 0 |
||
86 | //#define FAULT_INJECT_TRANSIENT 1 |
||
87 | //#define FAULT_INJECT_PERSISTENT 2 |
||
88 | const int FAULT_INJECT_NONE = 0; |
||
89 | const int FAULT_INJECT_TRANSIENT = 1; |
||
90 | const int FAULT_INJECT_PERSISTENT = 2; |
||
91 | |||
92 | //typedef struct TestFaultInject TestFaultInject; |
||
93 | class TestFaultInject { |
||
94 | public int iCnt; /* Remaining calls before fault injection */ |
||
95 | public int eFault; /* A FAULT_INJECT_* value */ |
||
96 | public int nFail; /* Number of faults injected */ |
||
97 | }; |
||
98 | |||
99 | /* |
||
100 | ** An instance of this structure is allocated for each VFS created. The |
||
101 | ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite |
||
102 | ** is set to point to it. |
||
103 | */ |
||
104 | class Testvfs { |
||
105 | public string zName; /* Name of this VFS */ |
||
106 | public sqlite3_vfs pParent; /* The VFS to use for file IO */ |
||
107 | public sqlite3_vfs pVfs; /* The testvfs registered with SQLite */ |
||
108 | public Tcl_Interp interp; /* Interpreter to run script in */ |
||
109 | public Tcl_Obj pScript; /* Script to execute */ |
||
110 | public TestvfsBuffer pBuffer; /* List of shared buffers */ |
||
111 | public int isNoshm; |
||
112 | |||
113 | public int mask; /* Mask controlling [script] and [ioerr] */ |
||
114 | |||
115 | public TestFaultInject ioerr_err; |
||
116 | public TestFaultInject full_err; |
||
117 | public TestFaultInject cantopen_err; |
||
118 | |||
119 | #if FALSE |
||
120 | public int iIoerrCnt; |
||
121 | public int ioerr; |
||
122 | public int nIoerrFail; |
||
123 | public int iFullCnt; |
||
124 | public int fullerr; |
||
125 | public int nFullFail; |
||
126 | #endif |
||
127 | |||
128 | public int iDevchar; |
||
129 | public int iSectorsize; |
||
130 | }; |
||
131 | |||
132 | /* |
||
133 | ** The Testvfs.mask variable is set to a combination of the following. |
||
134 | ** If a bit is clear in Testvfs.mask, then calls made by SQLite to the |
||
135 | ** corresponding VFS method is ignored for purposes of: |
||
136 | ** |
||
137 | ** + Simulating IO errors, and |
||
138 | ** + Invoking the Tcl callback script. |
||
139 | */ |
||
140 | //#define TESTVFS_SHMOPEN_MASK 0x00000001 |
||
141 | //#define TESTVFS_SHMLOCK_MASK 0x00000010 |
||
142 | //#define TESTVFS_SHMMAP_MASK 0x00000020 |
||
143 | //#define TESTVFS_SHMBARRIER_MASK 0x00000040 |
||
144 | //#define TESTVFS_SHMCLOSE_MASK 0x00000080 |
||
145 | const int TESTVFS_SHMOPEN_MASK =0x00000001; |
||
146 | const int TESTVFS_SHMLOCK_MASK =0x00000010; |
||
147 | const int TESTVFS_SHMMAP_MASK =0x00000020; |
||
148 | const int TESTVFS_SHMBARRIER_MASK =0x00000040; |
||
149 | const int TESTVFS_SHMCLOSE_MASK =0x00000080; |
||
150 | |||
151 | //#define TESTVFS_OPEN_MASK 0x00000100 |
||
152 | //#define TESTVFS_SYNC_MASK 0x00000200 |
||
153 | //#define TESTVFS_DELETE_MASK 0x00000400 |
||
154 | //#define TESTVFS_CLOSE_MASK 0x00000800 |
||
155 | //#define TESTVFS_WRITE_MASK 0x00001000 |
||
156 | //#define TESTVFS_TRUNCATE_MASK 0x00002000 |
||
157 | //#define TESTVFS_ACCESS_MASK 0x00004000 |
||
158 | //#define TESTVFS_FULLPATHNAME_MASK 0x00008000 |
||
159 | //#define TESTVFS_ALL_MASK 0x0001FFFF |
||
160 | const int TESTVFS_OPEN_MASK =0x00000100; |
||
161 | const int TESTVFS_SYNC_MASK =0x00000200; |
||
162 | const int TESTVFS_DELETE_MASK =0x00000400; |
||
163 | const int TESTVFS_CLOSE_MASK =0x00000800; |
||
164 | const int TESTVFS_WRITE_MASK =0x00001000; |
||
165 | const int TESTVFS_TRUNCATE_MASK =0x00002000; |
||
166 | const int TESTVFS_ACCESS_MASK =0x00004000; |
||
167 | const int TESTVFS_FULLPATHNAME_MASK =0x00008000; |
||
168 | const int TESTVFS_ALL_MASK =0x0001FFFF; |
||
169 | |||
170 | //#define TESTVFS_MAX_PAGES 1024 |
||
171 | const int TESTVFS_MAX_PAGES =1024; |
||
172 | |||
173 | /* |
||
174 | ** A shared-memory buffer. There is one of these objects for each shared |
||
175 | ** memory region opened by clients. If two clients open the same file, |
||
176 | ** there are two TestvfsFile structures but only one TestvfsBuffer structure. |
||
177 | */ |
||
178 | class TestvfsBuffer { |
||
179 | public string zFile; /* Associated file name */ |
||
180 | public int pgsz; /* Page size */ |
||
181 | public u8[] aPage = new u8[TESTVFS_MAX_PAGES]; /* Array of ckalloc'd pages */ |
||
182 | public TestvfsFd pFile; /* List of open handles */ |
||
183 | public TestvfsBuffer pNext; /* Next in linked list of all buffers */ |
||
184 | }; |
||
185 | |||
186 | |||
187 | //#define PARENTVFS(x) (((Testvfs )((x)->pAppData))->pParent) |
||
188 | static sqlite3_vfs PARENTVFS( sqlite3_vfs x ) |
||
189 | { |
||
190 | return ( (Testvfs)x.pAppData ).pParent; |
||
191 | } |
||
192 | |||
193 | //#define TESTVFS_MAX_ARGS 12 |
||
194 | const int TESTVFS_MAX_ARGS =12; |
||
195 | |||
196 | |||
197 | /* |
||
198 | ** Method declarations for TestvfsFile. |
||
199 | */ |
||
200 | //static int tvfsClose(sqlite3_file); |
||
201 | //static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); |
||
202 | //static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); |
||
203 | //static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size); |
||
204 | //static int tvfsSync(sqlite3_file*, int flags); |
||
205 | //static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize); |
||
206 | //static int tvfsLock(sqlite3_file*, int); |
||
207 | //static int tvfsUnlock(sqlite3_file*, int); |
||
208 | //static int tvfsCheckReservedLock(sqlite3_file*, int ); |
||
209 | //static int tvfsFileControl(sqlite3_file*, int op, object *pArg); |
||
210 | //static int tvfsSectorSize(sqlite3_file); |
||
211 | //static int tvfsDeviceCharacteristics(sqlite3_file); |
||
212 | |||
213 | ///* |
||
214 | //** Method declarations for tvfs_vfs. |
||
215 | //*/ |
||
216 | //static int tvfsOpen(sqlite3_vfs*, string , sqlite3_file*, int , int ); |
||
217 | //static int tvfsDelete(sqlite3_vfs*, string zName, int syncDir); |
||
218 | //static int tvfsAccess(sqlite3_vfs*, string zName, int flags, int ); |
||
219 | //static int tvfsFullPathname(sqlite3_vfs*, string zName, int, string zOut); |
||
220 | //#if !SQLITE_OMIT_LOAD_EXTENSION |
||
221 | //static void tvfsDlOpen(sqlite3_vfs*, string zFilename); |
||
222 | //static void tvfsDlError(sqlite3_vfs*, int nByte, string zErrMsg); |
||
223 | //static void (*tvfsDlSym(sqlite3_vfs*,void*, string zSymbol))(void); |
||
224 | //static void tvfsDlClose(sqlite3_vfs*, void); |
||
225 | //#endif //* SQLITE_OMIT_LOAD_EXTENSION */ |
||
226 | //static int tvfsRandomness(sqlite3_vfs*, int nByte, string zOut); |
||
227 | //static int tvfsSleep(sqlite3_vfs*, int microseconds); |
||
228 | //static int tvfsCurrentTime(sqlite3_vfs*, double); |
||
229 | |||
230 | //static int tvfsShmOpen(sqlite3_file); |
||
231 | //static int tvfsShmLock(sqlite3_file*, int , int, int); |
||
232 | //static int tvfsShmMap(sqlite3_file*,int,int,int, object volatile *); |
||
233 | //static void tvfsShmBarrier(sqlite3_file); |
||
234 | //static int tvfsShmUnmap(sqlite3_file*, int); |
||
235 | |||
236 | static sqlite3_io_methods tvfs_io_methods = new sqlite3_io_methods( |
||
237 | 2, /* iVersion */ |
||
238 | tvfsClose, /* xClose */ |
||
239 | tvfsRead, /* xRead */ |
||
240 | tvfsWrite, /* xWrite */ |
||
241 | tvfsTruncate, /* xTruncate */ |
||
242 | tvfsSync, /* xSync */ |
||
243 | tvfsFileSize, /* xFileSize */ |
||
244 | tvfsLock, /* xLock */ |
||
245 | tvfsUnlock, /* xUnlock */ |
||
246 | tvfsCheckReservedLock, /* xCheckReservedLock */ |
||
247 | tvfsFileControl, /* xFileControl */ |
||
248 | tvfsSectorSize, /* xSectorSize */ |
||
249 | tvfsDeviceCharacteristics, /* xDeviceCharacteristics */ |
||
250 | tvfsShmMap, /* xShmMap */ |
||
251 | tvfsShmLock, /* xShmLock */ |
||
252 | tvfsShmBarrier, /* xShmBarrier */ |
||
253 | tvfsShmUnmap /* xShmUnmap */ |
||
254 | ); |
||
255 | |||
256 | class errcode { |
||
257 | public int eCode; |
||
258 | public string zCode; |
||
259 | |||
260 | public errcode(int eCode, string zCode){ |
||
261 | this.eCode=eCode;this.zCode=zCode; |
||
262 | } |
||
263 | } |
||
264 | static int tvfsResultCode(Testvfs p, ref int pRc){ |
||
265 | errcode[] aCode = new errcode[] { |
||
266 | new errcode( SQLITE_OK, "SQLITE_OK" ), |
||
267 | new errcode( SQLITE_ERROR, "SQLITE_ERROR" ), |
||
268 | new errcode( SQLITE_IOERR, "SQLITE_IOERR" ), |
||
269 | new errcode( SQLITE_LOCKED, "SQLITE_LOCKED" ), |
||
270 | new errcode( SQLITE_BUSY, "SQLITE_BUSY" ) |
||
271 | }; |
||
272 | |||
273 | string z; |
||
274 | int i; |
||
275 | |||
276 | z = TCL.Tcl_GetStringResult(p.interp); |
||
277 | for(i=0; i<ArraySize(aCode); i++){ |
||
278 | if ( 0 == z.CompareTo( aCode[i].zCode ) ) |
||
279 | { |
||
280 | pRc = aCode[i].eCode; |
||
281 | return 1; |
||
282 | } |
||
283 | } |
||
284 | |||
285 | return 0; |
||
286 | } |
||
287 | |||
288 | static int tvfsInjectFault(TestFaultInject p){ |
||
289 | int ret = 0; |
||
290 | if ( p.eFault != 0 ) |
||
291 | { |
||
292 | p.iCnt--; |
||
293 | if( p.iCnt==0 || (p.iCnt<0 && p.eFault==FAULT_INJECT_PERSISTENT ) ){ |
||
294 | ret = 1; |
||
295 | p.nFail++; |
||
296 | } |
||
297 | } |
||
298 | return ret; |
||
299 | } |
||
300 | |||
301 | |||
302 | static int tvfsInjectIoerr(Testvfs p){ |
||
303 | return tvfsInjectFault(p.ioerr_err); |
||
304 | } |
||
305 | |||
306 | static int tvfsInjectFullerr(Testvfs p){ |
||
307 | return tvfsInjectFault(p.full_err); |
||
308 | } |
||
309 | static int tvfsInjectCantopenerr(Testvfs p){ |
||
310 | return tvfsInjectFault(p.cantopen_err); |
||
311 | } |
||
312 | |||
313 | |||
314 | static void tvfsExecTcl( |
||
315 | Testvfs p, |
||
316 | string zMethod, |
||
317 | Tcl_Obj arg1, |
||
318 | Tcl_Obj arg2, |
||
319 | Tcl_Obj arg3 |
||
320 | ){ |
||
321 | int rc; /* Return code from Tcl_EvalObj() */ |
||
322 | Tcl_Obj pEval; |
||
323 | Debug.Assert( p.pScript!=null ); |
||
324 | |||
325 | Debug.Assert( zMethod != null ); |
||
326 | Debug.Assert( p != null ); |
||
327 | Debug.Assert( arg2 == null || arg1 != null ); |
||
328 | Debug.Assert( arg3 == null || arg2 != null ); |
||
329 | |||
330 | pEval = TCL.Tcl_DuplicateObj(p.pScript); |
||
331 | TCL.Tcl_IncrRefCount(p.pScript); |
||
332 | TCL.Tcl_ListObjAppendElement( p.interp, pEval, TCL.Tcl_NewStringObj( zMethod, -1 ) ); |
||
333 | if ( arg1!=null ) |
||
334 | TCL.Tcl_ListObjAppendElement( p.interp, pEval, arg1 ); |
||
335 | if ( arg2 !=null ) |
||
336 | TCL.Tcl_ListObjAppendElement( p.interp, pEval, arg2 ); |
||
337 | if ( arg3 != null ) |
||
338 | TCL.Tcl_ListObjAppendElement( p.interp, pEval, arg3 ); |
||
339 | |||
340 | rc = TCL.Tcl_EvalObjEx(p.interp, pEval, TCL.TCL_EVAL_GLOBAL); |
||
341 | if ( rc != TCL.TCL_OK ) |
||
342 | { |
||
343 | TCL.Tcl_BackgroundError( p.interp ); |
||
344 | TCL.Tcl_ResetResult( p.interp ); |
||
345 | } |
||
346 | } |
||
347 | |||
348 | |||
349 | /* |
||
350 | ** Close an tvfs-file. |
||
351 | */ |
||
352 | static int tvfsClose(sqlite3_file pFile){ |
||
353 | int rc=0; |
||
354 | TestvfsFile pTestfile = (TestvfsFile )pFile; |
||
355 | TestvfsFd pFd = pTestfile.pFd; |
||
356 | Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
357 | |||
358 | Debugger.Break(); //TODO |
||
359 | //if( p.pScript != null && (p.mask&TESTVFS_CLOSE_MASK)!=0 ){ |
||
360 | // tvfsExecTcl(p, "xClose", |
||
361 | // Tcl_NewStringObj(pFd.zFilename, -1), pFd.pShmId, 0 |
||
362 | // ); |
||
363 | //} |
||
364 | |||
365 | //if( pFd.pShmId != null){ |
||
366 | // Tcl_DecrRefCount(pFd.pShmId); |
||
367 | // pFd.pShmId = null; |
||
368 | //} |
||
369 | //if ( pFile.pMethods != null ) |
||
370 | //{ |
||
371 | // ckfree((char )pFile.pMethods); |
||
372 | //} |
||
373 | //rc = sqlite3OsClose(pFd.pReal); |
||
374 | //ckfree((char )pFd); |
||
375 | //pTestfile.pFd = null; |
||
376 | return rc; |
||
377 | } |
||
378 | |||
379 | /* |
||
380 | ** Read data from an tvfs-file. |
||
381 | */ |
||
382 | static int tvfsRead( |
||
383 | sqlite3_file pFile, |
||
384 | byte[] zBuf, |
||
385 | int iAmt, |
||
386 | sqlite_int64 iOfst |
||
387 | ){ |
||
388 | TestvfsFd p = tvfsGetFd(pFile); |
||
389 | return sqlite3OsRead(p.pReal, zBuf, iAmt, iOfst); |
||
390 | } |
||
391 | |||
392 | /* |
||
393 | ** Write data to an tvfs-file. |
||
394 | */ |
||
395 | static int tvfsWrite( |
||
396 | sqlite3_file pFile, |
||
397 | byte[] zBuf, |
||
398 | int iAmt, |
||
399 | sqlite_int64 iOfst |
||
400 | ){ |
||
401 | int rc = SQLITE_OK; |
||
402 | Debugger.Break();//TODO |
||
403 | //TestvfsFd pFd = tvfsGetFd(pFile); |
||
404 | //Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
405 | |||
406 | //if ( p.pScript != null && (p.mask & TESTVFS_WRITE_MASK) != 0 ) |
||
407 | //{ |
||
408 | // tvfsExecTcl(p, "xWrite", |
||
409 | // TCL.Tcl_NewStringObj(pFd.zFilename, -1), pFd.pShmId, null |
||
410 | // ); |
||
411 | // tvfsResultCode(p, ref rc); |
||
412 | //} |
||
413 | |||
414 | //if( rc==SQLITE_OK && tvfsInjectFullerr(p)!=0 ){ |
||
415 | // rc = SQLITE_FULL; |
||
416 | //} |
||
417 | //if ( rc == SQLITE_OK && (p.mask & TESTVFS_WRITE_MASK) != 0 && tvfsInjectIoerr( p ) != 0 ) |
||
418 | //{ |
||
419 | // rc = SQLITE_IOERR; |
||
420 | //} |
||
421 | |||
422 | //if( rc==SQLITE_OK ){ |
||
423 | // rc = sqlite3OsWrite(pFd.pReal, zBuf, iAmt, iOfst); |
||
424 | //} |
||
425 | return rc; |
||
426 | } |
||
427 | |||
428 | /* |
||
429 | ** Truncate an tvfs-file. |
||
430 | */ |
||
431 | static int tvfsTruncate(sqlite3_file pFile, sqlite_int64 size){ |
||
432 | int rc = SQLITE_OK; |
||
433 | TestvfsFd pFd = tvfsGetFd(pFile); |
||
434 | Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
435 | |||
436 | if ( p.pScript != null && ( p.mask & TESTVFS_TRUNCATE_MASK ) != 0 ) |
||
437 | { |
||
438 | tvfsExecTcl(p, "xTruncate", |
||
439 | TCL.Tcl_NewStringObj(pFd.zFilename, -1), pFd.pShmId,null |
||
440 | ); |
||
441 | tvfsResultCode(p, ref rc); |
||
442 | } |
||
443 | |||
444 | if( rc==SQLITE_OK ){ |
||
445 | rc = sqlite3OsTruncate(pFd.pReal, size); |
||
446 | } |
||
447 | return rc; |
||
448 | } |
||
449 | |||
450 | /* |
||
451 | ** Sync an tvfs-file. |
||
452 | */ |
||
453 | static int tvfsSync(sqlite3_file pFile, int flags){ |
||
454 | int rc = SQLITE_OK; |
||
455 | TestvfsFd pFd = tvfsGetFd(pFile); |
||
456 | Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
457 | |||
458 | if ( p.pScript != null && ( p.mask & TESTVFS_SYNC_MASK ) != 0 ) |
||
459 | { |
||
460 | string zFlags = ""; |
||
461 | |||
462 | switch( flags ){ |
||
463 | case SQLITE_SYNC_NORMAL: |
||
464 | zFlags = "normal"; |
||
465 | break; |
||
466 | case SQLITE_SYNC_FULL: |
||
467 | zFlags = "full"; |
||
468 | break; |
||
469 | case SQLITE_SYNC_NORMAL|SQLITE_SYNC_DATAONLY: |
||
470 | zFlags = "normal|dataonly"; |
||
471 | break; |
||
472 | case SQLITE_SYNC_FULL|SQLITE_SYNC_DATAONLY: |
||
473 | zFlags = "full|dataonly"; |
||
474 | break; |
||
475 | default: |
||
476 | Debug.Assert(false); |
||
477 | break; |
||
478 | } |
||
479 | |||
480 | tvfsExecTcl(p, "xSync", |
||
481 | TCL.Tcl_NewStringObj(pFd.zFilename, -1), pFd.pShmId, |
||
482 | TCL.Tcl_NewStringObj( zFlags, -1 ) |
||
483 | ); |
||
484 | tvfsResultCode(p, ref rc); |
||
485 | } |
||
486 | |||
487 | if( rc==SQLITE_OK && tvfsInjectFullerr(p)!=0 ) rc = SQLITE_FULL; |
||
488 | |||
489 | if( rc==SQLITE_OK ){ |
||
490 | rc = sqlite3OsSync(pFd.pReal, flags); |
||
491 | } |
||
492 | |||
493 | return rc; |
||
494 | } |
||
495 | |||
496 | /* |
||
497 | ** Return the current file-size of an tvfs-file. |
||
498 | */ |
||
499 | static int tvfsFileSize(sqlite3_file pFile, ref sqlite_int64 pSize){ |
||
500 | TestvfsFd p = tvfsGetFd(pFile); |
||
501 | return sqlite3OsFileSize(p.pReal, ref pSize); |
||
502 | } |
||
503 | |||
504 | /* |
||
505 | ** Lock an tvfs-file. |
||
506 | */ |
||
507 | static int tvfsLock(sqlite3_file pFile, int eLock){ |
||
508 | TestvfsFd p = tvfsGetFd(pFile); |
||
509 | return sqlite3OsLock(p.pReal, eLock); |
||
510 | } |
||
511 | |||
512 | /* |
||
513 | ** Unlock an tvfs-file. |
||
514 | */ |
||
515 | static int tvfsUnlock(sqlite3_file pFile, int eLock){ |
||
516 | TestvfsFd p = tvfsGetFd(pFile); |
||
517 | return sqlite3OsUnlock(p.pReal, eLock); |
||
518 | } |
||
519 | |||
520 | /* |
||
521 | ** Check if another file-handle holds a RESERVED lock on an tvfs-file. |
||
522 | */ |
||
523 | static int tvfsCheckReservedLock( sqlite3_file pFile, ref int pResOut ) |
||
524 | { |
||
525 | TestvfsFd p = tvfsGetFd(pFile); |
||
526 | return sqlite3OsCheckReservedLock( p.pReal, ref pResOut ); |
||
527 | } |
||
528 | |||
529 | /* |
||
530 | ** File control method. For custom operations on an tvfs-file. |
||
531 | */ |
||
532 | static int tvfsFileControl( sqlite3_file pFile, int op, ref sqlite3_int64 pArg ) |
||
533 | { |
||
534 | TestvfsFd p = tvfsGetFd(pFile); |
||
535 | return sqlite3OsFileControl( p.pReal, (u32)op, ref pArg ); |
||
536 | } |
||
537 | |||
538 | /* |
||
539 | ** Return the sector-size in bytes for an tvfs-file. |
||
540 | */ |
||
541 | static int tvfsSectorSize(sqlite3_file pFile){ |
||
542 | TestvfsFd pFd = tvfsGetFd(pFile); |
||
543 | Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
544 | if( p.iSectorsize>=0 ){ |
||
545 | return p.iSectorsize; |
||
546 | } |
||
547 | return sqlite3OsSectorSize(pFd.pReal); |
||
548 | } |
||
549 | |||
550 | /* |
||
551 | ** Return the device characteristic flags supported by an tvfs-file. |
||
552 | */ |
||
553 | static int tvfsDeviceCharacteristics(sqlite3_file pFile){ |
||
554 | TestvfsFd pFd = tvfsGetFd(pFile); |
||
555 | Testvfs p = (Testvfs )pFd.pVfs.pAppData; |
||
556 | if( p.iDevchar>=0 ){ |
||
557 | return p.iDevchar; |
||
558 | } |
||
559 | return sqlite3OsDeviceCharacteristics(pFd.pReal); |
||
560 | } |
||
561 | |||
562 | /* |
||
563 | ** Open an tvfs file handle. |
||
564 | */ |
||
565 | static int tvfsOpen( |
||
566 | sqlite3_vfs pVfs, |
||
567 | string zName, |
||
568 | sqlite3_file pFile, |
||
569 | int flags, |
||
570 | ref int pOutFlags |
||
571 | ){ |
||
572 | int rc=0; |
||
573 | Debugger.Break();//TODO |
||
574 | //TestvfsFile pTestfile = (TestvfsFile)pFile; |
||
575 | //TestvfsFd pFd; |
||
576 | //Tcl_Obj pId = null; |
||
577 | //Testvfs p = (Testvfs )pVfs.pAppData; |
||
578 | |||
579 | //pFd = (TestvfsFd )ckalloc(sizeof(TestvfsFd) + PARENTVFS(pVfs).szOsFile); |
||
580 | //pFd = new TestvfsFd();// memset( pFd, 0, sizeof( TestvfsFd ) + PARENTVFS( pVfs ).szOsFile ); |
||
581 | //pFd.pShm = null; |
||
582 | //pFd.pShmId = null; |
||
583 | //pFd.zFilename = zName; |
||
584 | //pFd.pVfs = pVfs; |
||
585 | //pFd.pReal = (sqlite3_file )pFd[1]; |
||
586 | //pTestfile = new TestvfsFile();// memset( pTestfile, 0, sizeof( TestvfsFile ) ); |
||
587 | //pTestfile.pFd = pFd; |
||
588 | |||
589 | ///* Evaluate the Tcl script: |
||
590 | //** |
||
591 | //** SCRIPT xOpen FILENAME KEY-VALUE-ARGS |
||
592 | //** |
||
593 | //** If the script returns an SQLite error code other than SQLITE_OK, an |
||
594 | //** error is returned to the caller. If it returns SQLITE_OK, the new |
||
595 | //** connection is named "anon". Otherwise, the value returned by the |
||
596 | //** script is used as the connection name. |
||
597 | //*/ |
||
598 | //TCL.Tcl_ResetResult(p.interp); |
||
599 | //if ( p.pScript != null && ( p.mask & TESTVFS_OPEN_MASK ) != 0 ) |
||
600 | //{ |
||
601 | // Tcl_Obj pArg = TCL.Tcl_NewObj(); |
||
602 | // TCL.Tcl_IncrRefCount( pArg ); |
||
603 | // if( (flags&SQLITE_OPEN_MAIN_DB )!=0){ |
||
604 | // string z = zName[strlen(zName)+1]; |
||
605 | // while( *z ){ |
||
606 | // TCL.Tcl_ListObjAppendElement( 0, pArg, TCL.Tcl_NewStringObj( z, -1 ) ); |
||
607 | // z += strlen(z) + 1; |
||
608 | // TCL.Tcl_ListObjAppendElement( 0, pArg, TCL.Tcl_NewStringObj( z, -1 ) ); |
||
609 | // z += strlen(z) + 1; |
||
610 | // } |
||
611 | // } |
||
612 | // tvfsExecTcl(p, "xOpen", TCL.Tcl_NewStringObj(pFd.zFilename, -1), pArg, null); |
||
613 | // TCL.Tcl_DecrRefCount( pArg ); |
||
614 | // if( tvfsResultCode(p, ref rc)!=0 ){ |
||
615 | // if( rc!=SQLITE_OK ) return rc; |
||
616 | // }else{ |
||
617 | // pId = TCL.Tcl_GetObjResult(p.interp); |
||
618 | // } |
||
619 | //} |
||
620 | |||
621 | //if( (p.mask&TESTVFS_OPEN_MASK)!=0 && tvfsInjectIoerr(p) !=0) return SQLITE_IOERR; |
||
622 | //if( tvfsInjectCantopenerr(p)!=0 ) return SQLITE_CANTOPEN; |
||
623 | //if( tvfsInjectFullerr(p)!=0 ) return SQLITE_FULL; |
||
624 | |||
625 | //if( null==pId ){ |
||
626 | // pId = TCL.Tcl_NewStringObj("anon", -1); |
||
627 | //} |
||
628 | //TCL.Tcl_IncrRefCount( pId ); |
||
629 | //pFd.pShmId = pId; |
||
630 | //TCL.Tcl_ResetResult( p.interp ); |
||
631 | |||
632 | //rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, pFd.pReal, flags, pOutFlags); |
||
633 | //if ( pFd.pReal.pMethods != null ) |
||
634 | //{ |
||
635 | // sqlite3_io_methods pMethods; |
||
636 | // int nByte; |
||
637 | |||
638 | //if( pVfs.iVersion>1 ){ |
||
639 | // nByte = sizeof(sqlite3_io_methods); |
||
640 | //}else{ |
||
641 | // nByte = offsetof(sqlite3_io_methods, xShmMap); |
||
642 | //} |
||
643 | |||
644 | //pMethods = (sqlite3_io_methods)ckalloc( nByte ); |
||
645 | //memcpy(pMethods, &tvfs_io_methods, nByte); |
||
646 | //pMethods.iVersion = pVfs.iVersion; |
||
647 | //if( pVfs.iVersion>1 && ((Testvfs )pVfs.pAppData).isNoshm ){ |
||
648 | // pMethods.xShmUnmap = 0; |
||
649 | // pMethods.xShmLock = 0; |
||
650 | // pMethods.xShmBarrier = 0; |
||
651 | // pMethods.xShmMap = 0; |
||
652 | //} |
||
653 | // pFile.pMethods = pMethods; |
||
654 | //} |
||
655 | |||
656 | return rc; |
||
657 | } |
||
658 | |||
659 | /* |
||
660 | ** Delete the file located at zPath. If the dirSync argument is true, |
||
661 | ** ensure the file-system modifications are synced to disk before |
||
662 | ** returning. |
||
663 | */ |
||
664 | static int tvfsDelete(sqlite3_vfs pVfs, string zPath, int dirSync){ |
||
665 | int rc = SQLITE_OK; |
||
666 | Testvfs p = (Testvfs )pVfs.pAppData; |
||
667 | |||
668 | if( p.pScript !=null && (p.mask&TESTVFS_DELETE_MASK)!=0 ){ |
||
669 | tvfsExecTcl(p, "xDelete", |
||
670 | TCL.Tcl_NewStringObj( zPath, -1 ), TCL.Tcl_NewIntObj( dirSync ), null |
||
671 | ); |
||
672 | tvfsResultCode(p, ref rc); |
||
673 | } |
||
674 | if( rc==SQLITE_OK ){ |
||
675 | rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); |
||
676 | } |
||
677 | return rc; |
||
678 | } |
||
679 | |||
680 | /* |
||
681 | ** Test for access permissions. Return true if the requested permission |
||
682 | ** is available, or false otherwise. |
||
683 | */ |
||
684 | static int tvfsAccess( |
||
685 | sqlite3_vfs pVfs, |
||
686 | string zPath, |
||
687 | int flags, |
||
688 | ref int pResOut |
||
689 | ){ |
||
690 | Testvfs p = (Testvfs )pVfs.pAppData; |
||
691 | if ( p.pScript != null && ( p.mask & TESTVFS_ACCESS_MASK ) != 0 ) |
||
692 | { |
||
693 | int rc=0; |
||
694 | string zArg = ""; |
||
695 | if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; |
||
696 | if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; |
||
697 | if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; |
||
698 | tvfsExecTcl(p, "xAccess", |
||
699 | TCL.Tcl_NewStringObj( zPath, -1 ), TCL.Tcl_NewStringObj( zArg, -1 ), null |
||
700 | ); |
||
701 | if( tvfsResultCode(p, ref rc) !=0){ |
||
702 | if( rc!=SQLITE_OK ) return rc; |
||
703 | }else{ |
||
704 | Tcl_Interp interp = p.interp; |
||
705 | bool bTemp = false; |
||
706 | if ( !TCL.Tcl_GetBooleanFromObj( null, TCL.Tcl_GetObjResult( interp ), out bTemp ) ) |
||
707 | { |
||
708 | pResOut = bTemp ? 1 : 0; |
||
709 | return SQLITE_OK; |
||
710 | } |
||
711 | } |
||
712 | } |
||
713 | return sqlite3OsAccess( PARENTVFS( pVfs ), zPath, flags, ref pResOut ); |
||
714 | } |
||
715 | |||
716 | /* |
||
717 | ** Populate buffer zOut with the full canonical pathname corresponding |
||
718 | ** to the pathname in zPath. zOut is guaranteed to point to a buffer |
||
719 | ** of at least (DEVSYM_MAX_PATHNAME+1) bytes. |
||
720 | */ |
||
721 | static int tvfsFullPathname( |
||
722 | sqlite3_vfs pVfs, |
||
723 | string zPath, |
||
724 | int nOut, |
||
725 | StringBuilder zOut |
||
726 | ){ |
||
727 | Testvfs p = (Testvfs )pVfs.pAppData; |
||
728 | if ( p.pScript != null && ( p.mask & TESTVFS_FULLPATHNAME_MASK ) != 0 ) |
||
729 | { |
||
730 | int rc=0; |
||
731 | tvfsExecTcl(p, "xFullPathname", TCL.Tcl_NewStringObj(zPath, -1),null,null); |
||
732 | if( tvfsResultCode(p, ref rc) !=0){ |
||
733 | if( rc!=SQLITE_OK ) return rc; |
||
734 | } |
||
735 | } |
||
736 | return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); |
||
737 | } |
||
738 | |||
739 | #if !SQLITE_OMIT_LOAD_EXTENSION |
||
740 | /* |
||
741 | ** Open the dynamic library located at zPath and return a handle. |
||
742 | */ |
||
743 | static IntPtr tvfsDlOpen(sqlite3_vfs pVfs, string zPath){ |
||
744 | return sqlite3OsDlOpen(PARENTVFS(pVfs), zPath); |
||
745 | } |
||
746 | |||
747 | /* |
||
748 | ** Populate the buffer zErrMsg (size nByte bytes) with a human readable |
||
749 | ** utf-8 string describing the most recent error encountered associated |
||
750 | ** with dynamic libraries. |
||
751 | */ |
||
752 | static void tvfsDlError(sqlite3_vfs pVfs, int nByte, string zErrMsg){ |
||
753 | sqlite3OsDlError(PARENTVFS(pVfs), nByte, zErrMsg); |
||
754 | } |
||
755 | |||
756 | /* |
||
757 | ** Return a pointer to the symbol zSymbol in the dynamic library pHandle. |
||
758 | */ |
||
759 | static void tvfsDlSym(sqlite3_vfs pVfs, IntPtr p, string zSym){ |
||
760 | sqlite3OsDlSym(PARENTVFS(pVfs), p, ref zSym); |
||
761 | } |
||
762 | |||
763 | /* |
||
764 | ** Close the dynamic library handle pHandle. |
||
765 | */ |
||
766 | static void tvfsDlClose( sqlite3_vfs pVfs, IntPtr pHandle ) |
||
767 | { |
||
768 | sqlite3OsDlClose(PARENTVFS(pVfs), pHandle); |
||
769 | } |
||
770 | #endif //* SQLITE_OMIT_LOAD_EXTENSION */ |
||
771 | |||
772 | /* |
||
773 | ** Populate the buffer pointed to by zBufOut with nByte bytes of |
||
774 | ** random data. |
||
775 | */ |
||
776 | static int tvfsRandomness(sqlite3_vfs pVfs, int nByte, byte[] zBufOut){ |
||
777 | return sqlite3OsRandomness(PARENTVFS(pVfs), nByte, zBufOut); |
||
778 | } |
||
779 | |||
780 | /* |
||
781 | ** Sleep for nMicro microseconds. Return the number of microseconds |
||
782 | ** actually slept. |
||
783 | */ |
||
784 | static int tvfsSleep(sqlite3_vfs pVfs, int nMicro){ |
||
785 | return sqlite3OsSleep(PARENTVFS(pVfs), nMicro); |
||
786 | } |
||
787 | |||
788 | /* |
||
789 | ** Return the current time as a Julian Day number in pTimeOut. |
||
790 | */ |
||
791 | static int tvfsCurrentTime(sqlite3_vfs pVfs, double pTimeOut){ |
||
792 | return PARENTVFS(pVfs).xCurrentTime(PARENTVFS(pVfs), ref pTimeOut); |
||
793 | } |
||
794 | |||
795 | static int tvfsShmOpen(sqlite3_file pFile){ |
||
796 | Testvfs p; |
||
797 | int rc = SQLITE_OK; /* Return code */ |
||
798 | Debugger.Break();//TODO |
||
799 | //TestvfsBuffer pBuffer; /* Buffer to open connection to */ |
||
800 | //TestvfsFd pFd; /* The testvfs file structure */ |
||
801 | |||
802 | //pFd = tvfsGetFd(pFile); |
||
803 | //p = (Testvfs )pFd.pVfs.pAppData; |
||
804 | //Debug.Assert( pFd.pShmId && pFd.pShm==null && pFd.pNext==null ); |
||
805 | |||
806 | ///* Evaluate the Tcl script: |
||
807 | //** |
||
808 | //** SCRIPT xShmOpen FILENAME |
||
809 | //*/ |
||
810 | //TCL.Tcl_ResetResult(p.interp); |
||
811 | //if ( p.pScript != null && ( p.mask & TESTVFS_SHMOPEN_MASK ) != 0 ) |
||
812 | //{ |
||
813 | // tvfsExecTcl(p, "xShmOpen", TCL.Tcl_NewStringObj(pFd.zFilename, -1), 0, 0); |
||
814 | // if( tvfsResultCode(p, ref rc)!=0 ){ |
||
815 | // if( rc!=SQLITE_OK ) return rc; |
||
816 | // } |
||
817 | //} |
||
818 | |||
819 | //Debug.Assert( rc==SQLITE_OK ); |
||
820 | //if ( ( p.mask & TESTVFS_SHMOPEN_MASK ) != 0 && tvfsInjectIoerr( p ) ) |
||
821 | //{ |
||
822 | // return SQLITE_IOERR; |
||
823 | //} |
||
824 | |||
825 | ///* Search for a TestvfsBuffer. Create a new one if required. */ |
||
826 | //for(pBuffer=p.pBuffer; pBuffer!=null; pBuffer=pBuffer.pNext){ |
||
827 | // if( 0==strcmp(pFd.zFilename, pBuffer.zFile) ) break; |
||
828 | //} |
||
829 | //if( null==pBuffer ){ |
||
830 | // int nByte = sizeof(TestvfsBuffer) + strlen(pFd.zFilename) + 1; |
||
831 | // pBuffer = (TestvfsBuffer )ckalloc(nByte); |
||
832 | // memset(pBuffer, 0, nByte); |
||
833 | // pBuffer.zFile = (char )&pBuffer[1]; |
||
834 | // strcpy(pBuffer.zFile, pFd.zFilename); |
||
835 | // pBuffer.pNext = p.pBuffer; |
||
836 | // p.pBuffer = pBuffer; |
||
837 | //} |
||
838 | |||
839 | ///* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */ |
||
840 | //pFd.pNext = pBuffer.pFile; |
||
841 | //pBuffer.pFile = pFd; |
||
842 | //pFd.pShm = pBuffer; |
||
843 | return SQLITE_OK; |
||
844 | } |
||
845 | |||
846 | static void tvfsAllocPage(TestvfsBuffer p, int iPage, int pgsz){ |
||
847 | Debugger.Break();//TODO |
||
848 | //Debug.Assert( iPage < TESTVFS_MAX_PAGES ); |
||
849 | //if( p.aPage[iPage]==0 ){ |
||
850 | // p.aPage[iPage] = (u8 )ckalloc(pgsz); |
||
851 | // memset(p.aPage[iPage], 0, pgsz); |
||
852 | // p.pgsz = pgsz; |
||
853 | //} |
||
854 | } |
||
855 | |||
856 | static int tvfsShmMap( |
||
857 | sqlite3_file pFile, /* Handle open on database file */ |
||
858 | int iPage, /* Page to retrieve */ |
||
859 | int pgsz, /* Size of pages */ |
||
860 | int isWrite, /* True to extend file if necessary */ |
||
861 | out object pp /* OUT: Mapped memory */ |
||
862 | ){ |
||
863 | int rc = SQLITE_OK; |
||
864 | Debugger.Break();//TODO |
||
865 | pp = null; |
||
866 | //TestvfsFd pFd = tvfsGetFd( pFile ); |
||
867 | //Testvfs p = (Testvfs )(pFd.pVfs.pAppData); |
||
868 | |||
869 | //if( 0==pFd.pShm ){ |
||
870 | // rc = tvfsShmOpen(pFile); |
||
871 | // if( rc!=SQLITE_OK ){ |
||
872 | // return rc; |
||
873 | // } |
||
874 | //} |
||
875 | |||
876 | //if( p.pScript != null && (p.mask&TESTVFS_SHMMAP_MASK )!=0){ |
||
877 | // Tcl_Obj pArg = TCL.Tcl_NewObj(); |
||
878 | // Tcl_IncrRefCount(pArg); |
||
879 | // Tcl_ListObjAppendElement(p.interp, pArg, TCL.Tcl_NewIntObj(iPage)); |
||
880 | // Tcl_ListObjAppendElement(p.interp, pArg, TCL.Tcl_NewIntObj(pgsz)); |
||
881 | // Tcl_ListObjAppendElement(p.interp, pArg, TCL.Tcl_NewIntObj(isWrite)); |
||
882 | // tvfsExecTcl(p, "xShmMap", |
||
883 | // Tcl_NewStringObj(pFd.pShm.zFile, -1), pFd.pShmId, pArg |
||
884 | // ); |
||
885 | // tvfsResultCode(p, ref rc); |
||
886 | // Tcl_DecrRefCount(pArg); |
||
887 | //} |
||
888 | //if( rc==SQLITE_OK && (p.mask&TESTVFS_SHMMAP_MASK )!=0&& tvfsInjectIoerr(p) ){ |
||
889 | // rc = SQLITE_IOERR; |
||
890 | //} |
||
891 | |||
892 | //if( rc==SQLITE_OK && isWrite && !pFd.pShm.aPage[iPage] ){ |
||
893 | // tvfsAllocPage(pFd.pShm, iPage, pgsz); |
||
894 | //} |
||
895 | //pp = pFd.pShm.aPage[iPage]; |
||
896 | |||
897 | return rc; |
||
898 | } |
||
899 | |||
900 | |||
901 | static int tvfsShmLock( |
||
902 | sqlite3_file pFile, |
||
903 | int ofst, |
||
904 | int n, |
||
905 | int flags |
||
906 | ){ |
||
907 | int rc = SQLITE_OK; |
||
908 | Debugger.Break();//TODO |
||
909 | //TestvfsFd pFd = tvfsGetFd(pFile); |
||
910 | //Testvfs p = (Testvfs )(pFd.pVfs.pAppData); |
||
911 | //int nLock; |
||
912 | //StringBuilder zLock =new StringBuilder(80);//char zLock[80]; |
||
913 | |||
914 | //if( p.pScript !=null && (p.mask&TESTVFS_SHMLOCK_MASK)!=0 ){ |
||
915 | // sqlite3_snprintf(sizeof(zLock), zLock, "%d %d", ofst, n); |
||
916 | // nLock = strlen(zLock); |
||
917 | // if( flags & SQLITE_SHM_LOCK ){ |
||
918 | // strcpy(&zLock[nLock], " lock"); |
||
919 | // }else{ |
||
920 | // strcpy(&zLock[nLock], " unlock"); |
||
921 | // } |
||
922 | // nLock += strlen(&zLock[nLock]); |
||
923 | // if( flags & SQLITE_SHM_SHARED ){ |
||
924 | // strcpy(&zLock[nLock], " shared"); |
||
925 | // }else{ |
||
926 | // strcpy(&zLock[nLock], " exclusive"); |
||
927 | // } |
||
928 | // tvfsExecTcl(p, "xShmLock", |
||
929 | // Tcl_NewStringObj(pFd.pShm.zFile, -1), pFd.pShmId, |
||
930 | // Tcl_NewStringObj(zLock, -1) |
||
931 | // ); |
||
932 | // tvfsResultCode(p, ref rc); |
||
933 | //} |
||
934 | |||
935 | //if( rc==SQLITE_OK && (p.mask&TESTVFS_SHMLOCK_MASK )!=0&& tvfsInjectIoerr(p) ){ |
||
936 | // rc = SQLITE_IOERR; |
||
937 | //} |
||
938 | |||
939 | //if( rc==SQLITE_OK ){ |
||
940 | // int isLock = (flags & SQLITE_SHM_LOCK); |
||
941 | // int isExcl = (flags & SQLITE_SHM_EXCLUSIVE); |
||
942 | // u32 mask = (((1<<n)-1) << ofst); |
||
943 | // if( isLock ){ |
||
944 | // TestvfsFd p2; |
||
945 | // for(p2=pFd.pShm.pFile; p2; p2=p2.pNext){ |
||
946 | // if( p2==pFd ) continue; |
||
947 | // if( (p2.excllock&mask) || (isExcl && p2.sharedlock&mask) ){ |
||
948 | // rc = SQLITE_BUSY; |
||
949 | // break; |
||
950 | // } |
||
951 | // } |
||
952 | // if( rc==SQLITE_OK ){ |
||
953 | // if( isExcl ) pFd.excllock |= mask; |
||
954 | // if( null==isExcl ) pFd.sharedlock |= mask; |
||
955 | // } |
||
956 | // }else{ |
||
957 | // if( isExcl ) pFd.excllock &= (~mask); |
||
958 | // if( null==isExcl ) pFd.sharedlock &= (~mask); |
||
959 | // } |
||
960 | //} |
||
961 | |||
962 | return rc; |
||
963 | } |
||
964 | |||
965 | static void tvfsShmBarrier(sqlite3_file pFile){ |
||
966 | Debugger.Break();//TODO |
||
967 | //TestvfsFd pFd = tvfsGetFd(pFile); |
||
968 | //Testvfs p = (Testvfs )(pFd.pVfs.pAppData); |
||
969 | |||
970 | //if ( p.pScript != null && ( p.mask & TESTVFS_SHMBARRIER_MASK ) != 0 ) |
||
971 | //{ |
||
972 | // tvfsExecTcl(p, "xShmBarrier", |
||
973 | // Tcl_NewStringObj(pFd.pShm.zFile, -1), pFd.pShmId, 0 |
||
974 | // ); |
||
975 | //} |
||
976 | } |
||
977 | |||
978 | static int tvfsShmUnmap( |
||
979 | sqlite3_file pFile, |
||
980 | int deleteFlag |
||
981 | ){ |
||
982 | int rc = SQLITE_OK; |
||
983 | Debugger.Break();//TODO |
||
984 | //TestvfsFd pFd = tvfsGetFd( pFile ); |
||
985 | //Testvfs p = (Testvfs )(pFd.pVfs.pAppData); |
||
986 | //TestvfsBuffer pBuffer = pFd.pShm; |
||
987 | //TestvfsFd ppFd; |
||
988 | |||
989 | //if( null==pBuffer ) return SQLITE_OK; |
||
990 | //Debug.Assert( pFd.pShmId && pFd.pShm ); |
||
991 | |||
992 | //if ( p.pScript != null && ( p.mask & TESTVFS_SHMCLOSE_MASK ) != 0 ) |
||
993 | //{ |
||
994 | // tvfsExecTcl(p, "xShmUnmap", |
||
995 | // Tcl_NewStringObj(pFd.pShm.zFile, -1), pFd.pShmId, 0 |
||
996 | // ); |
||
997 | // tvfsResultCode(p, ref rc); |
||
998 | //} |
||
999 | |||
1000 | //for(ppFd=pBuffer.pFile; ppFd!=pFd; ppFd=&((ppFd).pNext)); |
||
1001 | //Debug.Assert( (ppFd)==pFd ); |
||
1002 | //ppFd = pFd.pNext; |
||
1003 | //pFd.pNext = 0; |
||
1004 | |||
1005 | //if( pBuffer.pFile==null ){ |
||
1006 | // int i; |
||
1007 | // TestvfsBuffer pp; |
||
1008 | // for(pp=p.pBuffer; pp!=pBuffer; pp=((pp).pNext)); |
||
1009 | // pp = (pp).pNext; |
||
1010 | // Debugger.Break();//TODO |
||
1011 | // //for(i=0; pBuffer.aPage[i]!= null; i++){ |
||
1012 | // // ckfree((char )pBuffer.aPage[i]); |
||
1013 | // //} |
||
1014 | // //ckfree((char )pBuffer); |
||
1015 | //} |
||
1016 | //pFd.pShm = null; |
||
1017 | |||
1018 | return rc; |
||
1019 | } |
||
1020 | |||
1021 | enum DB_enum_CMD { |
||
1022 | CMD_SHM, CMD_DELETE, CMD_FILTER, CMD_IOERR, CMD_SCRIPT, |
||
1023 | CMD_DEVCHAR, CMD_SECTORSIZE, CMD_FULLERR, CMD_CANTOPENERR |
||
1024 | }; |
||
1025 | class TestvfsSubcmd { |
||
1026 | public string zName; |
||
1027 | public DB_enum_CMD eCmd; |
||
1028 | public TestvfsSubcmd (string zName, DB_enum_CMD eCmd){this.zName=zName;this.eCmd=eCmd;} |
||
1029 | } |
||
1030 | class VfsMethod { |
||
1031 | public string zName; |
||
1032 | public int mask; |
||
1033 | public VfsMethod (string zName, int mask){this.zName=zName;this.mask=mask;} |
||
1034 | } |
||
1035 | |||
1036 | class DeviceFlag { |
||
1037 | public string zName; |
||
1038 | public int iValue; |
||
1039 | public DeviceFlag (string zName, int iValue){this.zName=zName;this.iValue=iValue;} |
||
1040 | } |
||
1041 | |||
1042 | class _aFlag |
||
1043 | { |
||
1044 | public string zName; |
||
1045 | public int iValue; |
||
1046 | public _aFlag( string zName, int iValue ) |
||
1047 | { |
||
1048 | this.zName = zName; |
||
1049 | this.iValue = iValue; |
||
1050 | } |
||
1051 | } |
||
1052 | |||
1053 | |||
1054 | static int testvfs_obj_cmd( |
||
1055 | ClientData cd, |
||
1056 | Tcl_Interp interp, |
||
1057 | int objc, |
||
1058 | Tcl_Obj[] objv |
||
1059 | ){ |
||
1060 | Debugger.Break();//TODO |
||
1061 | // Testvfs p = (Testvfs)cd; |
||
1062 | |||
1063 | // TestvfsSubcmd[] aSubcmd = new TestvfsSubcmd[] { |
||
1064 | // new TestvfsSubcmd( "shm", DB_enum_CMD.CMD_SHM ), |
||
1065 | // new TestvfsSubcmd( "delete", DB_enum_CMD.CMD_DELETE ), |
||
1066 | // new TestvfsSubcmd( "filter", DB_enum_CMD.CMD_FILTER ), |
||
1067 | // new TestvfsSubcmd( "ioerr", DB_enum_CMD.CMD_IOERR ), |
||
1068 | // new TestvfsSubcmd( "fullerr", DB_enum_CMD.CMD_FULLERR ), |
||
1069 | // new TestvfsSubcmd( "cantopenerr", DB_enum_CMD.CMD_CANTOPENERR ), |
||
1070 | // new TestvfsSubcmd( "script", DB_enum_CMD.CMD_SCRIPT ), |
||
1071 | // new TestvfsSubcmd( "devchar", DB_enum_CMD.CMD_DEVCHAR ), |
||
1072 | // new TestvfsSubcmd( "sectorsize", DB_enum_CMD.CMD_SECTORSIZE ), |
||
1073 | // new TestvfsSubcmd( 0, 0 ) |
||
1074 | // }; |
||
1075 | // int i=0; |
||
1076 | |||
1077 | // if( objc<2 ){ |
||
1078 | // TCL.Tcl_WrongNumArgs( interp, 1, objv, "SUBCOMMAND ..." ); |
||
1079 | // return TCL.TCL_ERROR; |
||
1080 | // } |
||
1081 | // if ( TCL.Tcl_GetIndexFromObjStruct( |
||
1082 | // interp, objv[1], aSubcmd, aSubcmd.Length, "subcommand", 0, ref i) |
||
1083 | // ){ |
||
1084 | // return TCL.TCL_ERROR; |
||
1085 | // } |
||
1086 | // TCL.Tcl_ResetResult( interp ); |
||
1087 | |||
1088 | // switch( aSubcmd[i].eCmd ){ |
||
1089 | // case DB_enum_CMD.CMD_SHM: { |
||
1090 | // Tcl_Obj pObj; |
||
1091 | // int i; |
||
1092 | // TestvfsBuffer pBuffer; |
||
1093 | // string zName; |
||
1094 | // if( objc!=3 && objc!=4 ){ |
||
1095 | // TCL.Tcl_WrongNumArgs( interp, 2, objv, "FILE ?VALUE?" ); |
||
1096 | // return TCL.TCL_ERROR; |
||
1097 | // } |
||
1098 | // zName = ckalloc(p.pParent.mxPathname); |
||
1099 | // p.pParent.xFullPathname( |
||
1100 | // p.pParent, TCL.Tcl_GetString(objv[2]), |
||
1101 | // p.pParent.mxPathname, zName |
||
1102 | // ); |
||
1103 | // for(pBuffer=p.pBuffer; pBuffer; pBuffer=pBuffer.pNext){ |
||
1104 | // if( 0==strcmp(pBuffer.zFile, zName) ) break; |
||
1105 | // } |
||
1106 | // ckfree(zName); |
||
1107 | // if( null==pBuffer ){ |
||
1108 | // TCL.Tcl_AppendResult( interp, "no such file: ", TCL.Tcl_GetString( objv[2] ), 0 ); |
||
1109 | // return TCL.TCL_ERROR; |
||
1110 | // } |
||
1111 | // if( objc==4 ){ |
||
1112 | // int n; |
||
1113 | // u8 *a = TCL.Tcl_GetByteArrayFromObj(objv[3], &n); |
||
1114 | // int pgsz = pBuffer.pgsz; |
||
1115 | // if( pgsz==0 ) pgsz = 65536; |
||
1116 | // for(i=0; ipgsz<n; i++){ |
||
1117 | // int nByte = pgsz; |
||
1118 | // tvfsAllocPage(pBuffer, i, pgsz); |
||
1119 | // if( n-ipgsz<pgsz ){ |
||
1120 | // nByte = n; |
||
1121 | // } |
||
1122 | // memcpy(pBuffer.aPage[i], &a[ipgsz], nByte); |
||
1123 | // } |
||
1124 | // } |
||
1125 | |||
1126 | // pObj = TCL.Tcl_NewObj(); |
||
1127 | // for(i=0; pBuffer.aPage[i]!=null; i++){ |
||
1128 | // int pgsz = pBuffer.pgsz; |
||
1129 | // if( pgsz==0 ) pgsz = 65536; |
||
1130 | // TCL.Tcl_AppendObjToObj(pObj, TCL.Tcl_NewByteArrayObj(pBuffer.aPage[i], pgsz)); |
||
1131 | // } |
||
1132 | // TCL.Tcl_SetObjResult( interp, pObj ); |
||
1133 | // break; |
||
1134 | // } |
||
1135 | // case DB_enum_CMD.CMD_FILTER: { |
||
1136 | //VfsMethod[] vfsmethod = new VfsMethod[] { |
||
1137 | // new VfsMethod( "xShmOpen", TESTVFS_SHMOPEN_MASK ), |
||
1138 | // new VfsMethod( "xShmLock", TESTVFS_SHMLOCK_MASK ), |
||
1139 | // new VfsMethod( "xShmBarrier", TESTVFS_SHMBARRIER_MASK ), |
||
1140 | // new VfsMethod( "xShmUnmap", TESTVFS_SHMCLOSE_MASK ), |
||
1141 | // new VfsMethod( "xShmMap", TESTVFS_SHMMAP_MASK ), |
||
1142 | // new VfsMethod( "xSync", TESTVFS_SYNC_MASK ), |
||
1143 | // new VfsMethod( "xDelete", TESTVFS_DELETE_MASK ), |
||
1144 | // new VfsMethod( "xWrite", TESTVFS_WRITE_MASK ), |
||
1145 | // new VfsMethod( "xTruncate", TESTVFS_TRUNCATE_MASK ), |
||
1146 | // new VfsMethod( "xOpen", TESTVFS_OPEN_MASK ), |
||
1147 | // new VfsMethod( "xClose", TESTVFS_CLOSE_MASK ), |
||
1148 | // new VfsMethod( "xAccess", TESTVFS_ACCESS_MASK ), |
||
1149 | // new VfsMethod( "xFullPathname", TESTVFS_FULLPATHNAME_MASK ), |
||
1150 | //}; |
||
1151 | // Tcl_Obj[] apElem = null; |
||
1152 | // int nElem = 0; |
||
1153 | // int i; |
||
1154 | // int mask = 0; |
||
1155 | // if( objc!=3 ){ |
||
1156 | // TCL.Tcl_WrongNumArgs( interp, 2, objv, "LIST" ); |
||
1157 | // return TCL.TCL_ERROR; |
||
1158 | // } |
||
1159 | // if ( TCL.Tcl_ListObjGetElements( interp, objv[2], ref nElem, ref apElem ) ) |
||
1160 | // { |
||
1161 | // return TCL.TCL_ERROR; |
||
1162 | // } |
||
1163 | // TCL.Tcl_ResetResult( interp ); |
||
1164 | // for(i=0; i<nElem; i++){ |
||
1165 | // int iMethod; |
||
1166 | // string zElem = TCL.Tcl_GetString(apElem[i]); |
||
1167 | // for(iMethod=0; iMethod<ArraySize(vfsmethod); iMethod++){ |
||
1168 | // if( strcmp(zElem, vfsmethod[iMethod].zName)==0 ){ |
||
1169 | // mask |= vfsmethod[iMethod].mask; |
||
1170 | // break; |
||
1171 | // } |
||
1172 | // } |
||
1173 | // if( iMethod==ArraySize(vfsmethod) ){ |
||
1174 | // TCL.Tcl_AppendResult( interp, "unknown method: ", zElem, 0 ); |
||
1175 | // return TCL.TCL_ERROR; |
||
1176 | // } |
||
1177 | // } |
||
1178 | // p.mask = mask; |
||
1179 | // break; |
||
1180 | // } |
||
1181 | |||
1182 | // case DB_enum_CMD.CMD_SCRIPT: { |
||
1183 | // if( objc==3 ){ |
||
1184 | // int nByte; |
||
1185 | // if( p.pScript !=null){ |
||
1186 | // TCL.Tcl_DecrRefCount( p.pScript ); |
||
1187 | // p.pScript = 0; |
||
1188 | // } |
||
1189 | // TCL.Tcl_GetStringFromObj( objv[2], &nByte ); |
||
1190 | // if( nByte>0 ){ |
||
1191 | // p.pScript = TCL.Tcl_DuplicateObj(objv[2]); |
||
1192 | // TCL.Tcl_IncrRefCount( p.pScript ); |
||
1193 | // } |
||
1194 | // }else if( objc!=2 ){ |
||
1195 | // TCL.Tcl_WrongNumArgs( interp, 2, objv, "?SCRIPT?" ); |
||
1196 | // return TCL.TCL_ERROR; |
||
1197 | // } |
||
1198 | |||
1199 | // TCL.Tcl_ResetResult( interp ); |
||
1200 | // if( p.pScript !=null) if( p.pScript )TCL.Tcl_SetObjResult(interp, p.pScript); |
||
1201 | |||
1202 | // break; |
||
1203 | // } |
||
1204 | |||
1205 | // /* |
||
1206 | // ** TESTVFS ioerr ?IFAIL PERSIST? |
||
1207 | // ** |
||
1208 | // ** Where IFAIL is an integer and PERSIST is boolean. |
||
1209 | // */ |
||
1210 | // case DB_enum_CMD.CMD_CANTOPENERR: |
||
1211 | // case DB_enum_CMD.CMD_IOERR: |
||
1212 | // case DB_enum_CMD.CMD_FULLERR: { |
||
1213 | // TestFaultInject pTest; |
||
1214 | // int iRet; |
||
1215 | |||
1216 | // switch( aSubcmd[i].eCmd ){ |
||
1217 | // case DB_enum_CMD.CMD_IOERR: pTest = p.ioerr_err; break; |
||
1218 | // case DB_enum_CMD.CMD_FULLERR: pTest = p.full_err; break; |
||
1219 | // case DB_enum_CMD.CMD_CANTOPENERR: pTest = p.cantopen_err; break; |
||
1220 | // default: Debug.Assert(false); |
||
1221 | // } |
||
1222 | // iRet = pTest.nFail; |
||
1223 | // pTest.nFail = 0; |
||
1224 | // pTest.eFault = 0; |
||
1225 | // pTest.iCnt = 0; |
||
1226 | |||
1227 | // if( objc==4 ){ |
||
1228 | // int iCnt, iPersist; |
||
1229 | // if ( TCL.TCL_OK != TCL.Tcl_GetIntFromObj( interp, objv[2], &iCnt ) |
||
1230 | // || TCL.TCL_OK != TCL.Tcl_GetBooleanFromObj( interp, objv[3], &iPersist ) |
||
1231 | // ){ |
||
1232 | // return TCL.TCL_ERROR; |
||
1233 | // } |
||
1234 | // pTest.eFault = iPersist != 0 ? FAULT_INJECT_PERSISTENT : FAULT_INJECT_TRANSIENT; |
||
1235 | // pTest.iCnt = iCnt; |
||
1236 | // }else if( objc!=2 ){ |
||
1237 | // TCL.Tcl_WrongNumArgs( interp, 2, objv, "?CNT PERSIST?" ); |
||
1238 | // return TCL.TCL_ERROR; |
||
1239 | // } |
||
1240 | // TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( iRet ) ); |
||
1241 | // break; |
||
1242 | // } |
||
1243 | |||
1244 | // case DB_enum_CMD.CMD_DELETE: { |
||
1245 | // TCL.Tcl_DeleteCommand( interp, TCL.Tcl_GetString( objv[0] ) ); |
||
1246 | // break; |
||
1247 | // } |
||
1248 | |||
1249 | // case DB_enum_CMD.CMD_DEVCHAR: { |
||
1250 | //_aFlag[] aFlag = new _aFlag[] { |
||
1251 | // new _aFlag( "default", -1 ), |
||
1252 | // new _aFlag( "atomic", SQLITE_IOCAP_ATOMIC ), |
||
1253 | // new _aFlag( "atomic512", SQLITE_IOCAP_ATOMIC512 ), |
||
1254 | // new _aFlag( "atomic1k", SQLITE_IOCAP_ATOMIC1K ), |
||
1255 | // new _aFlag( "atomic2k", SQLITE_IOCAP_ATOMIC2K ), |
||
1256 | // new _aFlag( "atomic4k", SQLITE_IOCAP_ATOMIC4K ), |
||
1257 | // new _aFlag( "atomic8k", SQLITE_IOCAP_ATOMIC8K ), |
||
1258 | // new _aFlag( "atomic16k", SQLITE_IOCAP_ATOMIC16K ), |
||
1259 | // new _aFlag( "atomic32k", SQLITE_IOCAP_ATOMIC32K ), |
||
1260 | // new _aFlag( "atomic64k", SQLITE_IOCAP_ATOMIC64K ), |
||
1261 | // new _aFlag( "sequential", SQLITE_IOCAP_SEQUENTIAL ), |
||
1262 | // new _aFlag( "safe_append", SQLITE_IOCAP_SAFE_APPEND ), |
||
1263 | // new _aFlag( "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ), |
||
1264 | // new _aFlag( 0, 0 ) |
||
1265 | // }; |
||
1266 | // Tcl_Obj pRet; |
||
1267 | // int iFlag; |
||
1268 | |||
1269 | // if( objc>3 ){ |
||
1270 | // Tcl_WrongNumArgs(interp, 2, objv, "?ATTR-LIST?"); |
||
1271 | // return TCL.TCL_ERROR; |
||
1272 | // } |
||
1273 | // if( objc==3 ){ |
||
1274 | // int j; |
||
1275 | // int iNew = 0; |
||
1276 | // Tcl_Obj[] flags = null; |
||
1277 | // int nFlags = 0; |
||
1278 | |||
1279 | // if ( TCL.Tcl_ListObjGetElements( interp, objv[2], ref nFlags, ref flags ) ) |
||
1280 | // { |
||
1281 | // return TCL.TCL_ERROR; |
||
1282 | // } |
||
1283 | |||
1284 | // for(j=0; j<nFlags; j++){ |
||
1285 | // int idx = 0; |
||
1286 | // if( Tcl_GetIndexFromObjStruct(interp, flags[j], aFlag, |
||
1287 | // aFlag.Length, "flag", 0, ref idx) |
||
1288 | // ){ |
||
1289 | // return TCL.TCL_ERROR; |
||
1290 | // } |
||
1291 | // if( aFlag[idx].iValue<0 && nFlags>1 ){ |
||
1292 | // TCL.Tcl_AppendResult( interp, "bad flags: ", TCL.Tcl_GetString( objv[2] ), 0 ); |
||
1293 | // return TCL.TCL_ERROR; |
||
1294 | // } |
||
1295 | // iNew |= aFlag[idx].iValue; |
||
1296 | // } |
||
1297 | |||
1298 | // p.iDevchar = iNew; |
||
1299 | // } |
||
1300 | |||
1301 | // pRet = TCL.Tcl_NewObj(); |
||
1302 | // for(iFlag=0; iFlag<aFlag.Length ; iFlag++)//sizeof(aFlag)/sizeof(aFlag[0]); iFlag++) |
||
1303 | // { |
||
1304 | // if( p.iDevchar & aFlag[iFlag].iValue ){ |
||
1305 | // TCL.Tcl_ListObjAppendElement( |
||
1306 | // interp, pRet, TCL.Tcl_NewStringObj(aFlag[iFlag].zName, -1) |
||
1307 | // ); |
||
1308 | // } |
||
1309 | // } |
||
1310 | // TCL.Tcl_SetObjResult( interp, pRet ); |
||
1311 | |||
1312 | // break; |
||
1313 | // } |
||
1314 | |||
1315 | // case DB_enum_CMD.CMD_SECTORSIZE: { |
||
1316 | // if( objc>3 ){ |
||
1317 | // TCL.Tcl_WrongNumArgs( interp, 2, objv, "?VALUE?" ); |
||
1318 | // return TCL.TCL_ERROR; |
||
1319 | // } |
||
1320 | // if( objc==3 ){ |
||
1321 | // int iNew = 0; |
||
1322 | // if( Tcl_GetIntFromObj(interp, objv[2], ref iNew) ){ |
||
1323 | // return TCL.TCL_ERROR; |
||
1324 | // } |
||
1325 | // p.iSectorsize = iNew; |
||
1326 | // } |
||
1327 | // TCL.Tcl_SetObjResult( interp, TCL.Tcl_NewIntObj( p.iSectorsize ) ); |
||
1328 | // break; |
||
1329 | // } |
||
1330 | // } |
||
1331 | return TCL.TCL_OK; |
||
1332 | } |
||
1333 | |||
1334 | static void testvfs_obj_del(ClientData cd){ |
||
1335 | Testvfs p = (Testvfs)cd; |
||
1336 | if ( p.pScript !=null) |
||
1337 | TCL.Tcl_DecrRefCount( ref p.pScript ); |
||
1338 | sqlite3_vfs_unregister(p.pVfs); |
||
1339 | Debugger.Break();//TODO |
||
1340 | //ckfree((char )p.pVfs); |
||
1341 | //ckfree((char )p); |
||
1342 | } |
||
1343 | |||
1344 | /* |
||
1345 | ** Usage: testvfs VFSNAME ?SWITCHES? |
||
1346 | ** |
||
1347 | ** Switches are: |
||
1348 | ** |
||
1349 | ** -noshm BOOLEAN (True to omit shm methods. Default false) |
||
1350 | ** -default BOOLEAN (True to make the vfs default. Default false) |
||
1351 | ** |
||
1352 | ** This command creates two things when it is invoked: an SQLite VFS, and |
||
1353 | ** a Tcl command. Both are named VFSNAME. The VFS is installed. It is not |
||
1354 | ** installed as the default VFS. |
||
1355 | ** |
||
1356 | ** The VFS passes all file I/O calls through to the underlying VFS. |
||
1357 | ** |
||
1358 | ** Whenever the xShmMap method of the VFS |
||
1359 | ** is invoked, the SCRIPT is executed as follows: |
||
1360 | ** |
||
1361 | ** SCRIPT xShmMap FILENAME ID |
||
1362 | ** |
||
1363 | ** The value returned by the invocation of SCRIPT above is interpreted as |
||
1364 | ** an SQLite error code and returned to SQLite. Either a symbolic |
||
1365 | ** "SQLITE_OK" or numeric "0" value may be returned. |
||
1366 | ** |
||
1367 | ** The contents of the shared-memory buffer associated with a given file |
||
1368 | ** may be read and set using the following command: |
||
1369 | ** |
||
1370 | ** VFSNAME shm FILENAME ?NEWVALUE? |
||
1371 | ** |
||
1372 | ** When the xShmLock method is invoked by SQLite, the following script is |
||
1373 | ** run: |
||
1374 | ** |
||
1375 | ** SCRIPT xShmLock FILENAME ID LOCK |
||
1376 | ** |
||
1377 | ** where LOCK is of the form "OFFSET NBYTE lock/unlock shared/exclusive" |
||
1378 | */ |
||
1379 | static int testvfs_cmd( |
||
1380 | ClientData cd, |
||
1381 | Tcl_Interp interp, |
||
1382 | int objc, |
||
1383 | Tcl_Obj[] objv |
||
1384 | ){ |
||
1385 | Debugger.Break();//TODO |
||
1386 | // sqlite3_vfs tvfs_vfs = new sqlite3_vfs( |
||
1387 | // 2, /* iVersion */ |
||
1388 | // 0, /* szOsFile */ |
||
1389 | // 0, /* mxPathname */ |
||
1390 | // null, /* pNext */ |
||
1391 | // null, /* zName */ |
||
1392 | // 0, /* pAppData */ |
||
1393 | // tvfsOpen, /* xOpen */ |
||
1394 | // tvfsDelete, /* xDelete */ |
||
1395 | // tvfsAccess, /* xAccess */ |
||
1396 | // tvfsFullPathname, /* xFullPathname */ |
||
1397 | //#if !SQLITE_OMIT_LOAD_EXTENSION |
||
1398 | // tvfsDlOpen, /* xDlOpen */ |
||
1399 | // tvfsDlError, /* xDlError */ |
||
1400 | // tvfsDlSym, /* xDlSym */ |
||
1401 | // tvfsDlClose, /* xDlClose */ |
||
1402 | //#else |
||
1403 | // null, /* xDlOpen */ |
||
1404 | // null, /* xDlError */ |
||
1405 | // null, /* xDlSym */ |
||
1406 | // null, /* xDlClose */ |
||
1407 | //#endif //* SQLITE_OMIT_LOAD_EXTENSION */ |
||
1408 | // tvfsRandomness, /* xRandomness */ |
||
1409 | // tvfsSleep, /* xSleep */ |
||
1410 | // tvfsCurrentTime, /* xCurrentTime */ |
||
1411 | // null, /* xGetLastError */ |
||
1412 | // null, /* xCurrentTimeInt64 */ |
||
1413 | // null, null, null |
||
1414 | // ); |
||
1415 | |||
1416 | // Testvfs p; /* New object */ |
||
1417 | // sqlite3_vfs pVfs; /* New VFS */ |
||
1418 | // string zVfs; |
||
1419 | // int nByte; /* Bytes of space to allocate at p */ |
||
1420 | |||
1421 | // int i; |
||
1422 | // int isNoshm = 0; /* True if -noshm is passed */ |
||
1423 | // int isDefault = 0; /* True if -default is passed */ |
||
1424 | // int szOsFile = 0; /* Value passed to -szosfile */ |
||
1425 | // int mxPathname = -1; /* Value passed to -mxpathname */ |
||
1426 | // int iVersion = 2; /* Value passed to -iversion */ |
||
1427 | |||
1428 | // if( objc<2 || 0!=(objc%2) ) goto bad_args; |
||
1429 | // for(i=2; i<objc; i += 2){ |
||
1430 | // int nSwitch; |
||
1431 | // string zSwitch; |
||
1432 | // zSwitch = TCL.Tcl_GetStringFromObj(objv[i], &nSwitch); |
||
1433 | |||
1434 | // if( nSwitch>2 && 0==strncmp("-noshm", zSwitch, nSwitch) ){ |
||
1435 | // if ( TCL.Tcl_GetBooleanFromObj( interp, objv[i + 1], &isNoshm ) ) |
||
1436 | // { |
||
1437 | // return TCL.TCL_ERROR; |
||
1438 | // } |
||
1439 | // } |
||
1440 | // else if( nSwitch>2 && 0==strncmp("-default", zSwitch, nSwitch) ){ |
||
1441 | // if ( TCL.Tcl_GetBooleanFromObj( interp, objv[i + 1], &isDefault ) ) |
||
1442 | // { |
||
1443 | // return TCL.TCL_ERROR; |
||
1444 | // } |
||
1445 | // } |
||
1446 | // else if( nSwitch>2 && 0==strncmp("-szosfile", zSwitch, nSwitch) ){ |
||
1447 | // if ( TCL.Tcl_GetIntFromObj( interp, objv[i + 1], &szOsFile ) ) |
||
1448 | // { |
||
1449 | // return TCL.TCL_ERROR; |
||
1450 | // } |
||
1451 | // } |
||
1452 | // else if( nSwitch>2 && 0==strncmp("-mxpathname", zSwitch, nSwitch) ){ |
||
1453 | // if ( TCL.Tcl_GetIntFromObj( interp, objv[i + 1], &mxPathname ) ) |
||
1454 | // { |
||
1455 | // return TCL.TCL_ERROR; |
||
1456 | // } |
||
1457 | // } |
||
1458 | // else if( nSwitch>2 && 0==strncmp("-iversion", zSwitch, nSwitch) ){ |
||
1459 | // if ( TCL.Tcl_GetIntFromObj( interp, objv[i + 1], &iVersion ) ) |
||
1460 | // { |
||
1461 | // return TCL.TCL_ERROR; |
||
1462 | // } |
||
1463 | // } |
||
1464 | // else{ |
||
1465 | // goto bad_args; |
||
1466 | // } |
||
1467 | // } |
||
1468 | |||
1469 | // if( szOsFile<sizeof(TestvfsFile) ){ |
||
1470 | // szOsFile = sizeof(TestvfsFile); |
||
1471 | // } |
||
1472 | |||
1473 | // zVfs = TCL.Tcl_GetString(objv[1]); |
||
1474 | // nByte = sizeof(Testvfs) + strlen(zVfs)+1; |
||
1475 | // p = (Testvfs )ckalloc(nByte); |
||
1476 | // memset(p, 0, nByte); |
||
1477 | // p.iDevchar = -1; |
||
1478 | // p.iSectorsize = -1; |
||
1479 | |||
1480 | // /* Create the new object command before querying SQLite for a default VFS |
||
1481 | // ** to use for 'real' IO operations. This is because creating the new VFS |
||
1482 | // ** may delete an existing [testvfs] VFS of the same name. If such a VFS |
||
1483 | // ** is currently the default, the new [testvfs] may end up calling the |
||
1484 | // ** methods of a deleted object. |
||
1485 | // */ |
||
1486 | // TCL.Tcl_CreateObjCommand( interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del ); |
||
1487 | // p.pParent = sqlite3_vfs_find(""); |
||
1488 | // p.interp = interp; |
||
1489 | |||
1490 | // p.zName = (char )&p[1]; |
||
1491 | // memcpy(p.zName, zVfs, strlen(zVfs)+1); |
||
1492 | |||
1493 | // pVfs = new sqlite3_vfs();//(sqlite3_vfs )ckalloc(sizeof(sqlite3_vfs)); |
||
1494 | // tvfs_vfs.CopyTo(pVfs);//memcpy( pVfs, &tvfs_vfs, sizeof( sqlite3_vfs ) ); |
||
1495 | // pVfs.pAppData = p; |
||
1496 | // pVfs.iVersion = iVersion; |
||
1497 | // pVfs.zName = p.zName; |
||
1498 | // pVfs.mxPathname = p.pParent.mxPathname; |
||
1499 | // if( mxPathname>=0 && mxPathname<pVfs.mxPathname ){ |
||
1500 | // pVfs.mxPathname = mxPathname; |
||
1501 | // } |
||
1502 | // pVfs.szOsFile = szOsFile; |
||
1503 | // p.pVfs = pVfs; |
||
1504 | // p.isNoshm = isNoshm; |
||
1505 | // p.mask = TESTVFS_ALL_MASK; |
||
1506 | |||
1507 | // sqlite3_vfs_register(pVfs, isDefault); |
||
1508 | |||
1509 | // return TCL.TCL_OK; |
||
1510 | |||
1511 | // bad_args: |
||
1512 | // TCL.Tcl_WrongNumArgs(interp, 1, objv, "VFSNAME ?-noshm BOOL? ?-default BOOL? ?-mxpathname INT? ?-szosfile INT? ?-iversion INT?"); |
||
1513 | return TCL.TCL_ERROR; |
||
1514 | } |
||
1515 | |||
1516 | static int Sqlitetestvfs_Init(Tcl_Interp interp){ |
||
1517 | TCL.Tcl_CreateObjCommand( interp, "testvfs", testvfs_cmd, null, null ); |
||
1518 | return TCL.TCL_OK; |
||
1519 | } |
||
1520 | #endif |
||
1521 | } |
||
1522 | #endif |
||
1523 | } |