~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2011-08-12 04:08:33 UTC
  • mfrom: (2385.2.17 refactor5)
  • Revision ID: me@mark.atwood.name-20110812040833-u6j85nc6ahuc0dtz
mergeĀ lp:~olafvdspek/drizzle/refactor5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2007 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 *
19
 
 * 2007-10-31   Paul McCullagh
20
 
 *
21
 
 * H&G2JCtL
22
 
 *
23
 
 * The new table cache. Caches all non-index data. This includes the data
24
 
 * files and the row pointer files.
25
 
 */
26
 
#ifndef __tabcache_h__
27
 
#define __tabcache_h__
28
 
 
29
 
struct XTTable;
30
 
struct XTOpenTable;
31
 
struct XTTabCache;
32
 
struct XTDatabase;
33
 
 
34
 
#include "thread_xt.h"
35
 
#include "filesys_xt.h"
36
 
#include "lock_xt.h"
37
 
 
38
 
#ifdef DEBUG
39
 
//#define XT_USE_CACHE_DEBUG_SIZES
40
 
//#define XT_NOT_INLINE
41
 
//#define CHECK_DOUBLE_READ
42
 
#endif
43
 
 
44
 
#ifdef XT_USE_CACHE_DEBUG_SIZES
45
 
 
46
 
#define XT_TC_PAGE_SIZE                         (4*1024)
47
 
#define XT_TC_SEGMENT_SHIFTS            1
48
 
 
49
 
#else
50
 
 
51
 
#define XT_TC_PAGE_SIZE                         (32*1024)
52
 
#define XT_TC_SEGMENT_SHIFTS            3
53
 
 
54
 
#endif
55
 
 
56
 
#define XT_TIME_DIFF(start, now) (\
57
 
        ((xtWord4) (now) < (xtWord4) (start)) ? \
58
 
        ((xtWord4) 0XFFFFFFFF - ((xtWord4) (start) - (xtWord4) (now))) : \
59
 
        ((xtWord4) (now) - (xtWord4) (start)))
60
 
 
61
 
#define XT_TC_SEGMENT_COUNT                     ((off_t) 1 << XT_TC_SEGMENT_SHIFTS)
62
 
#define XT_TC_SEGMENT_MASK                      (XT_TC_SEGMENT_COUNT - 1)
63
 
 
64
 
typedef struct XTTabCachePage {
65
 
        xtWord1                                 tcp_dirty;                                              /* TRUE if the page is dirty. */
66
 
        xtWord1                                 tcp_seg;                                                /* Segement number of the page. */
67
 
#ifdef XT_CLUSTER_FREE_RECORDS
68
 
        xtWord2                                 tcp_free_rec;                                   /* 0xFFFF if there is no free record in this page. */
69
 
#endif
70
 
        u_int                                   tcp_lock_count;                                 /* Number of read locks on this page. */
71
 
        u_int                                   tcp_hash_idx;                                   /* The hash index of the page. */
72
 
        u_int                                   tcp_page_idx;                                   /* The page address. */
73
 
        u_int                                   tcp_file_id;                                    /* The file id of the page. */
74
 
        xtDatabaseID                    tcp_db_id;                                              /* The ID of the database. */
75
 
        xtTableID                               tcp_tab_id;                                             /* The ID of the table of this cache page. */
76
 
        xtWord4                                 tcp_data_size;                                  /* Size of the data on this page. */
77
 
        xtOpSeqNo                               tcp_op_seq;                                             /* The operation sequence number (dirty pages have a operations sequence) */
78
 
        xtWord4                                 tcp_ru_time;                                    /* If this is in the top 1/4 don't change position in MRU list. */
79
 
        struct XTTabCachePage   *tcp_next;                                              /* Pointer to next page on hash list, or next free page on free list. */
80
 
        struct XTTabCachePage   *tcp_mr_used;                                   /* More recently used pages. */
81
 
        struct XTTabCachePage   *tcp_lr_used;                                   /* Less recently used pages. */
82
 
        xtWord1                                 tcp_data[XT_TC_PAGE_SIZE];              /* This is actually tci_page_size! */
83
 
} XTTabCachePageRec, *XTTabCachePagePtr;
84
 
 
85
 
/*
86
 
 * Each table has a "table operation sequence". This sequence is incremented by
87
 
 * each operation on the table. Each operation in the log is tagged by a
88
 
 * sequence number.
89
 
 *
90
 
 * The writter threads re-order operations in the log, and write the operations
91
 
 * to the database in sequence.
92
 
 *
93
 
 * It is safe to free a cache page when the sequence number of the cache page,
94
 
 * is less than or equal to the written sequence number.
95
 
 */
96
 
typedef struct XTTableSeq {
97
 
        xtOpSeqNo                               ts_next_seq;                                    /* The next sequence number for operations on the table. */
98
 
        xt_mutex_type                   ts_ns_lock;                                             /* Lock for the next sequence number. */
99
 
 
100
 
        xtBool ts_log_no_op(XTThreadPtr thread, xtTableID tab_id, xtOpSeqNo op_seq);
101
 
 
102
 
        /* Return the next operation sequence number. */
103
 
#ifdef XT_NOT_INLINE
104
 
        xtOpSeqNo ts_set_op_seq(XTTabCachePagePtr page);
105
 
 
106
 
        xtOpSeqNo ts_get_op_seq();
107
 
#else
108
 
        xtOpSeqNo ts_set_op_seq(XTTabCachePagePtr page)
109
 
        {
110
 
                xtOpSeqNo seq;
111
 
 
112
 
                xt_lock_mutex_ns(&ts_ns_lock);
113
 
                page->tcp_op_seq = seq = ts_next_seq++;
114
 
                xt_unlock_mutex_ns(&ts_ns_lock);
115
 
                return seq;
116
 
        }
117
 
 
118
 
        xtOpSeqNo ts_get_op_seq()
119
 
        {
120
 
                xtOpSeqNo seq;
121
 
 
122
 
                xt_lock_mutex_ns(&ts_ns_lock);
123
 
                seq = ts_next_seq++;
124
 
                xt_unlock_mutex_ns(&ts_ns_lock);
125
 
                return seq;
126
 
        }
127
 
#endif
128
 
 
129
 
        void xt_op_seq_init(XTThreadPtr self) {
130
 
                xt_init_mutex_with_autoname(self, &ts_ns_lock);
131
 
        }
132
 
 
133
 
        void xt_op_seq_set(XTThreadPtr XT_UNUSED(self), xtOpSeqNo n) {
134
 
                ts_next_seq = n;
135
 
        }
136
 
 
137
 
        void xt_op_seq_exit(XTThreadPtr XT_UNUSED(self)) {
138
 
                xt_free_mutex(&ts_ns_lock);
139
 
        }
140
 
 
141
 
#ifdef XT_NOT_INLINE
142
 
        static xtBool xt_op_is_before(register xtOpSeqNo now, register xtOpSeqNo then);
143
 
#else
144
 
        static inline xtBool xt_op_is_before(register xtOpSeqNo now, register xtOpSeqNo then)
145
 
        {
146
 
                if (now >= then) {
147
 
                        if ((now - then) > (xtOpSeqNo) 0xFFFFFFFF/2)
148
 
                                return TRUE;
149
 
                        return FALSE;
150
 
                }
151
 
                if ((then - now) > (xtOpSeqNo) 0xFFFFFFFF/2)
152
 
                        return FALSE;
153
 
                return TRUE;
154
 
        }
155
 
#endif
156
 
} XTTableSeqRec, *XTTableSeqPtr;
157
 
 
158
 
#ifdef XT_NO_ATOMICS
159
 
#define TAB_CAC_USE_PTHREAD_RW
160
 
#else
161
 
//#define TAB_CAC_USE_PTHREAD_RW
162
 
#define TAB_CAC_USE_XSMUTEX
163
 
//#define IDX_USE_SPINXSLOCK
164
 
#endif
165
 
 
166
 
#if defined(TAB_CAC_USE_PTHREAD_RW)
167
 
#define TAB_CAC_LOCK_TYPE                               xt_rwlock_type
168
 
#define TAB_CAC_INIT_LOCK(s, i)                 xt_init_rwlock_with_autoname(s, i)
169
 
#define TAB_CAC_FREE_LOCK(s, i)                 xt_free_rwlock(i)       
170
 
#define TAB_CAC_READ_LOCK(i, o)                 do { xt_slock_rwlock_ns(i); (void) (o); } while(0)
171
 
#define TAB_CAC_WRITE_LOCK(i, o)                do { xt_xlock_rwlock_ns(i); (void) (o); } while(0)
172
 
#define TAB_CAC_UNLOCK(i, o)                    do { xt_unlock_rwlock_ns(i); (void) (o); } while(0)
173
 
#elif defined(TAB_CAC_USE_XSMUTEX)
174
 
#define TAB_CAC_LOCK_TYPE                               XTMutexXSLockRec
175
 
#define TAB_CAC_INIT_LOCK(s, i)                 xt_xsmutex_init_with_autoname(s, i)
176
 
#define TAB_CAC_FREE_LOCK(s, i)                 xt_xsmutex_free(s, i)   
177
 
#define TAB_CAC_READ_LOCK(i, o)                 xt_xsmutex_slock(i, o)
178
 
#define TAB_CAC_WRITE_LOCK(i, o)                xt_xsmutex_xlock(i, o)
179
 
#define TAB_CAC_UNLOCK(i, o)                    xt_xsmutex_unlock(i, o)
180
 
#elif defined(TAB_CAC_USE_SPINXSLOCK)
181
 
#define TAB_CAC_LOCK_TYPE                               XTSpinXSLockRec
182
 
#define TAB_CAC_INIT_LOCK(s, i)                 xt_spinxslock_init_with_autoname(s, i)
183
 
#define TAB_CAC_FREE_LOCK(s, i)                 xt_spinxslock_free(s, i)        
184
 
#define TAB_CAC_READ_LOCK(i, o)                 xt_spinxslock_slock(i, o)
185
 
#define TAB_CAC_WRITE_LOCK(i, o)                xt_spinxslock_xlock(i, FALSE, o)
186
 
#define TAB_CAC_UNLOCK(i, o)                    xt_spinxslock_unlock(i, o)
187
 
#else
188
 
#error Please define the lock type
189
 
#endif
190
 
 
191
 
/* A disk cache segment. The cache is divided into a number of segments
192
 
 * to improve concurrency.
193
 
 */
194
 
typedef struct XTTabCacheSeg {
195
 
        TAB_CAC_LOCK_TYPE               tcs_lock;                                               /* The cache segment read/write lock. */
196
 
        XTTabCachePagePtr               *tcs_hash_table;
197
 
        size_t                                  tcs_cache_in_use;
198
 
#ifdef CHECK_DOUBLE_READ
199
 
        u_int                                   tcs_total_reads;
200
 
        u_int                                   tcs_read_not_req;
201
 
#endif
202
 
} XTTabCacheSegRec, *XTTabCacheSegPtr;
203
 
 
204
 
/*
205
 
 * The free'er thread has a list of tables to be purged from the cache.
206
 
 * If a table is in the list then it is not allowed to fetch a cache page from
207
 
 * that table.
208
 
 * The free'er thread goes through all the cache, and removes
209
 
 * all cache pages for any table in the purge list.
210
 
 * When a table has been purged it signals any threads waiting for the
211
 
 * purge to complete (this is usually due to a drop table).
212
 
 */
213
 
typedef struct XTTabCachePurge {
214
 
        int                                             tcp_state;                                              /* The state of the purge. */
215
 
        XTTableSeqPtr                   tcp_tab_seq;                                    /* Identifies the table to be purged from cache. */
216
 
} XTTabCachePurgeRec, *XTTabCachePurgePtr;
217
 
 
218
 
typedef struct XTTabCacheMem {
219
 
        xt_mutex_type                   tcm_lock;                                               /* The public cache lock. */
220
 
        xt_cond_type                    tcm_cond;                                               /* The public cache wait condition. */
221
 
        XTTabCacheSegRec                tcm_segment[XT_TC_SEGMENT_COUNT];
222
 
        XTTabCachePagePtr               tcm_lru_page;
223
 
        XTTabCachePagePtr               tcm_mru_page;
224
 
        xtWord4                                 tcm_ru_now;
225
 
        size_t                                  tcm_approx_page_count;
226
 
        size_t                                  tcm_hash_size;
227
 
        u_int                                   tcm_writer_thread_count;
228
 
        size_t                                  tcm_cache_size;
229
 
        size_t                                  tcm_cache_high;                                 /* The high water level of cache allocation. */
230
 
        size_t                                  tcm_low_level;                                  /* This is the level to which the freeer will free, once it starts working. */
231
 
        size_t                                  tcm_high_level;                                 /* This is the level at which the freeer will start to work (to avoid waiting)! */
232
 
        size_t                                  tcm_mid_level;                                  /* At this level the freeer will not sleep if there are threads waiting. */
233
 
 
234
 
        /* The free'er thread: */
235
 
        struct XTThread                 *tcm_freeer_thread;                             /* The freeer thread . */
236
 
        xt_mutex_type                   tcm_freeer_lock;                                /* The public cache lock. */
237
 
        xt_cond_type                    tcm_freeer_cond;                                /* The public cache wait condition. */
238
 
        u_int                                   tcm_purge_list_len;                             /* The length of the purge list. */
239
 
        XTTabCachePurgePtr              tcm_purge_list;                                 /* Non-NULL if a table is to be purged. */
240
 
        u_int                                   tcm_threads_waiting;                    /* Count of the number of threads waiting for the freeer. */
241
 
        xtBool                                  tcm_freeer_busy;
242
 
        u_int                                   tcm_free_try_count;
243
 
} XTTabCacheMemRec, *XTTabCacheMemPtr;
244
 
 
245
 
/*
246
 
 * This structure contains the information about a particular table
247
 
 * for the cache. Each table has its own page size, row size
248
 
 * and rows per page.
249
 
 * Tables also have 
250
 
 */
251
 
typedef struct XTTabCache {
252
 
        struct XTTable                  *tci_table;
253
 
        xtBool                                  tci_rec_file;                                   /* TRUE if this is a record file (handle data), as appossed to a row file. */
254
 
        size_t                                  tci_header_size;
255
 
        size_t                                  tci_page_size;
256
 
        size_t                                  tci_rec_size;
257
 
        size_t                                  tci_rows_per_page;
258
 
 
259
 
public:
260
 
        void                                    xt_tc_setup(struct XTTable *tab, xtBool rec_file, size_t head_size, size_t row_size);
261
 
        xtBool                                  xt_tc_write(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, size_t offset, size_t size, xtWord1 *data, xtOpSeqNo *op_seq, xtBool read, XTThreadPtr thread);
262
 
        xtBool                                  xt_tc_write_cond(XTThreadPtr self, XT_ROW_REC_FILE_PTR file, xtRefID ref_id, xtWord1 new_type, xtOpSeqNo *op_seq, xtXactID xn_id, xtRowID row_id, u_int stat_id, u_int rec_type);
263
 
        xtBool                                  xt_tc_read(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, size_t size, xtWord1 *data, XTThreadPtr thread);
264
 
        xtBool                                  xt_tc_read_4(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, xtWord4 *data, XTThreadPtr thread);
265
 
        xtBool                                  xt_tc_read_page(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, xtWord1 *data, XTThreadPtr thread);
266
 
        xtBool                                  xt_tc_get_page(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, xtBool load, XTTabCachePagePtr *page, size_t *offset, XTThreadPtr thread);
267
 
        void                                    xt_tc_release_page(XT_ROW_REC_FILE_PTR file, XTTabCachePagePtr page, XTThreadPtr thread);
268
 
        xtBool                                  tc_fetch(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, XTTabCacheSegPtr *ret_seg, XTTabCachePagePtr *ret_page, size_t *offset, xtBool read, XTThreadPtr thread);
269
 
 
270
 
        xtBool                                  xt_tc_lock_page(XT_ROW_REC_FILE_PTR file, XTTabCachePagePtr *page, xtRefID ref_id, size_t *offset, XTThreadPtr thread);
271
 
        void                                    xt_tc_unlock_page(XT_ROW_REC_FILE_PTR file, XTTabCachePagePtr page, xtOpSeqNo *op_seq, XTThreadPtr thread);
272
 
 
273
 
private:
274
 
        xtBool                                  tc_read_direct(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, size_t size, xtWord1 *data, XTThreadPtr thread);
275
 
        xtBool                                  tc_fetch_direct(XT_ROW_REC_FILE_PTR file, xtRefID ref_id, XTTabCacheSegPtr *ret_seg, XTTabCachePagePtr *ret_page, size_t *offset, XTThreadPtr thread);
276
 
} XTTabCacheRec, *XTTabCachePtr;
277
 
 
278
 
extern XTTabCacheMemRec xt_tab_cache;
279
 
 
280
 
void    xt_tc_init(XTThreadPtr self, size_t cache_size);
281
 
void    xt_tc_exit(XTThreadPtr self);
282
 
void    xt_tc_set_cache_size(size_t cache_size);
283
 
xtInt8  xt_tc_get_usage();
284
 
xtInt8  xt_tc_get_size();
285
 
xtInt8  xt_tc_get_high();
286
 
void    xt_load_pages(XTThreadPtr self, struct XTOpenTable *ot);
287
 
#ifdef DEBUG
288
 
void    xt_check_table_cache(struct XTTable *tab);
289
 
#endif
290
 
 
291
 
void    xt_quit_freeer(XTThreadPtr self);
292
 
void    xt_stop_freeer(XTThreadPtr self);
293
 
void    xt_start_freeer(XTThreadPtr self);
294
 
void    xt_wr_wake_freeer(XTThreadPtr self, struct XTDatabase *db);
295
 
 
296
 
#endif