wasCSharpSQLite – Blame information for rev

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Diagnostics;
3 using System.Text;
4  
5 using Bitmask = System.UInt64;
6 using u8 = System.Byte;
7 using u16 = System.UInt16;
8 using u32 = System.UInt32;
9  
10 namespace Community.CsharpSqlite
11 {
12 using sqlite3_int64 = System.Int64;
13 using MemJournal = Sqlite3.sqlite3_file;
14  
15 public partial class Sqlite3
16 {
17 /*
18 ** 2007 August 22
19 **
20 ** The author disclaims copyright to this source code. In place of
21 ** a legal notice, here is a blessing:
22 **
23 ** May you do good and not evil.
24 ** May you find forgiveness for yourself and forgive others.
25 ** May you share freely, never taking more than you give.
26 **
27 *************************************************************************
28 **
29 ** This file contains code use to implement an in-memory rollback journal.
30 ** The in-memory rollback journal is used to journal transactions for
31 ** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
32 *************************************************************************
33 ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
34 ** C#-SQLite is an independent reimplementation of the SQLite software library
35 **
36 ** SQLITE_SOURCE_ID: 2010-12-07 20:14:09 a586a4deeb25330037a49df295b36aaf624d0f45
37 **
38 *************************************************************************
39 */
40  
41 //#include "sqliteInt.h"
42  
43 /* Forward references to internal structures */
44 //typedef struct MemJournal MemJournal;
45 //typedef struct FilePoint FilePoint;
46 //typedef struct FileChunk FileChunk;
47  
48 /* Space to hold the rollback journal is allocated in increments of
49 ** this many bytes.
50 **
51 ** The size chosen is a little less than a power of two. That way,
52 ** the FileChunk object will have a size that almost exactly fills
53 ** a power-of-two allocation. This mimimizes wasted space in power-of-two
54 ** memory allocators.
55 */
56 //#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
57 const int JOURNAL_CHUNKSIZE = 4096;
58  
59 /* Macro to find the minimum of two numeric values.
60 */
61 //#if !MIN
62 //# define MIN(x,y) ((x)<(y)?(x):(y))
63 //#endif
64 static int MIN( int x, int y )
65 {
66 return ( x < y ) ? x : y;
67 }
68 static int MIN( int x, u32 y )
69 {
70 return ( x < y ) ? x : (int)y;
71 }
72  
73 /*
74 ** The rollback journal is composed of a linked list of these structures.
75 */
76 public class FileChunk
77 {
78 public FileChunk pNext; /* Next chunk in the journal */
79 public byte[] zChunk = new byte[JOURNAL_CHUNKSIZE]; /* Content of this chunk */
80 };
81  
82 /*
83 ** An instance of this object serves as a cursor into the rollback journal.
84 ** The cursor can be either for reading or writing.
85 */
86 public class FilePoint
87 {
88 public long iOffset; /* Offset from the beginning of the file */
89 public FileChunk pChunk; /* Specific chunk into which cursor points */
90 };
91  
92 /*
93 ** This subclass is a subclass of sqlite3_file. Each open memory-journal
94 ** is an instance of this class.
95 */
96 public partial class sqlite3_file
97 {
98 //public sqlite3_io_methods pMethods; /* Parent class. MUST BE FIRST */
99 public FileChunk pFirst; /* Head of in-memory chunk-list */
100 public FilePoint endpoint; /* Pointer to the end of the file */
101 public FilePoint readpoint; /* Pointer to the end of the last xRead() */
102 };
103  
104 /*
105 ** Read data from the in-memory journal file. This is the implementation
106 ** of the sqlite3_vfs.xRead method.
107 */
108 static int memjrnlRead(
109 sqlite3_file pJfd, /* The journal file from which to read */
110 byte[] zBuf, /* Put the results here */
111 int iAmt, /* Number of bytes to read */
112 sqlite3_int64 iOfst /* Begin reading at this offset */
113 )
114 {
115 MemJournal p = (MemJournal)pJfd;
116 byte[] zOut = zBuf;
117 int nRead = iAmt;
118 int iChunkOffset;
119 FileChunk pChunk;
120  
121 /* SQLite never tries to read past the end of a rollback journal file */
122 Debug.Assert( iOfst + iAmt <= p.endpoint.iOffset );
123  
124 if ( p.readpoint.iOffset != iOfst || iOfst == 0 )
125 {
126 int iOff = 0;
127 for ( pChunk = p.pFirst;
128 ALWAYS( pChunk != null ) && ( iOff + JOURNAL_CHUNKSIZE ) <= iOfst;
129 pChunk = pChunk.pNext
130 )
131 {
132 iOff += JOURNAL_CHUNKSIZE;
133 }
134 }
135 else
136 {
137 pChunk = p.readpoint.pChunk;
138 }
139  
140 iChunkOffset = (int)( iOfst % JOURNAL_CHUNKSIZE );
141 int izOut = 0;
142 do
143 {
144 int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
145 int nCopy = MIN( nRead, ( JOURNAL_CHUNKSIZE - iChunkOffset ) );
146 Buffer.BlockCopy( pChunk.zChunk, iChunkOffset, zOut, izOut, nCopy ); //memcpy( zOut, pChunk.zChunk[iChunkOffset], nCopy );
147 izOut += nCopy;// zOut += nCopy;
148 nRead -= iSpace;
149 iChunkOffset = 0;
150 } while ( nRead >= 0 && ( pChunk = pChunk.pNext ) != null && nRead > 0 );
151 p.readpoint.iOffset = (int)( iOfst + iAmt );
152 p.readpoint.pChunk = pChunk;
153  
154 return SQLITE_OK;
155 }
156  
157 /*
158 ** Write data to the file.
159 */
160 static int memjrnlWrite(
161 sqlite3_file pJfd, /* The journal file into which to write */
162 byte[] zBuf, /* Take data to be written from here */
163 int iAmt, /* Number of bytes to write */
164 sqlite3_int64 iOfst /* Begin writing at this offset into the file */
165 )
166 {
167 MemJournal p = (MemJournal)pJfd;
168 int nWrite = iAmt;
169 byte[] zWrite = zBuf;
170 int izWrite = 0;
171  
172 /* An in-memory journal file should only ever be appended to. Random
173 ** access writes are not required by sqlite.
174 */
175 Debug.Assert( iOfst == p.endpoint.iOffset );
176 UNUSED_PARAMETER( iOfst );
177  
178 while ( nWrite > 0 )
179 {
180 FileChunk pChunk = p.endpoint.pChunk;
181 int iChunkOffset = (int)( p.endpoint.iOffset % JOURNAL_CHUNKSIZE );
182 int iSpace = MIN( nWrite, JOURNAL_CHUNKSIZE - iChunkOffset );
183  
184 if ( iChunkOffset == 0 )
185 {
186 /* New chunk is required to extend the file. */
187 FileChunk pNew = new FileChunk();// sqlite3_malloc( sizeof( FileChunk ) );
188 if ( null == pNew )
189 {
190 return SQLITE_IOERR_NOMEM;
191 }
192 pNew.pNext = null;
193 if ( pChunk != null )
194 {
195 Debug.Assert( p.pFirst != null );
196 pChunk.pNext = pNew;
197 }
198 else
199 {
200 Debug.Assert( null == p.pFirst );
201 p.pFirst = pNew;
202 }
203 p.endpoint.pChunk = pNew;
204 }
205  
206 Buffer.BlockCopy( zWrite, izWrite, p.endpoint.pChunk.zChunk, iChunkOffset, iSpace ); //memcpy( &p.endpoint.pChunk.zChunk[iChunkOffset], zWrite, iSpace );
207 izWrite += iSpace;//zWrite += iSpace;
208 nWrite -= iSpace;
209 p.endpoint.iOffset += iSpace;
210 }
211  
212 return SQLITE_OK;
213 }
214  
215 /*
216 ** Truncate the file.
217 */
218 static int memjrnlTruncate( sqlite3_file pJfd, sqlite3_int64 size )
219 {
220 MemJournal p = (MemJournal)pJfd;
221 FileChunk pChunk;
222 Debug.Assert( size == 0 );
223 UNUSED_PARAMETER( size );
224 pChunk = p.pFirst;
225 while ( pChunk != null )
226 {
227 ////FileChunk pTmp = pChunk;
228 pChunk = pChunk.pNext;
229 //sqlite3_free( ref pTmp );
230 }
231 sqlite3MemJournalOpen( pJfd );
232 return SQLITE_OK;
233 }
234  
235 /*
236 ** Close the file.
237 */
238 static int memjrnlClose( MemJournal pJfd )
239 {
240 memjrnlTruncate( pJfd, 0 );
241 return SQLITE_OK;
242 }
243  
244  
245 /*
246 ** Sync the file.
247 **
248 ** Syncing an in-memory journal is a no-op. And, in fact, this routine
249 ** is never called in a working implementation. This implementation
250 ** exists purely as a contingency, in case some malfunction in some other
251 ** part of SQLite causes Sync to be called by mistake.
252 */
253 static int memjrnlSync( sqlite3_file NotUsed, int NotUsed2 )
254 {
255 UNUSED_PARAMETER2( NotUsed, NotUsed2 );
256 return SQLITE_OK;
257 }
258  
259 /*
260 ** Query the size of the file in bytes.
261 */
262 static int memjrnlFileSize( sqlite3_file pJfd, ref long pSize )
263 {
264 MemJournal p = (MemJournal)pJfd;
265 pSize = p.endpoint.iOffset;
266 return SQLITE_OK;
267 }
268  
269 /*
270 ** Table of methods for MemJournal sqlite3_file object.
271 */
272 static sqlite3_io_methods MemJournalMethods = new sqlite3_io_methods(
273 1, /* iVersion */
274 (dxClose)memjrnlClose, /* xClose */
275 (dxRead)memjrnlRead, /* xRead */
276 (dxWrite)memjrnlWrite, /* xWrite */
277 (dxTruncate)memjrnlTruncate, /* xTruncate */
278 (dxSync)memjrnlSync, /* xSync */
279 (dxFileSize)memjrnlFileSize, /* xFileSize */
280 null, /* xLock */
281 null, /* xUnlock */
282 null, /* xCheckReservedLock */
283 null, /* xFileControl */
284 null, /* xSectorSize */
285 null, /* xDeviceCharacteristics */
286 null, /* xShmMap */
287 null, /* xShmLock */
288 null, /* xShmBarrier */
289 null /* xShmUnlock */
290 );
291  
292 /*
293 ** Open a journal file.
294 */
295 static void sqlite3MemJournalOpen( sqlite3_file pJfd )
296 {
297 MemJournal p = (MemJournal)pJfd;
298 //memset( p, 0, sqlite3MemJournalSize() );
299 p.pFirst = null;
300 p.endpoint = new FilePoint();
301 p.readpoint = new FilePoint();
302 p.pMethods = MemJournalMethods;//(sqlite3_io_methods*)&MemJournalMethods;
303 }
304  
305 /*
306 ** Return true if the file-handle passed as an argument is
307 ** an in-memory journal
308 */
309 static bool sqlite3IsMemJournal( sqlite3_file pJfd )
310 {
311 return pJfd.pMethods == MemJournalMethods;
312 }
313  
314 /*
315 ** Return the number of bytes required to store a MemJournal file descriptor.
316 */
317 static int sqlite3MemJournalSize()
318 {
319 return 3096; // sizeof( MemJournal );
320 }
321 }
322 }