1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
/* Copyright (C) 2005 PrimeBase Technologies GmbH
*
* PrimeBase XT
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* 2005-05-24 Paul McCullagh
*
* H&G2JCtL
*/
#ifndef __xt_cache_h__
#define __xt_cache_h__
//#define XT_USE_MYSYS
#include "filesys_xt.h"
#include "index_xt.h"
struct XTOpenTable;
struct XTIdxReadBuffer;
#ifdef DEBUG
//#define XT_USE_CACHE_DEBUG_SIZES
//#define CHECK_BLOCK_TRAILERS
#endif
#ifdef XT_USE_CACHE_DEBUG_SIZES
#define XT_INDEX_CACHE_SEGMENT_SHIFTS 1
#else
#define XT_INDEX_CACHE_SEGMENT_SHIFTS 3
#endif
#define IDX_CAC_BLOCK_FREE 0
#define IDX_CAC_BLOCK_CLEAN 1
#define IDX_CAC_BLOCK_DIRTY 2 /* On the dirty list! */
#define IDX_CAC_BLOCK_FLUSHING 3 /* This page needs to be written to the index log. */
#define IDX_CAC_BLOCK_LOGGED 4 /* This page needs to be transfered from the index log to the index. */
#define IDX_CAC_MODIFYABLE(x) ((x) == IDX_CAC_BLOCK_CLEAN || (x) == IDX_CAC_BLOCK_DIRTY || (x) == IDX_CAC_BLOCK_LOGGED)
#define IDX_CAC_NOT_FREE(x) ((x) != IDX_CAC_BLOCK_FREE)
#ifdef XT_NO_ATOMICS
#define XT_IPAGE_USE_PTHREAD_RW
#else
#define XT_IPAGE_USE_SPINXSLOCK
#endif
#if defined(XT_IPAGE_USE_PTHREAD_RW)
#define XT_IPAGE_LOCK_TYPE xt_rwlock_type
#define XT_IPAGE_INIT_LOCK(s, i) xt_init_rwlock_with_autoname(s, i)
#define XT_IPAGE_FREE_LOCK(s, i) xt_free_rwlock(i)
#define XT_IPAGE_READ_LOCK(i) xt_slock_rwlock_ns(i)
#define XT_IPAGE_WRITE_LOCK(i, s) xt_xlock_rwlock_ns(i)
#define XT_IPAGE_WRITE_TRY_LOCK(i, s) xt_xlock_try_rwlock_ns(i)
#define XT_IPAGE_UNLOCK(i, x) xt_unlock_rwlock_ns(i)
#elif defined(XT_IPAGE_USE_SPINXSLOCK)
#define XT_IPAGE_LOCK_TYPE XTSpinXSLockRec
#define XT_IPAGE_INIT_LOCK(s, i) xt_spinxslock_init_with_autoname(s, i)
#define XT_IPAGE_FREE_LOCK(s, i) xt_spinxslock_free(s, i)
#define XT_IPAGE_READ_LOCK(i) xt_spinxslock_slock(i)
#define XT_IPAGE_WRITE_LOCK(i, o) xt_spinxslock_xlock(i, FALSE, o)
#define XT_IPAGE_WRITE_TRY_LOCK(i, o) xt_spinxslock_xlock(i, TRUE, o)
#define XT_IPAGE_UNLOCK(i, x) xt_spinxslock_unlock(i, x)
#else // XT_IPAGE_USE_SKEW_RW
#error Please define the lock type
#endif
enum XTPageLockType { XT_LOCK_READ, XT_LOCK_WRITE, XT_XLOCK_LEAF, XT_XLOCK_DEL_LEAF };
enum XTPageUnlockType { XT_UNLOCK_NONE, XT_UNLOCK_READ, XT_UNLOCK_WRITE, XT_UNLOCK_R_UPDATE, XT_UNLOCK_W_UPDATE };
/* A block is X locked if it is being changed or freed.
* A block is S locked if it is being read.
*/
typedef struct XTIndBlock {
xtIndexNodeID cb_address; /* The block address. */
u_int cb_file_id; /* The file id of the block. */
/* This is protected by cs_lock */
struct XTIndBlock *cb_next; /* Pointer to next block on hash list, or next free block on free list. */
/* This is protected by mi_dirty_lock */
struct XTIndBlock *cb_dirty_next; /* Double link for dirty blocks, next pointer. */
struct XTIndBlock *cb_dirty_prev; /* Double link for dirty blocks, previous pointer. */
/* This is protected by cg_lock */
xtWord4 cb_ru_time; /* If this is in the top 1/4 don't change position in MRU list. */
struct XTIndBlock *cb_mr_used; /* More recently used blocks. */
struct XTIndBlock *cb_lr_used; /* Less recently used blocks. */
/* Protected by cb_lock: */
XT_IPAGE_LOCK_TYPE cb_lock;
xtWord1 cb_state; /* Block status. */
#ifdef IND_OPT_DATA_WRITTEN
xtBool1 cb_header; /* TRUE if the header changed. */
xtWord2 cb_min_pos; /* The minimum dirty byte. */
xtWord2 cb_max_pos; /* The maximum dirty byte. */
#endif
volatile xtWord2 cb_handle_count; /* TRUE if this page is referenced by a handle. */
xtWord2 cp_del_count; /* Number of deleted entries. */
#ifdef XT_USE_DIRECT_IO_ON_INDEX
xtWord1 *cb_data;
#else
xtWord1 cb_data[XT_INDEX_PAGE_SIZE];
#endif
#ifdef CHECK_BLOCK_TRAILERS
xtWord1 cp_check[4];
#endif
} XTIndBlockRec, *XTIndBlockPtr;
typedef struct XTIndReference {
xtBool ir_xlock; /* Set to TRUE if the cache block is X locked. */
xtBool ir_updated; /* Set to TRUE if the cache block is updated. */
XTIndBlockPtr ir_block;
XTIdxBranchDPtr ir_branch;
} XTIndReferenceRec, *XTIndReferencePtr;
typedef struct XTIndFreeBlock {
XTDiskValue1 if_zero1_1; /* Must be set to zero. */
XTDiskValue1 if_zero2_1; /* Must be set to zero. */
XTDiskValue1 if_status_1;
XTDiskValue1 if_unused1_1;
XTDiskValue4 if_unused2_4;
XTDiskValue8 if_next_block_8;
} XTIndFreeBlockRec, *XTIndFreeBlockPtr;
typedef struct XTIndHandleBlock {
xtWord4 hb_ref_count;
struct XTIndHandleBlock *hb_next;
XTIdxBranchDRec hb_branch;
} XTIndHandleBlockRec, *XTIndHandleBlockPtr;
typedef struct XTIndHandle {
struct XTIndHandle *ih_next;
struct XTIndHandle *ih_prev;
XTSpinLockRec ih_lock;
xtIndexNodeID ih_address;
xtBool ih_cache_reference; /* True if this handle references the cache. */
union {
XTIndBlockPtr ih_cache_block;
XTIndHandleBlockPtr ih_handle_block;
} x;
XTIdxBranchDPtr ih_branch;
} XTIndHandleRec, *XTIndHandlePtr;
void xt_ind_init(XTThreadPtr self, size_t cache_size);
void xt_ind_exit(XTThreadPtr self);
xtInt8 xt_ind_get_usage();
xtInt8 xt_ind_get_size();
u_int xt_ind_get_blocks();
u_int xt_ind_get_free_blocks();
xtBool xt_ind_write(struct XTOpenTable *ot, XTIndexPtr ind, xtIndexNodeID offset, size_t size, xtWord1 *data);
xtBool xt_ind_write_cache(struct XTOpenTable *ot, xtIndexNodeID offset, size_t size, xtWord1 *data);
xtBool xt_ind_free_block(struct XTOpenTable *ot, XTIndexPtr ind, xtIndexNodeID offset);
xtBool xt_ind_read_bytes(struct XTOpenTable *ot, XTIndexPtr ind, xtIndexNodeID offset, size_t size, xtWord1 *data);
void xt_ind_check_cache(XTIndexPtr ind);
xtBool xt_ind_reserve(struct XTOpenTable *ot, u_int count, XTIdxBranchDPtr not_this);
void xt_ind_free_reserved(struct XTOpenTable *ot);
void xt_ind_unreserve(struct XTOpenTable *ot);
xtBool xt_ind_fetch(struct XTOpenTable *ot, XTIndexPtr ind, xtIndexNodeID node, XTPageLockType ltype, XTIndReferencePtr iref);
xtBool xt_ind_get(struct XTOpenTable *ot, xtIndexNodeID address, XTIndReferencePtr iref);
xtBool xt_ind_release(struct XTOpenTable *ot, XTIndexPtr ind, XTPageUnlockType utype, XTIndReferencePtr iref);
void xt_ind_lock_handle(XTIndHandlePtr handle);
void xt_ind_unlock_handle(XTIndHandlePtr handle);
xtBool xt_ind_copy_on_write(XTIndReferencePtr iref);
XTIndHandlePtr xt_ind_get_handle(struct XTOpenTable *ot, XTIndexPtr ind, XTIndReferencePtr iref);
void xt_ind_release_handle(XTIndHandlePtr handle, xtBool have_lock, XTThreadPtr thread);
#ifdef CHECK_BLOCK_TRAILERS
extern void check_block_trailers();
#endif
#ifdef DEBUG
//#define DEBUG_CHECK_IND_CACHE
#endif
//#define XT_TRACE_INDEX
#ifdef XT_TRACE_INDEX
#define IDX_TRACE(x, y, z) xt_trace(x, y, z)
#else
#define IDX_TRACE(x, y, z)
#endif
#endif
|