~drizzle-trunk/drizzle/development

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