1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
|
/* Copyright (c) 2007 PrimeBase Technologies GmbH
*
* PrimeBase XT
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* 2007-10-31 Paul McCullagh
*
* H&G2JCtL
*
* The new table cache. Caches all non-index data. This includes the data
* files and the row pointer files.
*/
#ifndef __xactlog_xt_h__
#define __xactlog_xt_h__
#include "pthread_xt.h"
#include "filesys_xt.h"
#include "sortedlist_xt.h"
struct XTThread;
struct XTOpenTable;
struct XTDatabase;
#ifdef DEBUG
//#define XT_USE_CACHE_DEBUG_SIZES
#endif
#ifdef XT_USE_CACHE_DEBUG_SIZES
#define XT_XLC_BLOCK_SHIFTS 5
#define XT_XLC_FILE_SLOTS 7
#define XT_XLC_SEGMENT_SHIFTS 1
#define XT_XLC_MAX_FLUSH_SEG_COUNT 10
#define XT_XLC_MAX_FREE_COUNT 10
#else
/* Block size is determined by the number of shifts 1 << 15 = 32K */
#define XT_XLC_BLOCK_SHIFTS 15
#define XT_XLC_FILE_SLOTS 71
/* The number of segments are determined by the segment shifts 1 << 3 = 8 */
#define XT_XLC_SEGMENT_SHIFTS 3
#define XT_XLC_MAX_FLUSH_SEG_COUNT 250
#define XT_XLC_MAX_FREE_COUNT 100
#endif
#define XT_XLC_BLOCK_SIZE (1 << XT_XLC_BLOCK_SHIFTS)
#define XT_XLC_BLOCK_MASK (XT_XLC_BLOCK_SIZE - 1)
#define XT_TIME_DIFF(start, now) (\
((xtWord4) (now) < (xtWord4) (start)) ? \
((xtWord4) 0XFFFFFFFF - ((xtWord4) (start) - (xtWord4) (now))) : \
((xtWord4) (now) - (xtWord4) (start)))
#define XLC_SEGMENT_COUNT ((off_t) 1 << XT_XLC_SEGMENT_SHIFTS)
#define XLC_SEGMENT_MASK (XLC_SEGMENT_COUNT - 1)
#define XLC_MAX_FLUSH_COUNT (XT_XLC_MAX_FLUSH_SEG_COUNT * XLC_SEGMENT_COUNT)
#define XLC_BLOCK_FREE 0
#define XLC_BLOCK_READING 1
#define XLC_BLOCK_CLEAN 2
#define XT_RECYCLE_LOGS 0
#define XT_DELETE_LOGS 1
#define XT_KEEP_LOGS 2
#define XT_XLOG_NO_WRITE_NO_FLUSH 0
#define XT_XLOG_WRITE_AND_FLUSH 1
#define XT_XLOG_WRITE_AND_NO_FLUSH 2
/* LOG CACHE ---------------------------------------------------- */
typedef struct XTXLogBlock {
off_t xlb_address; /* The block address. */
xtLogID xlb_log_id; /* The log id of the block. */
xtWord4 xlb_state; /* Block status. */
struct XTXLogBlock *xlb_next; /* Pointer to next block on hash list, or next free block on free list. */
xtWord1 xlb_data[XT_XLC_BLOCK_SIZE];
} XTXLogBlockRec, *XTXLogBlockPtr;
/* A disk cache segment. The cache is divided into a number of segments
* to improve concurrency.
*/
typedef struct XTXLogCacheSeg {
xt_mutex_type lcs_lock; /* The cache segment lock. */
xt_cond_type lcs_cond;
XTXLogBlockPtr *lcs_hash_table;
} XTXLogCacheSegRec, *XTXLogCacheSegPtr;
typedef struct XTXLogCache {
xt_mutex_type xlc_lock; /* The public cache lock. */
xt_cond_type xlc_cond; /* The public cache wait condition. */
XTXLogCacheSegRec xlc_segment[XLC_SEGMENT_COUNT];
XTXLogBlockPtr xlc_blocks;
XTXLogBlockPtr xlc_blocks_end;
XTXLogBlockPtr xlc_next_to_free;
xtWord4 xlc_free_count;
xtWord4 xlc_hash_size;
xtWord4 xlc_block_count;
xtWord8 xlc_upper_limit;
} XTXLogCacheRec;
/* LOG ENTRIES ---------------------------------------------------- */
#define XT_LOG_ENT_EOF 0
#define XT_LOG_ENT_HEADER 1
#define XT_LOG_ENT_NEW_LOG 2 /* Move to the next log! NOTE!! May not appear in a group!! */
#define XT_LOG_ENT_DEL_LOG 3 /* Delete the given transaction/data log. */
#define XT_LOG_ENT_NEW_TAB 4 /* This record indicates a new table was created. */
#define XT_LOG_ENT_COMMIT 5 /* Transaction was committed. */
#define XT_LOG_ENT_ABORT 6 /* Transaction was aborted. */
#define XT_LOG_ENT_CLEANUP 7 /* Written after a cleanup. */
#define XT_LOG_ENT_REC_MODIFIED 8 /* This records has been modified by the transaction. */
#define XT_LOG_ENT_UPDATE 9
#define XT_LOG_ENT_UPDATE_BG 10
#define XT_LOG_ENT_UPDATE_FL 11
#define XT_LOG_ENT_UPDATE_FL_BG 12
#define XT_LOG_ENT_INSERT 13
#define XT_LOG_ENT_INSERT_BG 14
#define XT_LOG_ENT_INSERT_FL 15
#define XT_LOG_ENT_INSERT_FL_BG 16
#define XT_LOG_ENT_DELETE 17
#define XT_LOG_ENT_DELETE_BG 18
#define XT_LOG_ENT_DELETE_FL 19
#define XT_LOG_ENT_DELETE_FL_BG 20
#define XT_DEFUNKT_REC_FREED 21 /* This record has been placed in the free list. */
#define XT_DEFUNKT_REC_REMOVED 22 /* Free record and dependecies: index references, blob references. */
#define XT_DEFUNKT_REC_REMOVED_EXT 23 /* Free record and dependecies: index references, extended data, blob references. */
#define XT_LOG_ENT_REC_REMOVED_BI 38 /* Free record and dependecies: includes before image of record, for freeing index, etc. */
#define XT_LOG_ENT_REC_REMOVED_BI_L 40 /* Free record and dependecies: as above, but link the record into the free list. */
#define XT_LOG_ENT_REC_MOVED 24 /* The record has been moved by the compactor. */
#define XT_LOG_ENT_REC_CLEANED 25 /* This record has been cleaned by the sweeper. */
#define XT_LOG_ENT_REC_CLEANED_1 26 /* This record has been cleaned by the sweeper (short form). */
#define XT_LOG_ENT_REC_UNLINKED 27 /* The record after this record is unlinked from the variation list. */
#define XT_LOG_ENT_ROW_NEW 28 /* Row allocated from the EOF. */
#define XT_LOG_ENT_ROW_NEW_FL 29 /* Row allocated from the free list. */
#define XT_LOG_ENT_ROW_ADD_REC 30 /* Record added to the row. */
#define XT_LOG_ENT_ROW_SET 31
#define XT_LOG_ENT_ROW_FREED 32
#define XT_LOG_ENT_OP_SYNC 33 /* Operations syncronised. */
#define XT_LOG_ENT_EXT_REC_OK 34 /* An extended record */
#define XT_LOG_ENT_EXT_REC_DEL 35 /* A deleted extended record */
#define XT_LOG_ENT_NO_OP 36 /* If write to the database fails, we still try to log the
* op code, in an attempt to continue, if writting to log
* still works.
*/
#define XT_LOG_ENT_END_OF_LOG 37 /* This is a record that indicates the end of the log, and
* fills to the end of a 512 byte block.
*/
#define XT_LOG_ENT_PREPARE 39 /* XA prepare log entry. */
#define XT_LOG_FILE_MAGIC 0xAE88FE12
#define XT_LOG_VERSION_NO 1
typedef struct XTXactLogHeader {
xtWord1 xh_status_1; /* XT_LOG_ENT_HEADER */
xtWord1 xh_checksum_1;
XTDiskValue4 xh_size_4; /* Must be set to sizeof(XTXactLogHeaderDRec). */
XTDiskValue8 xh_free_space_8; /* The accumulated free space in this file. */
XTDiskValue8 xh_file_len_8; /* The last confirmed correct file length (always set on close). */
XTDiskValue8 xh_comp_pos_8; /* Compaction position (XT_DL_STATUS_CO_SOURCE only). */
xtWord1 xh_comp_stat_1; /* The compaction status XT_DL_STATUS_CO_SOURCE/XT_DL_STATUS_CO_TARGET */
XTDiskValue4 xh_log_id_4;
XTDiskValue2 xh_version_2; /* XT_LOG_VERSION_NO */
XTDiskValue2 xh_unused_2; /* Set to zero (added because xh_version_2 was XTDiskValue4), but treated as 2 */
XTDiskValue4 xh_magic_4; /* MUST always be at the end of the structure!! */
} XTXactLogHeaderDRec, *XTXactLogHeaderDPtr;
/* This is the original log head size (don't change): */
#define XT_MIN_LOG_HEAD_SIZE (offsetof(XTXactLogHeaderDRec, xh_log_id_4) + 4)
#define XT_LOG_HEAD_MAGIC(b, l) XT_GET_DISK_4(((xtWord1 *) (b)) + (l) - 4)
typedef struct XTXactNewLogEntry {
xtWord1 xl_status_1; /* XT_LOG_ENT_NEW_LOG, XT_LOG_ENT_DEL_LOG */
xtWord1 xl_checksum_1;
XTDiskValue4 xl_log_id_4; /* Store the current table ID. */
} XTXactNewLogEntryDRec, *XTXactNewLogEntryDPtr;
typedef struct XTXactNewTabEntry {
xtWord1 xt_status_1; /* XT_LOG_ENT_NEW_TAB */
xtWord1 xt_checksum_1;
XTDiskValue4 xt_tab_id_4; /* Store the current table ID. */
} XTXactNewTabEntryDRec, *XTXactNewTabEntryDPtr;
/* This record must appear in a transaction group, and therefore has no transaction ID: */
typedef struct XTXactEndEntry {
xtWord1 xe_status_1; /* XT_LOG_ENT_COMMIT, XT_LOG_ENT_ABORT */
xtWord1 xe_checksum_1;
XTDiskValue4 xe_xact_id_4; /* The transaction. */
XTDiskValue4 xe_not_used_4; /* Was the end sequence number (no longer used - v1.0.04+), set to zero). */
} XTXactEndEntryDRec, *XTXactEndEntryDPtr;
typedef struct XTXactPrepareEntry {
xtWord1 xp_status_1; /* XT_LOG_ENT_PREPARE */
XTDiskValue2 xp_checksum_2;
XTDiskValue4 xp_xact_id_4; /* The transaction. */
xtWord1 xp_xa_len_1; /* The length of the XA data. */
xtWord1 xp_xa_data[XT_MAX_XA_DATA_SIZE];
} XTXactPrepareEntryDRec, *XTXactPrepareEntryDPtr;
typedef struct XTXactCleanupEntry {
xtWord1 xc_status_1; /* XT_LOG_ENT_CLEANUP */
xtWord1 xc_checksum_1;
XTDiskValue4 xc_xact_id_4; /* The transaction that was cleaned up. */
} XTXactCleanupEntryDRec, *XTXactCleanupEntryDPtr;
typedef struct XTactUpdateEntry {
xtWord1 xu_status_1; /* XT_LOG_ENT_REC_MODIFIED, XT_LOG_ENT_UPDATE, XT_LOG_ENT_INSERT, XT_LOG_ENT_DELETE */
/* XT_LOG_ENT_UPDATE_BG, XT_LOG_ENT_INSERT_BG, XT_LOG_ENT_DELETE_BG */
XTDiskValue2 xu_checksum_2;
XTDiskValue4 xu_op_seq_4; /* Operation sequence number. */
XTDiskValue4 xu_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 xu_rec_id_4; /* Offset of the new updated record. */
XTDiskValue2 xu_size_2; /* Size of the record data. */
/* This is the start of the actual record data: */
xtWord1 xu_rec_type_1; /* Type of the record. */
xtWord1 xu_stat_id_1;
xtDiskRecordID4 xu_prev_rec_id_4; /* The previous variation of this record. */
XTDiskValue4 xu_xact_id_4; /* The transaction ID. */
XTDiskValue4 xu_row_id_4; /* The row ID of this record. */
} XTactUpdateEntryDRec, *XTactUpdateEntryDPtr;
typedef struct XTactUpdateFLEntry {
xtWord1 xf_status_1; /* XT_LOG_ENT_UPDATE_FL, XT_LOG_ENT_INSERT_FL, XT_LOG_ENT_DELETE_FL */
/* XT_LOG_ENT_UPDATE_FL_BG, XT_LOG_ENT_INSERT_FL_BG, XT_LOG_ENT_DELETE_FL_BG */
XTDiskValue2 xf_checksum_2;
XTDiskValue4 xf_op_seq_4; /* Operation sequence number. */
XTDiskValue4 xf_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 xf_rec_id_4; /* Offset of the new updated record. */
XTDiskValue2 xf_size_2; /* Size of the record data. */
xtDiskRecordID4 xf_free_rec_id_4; /* Update to the free list. */
/* This is the start of the actual record data: */
xtWord1 xf_rec_type_1; /* Type of the record. */
xtWord1 xf_stat_id_1;
xtDiskRecordID4 xf_prev_rec_id_4; /* The previous variation of this record. */
XTDiskValue4 xf_xact_id_4; /* The transaction ID. */
XTDiskValue4 xf_row_id_4; /* The row ID of this record. */
} XTactUpdateFLEntryDRec, *XTactUpdateFLEntryDPtr;
typedef struct XTactFreeRecEntry {
xtWord1 fr_status_1; /* XT_DEFUNKT_REC_REMOVED, XT_DEFUNKT_REC_REMOVED_EXT, XT_DEFUNKT_REC_FREED */
xtWord1 fr_checksum_1;
XTDiskValue4 fr_op_seq_4; /* Operation sequence number. */
XTDiskValue4 fr_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 fr_rec_id_4; /* Offset of the new written record. */
/* This data confirms the record state for release of
* attached resources (extended records, indexes and blobs)
*/
xtWord1 fr_stat_id_1; /* The statement ID of the record. */
XTDiskValue4 fr_xact_id_4; /* The transaction ID of the record. */
/* This is the start of the actual record data: */
xtWord1 fr_rec_type_1;
xtWord1 fr_not_used_1;
xtDiskRecordID4 fr_next_rec_id_4; /* The next block on the free list. */
} XTactFreeRecEntryDRec, *XTactFreeRecEntryDPtr;
typedef struct XTactRemoveBIEntry {
xtWord1 rb_status_1; /* XT_LOG_ENT_REC_REMOVED_BI */
XTDiskValue2 rb_checksum_2;
XTDiskValue4 rb_op_seq_4; /* Operation sequence number. */
XTDiskValue4 rb_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 rb_rec_id_4; /* Offset of the new written record. */
XTDiskValue2 rb_size_2; /* Size of the record data. */
xtWord1 rb_new_rec_type_1; /* New type of the record (needed for below). */
/* This is the start of the record data, with some fields overwritten for the free: */
xtWord1 rb_rec_type_1; /* Type of the record. */
xtWord1 rb_stat_id_1;
xtDiskRecordID4 rb_next_rec_id_4; /* The next block on the free list (overwritten). */
XTDiskValue4 rb_xact_id_4; /* The transaction ID. */
XTDiskValue4 rb_row_id_4; /* The row ID of this record. */
} XTactRemoveBIEntryDRec, *XTactRemoveBIEntryDPtr;
typedef struct XTactRemoveBILEntry {
xtWord1 bl_status_1; /* XT_LOG_ENT_REC_REMOVED_BI_L */
XTDiskValue2 bl_checksum_2;
XTDiskValue4 bl_op_seq_4; /* Operation sequence number. */
XTDiskValue4 bl_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 bl_rec_id_4; /* Offset of the new written record. */
XTDiskValue2 bl_size_2; /* Size of the record data. */
xtWord1 bl_new_rec_type_1; /* New type of the record (needed for below). */
xtDiskRecordID4 bl_prev_rec_id_4; /* Offset of the new written record. */
/* This is the start of the record data, with some fields overwritten for the free: */
xtWord1 bl_rec_type_1; /* Type of the record. */
xtWord1 bl_stat_id_1;
xtDiskRecordID4 bl_next_rec_id_4; /* The next block on the free list (overwritten). */
XTDiskValue4 bl_xact_id_4; /* The transaction ID. */
XTDiskValue4 bl_row_id_4; /* The row ID of this record. */
} XTactRemoveBILEntryDRec, *XTactRemoveBILEntryDPtr;
typedef struct XTactWriteRecEntry {
xtWord1 xw_status_1; /* XT_LOG_ENT_REC_MOVED, XT_LOG_ENT_REC_CLEANED, XT_LOG_ENT_REC_CLEANED_1,
* XT_LOG_ENT_REC_UNLINKED */
xtWord1 xw_checksum_1;
XTDiskValue4 xw_op_seq_4; /* Operation sequence number. */
XTDiskValue4 xw_tab_id_4; /* Table ID of the record. */
xtDiskRecordID4 xw_rec_id_4; /* Offset of the new written record. */
/* This is the start of the actual record data: */
xtWord1 xw_rec_type_1;
xtWord1 xw_stat_id_1;
xtDiskRecordID4 xw_next_rec_id_4; /* The next block on the free list. */
} XTactWriteRecEntryDRec, *XTactWriteRecEntryDPtr;
typedef struct XTactRowAddedEntry {
xtWord1 xa_status_1; /* XT_LOG_ENT_ROW_NEW or XT_LOG_ENT_ROW_NEW_FL */
xtWord1 xa_checksum_1;
XTDiskValue4 xa_op_seq_4; /* Operation sequence number. */
XTDiskValue4 xa_tab_id_4; /* Table ID of the record. */
XTDiskValue4 xa_row_id_4; /* The row ID of the row allocated. */
XTDiskValue4 xa_free_list_4; /* Change to the free list (ONLY for XT_LOG_ENT_ROW_NEW_FL). */
} XTactRowAddedEntryDRec, *XTactRowAddedEntryDPtr;
typedef struct XTactWriteRowEntry {
xtWord1 wr_status_1; /* XT_LOG_ENT_ROW_ADD_REC, XT_LOG_ENT_ROW_SET, XT_LOG_ENT_ROW_FREED */
xtWord1 wr_checksum_1;
XTDiskValue4 wr_op_seq_4; /* Operation sequence number. */
XTDiskValue4 wr_tab_id_4; /* Table ID of the record. */
XTDiskValue4 wr_row_id_4; /* Row ID of the row that was modified. */
/* This is the start of the actual record data: */
XTDiskValue4 wr_ref_id_4; /* The row reference data. */
} XTactWriteRowEntryDRec, *XTactWriteRowEntryDPtr;
typedef struct XTactOpSyncEntry {
xtWord1 os_status_1; /* XT_LOG_ENT_OP_SYNC */
xtWord1 os_checksum_1;
XTDiskValue4 os_time_4; /* Time of the restart. */
} XTactOpSyncEntryDRec, *XTactOpSyncEntryDPtr;
typedef struct XTactNoOpEntry {
xtWord1 no_status_1; /* XT_LOG_ENT_NO_OP */
xtWord1 no_checksum_1;
XTDiskValue4 no_op_seq_4; /* Operation sequence number. */
XTDiskValue4 no_tab_id_4; /* Table ID of the record. */
} XTactNoOpEntryDRec, *XTactNoOpEntryDPtr;
typedef struct XTactExtRecEntry {
xtWord1 er_status_1; /* XT_LOG_ENT_EXT_REC_OK, XT_LOG_ENT_EXT_REC_DEL */
XTDiskValue4 er_data_size_4; /* Size of this record data area only. */
XTDiskValue4 er_tab_id_4; /* The table referencing this extended record. */
xtDiskRecordID4 er_rec_id_4; /* The ID of the reference record. */
xtWord1 er_data[XT_VAR_LENGTH];
} XTactExtRecEntryDRec, *XTactExtRecEntryDPtr;
typedef union XTXactLogBuffer {
XTXactLogHeaderDRec xh;
XTXactNewLogEntryDRec xl;
XTXactNewTabEntryDRec xt;
XTXactEndEntryDRec xe;
XTXactCleanupEntryDRec xc;
XTactUpdateEntryDRec xu;
XTactUpdateFLEntryDRec xf;
XTactFreeRecEntryDRec fr;
XTactRemoveBIEntryDRec rb;
XTactRemoveBILEntryDRec bl;
XTactWriteRecEntryDRec xw;
XTactRowAddedEntryDRec xa;
XTactWriteRowEntryDRec wr;
XTactOpSyncEntryDRec os;
XTactExtRecEntryDRec er;
XTactNoOpEntryDRec no;
XTXactPrepareEntryDRec xp;
} XTXactLogBufferDRec, *XTXactLogBufferDPtr;
/* ---------------------------------------- */
typedef struct XTXactSeqRead {
size_t xseq_buffer_size; /* Size of the buffer. */
xtBool xseq_load_cache; /* TRUE if reads should load the cache! */
xtLogID xseq_log_id;
XTOpenFilePtr xseq_log_file;
off_t xseq_log_eof;
xtLogOffset xseq_buf_log_offset; /* File offset of the buffer. */
size_t xseq_buffer_len; /* Amount of data in the buffer. */
xtWord1 *xseq_buffer;
xtLogID xseq_rec_log_id; /* The current record log ID. */
xtLogOffset xseq_rec_log_offset; /* The current log read position. */
size_t xseq_record_len; /* The length of the current record. */
} XTXactSeqReadRec, *XTXactSeqReadPtr;
typedef struct XTXactLogFile {
xtLogID lf_log_id;
off_t lr_file_len; /* The log file size (0 means this is the last log) */
} XTXactLogFileRec, *XTXactLogFilePtr;
/*
* The transaction log. Each database has one.
*/
/* Does not seem to make much difference... */
#ifndef XT_NO_ATOMICS
/* This function uses atomic ops: */
//#define XT_XLOG_WAIT_SPINS
#endif
typedef struct XTDatabaseLog {
struct XTDatabase *xl_db;
off_t xl_log_file_threshold;
u_int xl_log_file_count; /* Number of logs to use (>= 1). */
u_int xt_log_file_dyn_count; /* A dynamic value to add to log file count. */
u_int xt_log_file_dyn_dec; /* Used to descide when to decrement the dynamic count. */
size_t xl_size_of_buffers; /* The size of both log buffers. */
xtWord8 xl_log_bytes_written; /* The total number of bytes written to the log, after recovery. */
xtWord8 xl_log_bytes_flushed; /* The total number of bytes flushed to the log, after recovery. */
xtWord8 xl_log_bytes_read; /* The total number of log bytes read, after recovery. */
u_int xl_last_flush_time; /* Last flush time in micro-seconds. */
/* The writer log buffer: */
xt_mutex_type xl_write_lock;
xt_cond_type xl_write_cond;
#ifdef XT_XLOG_WAIT_SPINS
xtWord4 xt_writing; /* 1 if a thread is writing. */
xtWord4 xt_waiting; /* Count of the threads waiting on the xl_write_cond. */
#else
xtBool xt_writing; /* TRUE if a thread is writing. */
#endif
xtLogID xl_log_id; /* The number of the write log. */
XTOpenFilePtr xl_log_file; /* The open write log. */
XTSpinLockRec xl_buffer_lock; /* This locks both the write and the append log buffers. */
xtLogID xl_max_log_id; /* The ID of the highest log on disk. */
xtLogID xl_write_log_id; /* This is the log ID were the write data will go. */
xtLogOffset xl_write_log_offset; /* The file offset of the write log. */
size_t xl_write_buf_pos;
size_t xl_write_buf_pos_start;
xtWord1 *xl_write_buffer;
xtBool xl_write_done; /* TRUE if the write buffer has been written! */
xtLogID xl_append_log_id; /* This is the log ID were the append data will go. */
xtLogOffset xl_append_log_offset; /* The file offset in the log were the append data will go. */
size_t xl_append_buf_pos; /* The amount of data in the append buffer. */
size_t xl_append_buf_pos_start; /* The amount of data in the append buffer already written. */
xtWord1 *xl_append_buffer;
xtLogID xl_flush_log_id; /* The last log flushed. */
xtLogOffset xl_flush_log_offset; /* The position in the log flushed. */
void xlog_setup(struct XTThread *self, struct XTDatabase *db, off_t log_file_size, size_t transaction_buffer_size, int log_count);
xtBool xlog_set_write_offset(xtLogID log_id, xtLogOffset log_offset, xtLogID max_log_id, struct XTThread *thread);
void xlog_close(struct XTThread *self);
void xlog_exit(struct XTThread *self);
void xlog_name(size_t size, char *path, xtLogID log_id);
int xlog_delete_log(xtLogID del_log_id, struct XTThread *thread);
xtBool xlog_append(struct XTThread *thread, size_t size1, xtWord1 *data1, size_t size2, xtWord1 *data2, int flush_log_at_trx_commit, xtLogID *log_id, xtLogOffset *log_offset);
xtBool xlog_flush(struct XTThread *thread);
xtBool xlog_flush_pending();
xtBool xlog_seq_init(XTXactSeqReadPtr seq, size_t buffer_size, xtBool load_cache);
void xlog_seq_exit(XTXactSeqReadPtr seq);
void xlog_seq_close(XTXactSeqReadPtr seq);
xtBool xlog_seq_start(XTXactSeqReadPtr seq, xtLogID log_id, xtLogOffset log_offset, xtBool missing_ok);
xtBool xlog_rnd_read(XTXactSeqReadPtr seq, xtLogID log_id, xtLogOffset log_offset, size_t size, xtWord1 *data, size_t *read, struct XTThread *thread);
size_t xlog_bytes_to_write();
xtBool xlog_read_from_cache(XTXactSeqReadPtr seq, xtLogID log_id, xtLogOffset log_offset, size_t size, off_t eof, xtWord1 *buffer, size_t *data_read, struct XTThread *thread);
xtBool xlog_write_thru(XTXactSeqReadPtr seq, size_t size, xtWord1 *data, struct XTThread *thread);
xtBool xlog_verify(XTXactLogBufferDPtr record, size_t rec_size, xtLogID log_id);
xtBool xlog_seq_next(XTXactSeqReadPtr seq, XTXactLogBufferDPtr *entry, xtBool verify, struct XTThread *thread);
void xlog_seq_skip(XTXactSeqReadPtr seq, size_t size);
private:
xtBool xlog_open_log(xtLogID log_id, off_t curr_eof, struct XTThread *thread);
} XTDatabaseLogRec, *XTDatabaseLogPtr;
xtBool xt_xlog_flush_log(struct XTDatabase *db, struct XTThread *thread);
xtBool xt_xlog_log_data(struct XTThread *thread, size_t len, XTXactLogBufferDPtr log_entry, int flush_log_at_trx_commit);
xtBool xt_xlog_modify_table(xtTableID tab_id, u_int status, xtOpSeqNo op_seq, xtWord1 new_rec_type, xtRecordID free_rec_id, xtRecordID address, size_t size, xtWord1 *data, struct XTThread *thread);
void xt_xlog_init(struct XTThread *self, size_t cache_size);
void xt_xlog_exit(struct XTThread *self);
xtInt8 xt_xlog_get_usage();
xtInt8 xt_xlog_get_size();
xtLogID xt_xlog_get_min_log(struct XTThread *self, struct XTDatabase *db);
void xt_xlog_delete_logs(struct XTThread *self, struct XTDatabase *db);
void xt_start_writer(struct XTThread *self, struct XTDatabase *db);
void xt_wait_for_writer(struct XTThread *self, struct XTDatabase *db);
void xt_stop_writer(struct XTThread *self, struct XTDatabase *db);
#endif
|