~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-04-12 07:43:55 UTC
  • mfrom: (1455.3.13 drizzle-pbxt-6)
  • Revision ID: brian@gaz-20100412074355-udi9dwjlcnmz0oz6
Merge PBXT

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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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)                 xt_slock_rwlock_ns(i)
 
171
#define TAB_CAC_WRITE_LOCK(i, o)                xt_xlock_rwlock_ns(i)
 
172
#define TAB_CAC_UNLOCK(i, o)                    xt_unlock_rwlock_ns(i)
 
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