1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* 2005-02-08 Paul McCullagh
23
#ifndef __xt_table_h__
24
#define __xt_table_h__
28
#include "datalog_xt.h"
29
#include "filesys_xt.h"
30
#include "hashtab_xt.h"
35
#include "tabcache_xt.h"
36
#include "xactlog_xt.h"
45
#define XT_TAB_INCOMPATIBLE_VERSION 4
46
#define XT_TAB_CURRENT_VERSION 5
48
/* This version of the index does not have lazy
49
* delete. The new version is compatible with
50
* this and maintains the old format.
52
#define XT_IND_NO_LAZY_DELETE 3
53
#define XT_IND_LAZY_DELETE_OK 4
54
#ifdef XT_USE_LAZY_DELETE
55
#define XT_IND_CURRENT_VERSION XT_IND_LAZY_DELETE_OK
57
#define XT_IND_CURRENT_VERSION XT_IND_NO_LAZY_DELETE
60
#define XT_HEAD_BUFFER_SIZE 1024
62
#define XT_TABLE_NAME_BUF_SIZE (XT_IDENTIFIER_NAME_SIZE + XT_IDENTIFIER_NAME_SIZE + XT_IDENTIFIER_NAME_SIZE + 3)
65
//#define XT_TRACK_INDEX_UPDATES
66
//#define XT_TRACK_RETURNED_ROWS
70
* NOTE: Records may only be freed (placed on the free list), after
71
* all currently running transactions have ended.
72
* The reason is, running transactions may have references in memory
73
* to these records (a sequential scan has a large buffer).
74
* If the records are freed they may be re-used. This will
75
* cause problems because the references will then refer to
78
* As a result, deleted records are first placed in the
79
* REMOVED state. Later, when transactions have quit, they
82
#define XT_TAB_STATUS_FREED 0x00 /* On the free list. */
83
#define XT_TAB_STATUS_DELETE 0x01 /* A transactional delete record (an "update" that indicates a delete). */
84
#define XT_TAB_STATUS_FIXED 0x02
85
#define XT_TAB_STATUS_VARIABLE 0x03 /* Uses one block, but has the variable format. */
86
#define XT_TAB_STATUS_EXT_DLOG 0x04 /* Variable format, and the trailing part of the record in the data log. */
87
#define XT_TAB_STATUS_EXT_HDATA 0x05 /* Variable format, and the trailing part of the record in the handle data file. */
88
#define XT_TAB_STATUS_DATA 0x06 /* A block of data with a next pointer (5 bytes overhead). */
89
#define XT_TAB_STATUS_END_DATA 0x07 /* An block of data without an end pointer (1 byte overhead). */
90
#define XT_TAB_STATUS_MASK 0x0F
92
#define XT_TAB_STATUS_DEL_CLEAN (XT_TAB_STATUS_DELETE | XT_TAB_STATUS_CLEANED_BIT)
93
#define XT_TAB_STATUS_FIX_CLEAN (XT_TAB_STATUS_FIXED | XT_TAB_STATUS_CLEANED_BIT)
94
#define XT_TAB_STATUS_VAR_CLEAN (XT_TAB_STATUS_VARIABLE | XT_TAB_STATUS_CLEANED_BIT)
95
#define XT_TAB_STATUS_EXT_CLEAN (XT_TAB_STATUS_EXT_DLOG | XT_TAB_STATUS_CLEANED_BIT)
97
#define XT_TAB_STATUS_CLEANED_BIT 0x80 /* This bit is set when the record is cleaned and committed. */
99
#define XT_REC_IS_CLEAN(x) ((x) & XT_TAB_STATUS_CLEANED_BIT)
100
#define XT_REC_IS_FREE(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_FREED)
101
#define XT_REC_IS_DELETE(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_DELETE)
102
#define XT_REC_IS_FIXED(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_FIXED)
103
#define XT_REC_IS_VARIABLE(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_VARIABLE)
104
#define XT_REC_IS_EXT_DLOG(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_EXT_DLOG)
105
#define XT_REC_IS_EXT_HDATA(x) (((x) & XT_TAB_STATUS_MASK) == XT_TAB_STATUS_EXT_HDATA)
106
#define XT_REC_NOT_VALID(x) (XT_REC_IS_FREE(x) || XT_REC_IS_DELETE(x))
108
/* Results for xt_use_table_by_id(): */
110
#define XT_TAB_NOT_FOUND 1
111
#define XT_TAB_NO_DICTIONARY 2
112
#define XT_TAB_POOL_CLOSED 3 /* Cannot open table at the moment, the pool is closed. */
113
#define XT_TAB_FAILED 4
116
#define XT_TAB_ROW_USE_PTHREAD_RW
118
//#define XT_TAB_ROW_USE_PTHREAD_RW
119
#define XT_TAB_ROW_USE_XSMUTEX
120
//#define XT_TAB_ROW_USE_SPINXSLOCK
121
//#define XT_TAB_ROW_USE_SPINLOCK
124
#if defined(XT_TAB_ROW_USE_PTHREAD_RW)
125
#define XT_TAB_ROW_LOCK_TYPE xt_rwlock_type
126
#define XT_TAB_ROW_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
127
#define XT_TAB_ROW_FREE_LOCK(s, i) xt_free_rwlock(i)
128
#define XT_TAB_ROW_READ_LOCK(i, s) xt_slock_rwlock_ns(i)
129
#define XT_TAB_ROW_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
130
#define XT_TAB_ROW_UNLOCK(i, s) xt_unlock_rwlock_ns(i)
131
#elif defined(XT_TAB_ROW_USE_XSMUTEX)
132
#define XT_TAB_ROW_LOCK_TYPE XTMutexXSLockRec
133
#define XT_TAB_ROW_INIT_LOCK(s, i) xt_xsmutex_init_with_autoname(s, i)
134
#define XT_TAB_ROW_FREE_LOCK(s, i) xt_xsmutex_free(s, i)
135
#define XT_TAB_ROW_READ_LOCK(i, s) xt_xsmutex_slock(i, (s)->t_id)
136
#define XT_TAB_ROW_WRITE_LOCK(i, s) xt_xsmutex_xlock(i, (s)->t_id)
137
#define XT_TAB_ROW_UNLOCK(i, s) xt_xsmutex_unlock(i, (s)->t_id)
138
#elif defined(XT_TAB_ROW_USE_SPINXSLOCK)
139
#define XT_TAB_ROW_LOCK_TYPE XTSpinXSLockRec
140
#define XT_TAB_ROW_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
141
#define XT_TAB_ROW_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
142
#define XT_TAB_ROW_READ_LOCK(i, s) xt_spinxslock_slock(i, (s)->t_id)
143
#define XT_TAB_ROW_WRITE_LOCK(i, s) xt_spinxslock_xlock(i, FALSE, (s)->t_id)
144
#define XT_TAB_ROW_UNLOCK(i, s) xt_spinxslock_unlock(i, (s)->t_id)
145
#elif defined(XT_TAB_ROW_USE_SPINLOCK)
146
#define XT_TAB_ROW_LOCK_TYPE XTSpinLockRec
147
#define XT_TAB_ROW_INIT_LOCK(s, i) xt_spinlock_init_with_autoname(s, i)
148
#define XT_TAB_ROW_FREE_LOCK(s, i) xt_spinlock_free(s, i)
149
#define XT_TAB_ROW_READ_LOCK(i, s) xt_spinlock_lock(i)
150
#define XT_TAB_ROW_WRITE_LOCK(i, s) xt_spinlock_lock(i)
151
#define XT_TAB_ROW_UNLOCK(i, s) xt_spinlock_unlock(i)
153
#error Please define the lock type
156
/* ------- TABLE DATA FILE ------- */
158
#define XT_TAB_DATA_MAGIC 0x1234ABCD
160
#define XT_FORMAT_DEF_SPACE 512
162
#define XT_TF_REAL_TEMP_TABLE 1 /* A real temp table, created by the user. */
163
#define XT_TF_MEMORY_TABLE 2
164
#define XT_TF_DDL_TEMP_TABLE 4 /* A temp table created for DDL purposes. */
166
#define XT_IS_TEMP_TABLE(x) ((x) & (XT_TF_REAL_TEMP_TABLE | XT_TF_MEMORY_TABLE | XT_TF_DDL_TEMP_TABLE))
168
#define XT_TABLE_TYPE_STANDARD 1
169
#define XT_TABLE_TYPE_TEMPORARY 2
170
#define XT_TABLE_TYPE_INTERNAL 3
171
#define XT_TABLE_TYPE_FUNCTION 4
174
* This header ensures that no record in the data file has the offset 0.
176
typedef struct XTTableHead {
177
XTDiskValue4 th_head_size_4; /* The size of the table header. */
178
XTDiskValue4 th_op_seq_4;
179
XTDiskValue6 th_row_free_6;
180
XTDiskValue6 th_row_eof_6;
181
XTDiskValue6 th_row_fnum_6;
182
XTDiskValue6 th_rec_free_6;
183
XTDiskValue6 th_rec_eof_6;
184
XTDiskValue6 th_rec_fnum_6;
185
} XTTableHeadDRec, *XTTableHeadDPtr;
187
typedef struct XTTableFormat {
188
XTDiskValue4 tf_format_size_4; /* The size of this structure (table format). */
189
XTDiskValue4 tf_tab_head_size_4; /* The offset of the first record in the data handle file. */
190
XTDiskValue2 tf_tab_version_2; /* The table version number. */
191
XTDiskValue2 tf_tab_unused_2; /* Unused, set to zero */
192
XTDiskValue4 tf_rec_size_4; /* The maximum size of records in the table. */
193
XTDiskValue1 tf_rec_fixed_1; /* Set to 1 if this table contains fixed length records. */
194
XTDiskValue1 tf_reserved_1;
195
XTDiskValue8 tf_min_auto_inc_8; /* This is the minimum auto-increment value. */
196
xtWord1 tf_reserved[64]; /* Reserved, set to 0. */
197
char tf_definition[XT_VAR_LENGTH]; /* A cstring, currently it only contains the foreign key information. */
198
} XTTableFormatDRec, *XTTableFormatDPtr;
200
#define XT_STAT_ID_MASK(x) ((x) & (u_int) 0x000000FF)
202
/* A record that fits completely in the data file record */
203
typedef struct XTTabRecHead {
204
xtWord1 tr_rec_type_1;
205
xtWord1 tr_stat_id_1;
206
xtDiskRecordID4 tr_prev_rec_id_4; /* The previous variation of this record. */
207
XTDiskValue4 tr_xact_id_4; /* The transaction ID. */
208
XTDiskValue4 tr_row_id_4; /* The row ID of this record. */
209
} XTTabRecHeadDRec, *XTTabRecHeadDPtr;
211
typedef struct XTTabRecFix {
212
xtWord1 tr_rec_type_1; /* XT_TAB_STATUS_FREED, XT_TAB_STATUS_DELETE,
213
* XT_TAB_STATUS_FIXED, XT_TAB_STATUS_VARIABLE */
214
xtWord1 tr_stat_id_1;
215
xtDiskRecordID4 tr_prev_rec_id_4; /* The previous variation of this record. */
216
XTDiskValue4 tr_xact_id_4; /* The transaction ID. */
217
XTDiskValue4 tr_row_id_4; /* The row ID of this record. */
218
xtWord1 rf_data[XT_VAR_LENGTH]; /* NOTE: This data is in RAW MySQL format. */
219
} XTTabRecFixDRec, *XTTabRecFixDPtr;
221
/* An extended record that overflows into the log file: */
222
typedef struct XTTabRecExt {
223
xtWord1 tr_rec_type_1; /* XT_TAB_STATUS_EXT_DLOG */
224
xtWord1 tr_stat_id_1;
225
xtDiskRecordID4 tr_prev_rec_id_4; /* The previous variation of this record. */
226
XTDiskValue4 tr_xact_id_4; /* The transaction ID. */
227
XTDiskValue4 tr_row_id_4; /* The row ID of this record. */
228
XTDiskValue2 re_log_id_2; /* Reference to overflow area, log ID */
229
XTDiskValue6 re_log_offs_6; /* Reference to the overflow area, log offset */
230
XTDiskValue4 re_log_dat_siz_4; /* Size of the overflow data. */
231
xtWord1 re_data[XT_VAR_LENGTH]; /* This data is in packed PBXT format. */
232
} XTTabRecExtDRec, *XTTabRecExtDPtr;
234
typedef struct XTTabRecExtHdat {
235
xtWord1 tr_rec_type_1; /* XT_TAB_STATUS_EXT_HDATA */
236
xtWord1 tr_stat_id_1;
237
xtDiskRecordID4 tr_prev_rec_id_4; /* The previous variation of this record. */
238
XTDiskValue4 tr_xact_id_4; /* The transaction ID. */
239
XTDiskValue4 tr_row_id_4; /* The row ID of this record. */
240
XTDiskValue4 eh_blk_rec_id_4; /* The record ID of the next block. */
241
XTDiskValue2 eh_blk_siz_2; /* The total size of the data in the trailing blocks */
242
xtWord1 eh_data[XT_VAR_LENGTH]; /* This data is in packed PBXT format. */
243
} XTTabRecExtHdatDRec, *XTTabRecExtHdatDPtr;
245
typedef struct XTTabRecData {
246
xtWord1 tr_rec_type_1; /* XT_TAB_STATUS_DATA */
247
XTDiskValue4 rd_blk_rec_id_4; /* The record ID of the next block. */
248
xtWord1 rd_data[XT_VAR_LENGTH]; /* This data is in packed PBXT format. */
249
} XTTabRecDataDRec, *XTTabRecDataDPtr;
251
typedef struct XTTabRecEndDat {
252
xtWord1 tr_rec_type_1; /* XT_TAB_STATUS_END_DATA */
253
xtWord1 ed_data[XT_VAR_LENGTH]; /* This data is in packed PBXT format. */
254
} XTTabRecEndDatDRec, *XTTabRecEndDatDPtr;
256
#define XT_REC_FIX_HEADER_SIZE sizeof(XTTabRecHeadDRec)
257
#define XT_REC_EXT_HEADER_SIZE offsetof(XTTabRecExtDRec, re_data)
258
#define XT_REC_FIX_EXT_HEADER_DIFF (XT_REC_EXT_HEADER_SIZE - XT_REC_FIX_HEADER_SIZE)
260
typedef struct XTTabRecFree {
261
xtWord1 rf_rec_type_1;
262
xtWord1 rf_not_used_1;
263
xtDiskRecordID4 rf_next_rec_id_4; /* The next block on the free list. */
264
} XTTabRecFreeDRec, *XTTabRecFreeDPtr;
266
typedef struct XTTabRecInfo {
267
XTTabRecFixDPtr ri_fix_rec_buf; /* This references the start of the buffer (set for all types of records) */
268
XTTabRecExtDPtr ri_ext_rec; /* This is only set for extended records. */
269
xtWord4 ri_rec_buf_size;
270
XTactExtRecEntryDPtr ri_log_buf;
271
xtWord4 ri_log_data_size; /* This size of the data in the log record. */
272
xtRecordID ri_rec_id; /* The record ID. */
273
} XTTabRecInfoRec, *XTTabRecInfoPtr;
275
class XTFlushRecRowTask : public XTLockTask {
277
XTFlushRecRowTask() : XTLockTask(),
281
virtual xtBool tk_task(XTThreadPtr thread);
282
virtual void tk_reference();
283
virtual void tk_release();
285
struct XTTable *frt_table;
288
/* ------- TABLE ROW FILE ------- */
290
#define XT_TAB_ROW_SHIFTS 2
291
#define XT_TAB_ROW_MAGIC 0x4567CDEF
292
//#define XT_TAB_ROW_FREE 0
293
//#define XT_TAB_ROW_IN_USE 1
296
* NOTE: The shift count assumes the size of a table row
297
* reference is 8 bytes (XT_TAB_ROW_SHIFTS)
299
typedef struct XTTabRowRef {
300
XTDiskValue4 rr_ref_id_4; /* 4-byte reference, could be a RowID or a RecordID
301
* If this row is free, then it is a RowID, which
302
* references the next free row.
303
* If it is in use, then it is a RecordID which
304
* points to the first record in the variation
307
} XTTabRowRefDRec, *XTTabRowRefDPtr;
310
* This is the header for the row file. The size MUST be a
311
* the same size as sizeof(XTTabRowRefDRec)
313
typedef struct XTTabRowHead {
314
XTDiskValue4 rh_magic_4;
315
} XTTabRowHeadDRec, *XTTabRowHeadDPtr;
317
/* ------- TABLE & OPEN TABLES & TABLE LISTING ------- */
319
#ifdef XT_SORT_REC_WRITES
321
typedef struct XTDelayWrite {
326
} XTDelayWriteRec, *XTDelayWritePtr;
331
* Temporary tables do not need to be flused,
332
* and they also do not need to be recovered!
333
* Currently this is determined by the name of the
336
typedef struct XTTable : public XTHeap {
337
struct XTDatabase *tab_db; /* Heap pointer */
338
XTPathStrPtr tab_name;
339
xtBool tab_free_locks;
342
xtWord8 tab_auto_inc; /* The last value returned as an auto-increment value {PRE-INC}. */
343
XTSpinLockRec tab_ainc_lock; /* Lock for the auto-increment counter. */
345
size_t tab_index_format_offset;
346
size_t tab_index_header_size;
347
size_t tab_index_page_size;
348
u_int tab_index_block_shifts;
349
XTIndexHeadDPtr tab_index_head;
350
size_t tab_table_format_offset;
351
size_t tab_table_head_size;
352
XTDictionaryRec tab_dic;
353
xt_mutex_type tab_dic_field_lock; /* Lock for setting field->ptr!. */
355
XTRowLocksRec tab_locks; /* The locks held on this table. */
357
XTTableSeqRec tab_seq; /* The table operation sequence. */
358
XTTabCacheRec tab_rows;
359
XTTabCacheRec tab_recs;
361
/* Used to apply operations to the database in order. */
362
XTSortedListPtr tab_op_list; /* The operation list. Operations to be applied. */
364
/* Values that belong in the header when flushed! */
365
xtBool1 tab_flush_pending; /* TRUE if the table needs to be flushed */
366
xtBool1 tab_op_seq_set; /* TRUE if operation sequence has been set during recovery. */
367
xtBool1 tab_recovery_not_done; /* TRUE if recovery was not done. */
368
xtBool1 tab_repair_pending; /* TRUE if the table has been marked for repair */
369
off_t tab_bytes_to_flush; /* Number of bytes of the record/row files to flush. */
371
xtOpSeqNo tab_head_op_seq; /* The number of the operation last applied to the database. */
372
xtRowID tab_head_row_free_id;
373
xtRowID tab_head_row_eof_id;
374
xtWord4 tab_head_row_fnum;
375
xtRecordID tab_head_rec_free_id;
376
xtRecordID tab_head_rec_eof_id;
377
xtWord4 tab_head_rec_fnum;
379
xtOpSeqNo tab_co_op_seq; /* The operation last applied by the compactor. */
380
xtOpSeqNo tab_wr_op_seq; /* The operation last applied by the writer. */
381
xtBool tab_wr_wake_freeer; /* Set to TRUE if the writer must wake the freeer. */
382
xtOpSeqNo tab_wake_freeer_op; /* Set to the sequence number the freeer is waiting for. */
384
XTSpinLockRec tab_mem_lock; /* A spin lock for the allocation of memory based extended records. */
385
size_t tab_mem_total; /* Total amount of memory used by all memory based extended records. */
386
size_t tab_mem_ind_size; /* The total size of the index. */
387
size_t tab_mem_ind_usage; /* The total slots used in the index. */
388
size_t tab_mem_ind_free; /* Offset of the next free slot in the index (0 if none). */
389
xtWord1 **tab_mem_index; /* An array of pointers to extended records. */
391
XTFilePtr tab_row_file;
392
xtRowID tab_row_eof_id; /* Indicates the EOF of the table row file. */
393
xtRowID tab_row_free_id; /* The start of the free list in the table row file. */
394
xtWord4 tab_row_fnum; /* The count of the number of free rows on the free list. */
395
xt_mutex_type tab_row_lock; /* Lock for updating the EOF and free list. */
396
XT_TAB_ROW_LOCK_TYPE tab_row_rwlock[XT_ROW_RWLOCKS]; /* Used to lock a row during update. */
398
xt_mutex_type tab_rec_flush_lock; /* Required while the record/row files are being flushed. */
399
XTFlushRecRowTask *tab_rec_flush_task;
400
XTFilePtr tab_rec_file;
401
#ifdef XT_REC_FLUSH_THRESHOLD
402
u_int tab_rec_wr_last_flush; /* Byte output level of the writer at last flush. */
404
xtRecordID tab_rec_eof_id; /* This value can only grow. */
405
xtRecordID tab_rec_free_id;
406
xtWord4 tab_rec_fnum; /* The count of the number of free rows on the free list. */
407
xt_mutex_type tab_rec_lock; /* Lock for the free list. */
408
#ifdef XT_SORT_REC_WRITES
409
xtOpSeqNo tab_rec_dw_op_seq;
410
XTSortedListPtr tab_rec_dw_writes;
411
size_t tab_rec_dw_data_size;
412
size_t tab_rec_dw_data_usage;
413
xtWord1 *tab_rec_dw_data;
416
xt_mutex_type tab_ind_stat_lock; /* Aquired when calculating index statistics. */
417
time_t tab_ind_stat_calc_time; /* Zero means the index stats have not be calculated, otherwize this is a time. */
419
xt_mutex_type tab_ind_flush_lock; /* Required while the index file is being flushed. */
420
XTFlushIndexTask *tab_ind_flush_task;
421
XTIndexLogPtr tab_ind_flush_ilog; /* The ilog used to flush the index file. */
422
XTIndDirtyList tab_ind_dirty_list; /* A list of dirty blocks to be flushed for this index. */
423
xtLogID tab_ind_rec_log_id; /* The point before which index entries have been written. */
424
xtLogOffset tab_ind_rec_log_offset; /* The log offset of the write point. */
425
XTFilePtr tab_ind_file;
426
xtIndexNodeID tab_ind_eof; /* This value can only grow. */
427
xtIndexNodeID tab_ind_free; /* The start of the free page list of the index. */
428
XTIndFreeListPtr tab_ind_free_list; /* A cache of the free list (if exists, don't go to disk!) */
429
xt_mutex_type tab_ind_lock; /* Lock for reading and writing the index free list. */
430
#ifdef PRINT_IND_FLUSH_STATS
432
xtWord8 tab_ind_flush_time;
435
} XTTableHRec, *XTTableHPtr; /* Heap pointer */
437
/* Used for an in-memory list of the tables, ordered by ID. */
438
typedef struct XTTableEntry {
441
struct XTTablePath *te_tab_path;
443
XTTableHPtr te_table;
445
} XTTableEntryRec, *XTTableEntryPtr;
447
typedef struct XTOpenTable {
448
struct XTThread *ot_thread; /* The thread currently using this open table. */
449
XTTableHPtr ot_table; /* PBXT table information. */
451
struct XTOpenTable *ot_otp_next_free; /* Next free open table in the open table pool. */
452
struct XTOpenTable *ot_otp_mr_used;
453
struct XTOpenTable *ot_otp_lr_used;
454
time_t ot_otp_free_time; /* The time this table was place on the free list. */
456
//struct XTOpenTable *ot_pool_next; /* Next pointer for open table pool. */
458
XT_ROW_REC_FILE_PTR ot_rec_file;
459
XT_ROW_REC_FILE_PTR ot_row_file;
460
XTOpenFilePtr ot_ind_file;
461
u_int ot_err_index_no; /* The number of the index on which the last error occurred */
463
xtBool ot_rec_fixed; /* Cached from table for quick access. */
464
size_t ot_rec_size; /* Cached from table for quick access. */
466
char ot_error_key[XT_IDENTIFIER_NAME_SIZE];
467
struct XTOpenTable *ot_prev_update; /* The UPDATE statement stack! {UPDATE-STACK} */
468
u_int ot_update_id; /* The update statement ID. */
469
xtBool ot_for_update; /* True if reading FOR UPDATE. */
470
xtBool ot_is_modify; /* True if UPDATE or DELETE. */
471
xtRowID ot_temp_row_lock; /* The temporary row lock set on this table. */
472
u_int ot_cols_req; /* The number of columns required from the table. */
474
/* GOTCHA: Separate buffers for reading and writing rows because
475
* of blob references, to this buffer, as in this test:
477
* drop table if exists t1;
478
* CREATE TABLE t1 (id MEDIUMINT NOT NULL, b1 BIT(8), vc TEXT,
479
* bc CHAR(255), d DECIMAL(10,4) DEFAULT 0,
480
* f FLOAT DEFAULT 0, total BIGINT UNSIGNED,
482
* PARTITION BY RANGE (YEAR(t))
483
* (PARTITION p1 VALUES LESS THAN (2005),
484
* PARTITION p2 VALUES LESS THAN MAXVALUE);
486
* INSERT INTO t1 VALUES(412,1,'eTesting MySQL databases is a cool ',
487
* 'EEEMust make it bug free for the customer',
488
* 654321.4321,15.21,0,1965,"2005-11-14");
490
* UPDATE t1 SET b1 = 0, t="2006-02-22" WHERE id = 412;
493
size_t ot_row_rbuf_size; /* The current size of the read row buffer (resized dynamically). */
494
xtWord1 *ot_row_rbuffer; /* The row buffer for reading rows. */
495
size_t ot_row_wbuf_size; /* The current size of the write row buffer (resized dynamically). */
496
xtWord1 *ot_row_wbuffer; /* The row buffer for writing rows. */
498
/* Details of the current record: */
499
xtRecordID ot_curr_rec_id; /* The offset of the current record. */
500
xtRowID ot_curr_row_id; /* The row ID of the current record. */
501
xtBool ot_curr_updated; /* TRUE if the current record was updated by the current transaction. */
503
XTIndBlockPtr ot_ind_res_bufs; /* A list of reserved index buffers. */
504
u_int ot_ind_res_count; /* The number of reserved buffers. */
505
#ifdef XT_TRACK_INDEX_UPDATES
506
u_int ot_ind_changed;
507
u_int ot_ind_reserved;
510
#ifdef XT_TRACK_RETURNED_ROWS
511
u_int ot_rows_ret_max;
512
u_int ot_rows_ret_curr;
513
xtRecordID *ot_rows_returned;
515
/* GOTCHA: Separate buffers for reading and writing the index are required
516
* because MySQL sometimes scans and updates an index with the same
519
XTIdxItemRec ot_ind_state; /* Decribes the state of the index buffer. */
520
XTIndHandlePtr ot_ind_rhandle; /* This handle references a block which is being used in a sequential scan. */
521
#ifdef CHECK_IF_WRITE_WAS_OK
522
XTIdxBranchDRec ot_ind_tmp_buf; /* A temporary read buffer. */
524
XTIdxBranchDRec ot_ind_wbuf; /* Buffer for the current index node for writing. */
525
xtWord1 ot_ind_wbuf2[XT_INDEX_PAGE_SIZE]; /* Overflow for the write buffer when a node is too big. */
527
/* Note: the fields below ot_ind_rbuf are not zero'ed out on creation
530
xtRecordID ot_seq_rec_id; /* Current position of a sequential scan. */
531
xtRecordID ot_seq_eof_id; /* The EOF at the start of the sequential scan. */
532
XTTabCachePagePtr ot_seq_page; /* If ot_seq_buffer is non-NULL, then a page has been locked! */
533
xtWord1 *ot_seq_data; /* Non-NULL if the data references memory mapped memory, or if it was
534
* allocated if no memory mapping is being used.
537
size_t ot_seq_offset; /* Offset on the current page. */
538
} XTOpenTableRec, *XTOpenTablePtr;
540
#define XT_DATABASE_NAME_SIZE XT_IDENTIFIER_NAME_SIZE
542
#define XT_TD_FROM_DIRECTORY 1
543
#define XT_TD_FROM_TAB_FILE 2
545
typedef struct XTTableDesc {
546
char td_tab_name[XT_TABLE_NAME_SIZE+4]; // 4 extra for DEL# (tables being deleted)
549
struct XTTablePath *td_tab_path; // The path of the table.
550
struct XTDatabase *td_db;
556
XTOpenDirPtr td_open_dir;
563
} XTTableDescRec, *XTTableDescPtr;
566
typedef struct XTFilesOfTable {
568
XTPathStrPtr ft_tab_name;
570
char ft_file_path[PATH_MAX];
571
} XTFilesOfTableRec, *XTFilesOfTablePtr;
573
typedef struct XTRestrictItem {
575
xtRecordID ri_rec_id;
576
} XTRestrictItemRec, *XTRestrictItemPtr;
578
int xt_tab_compare_names(const char *n1, const char *n2);
579
int xt_tab_compare_paths(char *n1, char *n2);
580
void xt_tab_init_db(struct XTThread *self, struct XTDatabase *db);
581
void xt_tab_exit_db(struct XTThread *self, struct XTDatabase *db);
583
char *xt_tab_file_to_name(size_t size, char *tab_name, char *file_name);
585
void xt_create_table(struct XTThread *self, XTPathStrPtr name, XTDictionaryPtr dic);
586
XTTableHPtr xt_use_table(struct XTThread *self, XTPathStrPtr name, xtBool no_load, xtBool missing_ok);
587
void xt_sync_flush_table(struct XTThread *self, XTOpenTablePtr ot, int timeout);
588
xtBool xt_async_flush_record_row(XTTableHPtr tab, xtBool notify_complete, XTThreadPtr thread);
589
xtBool xt_flush_record_row(XTOpenTablePtr ot, off_t *bytes_flushed, xtBool have_table_loc);
590
void xt_flush_table(struct XTThread *self, XTOpenTablePtr ot);
591
XTTableHPtr xt_use_table_no_lock(XTThreadPtr self, struct XTDatabase *db, XTPathStrPtr name, xtBool no_load, xtBool missing_ok, XTDictionaryPtr dic);
592
XTTableHPtr xt_use_table_by_id(XTThreadPtr self, struct XTDatabase *db, xtTableID tab_id, int *result);
593
XTTableHPtr xt_use_table_by_id_ns(struct XTDatabase *db, xtTableID tab_id);
594
XTOpenTablePtr xt_open_table(XTTableHPtr tab);
595
void xt_close_table(XTOpenTablePtr ot, xtBool flush, xtBool have_table_lock);
596
void xt_drop_table(struct XTThread *self, XTPathStrPtr name, xtBool drop_db);
597
void xt_check_table(XTThreadPtr self, XTOpenTablePtr tab);
598
void xt_rename_table(struct XTThread *self, XTPathStrPtr old_name, XTPathStrPtr new_name);
600
void xt_describe_tables_init(struct XTThread *self, struct XTDatabase *db, XTTableDescPtr td);
601
xtBool xt_describe_tables_next(struct XTThread *self, XTTableDescPtr td);
602
void xt_describe_tables_exit(struct XTThread *self, XTTableDescPtr td);
604
xtBool xt_table_exists(struct XTDatabase *db);
606
void xt_enum_tables_init(u_int *edx);
607
XTTableEntryPtr xt_enum_tables_next(struct XTThread *self, struct XTDatabase *db, u_int *edx);
609
void xt_enum_files_of_tables_init(XTPathStrPtr tab_name, xtTableID tab_id, XTFilesOfTablePtr ft);
610
xtBool xt_enum_files_of_tables_next(XTFilesOfTablePtr ft);
612
xtBool xt_tab_seq_init(XTOpenTablePtr ot);
613
void xt_tab_seq_reset(XTOpenTablePtr ot);
614
void xt_tab_seq_exit(XTOpenTablePtr ot);
615
xtBool xt_tab_seq_next(XTOpenTablePtr ot, xtWord1 *buffer, xtBool *eof);
616
void xt_tab_seq_repeat(XTOpenTablePtr ot);
618
xtBool xt_tab_new_record(XTOpenTablePtr ot, xtWord1 *buffer);
619
xtBool xt_tab_delete_record(XTOpenTablePtr ot, xtWord1 *buffer);
620
xtBool xt_tab_restrict_rows(XTBasicListPtr list, struct XTThread *thread);
621
xtBool xt_tab_update_record(XTOpenTablePtr ot, xtWord1 *before_buf, xtWord1 *after_buf);
622
int xt_tab_visible(XTOpenTablePtr ot);
623
int xt_tab_read_record(register XTOpenTablePtr ot, xtWord1 *buffer);
624
int xt_tab_dirty_read_record(register XTOpenTablePtr ot, xtWord1 *buffer);
625
void xt_tab_load_row_pointers(XTThreadPtr self, XTOpenTablePtr ot);
626
void xt_tab_load_table(struct XTThread *self, XTOpenTablePtr ot);
627
xtBool xt_tab_load_record(register XTOpenTablePtr ot, xtRecordID rec_id, XTInfoBufferPtr rec_buf);
628
int xt_tab_remove_record(XTOpenTablePtr ot, xtRecordID rec_id, xtWord1 *rec_data, xtRecordID *prev_var_rec_id, xtBool clean_delete, xtRowID row_id, xtXactID xn_id);
629
int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXactID *xn_id, xtRowID *out_rowid, xtBool *out_updated);
630
void xt_tab_store_header(XTOpenTablePtr ot, XTTableHeadDPtr rec_head);
631
xtBool xt_tab_write_min_auto_inc(XTOpenTablePtr ot);
633
xtBool xt_tab_get_row(register XTOpenTablePtr ot, xtRowID row_id, xtRecordID *var_rec_id);
634
xtBool xt_tab_set_row(XTOpenTablePtr ot, u_int status, xtRowID row_id, xtRecordID var_rec_id);
635
xtBool xt_tab_free_row(XTOpenTablePtr ot, XTTableHPtr tab, xtRowID row_id);
637
xtBool xt_tab_load_ext_data(XTOpenTablePtr ot, xtRecordID load_rec_id, xtWord1 *buffer, u_int cols_req);
638
xtBool xt_tab_put_rec_data(XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer, xtOpSeqNo *op_seq);
639
xtBool xt_tab_put_eof_rec_data(XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer, xtOpSeqNo *op_seq);
640
xtBool xt_tab_put_log_op_rec_data(XTOpenTablePtr ot, u_int status, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *buffer);
641
xtBool xt_tab_put_log_rec_data(XTOpenTablePtr ot, u_int status, xtRecordID free_rec_id, xtRecordID rec_id, size_t size, xtWord1 *buffer, xtOpSeqNo *op_seq);
642
xtBool xt_tab_get_rec_data(register XTOpenTablePtr ot, xtRecordID rec_id, size_t size, xtWord1 *buffer);
643
void xt_tab_disable_index(XTTableHPtr tab, u_int ind_error);
644
void xt_tab_set_index_error(XTTableHPtr tab);
646
XTFileType xt_rec_file_type(xtBool heap_tab);
647
XTFileType xt_row_file_type(xtBool heap_tab);
648
XTFileType xt_ind_file_type(xtBool heap_tab);
650
void xt_tab_make_table_name(XTPathStrPtr tab_path, char *table_name, size_t size);
651
xtBool xt_tab_is_table_repair_pending(XTTableHPtr tab);
652
void xt_tab_table_repaired(XTTableHPtr tab);
653
void xt_tab_set_table_repair_pending(XTTableHPtr tab);
655
xtBool xt_tab_get_ext_slot(XTTableHPtr tab, xtLogID *log_id, xtLogOffset *log_offset, size_t req_size);
656
xtBool xt_tab_save_ext_record(XTTableHPtr tab, xtLogID log_id, xtLogOffset log_offset, size_t size, xtWord1 *data);
657
void xt_tab_read_ext_record(XTTableHPtr tab, xtLogID log_id, xtLogOffset log_offset, size_t size, xtWord1 *data);
658
void xt_tab_free_ext_slot(XTTableHPtr tab, xtLogID log_id, xtLogOffset log_offset, size_t size);
660
inline off_t xt_row_id_to_row_offset(register XTTableHPtr tab, xtRowID row_id)
662
return (off_t) tab->tab_rows.tci_header_size + (off_t) (row_id - 1) * (off_t) tab->tab_rows.tci_rec_size;
665
inline xtRowID xt_row_offset_row_id(register XTTableHPtr tab, off_t rec_offs)
668
if (((rec_offs - (off_t) tab->tab_rows.tci_header_size) % (off_t) tab->tab_rows.tci_rec_size) != 0) {
669
printf("ERROR! Not a valid record offset!\n");
672
return (xtRowID) ((rec_offs - (off_t) tab->tab_rows.tci_header_size) / (off_t) tab->tab_rows.tci_rec_size) + 1;
675
inline off_t xt_rec_id_to_rec_offset(register XTTableHPtr tab, xtRefID ref_id)
679
return (off_t) tab->tab_recs.tci_header_size + (off_t) (ref_id-1) * (off_t) tab->tab_recs.tci_rec_size;
682
inline xtRefID xt_rec_offset_rec_id(register XTTableHPtr tab, off_t ref_offs)
687
if (((ref_offs - (off_t) tab->tab_recs.tci_header_size) % (off_t) tab->tab_recs.tci_rec_size) != 0) {
688
printf("ERROR! Not a valid record offset!\n");
692
return (xtRefID) ((ref_offs - (off_t) tab->tab_recs.tci_header_size) / (off_t) tab->tab_recs.tci_rec_size)+1;
695
inline off_t xt_ind_node_to_offset(register XTTableHPtr tab, xtIndexNodeID node_id)
697
if (!XT_NODE_ID(node_id))
699
return (off_t) tab->tab_index_header_size + (off_t) (XT_NODE_ID(node_id)-1) * (off_t) tab->tab_index_page_size;
702
inline xtIndexNodeID xt_ind_offset_to_node(register XTTableHPtr tab, off_t ind_offs)
707
return XT_RET_NODE_ID(0);
709
if (((ind_offs - (off_t) tab->tab_index_header_size) % (off_t) tab->tab_index_page_size) != 0) {
710
printf("ERROR! Not a valid index offset!\n");
714
return XT_RET_NODE_ID(((ind_offs - (off_t) tab->tab_index_header_size) / (off_t) tab->tab_index_page_size)+1);
717
inline xtBool xt_tab_write_rec(XTOpenTablePtr ot, off_t offset, size_t size, xtWord1 *data)
719
return xt_pwrite_file(ot->ot_rec_file, offset, size, data, &ot->ot_thread->st_statistics.st_rec, ot->ot_thread);
722
inline xtBool xt_tab_write_row(XTOpenTablePtr ot, off_t offset, size_t size, xtWord1 *data)
724
return xt_pwrite_file(ot->ot_row_file, offset, size, data, &ot->ot_thread->st_statistics.st_rec, ot->ot_thread);
727
#define XT_RESIZE_ROW_BUFFER(thr, rb, size) \
729
if (rb->rb_size < size) { \
730
xt_realloc(thr, (void **) &rb->x.rb_buffer, size); \
731
rb->rb_size = size; \