~ubuntu-branches/ubuntu/natty/postgresql-8.4/natty-updates

« back to all changes in this revision

Viewing changes to src/include/storage/buf_internals.h

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * buf_internals.h
 
4
 *        Internal definitions for buffer manager and the buffer replacement
 
5
 *        strategy.
 
6
 *
 
7
 *
 
8
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 
9
 * Portions Copyright (c) 1994, Regents of the University of California
 
10
 *
 
11
 * $PostgreSQL$
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#ifndef BUFMGR_INTERNALS_H
 
16
#define BUFMGR_INTERNALS_H
 
17
 
 
18
#include "storage/buf.h"
 
19
#include "storage/lwlock.h"
 
20
#include "storage/shmem.h"
 
21
#include "storage/smgr.h"
 
22
#include "storage/spin.h"
 
23
#include "utils/relcache.h"
 
24
 
 
25
 
 
26
/*
 
27
 * Flags for buffer descriptors
 
28
 *
 
29
 * Note: TAG_VALID essentially means that there is a buffer hashtable
 
30
 * entry associated with the buffer's tag.
 
31
 */
 
32
#define BM_DIRTY                                (1 << 0)                /* data needs writing */
 
33
#define BM_VALID                                (1 << 1)                /* data is valid */
 
34
#define BM_TAG_VALID                    (1 << 2)                /* tag is assigned */
 
35
#define BM_IO_IN_PROGRESS               (1 << 3)                /* read or write in progress */
 
36
#define BM_IO_ERROR                             (1 << 4)                /* previous I/O failed */
 
37
#define BM_JUST_DIRTIED                 (1 << 5)                /* dirtied since write started */
 
38
#define BM_PIN_COUNT_WAITER             (1 << 6)                /* have waiter for sole pin */
 
39
#define BM_CHECKPOINT_NEEDED    (1 << 7)                /* must write for checkpoint */
 
40
 
 
41
typedef bits16 BufFlags;
 
42
 
 
43
/*
 
44
 * The maximum allowed value of usage_count represents a tradeoff between
 
45
 * accuracy and speed of the clock-sweep buffer management algorithm.  A
 
46
 * large value (comparable to NBuffers) would approximate LRU semantics.
 
47
 * But it can take as many as BM_MAX_USAGE_COUNT+1 complete cycles of
 
48
 * clock sweeps to find a free buffer, so in practice we don't want the
 
49
 * value to be very large.
 
50
 */
 
51
#define BM_MAX_USAGE_COUNT      5
 
52
 
 
53
/*
 
54
 * Buffer tag identifies which disk block the buffer contains.
 
55
 *
 
56
 * Note: the BufferTag data must be sufficient to determine where to write the
 
57
 * block, without reference to pg_class or pg_tablespace entries.  It's
 
58
 * possible that the backend flushing the buffer doesn't even believe the
 
59
 * relation is visible yet (its xact may have started before the xact that
 
60
 * created the rel).  The storage manager must be able to cope anyway.
 
61
 *
 
62
 * Note: if there's any pad bytes in the struct, INIT_BUFFERTAG will have
 
63
 * to be fixed to zero them, since this struct is used as a hash key.
 
64
 */
 
65
typedef struct buftag
 
66
{
 
67
        RelFileNode rnode;                      /* physical relation identifier */
 
68
        ForkNumber      forkNum;
 
69
        BlockNumber blockNum;           /* blknum relative to begin of reln */
 
70
} BufferTag;
 
71
 
 
72
#define CLEAR_BUFFERTAG(a) \
 
73
( \
 
74
        (a).rnode.spcNode = InvalidOid, \
 
75
        (a).rnode.dbNode = InvalidOid, \
 
76
        (a).rnode.relNode = InvalidOid, \
 
77
        (a).forkNum = InvalidForkNumber, \
 
78
        (a).blockNum = InvalidBlockNumber \
 
79
)
 
80
 
 
81
#define INIT_BUFFERTAG(a,xx_rnode,xx_forkNum,xx_blockNum) \
 
82
( \
 
83
        (a).rnode = (xx_rnode), \
 
84
        (a).forkNum = (xx_forkNum), \
 
85
        (a).blockNum = (xx_blockNum) \
 
86
)
 
87
 
 
88
#define BUFFERTAGS_EQUAL(a,b) \
 
89
( \
 
90
        RelFileNodeEquals((a).rnode, (b).rnode) && \
 
91
        (a).blockNum == (b).blockNum && \
 
92
        (a).forkNum == (b).forkNum \
 
93
)
 
94
 
 
95
/*
 
96
 * The shared buffer mapping table is partitioned to reduce contention.
 
97
 * To determine which partition lock a given tag requires, compute the tag's
 
98
 * hash code with BufTableHashCode(), then apply BufMappingPartitionLock().
 
99
 * NB: NUM_BUFFER_PARTITIONS must be a power of 2!
 
100
 */
 
101
#define BufTableHashPartition(hashcode) \
 
102
        ((hashcode) % NUM_BUFFER_PARTITIONS)
 
103
#define BufMappingPartitionLock(hashcode) \
 
104
        ((LWLockId) (FirstBufMappingLock + BufTableHashPartition(hashcode)))
 
105
 
 
106
/*
 
107
 *      BufferDesc -- shared descriptor/state data for a single shared buffer.
 
108
 *
 
109
 * Note: buf_hdr_lock must be held to examine or change the tag, flags,
 
110
 * usage_count, refcount, or wait_backend_pid fields.  buf_id field never
 
111
 * changes after initialization, so does not need locking.      freeNext is
 
112
 * protected by the BufFreelistLock not buf_hdr_lock.  The LWLocks can take
 
113
 * care of themselves.  The buf_hdr_lock is *not* used to control access to
 
114
 * the data in the buffer!
 
115
 *
 
116
 * An exception is that if we have the buffer pinned, its tag can't change
 
117
 * underneath us, so we can examine the tag without locking the spinlock.
 
118
 * Also, in places we do one-time reads of the flags without bothering to
 
119
 * lock the spinlock; this is generally for situations where we don't expect
 
120
 * the flag bit being tested to be changing.
 
121
 *
 
122
 * We can't physically remove items from a disk page if another backend has
 
123
 * the buffer pinned.  Hence, a backend may need to wait for all other pins
 
124
 * to go away.  This is signaled by storing its own PID into
 
125
 * wait_backend_pid and setting flag bit BM_PIN_COUNT_WAITER.  At present,
 
126
 * there can be only one such waiter per buffer.
 
127
 *
 
128
 * We use this same struct for local buffer headers, but the lock fields
 
129
 * are not used and not all of the flag bits are useful either.
 
130
 */
 
131
typedef struct sbufdesc
 
132
{
 
133
        BufferTag       tag;                    /* ID of page contained in buffer */
 
134
        BufFlags        flags;                  /* see bit definitions above */
 
135
        uint16          usage_count;    /* usage counter for clock sweep code */
 
136
        unsigned        refcount;               /* # of backends holding pins on buffer */
 
137
        int                     wait_backend_pid;               /* backend PID of pin-count waiter */
 
138
 
 
139
        slock_t         buf_hdr_lock;   /* protects the above fields */
 
140
 
 
141
        int                     buf_id;                 /* buffer's index number (from 0) */
 
142
        int                     freeNext;               /* link in freelist chain */
 
143
 
 
144
        LWLockId        io_in_progress_lock;    /* to wait for I/O to complete */
 
145
        LWLockId        content_lock;   /* to lock access to buffer contents */
 
146
} BufferDesc;
 
147
 
 
148
#define BufferDescriptorGetBuffer(bdesc) ((bdesc)->buf_id + 1)
 
149
 
 
150
/*
 
151
 * The freeNext field is either the index of the next freelist entry,
 
152
 * or one of these special values:
 
153
 */
 
154
#define FREENEXT_END_OF_LIST    (-1)
 
155
#define FREENEXT_NOT_IN_LIST    (-2)
 
156
 
 
157
/*
 
158
 * Macros for acquiring/releasing a shared buffer header's spinlock.
 
159
 * Do not apply these to local buffers!
 
160
 *
 
161
 * Note: as a general coding rule, if you are using these then you probably
 
162
 * need to be using a volatile-qualified pointer to the buffer header, to
 
163
 * ensure that the compiler doesn't rearrange accesses to the header to
 
164
 * occur before or after the spinlock is acquired/released.
 
165
 */
 
166
#define LockBufHdr(bufHdr)              SpinLockAcquire(&(bufHdr)->buf_hdr_lock)
 
167
#define UnlockBufHdr(bufHdr)    SpinLockRelease(&(bufHdr)->buf_hdr_lock)
 
168
 
 
169
 
 
170
/* in buf_init.c */
 
171
extern PGDLLIMPORT BufferDesc *BufferDescriptors;
 
172
 
 
173
/* in localbuf.c */
 
174
extern BufferDesc *LocalBufferDescriptors;
 
175
 
 
176
/* event counters in buf_init.c */
 
177
extern long int ReadBufferCount;
 
178
extern long int ReadLocalBufferCount;
 
179
extern long int BufferHitCount;
 
180
extern long int LocalBufferHitCount;
 
181
extern long int BufferFlushCount;
 
182
extern long int LocalBufferFlushCount;
 
183
extern long int BufFileReadCount;
 
184
extern long int BufFileWriteCount;
 
185
 
 
186
 
 
187
/*
 
188
 * Internal routines: only called by bufmgr
 
189
 */
 
190
 
 
191
/* freelist.c */
 
192
extern volatile BufferDesc *StrategyGetBuffer(BufferAccessStrategy strategy,
 
193
                                  bool *lock_held);
 
194
extern void StrategyFreeBuffer(volatile BufferDesc *buf);
 
195
extern bool StrategyRejectBuffer(BufferAccessStrategy strategy,
 
196
                                         volatile BufferDesc *buf);
 
197
 
 
198
extern int      StrategySyncStart(uint32 *complete_passes, uint32 *num_buf_alloc);
 
199
extern Size StrategyShmemSize(void);
 
200
extern void StrategyInitialize(bool init);
 
201
 
 
202
/* buf_table.c */
 
203
extern Size BufTableShmemSize(int size);
 
204
extern void InitBufTable(int size);
 
205
extern uint32 BufTableHashCode(BufferTag *tagPtr);
 
206
extern int      BufTableLookup(BufferTag *tagPtr, uint32 hashcode);
 
207
extern int      BufTableInsert(BufferTag *tagPtr, uint32 hashcode, int buf_id);
 
208
extern void BufTableDelete(BufferTag *tagPtr, uint32 hashcode);
 
209
 
 
210
/* localbuf.c */
 
211
extern void LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum,
 
212
                                                                BlockNumber blockNum);
 
213
extern BufferDesc *LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum,
 
214
                                 BlockNumber blockNum, bool *foundPtr);
 
215
extern void MarkLocalBufferDirty(Buffer buffer);
 
216
extern void DropRelFileNodeLocalBuffers(RelFileNode rnode, ForkNumber forkNum,
 
217
                                                        BlockNumber firstDelBlock);
 
218
extern void AtEOXact_LocalBuffers(bool isCommit);
 
219
 
 
220
#endif   /* BUFMGR_INTERNALS_H */