summaryrefslogtreecommitdiff
path: root/src/dbinc/qam.h
blob: 657c11e24fca059a56ccf1c46fb2aa3af3332f6a (plain)
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
197
198
199
200
201
202
203
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 1999, 2012 Oracle and/or its affiliates.  All rights reserved.
 *
 * $Id$
 */

#ifndef	_DB_QAM_H_
#define	_DB_QAM_H_

#if defined(__cplusplus)
extern "C" {
#endif

/*
 * QAM data elements: a status field and the data.
 */
typedef struct _qamdata {
	u_int8_t  flags;	/* 00: delete bit. */
#define	QAM_VALID	0x01
#define	QAM_SET		0x02
	u_int8_t  data[1];	/* Record. */
} QAMDATA;

struct __queue;		typedef struct __queue QUEUE;
struct __qcursor;	typedef struct __qcursor QUEUE_CURSOR;

struct __qcursor {
	/* struct __dbc_internal */
	__DBC_INTERNAL

	/* Queue private part */

	/* Per-thread information: queue private. */
	db_recno_t	 recno;		/* Current record number. */

	u_int32_t	 flags;
};

typedef struct __mpfarray {
	u_int32_t n_extent;		/* Number of extents in table. */
	u_int32_t low_extent;		/* First extent open. */
	u_int32_t hi_extent;		/* Last extent open. */
	struct __qmpf {
		int pinref;
		DB_MPOOLFILE *mpf;
	} *mpfarray;			 /* Array of open extents. */
} MPFARRAY;

/*
 * The in-memory, per-tree queue data structure.
 */
struct __queue {
	db_pgno_t q_meta;		/* Database meta-data page. */
	db_pgno_t q_root;		/* Database root page. */

	int	  re_pad;		/* Fixed-length padding byte. */
	u_int32_t re_len;		/* Length for fixed-length records. */
	u_int32_t rec_page;		/* records per page */
	u_int32_t page_ext;		/* Pages per extent */
	MPFARRAY array1, array2;	/* File arrays. */

					/* Extent file configuration: */
	DBT pgcookie;			/* Initialized pgcookie. */
	DB_PGINFO pginfo;		/* Initialized pginfo struct. */

	char *path;			/* Space allocated to file pathname. */
	char *name;			/* The name of the file. */
	char *dir;			/* The dir of the file. */
	int mode;			/* Mode to open extents. */
};

/* Format for queue extent names. */
#define	QUEUE_EXTENT		"%s%c__dbq.%s.%d"
#define	QUEUE_EXTENT_HEAD	"__dbq.%s."
#define	QUEUE_EXTENT_PREFIX	"__dbq."

typedef struct __qam_filelist {
	DB_MPOOLFILE *mpf;
	u_int32_t id;
} QUEUE_FILELIST;

/*
 * Calculate the page number of a recno.
 *
 * Number of records per page =
 *	Divide the available space on the page by the record len + header.
 *
 * Page number for record =
 *	divide the physical record number by the records per page
 *	add the root page number
 *	For now the root page will always be 1, but we might want to change
 *	in the future (e.g. multiple fixed len queues per file).
 *
 * Index of record on page =
 *	physical record number, less the logical pno times records/page
 */
#define	CALC_QAM_RECNO_PER_PAGE(dbp)					\
    (((dbp)->pgsize - QPAGE_SZ(dbp)) /					\
    (u_int32_t)DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) +		\
    ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)))

#define	QAM_RECNO_PER_PAGE(dbp)	(((QUEUE*)(dbp)->q_internal)->rec_page)

#define	QAM_RECNO_PAGE(dbp, recno)					\
    (((QUEUE *)(dbp)->q_internal)->q_root				\
    + (((recno) - 1) / QAM_RECNO_PER_PAGE(dbp)))

#define	QAM_PAGE_EXTENT(dbp, pgno)					\
    (((pgno) - 1) / ((QUEUE *)(dbp)->q_internal)->page_ext)

#define	QAM_RECNO_EXTENT(dbp, recno)					\
    QAM_PAGE_EXTENT(dbp, QAM_RECNO_PAGE(dbp, recno))

#define	QAM_RECNO_INDEX(dbp, pgno, recno)				\
    (u_int32_t)(((recno) - 1) - (QAM_RECNO_PER_PAGE(dbp)		\
    * (pgno - ((QUEUE *)(dbp)->q_internal)->q_root)))

#define	QAM_GET_RECORD(dbp, page, index)				\
    ((QAMDATA *)((u_int8_t *)(page) + (QPAGE_SZ(dbp) +			\
    (DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) +				\
    ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index))))

#define QAM_OUTSIDE_QUEUE(meta, recno)					\
	(((meta)->cur_recno >= (meta)->first_recno ?			\
	    ((recno) < (meta)->first_recno ||				\
	         (recno) > (meta)->cur_recno) :				\
	    ((recno) > (meta)->cur_recno && 				\
	        (recno) < (meta)->first_recno)))

#define	QAM_AFTER_CURRENT(meta, recno)					\
	((recno) == (meta)->cur_recno ||				\
	(QAM_OUTSIDE_QUEUE(meta, recno) &&				\
        ((recno) - (meta)->cur_recno) <= ((meta)->first_recno - (recno))))

#define	QAM_BEFORE_FIRST(meta, recno)					\
	(QAM_OUTSIDE_QUEUE(meta, recno) &&				\
	((meta)->first_recno - (recno)) < ((recno) - (meta)->cur_recno))

#define	QAM_NOT_VALID(meta, recno)					\
    (recno == RECNO_OOB ||						\
	QAM_BEFORE_FIRST(meta, recno) || QAM_AFTER_CURRENT(meta, recno))

#define QAM_WAKEUP(dbc, ret) do {					\
	if (STD_LOCKING(dbc)) {						\
		dbc->lock.pgno = PGNO_INVALID;				\
		dbc->lock.type = DB_PAGE_LOCK;				\
		ret = __lock_wakeup((dbc)->dbp->env, &(dbc)->lock_dbt);	\
	} else								\
		ret = 0;						\
} while (0)

/* Handle wrap around. */
#define QAM_INC_RECNO(recno) do {					\
	recno++;							\
} while (recno == RECNO_OOB)

#define QAM_DEC_RECNO(recno) do {					\
	recno--;							\
} while (recno == RECNO_OOB)


/*
 * Log opcodes for the mvptr routine.
 */
#define	QAM_SETFIRST		0x01
#define	QAM_SETCUR		0x02
#define	QAM_TRUNCATE		0x04

typedef enum {
	QAM_PROBE_GET,
	QAM_PROBE_PUT,
	QAM_PROBE_DIRTY,
	QAM_PROBE_MPF
} qam_probe_mode;

/*
 * Ops for __qam_nameop.
 */
typedef enum {
	QAM_NAME_DISCARD,
	QAM_NAME_RENAME,
	QAM_NAME_REMOVE
} qam_name_op;

#define	__qam_fget(dbc, pgnoaddr, flags, addrp)		\
	__qam_fprobe(dbc, *pgnoaddr,					\
	    addrp, QAM_PROBE_GET, DB_PRIORITY_UNCHANGED, flags)

#define	__qam_fput(dbc, pgno, addrp, priority)			\
	__qam_fprobe(dbc, pgno, addrp, QAM_PROBE_PUT, priority, 0)

#define	__qam_dirty(dbc, pgno, pagep, priority)		\
	__qam_fprobe(dbc, pgno, pagep, QAM_PROBE_DIRTY, priority, 0)

#if defined(__cplusplus)
}
#endif

#include "dbinc_auto/qam_auto.h"
#include "dbinc_auto/qam_ext.h"
#endif /* !_DB_QAM_H_ */