~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to plugin/pbxt/src/index_xt.h

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-10-02 14:17:48 UTC
  • mfrom: (1.1.1 upstream)
  • mto: (2.1.17 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20101002141748-m6vbfbfjhrw1153e
Tags: 2010.09.1802-1
* New upstream release.
* Removed pid-file argument hack.
* Updated GPL-2 address to be new address.
* Directly copy in drizzledump.1 since debian doesn't have sphinx 1.0 yet.
* Link to jquery from libjs-jquery. Add it as a depend.
* Add drizzled.8 symlink to the install files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
 
2
 *
 
3
 * PrimeBase XT
 
4
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 *
 
19
 * 2005-09-30   Paul McCullagh
 
20
 *
 
21
 * H&G2JCtL
 
22
 */
 
23
#ifndef __xt_index_h__
 
24
#define __xt_index_h__
 
25
 
 
26
#ifdef DRIZZLED
 
27
#include <drizzled/definitions.h>
 
28
#include <drizzled/sql_bitmap.h>
 
29
#include <drizzled/field.h>
 
30
using drizzled::Field;
 
31
#else
 
32
#include <mysql_version.h>
 
33
#include <my_bitmap.h>
 
34
#endif
 
35
#include <time.h>
 
36
 
 
37
#include "thread_xt.h"
 
38
#include "linklist_xt.h"
 
39
#include "datalog_xt.h"
 
40
#include "datadic_xt.h"
 
41
 
 
42
#ifndef MYSQL_VERSION_ID
 
43
#error MYSQL_VERSION_ID must be defined!
 
44
#endif
 
45
 
 
46
//#define PRINT_IND_FLUSH_STATS
 
47
 
 
48
/* Define this to gather data on what area
 
49
 * of an index page is being written.
 
50
 */
 
51
#define IND_OPT_DATA_WRITTEN
 
52
 
 
53
#ifdef IND_OPT_DATA_WRITTEN
 
54
/* This is a debug switch that compares
 
55
 * the contents of a cached page
 
56
 * to the data just written to disk
 
57
 *
 
58
 * It requires information on what parts
 
59
 * of the cache page have been changed.
 
60
 */
 
61
//#define CHECK_IF_WRITE_WAS_OK
 
62
#endif
 
63
 
 
64
#ifdef IND_OPT_DATA_WRITTEN
 
65
/* Write only those parts of an index
 
66
 * page that have been modified.
 
67
 */
 
68
#define IND_WRITE_MIN_DATA
 
69
#endif
 
70
 
 
71
/*
 
72
 * Define this in order to complete write the
 
73
 * end of an index page (i.e. unused space),
 
74
 * if the next page to be written is the
 
75
 * one that follows this page.
 
76
 * Note that this does not work optimilly
 
77
 * with the option to write minimum data.
 
78
 */
 
79
//#define IND_FILL_BLOCK_TO_NEXT
 
80
 
 
81
/* Define this all writes to the index
 
82
 * file should be in block sizes and on
 
83
 * block boundaries.
 
84
 */
 
85
//#define IND_WRITE_IN_BLOCK_SIZES
 
86
 
 
87
/* This is the block size used to write the index: */
 
88
#define IND_WRITE_BLOCK_SIZE                            XT_BLOCK_SIZE_FOR_DIRECT_IO
 
89
//#define IND_WRITE_BLOCK_SIZE                          (1024*1)
 
90
 
 
91
/*
 
92
 * Define this to skew the split of nodes
 
93
 * when adding to the end of an index.
 
94
 */
 
95
#define IND_SKEW_SPLIT_ON_APPEND
 
96
 
 
97
/*
 
98
 * The maximum amount of data to write before
 
99
 * flushing the index file.
 
100
 */
 
101
#define IND_FLUSH_THRESHOLD                                     (512 * 1024 * 1024)
 
102
 
 
103
struct XTDictionary;
 
104
struct XTTable;
 
105
struct XTOpenTable;
 
106
struct XTIndex;
 
107
struct XTIndBlock;
 
108
struct XTTable;
 
109
struct XTThread;
 
110
class Field;
 
111
 
 
112
/*
 
113
 * INDEX ROLLBACK
 
114
 *
 
115
 * When a transaction is rolled back, the index entries are not
 
116
 * garbage collected!! Instead, the index entries are deleted
 
117
 * when the data record is garbage collected.
 
118
 *
 
119
 * When an index record is written, and this record replaces
 
120
 * some other record (i.e. a node is updated). The new record
 
121
 * references its predecessor.
 
122
 *
 
123
 * On cleanup (rollback or commit), the predecessor records
 
124
 * are garbage collected.
 
125
 *
 
126
 * NOTE: It is possible to loose memory if a crash occurs during
 
127
 * index modification. This can occur if a node is split and
 
128
 * we crash between writing the 2 new records.
 
129
 *
 
130
 */ 
 
131
 
 
132
/*
 
133
 * These flags influence the way the compare and search
 
134
 * routines function.
 
135
 *
 
136
 * The low-order 16 bits are reserved for the caller
 
137
 * (i.e. MySQL specific stuff).
 
138
 */
 
139
#define XT_SEARCH_WHOLE_KEY                     0x10000000              /* This flag is used to search for an insertion point, or to find
 
140
                                                                                                         * a particular slot that has already been inserted into the
 
141
                                                                                                         * index. The compare includes the handle of the variation.
 
142
                                                                                                         */
 
143
#define XT_SEARCH_AFTER_KEY                     0x20000000              /* This flags searches for the position just after the given key.
 
144
                                                                                                         * Even if the key is not found, success is possible if there
 
145
                                                                                                         * is a value in the index that would be after the search key.
 
146
                                                                                                         *
 
147
                                                                                                         * If this flag is not set then we search for the first
 
148
                                                                                                         * occurrence of the key in the index. If not found we 
 
149
                                                                                                         * take the position just after the search key.
 
150
                                                                                                         */
 
151
#define XT_SEARCH_FIRST_FLAG            0x40000000              /* Use this flags to find the first position in the index.
 
152
                                                                                                         * When set, the actual key value is ignored.
 
153
                                                                                                         */
 
154
#define XT_SEARCH_AFTER_LAST_FLAG       0x80000000              /* Search out the position after the last in the index.
 
155
                                                                                                         * When set, the actual key value is ignored.
 
156
                                                                                                         */
 
157
 
 
158
#define XT_INDEX_MAX_KEY_SIZE_MAX       2048                    /* These are allocated on the stack, so this is the maximum! */
 
159
 
 
160
#define XT_INDEX_MAX_KEY_SIZE           ((XT_INDEX_PAGE_SIZE >> 1) > XT_INDEX_MAX_KEY_SIZE_MAX ? XT_INDEX_MAX_KEY_SIZE_MAX : (XT_INDEX_PAGE_SIZE >> 1))
 
161
 
 
162
#define XT_IS_NODE_BIT                          0x8000
 
163
 
 
164
#define XT_IS_NODE(x)                           ((x) & XT_IS_NODE_BIT)
 
165
 
 
166
#define XT_NODE_REF_SIZE                        4
 
167
#define XT_GET_NODE_REF(t, x)           XT_RET_NODE_ID(XT_GET_DISK_4(x))
 
168
#define XT_SET_NODE_REF(t, x, y)        XT_SET_DISK_4((x), XT_NODE_ID(y))
 
169
 
 
170
#define XT_MAX_RECORD_REF_SIZE          8
 
171
 
 
172
#define XT_INDEX_PAGE_HEAD_SIZE         offsetof(XTIdxBranchDRec, tb_data)
 
173
#define XT_INDEX_PAGE_DATA_SIZE         (XT_INDEX_PAGE_SIZE - 2)                                // XT_INDEX_PAGE_HEAD_SIZE == 2!
 
174
 
 
175
#define XT_MAKE_LEAF_SIZE(x)            ((x) + XT_INDEX_PAGE_HEAD_SIZE)
 
176
 
 
177
#define XT_MAKE_NODE_SIZE(x)            (((x) + XT_INDEX_PAGE_HEAD_SIZE) | XT_IS_NODE_BIT)
 
178
 
 
179
#define XT_MAKE_BRANCH_SIZE(x, y)       (((x) + XT_INDEX_PAGE_HEAD_SIZE) | ((y) ? XT_IS_NODE_BIT : 0))
 
180
 
 
181
#define XT_GET_INDEX_BLOCK_LEN(x)       ((x) & 0x7FFF)
 
182
 
 
183
#define XT_GET_BRANCH_DATA_SIZE(x)      (XT_GET_INDEX_BLOCK_LEN(x) - XT_INDEX_PAGE_HEAD_SIZE)
 
184
 
 
185
#define XT_DIRTY_BLOCK_LIST_SIZE        4096
 
186
 
 
187
typedef struct XTIndexHead {
 
188
        XTDiskValue4            tp_format_offset_4;     /* The offset of the format part of the header. */
 
189
 
 
190
        XTDiskValue4            tp_header_size_4;       /* The  size of the header. */
 
191
        XTDiskValue6            tp_not_used_6;
 
192
 
 
193
        XTDiskValue6            tp_ind_eof_6;
 
194
        XTDiskValue6            tp_ind_free_6;
 
195
 
 
196
        /* The index roots follow. Each is if_node_ref_size_1 size. */
 
197
        xtWord1                         tp_data[XT_VAR_LENGTH];
 
198
} XTIndexHeadDRec, *XTIndexHeadDPtr;
 
199
 
 
200
typedef struct XTIndexFormat {
 
201
        XTDiskValue4            if_format_size_4;       /* The size of this structure (index format). */
 
202
        XTDiskValue2            if_tab_version_2;       /* The table version number. */
 
203
        XTDiskValue2            if_ind_version_2;       /* The index version number. */
 
204
        XTDiskValue1            if_node_ref_size_1;     /* This size of index node reference in indexes (default 4 bytes). */
 
205
        XTDiskValue1            if_rec_ref_size_1;      /* The size of record references in the indexes (default 4 bytes). */
 
206
        XTDiskValue4            if_page_size_4;
 
207
} XTIndexFormatDRec, *XTIndexFormatDPtr;
 
208
 
 
209
typedef struct XTIdxBranch {
 
210
        XTDiskValue2            tb_size_2;                      /* No of bytes used below. */
 
211
        
 
212
        /* We enough space for 2 buffers when splitting! */
 
213
        xtWord1                         tb_data[XT_INDEX_PAGE_DATA_SIZE];
 
214
} XTIdxBranchDRec, *XTIdxBranchDPtr;
 
215
 
 
216
typedef struct XTIdxItem {
 
217
        u_int                           i_total_size;           /* Size of the data in the searched branch (excludes 2 byte header). */
 
218
        u_int                           i_item_size;            /* Size of the item at this position. */
 
219
        u_int                           i_node_ref_size;
 
220
        u_int                           i_item_offset;          /* Item offset. */
 
221
} XTIdxItemRec, *XTIdxItemPtr;
 
222
 
 
223
typedef struct XTIdxResult {
 
224
        xtBool                          sr_found;                       /* TRUE if the key was found. */
 
225
        xtBool                          sr_duplicate;           /* TRUE if the duplicate was found. */
 
226
        xtBool                          sr_last_item;           /* TRUE if the last item was found. */
 
227
        xtRecordID                      sr_rec_id;                      /* Reference to the record of the found key. */
 
228
        xtRowID                         sr_row_id;
 
229
        xtIndexNodeID           sr_branch;                      /* Branch to follow when searching a node. */
 
230
        XTIdxItemRec            sr_item;
 
231
} XTIdxResultRec, *XTIdxResultPtr;
 
232
 
 
233
typedef struct XTIdxKeyValue {
 
234
        int                                     sv_flags;
 
235
        xtRecordID                      sv_rec_id;
 
236
        xtRowID                         sv_row_id;
 
237
        u_int                           sv_length;
 
238
        xtWord1                         *sv_key;
 
239
} XTIdxKeyValueRec, *XTIdxKeyValuePtr;
 
240
 
 
241
typedef struct XTIdxSearchKey {
 
242
        xtBool                          sk_on_key;                      /* TRUE if we are positioned on the search key. */
 
243
        XTIdxKeyValueRec        sk_key_value;           /* The value of the search key. */
 
244
        xtWord1                         sk_key_buf[XT_INDEX_MAX_KEY_SIZE];
 
245
} XTIdxSearchKeyRec, *XTIdxSearchKeyPtr;
 
246
 
 
247
typedef void (*XTScanBranchFunc)(struct XTTable *tab, struct XTIndex *ind, XTIdxBranchDPtr branch, register XTIdxKeyValuePtr value, register XTIdxResultRec *result);
 
248
typedef void (*XTPrevItemFunc)(struct XTTable *tab, struct XTIndex *ind, XTIdxBranchDPtr branch, register XTIdxResultRec *result);
 
249
typedef void (*XTLastItemFunc)(struct XTTable *tab, struct XTIndex *ind, XTIdxBranchDPtr branch, register XTIdxResultRec *result);
 
250
 
 
251
typedef int (*XTSimpleCompFunc)(struct XTIndex *ind, u_int key_length, xtWord1 *key_value, xtWord1 *b_value);
 
252
 
 
253
#ifdef DRIZZLED
 
254
namespace drizzled
 
255
{
 
256
  struct charset_info_st;
 
257
}
 
258
using drizzled::charset_info_st;
 
259
#else
 
260
struct charset_info_st;
 
261
#endif
 
262
 
 
263
typedef struct XTIndexSeg               /* Key-portion */
 
264
{
 
265
        u_int                           col_idx;                        /* The table column index of this component. */
 
266
        u_int                           is_recs_in_range;       /* Value returned by records_in_range(). */
 
267
        u_int                           is_selectivity;         /* The number of unique values per mi_select_total. */
 
268
        xtWord1                         type;                           /* Type of key (for sort) */
 
269
        xtWord1                         language;
 
270
        xtWord1                         null_bit;                       /* bitmask to test for NULL */
 
271
        xtWord1                         bit_start,bit_end;      /* if bit field */
 
272
        xtWord1                         bit_pos,bit_length;     /* (not used in 4.1) */
 
273
        xtWord2                         flag;
 
274
        xtWord2                         length;                         /* Keylength */
 
275
        xtWord4                         start;                          /* Start of key in record */
 
276
        xtWord4                         null_pos;                       /* position to NULL indicator */
 
277
        MX_CONST_CHARSET_INFO   *charset;
 
278
} XTIndexSegRec, *XTIndexSegPtr;
 
279
 
 
280
typedef struct XTIndFreeList {
 
281
        struct XTIndFreeList    *fl_next_list;                          /* List of free pages for this index. */
 
282
        u_int                                   fl_start;                                       /* Start for allocating from the front of the list. */
 
283
        u_int                                   fl_free_count;                          /* Total items in the free list. */
 
284
        xtIndexNodeID                   fl_page_id[XT_VAR_LENGTH];      /* List of page ID's of the free pages. */
 
285
} XTIndFreeListRec, *XTIndFreeListPtr;
 
286
 
 
287
typedef struct XTIndDirtyBlocks {
 
288
        struct XTIndDirtyBlocks *db_next;
 
289
        struct XTIndBlock               *db_blocks[XT_DIRTY_BLOCK_LIST_SIZE];
 
290
} XTIndDirtyBlocksRec, *XTIndDirtyBlocksPtr;
 
291
 
 
292
typedef struct XTIndDirtyListItor {
 
293
        u_int                                   dli_i;
 
294
        u_int                                   dli_count;
 
295
        XTIndDirtyBlocksPtr             dli_list;
 
296
 
 
297
        void dli_reset() {
 
298
                dli_i = 0;
 
299
                dli_count = 0;
 
300
                dli_list = NULL;
 
301
        }
 
302
} XTIndDirtyListItorRec, *XTIndDirtyListItorPtr;
 
303
 
 
304
typedef struct XTIndDirtyList {
 
305
        u_int                                   dl_total_blocks;                        /* Count of the dirty blocks. */
 
306
        u_int                                   dl_list_usage;                          /* The number of elements used in the first block list: */
 
307
        XTIndDirtyBlocksPtr             dl_block_lists;                         /* A chain of dirty blocks. */
 
308
 
 
309
        xtBool  dl_add_block(struct XTIndBlock *block);
 
310
        void    dl_sort_blocks();
 
311
        void    dl_free_all();
 
312
 
 
313
        inline struct XTIndBlock *dl_next_block(XTIndDirtyListItorPtr it) {
 
314
                struct XTIndBlock *block;
 
315
 
 
316
                if (it->dli_i == it->dli_count) {
 
317
                        if (it->dli_list) {
 
318
                                it->dli_count = XT_DIRTY_BLOCK_LIST_SIZE;
 
319
                                it->dli_list = it->dli_list->db_next;
 
320
                        }
 
321
                        else {
 
322
                                it->dli_count = dl_list_usage;
 
323
                                it->dli_list = dl_block_lists;
 
324
                        }
 
325
                        it->dli_i = 0;
 
326
                        if (!it->dli_list)
 
327
                                return NULL;
 
328
                }
 
329
 
 
330
                block = it->dli_list->db_blocks[it->dli_i];
 
331
                it->dli_i++;
 
332
                return block;
 
333
        }
 
334
} XTIndDirtyListRec, *XTIndDirtyListPtr;
 
335
 
 
336
/*
 
337
 * XT_INDEX_USE_PTHREAD_RW:
 
338
 * The stardard pthread RW lock is currently the fastest for INSERTs
 
339
 * in 32 threads on smalltab: runTest(SMALL_INSERT_TEST, 32, dbUrl)
 
340
 */
 
341
/*
 
342
 * XT_INDEX_USE_RWMUTEX:
 
343
 * But the RW mutex is a close second, if not just as fast.
 
344
 * If it is at least as fast, then it is better because read lock
 
345
 * overhead is then zero.
 
346
 *
 
347
 * If definitely does get in the way of the 
 
348
 */ 
 
349
/* XT_INDEX_USE_PTHREAD_RW:
 
350
 * But this is clearly better on Linux. 216682 instead of 169259
 
351
 * payment transactions (DBT2 in non-conflict transactions,
 
352
 * using only the customer table).
 
353
 *
 
354
 * 27.2.2009:
 
355
 * The story continues. I have now fixed a bug in RW MUTEX that
 
356
 * may have been slowing things down (see {RACE-WR_MUTEX}).
 
357
 *
 
358
 * So we will need to test "customer payment" again.
 
359
 *
 
360
 * 3.3.2009
 
361
 * Latest test show that RW mutex is slightly faster:
 
362
 * 127460 to 123574 payment transactions.
 
363
 */
 
364
 
 
365
#ifdef XT_NO_ATOMICS
 
366
#define XT_INDEX_USE_PTHREAD_RW
 
367
#else
 
368
//#define XT_INDEX_USE_PTHREAD_RW
 
369
#define XT_TAB_ROW_USE_XSMUTEX
 
370
//#define XT_INDEX_SPINXSLOCK
 
371
#endif
 
372
 
 
373
#if defined(XT_INDEX_USE_PTHREAD_RW)
 
374
#define XT_INDEX_LOCK_TYPE                              xt_rwlock_type
 
375
#define XT_INDEX_INIT_LOCK(s, i)                xt_init_rwlock_with_autoname(s, &(i)->mi_rwlock)
 
376
#define XT_INDEX_FREE_LOCK(s, i)                xt_free_rwlock(&(i)->mi_rwlock) 
 
377
#define XT_INDEX_READ_LOCK(i, o)                do { xt_slock_rwlock_ns(&(i)->mi_rwlock); (void) (o); } while(0)
 
378
#define XT_INDEX_WRITE_LOCK(i, o)               do { xt_xlock_rwlock_ns(&(i)->mi_rwlock); (void) (o); } while(0)
 
379
#define XT_INDEX_UNLOCK(i, o)                   do { xt_unlock_rwlock_ns(&(i)->mi_rwlock); (void) (o); } while(0)
 
380
#define XT_INDEX_HAVE_XLOCK(i, o)               TRUE
 
381
#elif defined(XT_TAB_ROW_USE_XSMUTEX)
 
382
#define XT_INDEX_LOCK_TYPE                              XTMutexXSLockRec
 
383
#define XT_INDEX_INIT_LOCK(s, i)                xt_xsmutex_init_with_autoname(s, &(i)->mi_rwlock)
 
384
#define XT_INDEX_FREE_LOCK(s, i)                xt_xsmutex_free(s, &(i)->mi_rwlock)     
 
385
#define XT_INDEX_READ_LOCK(i, o)                xt_xsmutex_slock(&(i)->mi_rwlock, (o)->ot_thread->t_id)
 
386
#define XT_INDEX_WRITE_LOCK(i, o)               xt_xsmutex_xlock(&(i)->mi_rwlock, (o)->ot_thread->t_id)
 
387
#define XT_INDEX_UNLOCK(i, o)                   xt_xsmutex_unlock(&(i)->mi_rwlock, (o)->ot_thread->t_id)
 
388
#define XT_INDEX_HAVE_XLOCK(i, o)               ((i)->sxs_xlocker == (o)->ot_thread->t_id)
 
389
#elif defined(XT_INDEX_SPINXSLOCK)
 
390
#define XT_INDEX_LOCK_TYPE                              XTSpinXSLockRec
 
391
#define XT_INDEX_INIT_LOCK(s, i)                xt_spinxslock_init_with_autoname(s, &(i)->mi_rwlock)
 
392
#define XT_INDEX_FREE_LOCK(s, i)                xt_spinxslock_free(s, &(i)->mi_rwlock)  
 
393
#define XT_INDEX_READ_LOCK(i, o)                xt_spinxslock_slock(&(i)->mi_rwlock, (o)->ot_thread->t_id)
 
394
#define XT_INDEX_WRITE_LOCK(i, o)               xt_spinxslock_xlock(&(i)->mi_rwlock, FALSE, (o)->ot_thread->t_id)
 
395
#define XT_INDEX_UNLOCK(i, o)                   xt_spinxslock_unlock(&(i)->mi_rwlock, (o)->ot_thread->t_id)
 
396
#define XT_INDEX_HAVE_XLOCK(i, o)               ((i)->mi_rwlock.nrw_xlocker == (o)->ot_thread->t_id)
 
397
#else
 
398
#error Please define the lock type
 
399
#endif
 
400
 
 
401
/* The R/W lock on the index is used as follows:
 
402
 * Read Lock - used for operations on the index that are not of a structural nature.
 
403
 * This includes any read operation and update operations that change an index
 
404
 * node.
 
405
 * Write lock - used to change the structure of the index. This includes adding
 
406
 * and deleting pages.
 
407
 */
 
408
typedef struct XTIndex {
 
409
        u_int                           mi_index_no;                            /* The index number (used by MySQL). */
 
410
 
 
411
        /* Protected by the mi_rwlock lock: */
 
412
        XT_INDEX_LOCK_TYPE      mi_rwlock;                                      /* This lock protects the structure of the index.
 
413
                                                                                                         * Read lock - structure may not change, but pages may change.
 
414
                                                                                                         * Write lock - structure of index may be changed.
 
415
                                                                                                         */
 
416
        xtIndexNodeID           mi_root;                                        /* The index root node. */
 
417
        XTIndFreeListPtr        mi_free_list;                           /* List of free pages for this index. */
 
418
        
 
419
        /* Protected by the mi_dirty_lock: */
 
420
        XTSpinLockRec           mi_dirty_lock;                          /* Spin lock protecting the dirty & free lists. */
 
421
        struct XTIndBlock       *mi_dirty_list;                         /* List of dirty pages for this index. */
 
422
        u_int                           mi_dirty_blocks;                        /* Count of the dirty blocks. */
 
423
 
 
424
        /* Index contants: */
 
425
        u_int                           mi_flags;
 
426
        u_int                           mi_key_size;
 
427
        u_int                           mi_max_items;                           /* The maximum number of items that can fit in a leaf node. */
 
428
        xtBool                          mi_key_corrupted;                       /* Set to TRUE if a currupted index key is detected. */
 
429
        xtBool                          mi_fix_key;
 
430
        xtBool                          mi_lazy_delete;                         /* TRUE if index entries are "lazy deleted". */
 
431
        u_int                           mi_single_type;                         /* Used when the index contains a single field. */
 
432
        u_int                           mi_select_total;
 
433
        XTScanBranchFunc        mi_scan_branch;
 
434
        XTPrevItemFunc          mi_prev_item;
 
435
        XTLastItemFunc          mi_last_item;
 
436
        XTSimpleCompFunc        mi_simple_comp_key;
 
437
        MX_BITMAP                       mi_col_map;                                     /* Bit-map of columns in the index. */
 
438
        u_int                           mi_subset_of;                           /* Indicates if this index is a complete subset of someother index. */
 
439
        u_int                           mi_seg_count;
 
440
        XTIndexSegRec           mi_seg[200];
 
441
} XTIndexRec, *XTIndexPtr;
 
442
 
 
443
#define XT_INDEX_OK                             0
 
444
#define XT_INDEX_TOO_OLD                1
 
445
#define XT_INDEX_TOO_NEW                2
 
446
#define XT_INDEX_BAD_BLOCK              3
 
447
#define XT_INDEX_CORRUPTED              4
 
448
#define XT_INDEX_MISSING                5
 
449
#define XT_INDEX_NOT_RECOVERED  6
 
450
 
 
451
typedef void (*XTFreeDicFunc)(struct XTThread *self, struct XTDictionary *dic);
 
452
 
 
453
typedef struct XTDictionary {
 
454
        XTDDTable                       *dic_table;                                     /* XT table information. */
 
455
 
 
456
        /* Table binary information. */
 
457
        u_int                           dic_mysql_buf_size;                     /* This is the size of the MySQL buffer (row size + null bytes). */
 
458
        u_int                           dic_mysql_rec_size;                     /* This is the size of the fixed length MySQL row. */
 
459
        u_int                           dic_rec_size;                           /* This is the size of the handle data file record. */
 
460
        xtBool                          dic_rec_fixed;                          /* TRUE if the record has a fixed length size. */
 
461
        u_int                           dic_tab_flags;                          /* Table flags: XT_TF_MEMORY_TABLE, XT_TF_MEMORY_TABLE. */
 
462
        xtWord8                         dic_min_auto_inc;                       /* The minimum auto-increment value. */
 
463
        xtWord8                         dic_min_row_size;
 
464
        xtWord8                         dic_max_row_size;
 
465
        xtWord8                         dic_ave_row_size;
 
466
        xtWord8                         dic_def_ave_row_size;           /* Defined row size set by the user. */
 
467
        u_int                           dic_no_of_cols;                         /* Number of columns. */
 
468
        u_int                           dic_fix_col_count;                      /* The number of columns always in the fixed part of a extended record. */
 
469
        u_int                           dic_ind_cols_req;                       /* The number of columns required to build all indexes. */
 
470
        xtWord8                         dic_ind_rec_len;                        /* Length of the record part that is needed for all index columns! */
 
471
 
 
472
        /* BLOB columns: */
 
473
        u_int                           dic_blob_cols_req;                      /* The number of the columns required to load all LONGBLOB columns. */
 
474
        u_int                           dic_blob_count;
 
475
        Field                           **dic_blob_cols;
 
476
 
 
477
        /* MySQL related information. NULL when no tables are open from MySQL side! */
 
478
        xtBool                          dic_no_lazy_delete;                     /* FALSE if lazy delete is OK. */
 
479
        u_int                           dic_disable_index;                      /* Non-zero if the index cannot be used. */
 
480
        u_int                           dic_index_ver;                          /* The version of the index. */
 
481
        u_int                           dic_key_count;
 
482
        XTIndexPtr                      *dic_keys;                                      /* MySQL/PBXT key description */
 
483
        xtWord1                         dic_table_type;                 /* XT_TABLE_TYPE_VALUE, so far used only in Drizzled */
 
484
        STRUCT_TABLE            *dic_my_table;                          /* MySQL table */
 
485
} XTDictionaryRec, *XTDictionaryPtr;
 
486
 
 
487
#define XT_DT_LOG_HEAD                          0
 
488
#define XT_DT_INDEX_PAGE                        1
 
489
#define XT_DT_FREE_LIST                         2
 
490
#define XT_DT_HEADER                            3
 
491
#define XT_DT_SHORT_IND_PAGE            4
 
492
#define XT_DT_MOD_IND_PAGE                      5
 
493
#define XT_DT_MOD_IND_PAGE_HEAD         6
 
494
#define XT_DT_SET_PAGE_HEAD                     7
 
495
#define XT_DT_2_MOD_IND_PAGE            8
 
496
#define XT_DT_MOD_IND_PAGE_EOB          9
 
497
#define XT_DT_MOD_IND_PAGE_HEAD_EOB     10
 
498
#define XT_DT_2_MOD_IND_PAGE_EOB        11
 
499
 
 
500
typedef struct XTIndLogHead {
 
501
        xtWord1                                 ilh_data_type;                          /* XT_DT_LOG_HEAD */
 
502
        XTDiskValue4                    ilh_tab_id_4;
 
503
        XTDiskValue4                    ilh_log_eof_4;                          /* The entire size of the log (0 if invalid!) */
 
504
} XTIndLogHeadDRec, *XTIndLogHeadDPtr;
 
505
 
 
506
typedef struct XTIndPageData {
 
507
        xtWord1                                 ild_data_type;
 
508
        XTDiskValue4                    ild_page_id_4;
 
509
        xtWord1                                 ild_data[XT_VAR_LENGTH];
 
510
} XTIndPageDataDRec, *XTIndPageDataDPtr;
 
511
 
 
512
typedef struct XTIndHeadData {
 
513
        xtWord1                                 ilh_data_type;
 
514
        XTDiskValue2                    ilh_head_size_2;
 
515
        xtWord1                                 ilh_data[XT_VAR_LENGTH];
 
516
} XTIndHeadDataDRec, *XTIndHeadDataDPtr;
 
517
 
 
518
typedef struct XTIndSetPageHeadData {
 
519
        xtWord1                                 ild_data_type;                          /* XT_DT_SET_PAGE_HEAD */
 
520
        XTDiskValue4                    ild_page_id_4;
 
521
        XTDiskValue2                    ild_page_head_2;                        /* The page header (first 2 bytes) */
 
522
} XTIndSetPageHeadDataDRec, *XTIndSetPageHeadDataDPtr;
 
523
 
 
524
typedef struct XTIndShortPageData {
 
525
        xtWord1                                 ild_data_type;                          /* XT_DT_SHORT_IND_PAGE */
 
526
        XTDiskValue4                    ild_page_id_4;
 
527
        XTDiskValue2                    ild_size_2;                                     /* Size of the data. */
 
528
        xtWord1                                 ild_data[XT_VAR_LENGTH];
 
529
} XTIndShortPageDataDRec, *XTIndShortPageDataDPtr;
 
530
 
 
531
typedef struct XTIndModPageData {
 
532
        xtWord1                                 ild_data_type;                          /* XT_DT_MOD_IND_PAGE */
 
533
        XTDiskValue4                    ild_page_id_4;
 
534
        XTDiskValue2                    ild_size_2;                                     /* Size of the data. */                         
 
535
        XTDiskValue2                    ild_offset_2;                           /* Offset into the page. */
 
536
        xtWord1                                 ild_data[XT_VAR_LENGTH];
 
537
} XTIndModPageDataDRec, *XTIndModPageDataDPtr;
 
538
 
 
539
typedef struct XTIndModPageHeadData {
 
540
        xtWord1                                 ild_data_type;                          /* XT_DT_MOD_IND_PAGE_HEAD/XT_DT_MOD_IND_PAGE_HEAD_EOB */
 
541
        XTDiskValue4                    ild_page_id_4;
 
542
        XTDiskValue2                    ild_size_2;                                     /* Size of the data. */
 
543
        XTDiskValue2                    ild_offset_2;                           /* Offset into the page. */
 
544
        XTDiskValue2                    ild_page_head_2;                        /* The page header (first 2 bytes) */
 
545
        xtWord1                                 ild_data[XT_VAR_LENGTH];
 
546
} XTIndModPageHeadDataDRec, *XTIndModPageHeadDataDPtr;
 
547
 
 
548
typedef struct XTIndDoubleModPageData {
 
549
        xtWord1                                 dld_data_type;                          /* XT_DT_2_MOD_IND_PAGE/XT_DT_2_MOD_IND_PAGE_EOB */
 
550
        XTDiskValue4                    dld_page_id_4;
 
551
        XTDiskValue2                    dld_size1_2;                            /* Size of the first data block, offset 0. */                           
 
552
        XTDiskValue2                    dld_offset2_2;                          /* Offset of second data block. */
 
553
        XTDiskValue2                    dld_size2_2;                            /* Size of the second data block. */                            
 
554
        xtWord1                                 dld_data[XT_VAR_LENGTH];
 
555
} XTIndDoubleModPageDataDRec, *XTIndDoubleModPageDataDPtr;
 
556
 
 
557
typedef struct XTIndexLog {
 
558
        struct XTIndexLogPool   *il_pool;
 
559
        struct XTIndexLog               *il_next_in_pool;
 
560
 
 
561
        xtLogID                                 il_log_id;                                              /* The ID of the data log. */
 
562
        XTOpenFilePtr                   il_of;
 
563
        size_t                                  il_buffer_size;
 
564
        xtWord1                                 *il_buffer;
 
565
 
 
566
        xtTableID                               il_tab_id;
 
567
        off_t                                   il_log_eof;     
 
568
        size_t                                  il_buffer_len;
 
569
        off_t                                   il_buffer_offset;
 
570
        XTSpinLockRec                   il_write_lock;
 
571
        size_t                                  il_bytes_written;
 
572
 
 
573
        xtBool                                  il_reset(struct XTOpenTable *ot);
 
574
        void                                    il_close(xtBool delete_it);
 
575
        void                                    il_release();
 
576
        xtBool                                  il_data_written();
 
577
 
 
578
        xtBool                                  il_write_byte(struct XTOpenTable *ot, xtWord1 val);
 
579
        xtBool                                  il_write_word4(struct XTOpenTable *ot, xtWord4 value);
 
580
        xtBool                                  il_write_block(struct XTOpenTable *ot, struct XTIndBlock *block);
 
581
        xtBool                                  il_write_free_list(struct XTOpenTable *ot, u_int free_count, XTIndFreeListPtr free_list);
 
582
        xtBool                                  il_require_space(size_t bytes, XTThreadPtr thread);
 
583
        xtBool                                  il_write_header(struct XTOpenTable *ot, size_t head_size, xtWord1 *head_data);
 
584
        xtBool                                  il_flush(struct XTOpenTable *ot);
 
585
        xtBool                                  il_apply_log_write(struct XTOpenTable *ot);
 
586
        xtBool                                  il_apply_log_flush(struct XTOpenTable *ot);
 
587
        inline xtBool                   il_pwrite_file(struct XTOpenTable *ot, off_t offs, size_t siz, void *dat);
 
588
        inline xtBool                   il_flush_file(struct XTOpenTable *ot);
 
589
        
 
590
        xtBool                                  il_open_table(struct XTOpenTable **ot);
 
591
        void                                    il_close_table(struct XTOpenTable *ot);
 
592
} XTIndexLogRec, *XTIndexLogPtr;
 
593
 
 
594
typedef struct XTIndexLogPool {
 
595
        struct XTDatabase               *ilp_db;
 
596
        size_t                                  ilp_log_buffer_size;
 
597
        u_int                                   il_pool_count;
 
598
        XTIndexLogPtr                   ilp_log_pool;
 
599
        xt_mutex_type                   ilp_lock;                                               /* The public pool lock. */
 
600
        xtLogID                                 ilp_next_log_id;
 
601
 
 
602
        void                                    ilp_init(struct XTThread *self, struct XTDatabase *db, size_t log_buffer_size);
 
603
        void                                    ilp_close(struct XTThread *self, xtBool lock);
 
604
        void                                    ilp_exit(struct XTThread *self);
 
605
        void                                    ilp_name(size_t size, char *path, xtLogID log_id);
 
606
 
 
607
        xtBool                                  ilp_open_log(XTIndexLogPtr *il, xtLogID log_id, xtBool excl, XTThreadPtr thread);
 
608
 
 
609
        xtBool                                  ilp_get_log(XTIndexLogPtr *il, XTThreadPtr thread);
 
610
        void                                    ilp_release_log(XTIndexLogPtr il);
 
611
} XTIndexLogPoolRec, *XTIndexLogPoolPtr;
 
612
 
 
613
class XTFlushIndexTask : public XTLockTask {
 
614
        public:
 
615
        XTFlushIndexTask() : XTLockTask(),
 
616
                fit_table(NULL),
 
617
                fit_checkpoint(FALSE),
 
618
                fit_dirty_blocks(0),
 
619
                fit_blocks_flushed(0)
 
620
        { }
 
621
 
 
622
        virtual xtBool  tk_task(XTThreadPtr thread);
 
623
        virtual void    tk_reference();
 
624
        virtual void    tk_release();
 
625
 
 
626
        struct XTTable          *fit_table;
 
627
        xtBool                          fit_checkpoint;
 
628
        u_int                           fit_dirty_blocks;                       /* The number of dirty blocks being flushed! */
 
629
        u_int                           fit_blocks_flushed;
 
630
};
 
631
 
 
632
/* A record reference consists of a record ID and a row ID: */
 
633
inline void xt_get_record_ref(register xtWord1 *item, xtRecordID *rec_id, xtRowID *row_id) {
 
634
        *rec_id = XT_GET_DISK_4(item);
 
635
        item += 4;
 
636
        *row_id = XT_GET_DISK_4(item);
 
637
}
 
638
 
 
639
inline void xt_get_res_record_ref(register xtWord1 *item, register XTIdxResultRec *result) {
 
640
        result->sr_rec_id = XT_GET_DISK_4(item);
 
641
        item += 4;
 
642
        result->sr_row_id = XT_GET_DISK_4(item);
 
643
}
 
644
 
 
645
inline void xt_set_record_ref(register xtWord1 *item, xtRecordID rec_id, xtRowID row_id) {
 
646
        XT_SET_DISK_4(item, rec_id);
 
647
        item += 4;
 
648
        XT_SET_DISK_4(item, row_id);
 
649
}
 
650
 
 
651
inline void xt_set_val_record_ref(register xtWord1 *item, register XTIdxKeyValuePtr value) {
 
652
        XT_SET_DISK_4(item, value->sv_rec_id);
 
653
        item += 4;
 
654
        XT_SET_DISK_4(item, value->sv_row_id);
 
655
}
 
656
 
 
657
xtBool  xt_idx_insert(struct XTOpenTable *ot, struct XTIndex *ind, xtRowID row_id, xtRecordID rec_id, xtWord1 *rec_buf, xtWord1 *bef_buf, xtBool allow_dups);
 
658
xtBool  xt_idx_delete(struct XTOpenTable *ot, struct XTIndex *ind, xtRecordID rec_id, xtWord1 *rec_buf);
 
659
xtBool  xt_idx_update_row_id(struct XTOpenTable *ot, struct XTIndex *ind, xtRecordID rec_id, xtRowID row_id, xtWord1 *rec_buf);
 
660
void    xt_idx_prep_key(struct XTIndex *ind, register XTIdxSearchKeyPtr search_key, int flags, xtWord1 *in_key_buf, size_t in_key_length);
 
661
xtBool  xt_idx_research(struct XTOpenTable *ot, struct XTIndex *ind);
 
662
xtBool  xt_idx_search(struct XTOpenTable *ot, struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
 
663
xtBool  xt_idx_search_prev(struct XTOpenTable *ot, struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
 
664
xtBool  xt_idx_next(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
 
665
xtBool  xt_idx_prev(register struct XTOpenTable *ot, register struct XTIndex *ind, register XTIdxSearchKeyPtr search_key);
 
666
xtBool  xt_idx_read(struct XTOpenTable *ot, struct XTIndex *ind, xtWord1 *rec_buf);
 
667
void    xt_ind_set_index_selectivity(struct XTOpenTable *ot, XTThreadPtr thread);
 
668
void    xt_check_indices(struct XTOpenTable *ot);
 
669
void    xt_load_indices(XTThreadPtr self, struct XTOpenTable *ot);
 
670
void    xt_ind_count_deleted_items(struct XTTable *ot, struct XTIndex *ind, struct XTIndBlock *block);
 
671
xtBool  xt_async_flush_indices(struct XTTable *tab, xtBool notify_complete, xtBool notify_before_write, struct XTThread *thread);
 
672
xtBool  xt_flush_indices(struct XTOpenTable *ot, off_t *bytes_flushed, xtBool have_table_lock, XTFlushIndexTask *ft);
 
673
void    xt_ind_track_dump_block(struct XTTable *tab, xtIndexNodeID address);
 
674
 
 
675
#define XT_S_MODE_MATCH         0
 
676
#define XT_S_MODE_NEXT          1
 
677
#define XT_S_MODE_PREV          2
 
678
xtBool  xt_idx_match_search(struct XTOpenTable *ot, struct XTIndex *ind, register XTIdxSearchKeyPtr search_key, xtWord1 *buf, int mode);
 
679
 
 
680
int             xt_compare_2_int4(XTIndexPtr ind, uint key_length, xtWord1 *key_value, xtWord1 *b_value);
 
681
int             xt_compare_3_int4(XTIndexPtr ind, uint key_length, xtWord1 *key_value, xtWord1 *b_value);
 
682
void    xt_scan_branch_single(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxKeyValuePtr value, register XTIdxResultRec *result);
 
683
void    xt_scan_branch_fix(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxKeyValuePtr value, register XTIdxResultRec *result);
 
684
void    xt_scan_branch_fix_simple(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxKeyValuePtr value, register XTIdxResultRec *result);
 
685
void    xt_scan_branch_var(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxKeyValuePtr value, register XTIdxResultRec *result);
 
686
 
 
687
void    xt_prev_branch_item_fix(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxResultRec *result);
 
688
void    xt_prev_branch_item_var(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxResultRec *result);
 
689
 
 
690
void    xt_last_branch_item_fix(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxResultPtr result);
 
691
void    xt_last_branch_item_var(struct XTTable *tab, XTIndexPtr ind, XTIdxBranchDPtr branch, register XTIdxResultPtr result);
 
692
xtBool  xt_idx_lazy_delete_on_leaf(XTIndexPtr ind, struct XTIndBlock *block, xtWord2 branch_size);
 
693
 
 
694
//#define TRACK_ACTIVITY
 
695
#ifdef TRACK_ACTIVITY
 
696
 
 
697
#define TRACK_BLOCK_ALLOC(x)    track_work(xt_ind_offset_to_node(tab, x), "A")
 
698
#define TRACK_BLOCK_FREE(x)             track_work(xt_ind_offset_to_node(ot->ot_table, x), "-")
 
699
#define TRACK_BLOCK_SPLIT(x)    track_work(xt_ind_offset_to_node(ot->ot_table, x), "/")
 
700
#define TRACK_BLOCK_WRITE(x)    track_work(xt_ind_offset_to_node(ot->ot_table, x), "w")
 
701
#define TRACK_BLOCK_FLUSH_N(x)  track_work(x, "F")
 
702
#define TRACK_BLOCK_TO_FLUSH(x) track_work(x, "f")
 
703
 
 
704
xtPublic void track_work(u_int block, char *what);
 
705
#else
 
706
 
 
707
#define TRACK_BLOCK_ALLOC(x)
 
708
#define TRACK_BLOCK_FREE(x)
 
709
#define TRACK_BLOCK_SPLIT(x)
 
710
#define TRACK_BLOCK_WRITE(x)
 
711
#define TRACK_BLOCK_FLUSH_N(x)
 
712
#define TRACK_BLOCK_TO_FLUSH(x)
 
713
 
 
714
#endif
 
715
 
 
716
#endif
 
717