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