Query in SQL function still not schema-safe; add a couple
[PostgreSQL.git] / src / backend / storage / buffer / buf_init.c
blobe0211f57ee31ba5c52ae92ab3eb3dacca03b5e51
1 /*-------------------------------------------------------------------------
3 * buf_init.c
4 * buffer manager initialization routines
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * IDENTIFICATION
11 * $PostgreSQL$
13 *-------------------------------------------------------------------------
15 #include "postgres.h"
17 #include "storage/bufmgr.h"
18 #include "storage/buf_internals.h"
21 BufferDesc *BufferDescriptors;
22 char *BufferBlocks;
23 int32 *PrivateRefCount;
25 /* statistics counters */
26 long int ReadBufferCount;
27 long int ReadLocalBufferCount;
28 long int BufferHitCount;
29 long int LocalBufferHitCount;
30 long int BufferFlushCount;
31 long int LocalBufferFlushCount;
32 long int BufFileReadCount;
33 long int BufFileWriteCount;
37 * Data Structures:
38 * buffers live in a freelist and a lookup data structure.
41 * Buffer Lookup:
42 * Two important notes. First, the buffer has to be
43 * available for lookup BEFORE an IO begins. Otherwise
44 * a second process trying to read the buffer will
45 * allocate its own copy and the buffer pool will
46 * become inconsistent.
48 * Buffer Replacement:
49 * see freelist.c. A buffer cannot be replaced while in
50 * use either by data manager or during IO.
53 * Synchronization/Locking:
55 * IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
56 * It must be set when an IO is initiated and cleared at
57 * the end of the IO. It is there to make sure that one
58 * process doesn't start to use a buffer while another is
59 * faulting it in. see WaitIO and related routines.
61 * refcount -- Counts the number of processes holding pins on a buffer.
62 * A buffer is pinned during IO and immediately after a BufferAlloc().
63 * Pins must be released before end of transaction.
65 * PrivateRefCount -- Each buffer also has a private refcount that keeps
66 * track of the number of times the buffer is pinned in the current
67 * process. This is used for two purposes: first, if we pin a
68 * a buffer more than once, we only need to change the shared refcount
69 * once, thus only lock the shared state once; second, when a transaction
70 * aborts, it should only unpin the buffers exactly the number of times it
71 * has pinned them, so that it will not blow away buffers of another
72 * backend.
77 * Initialize shared buffer pool
79 * This is called once during shared-memory initialization (either in the
80 * postmaster, or in a standalone backend).
82 void
83 InitBufferPool(void)
85 bool foundBufs,
86 foundDescs;
88 BufferDescriptors = (BufferDesc *)
89 ShmemInitStruct("Buffer Descriptors",
90 NBuffers * sizeof(BufferDesc), &foundDescs);
92 BufferBlocks = (char *)
93 ShmemInitStruct("Buffer Blocks",
94 NBuffers * (Size) BLCKSZ, &foundBufs);
96 if (foundDescs || foundBufs)
98 /* both should be present or neither */
99 Assert(foundDescs && foundBufs);
100 /* note: this path is only taken in EXEC_BACKEND case */
102 else
104 BufferDesc *buf;
105 int i;
107 buf = BufferDescriptors;
110 * Initialize all the buffer headers.
112 for (i = 0; i < NBuffers; buf++, i++)
114 CLEAR_BUFFERTAG(buf->tag);
115 buf->flags = 0;
116 buf->usage_count = 0;
117 buf->refcount = 0;
118 buf->wait_backend_pid = 0;
120 SpinLockInit(&buf->buf_hdr_lock);
122 buf->buf_id = i;
125 * Initially link all the buffers together as unused. Subsequent
126 * management of this list is done by freelist.c.
128 buf->freeNext = i + 1;
130 buf->io_in_progress_lock = LWLockAssign();
131 buf->content_lock = LWLockAssign();
134 /* Correct last entry of linked list */
135 BufferDescriptors[NBuffers - 1].freeNext = FREENEXT_END_OF_LIST;
138 /* Init other shared buffer-management stuff */
139 StrategyInitialize(!foundDescs);
143 * Initialize access to shared buffer pool
145 * This is called during backend startup (whether standalone or under the
146 * postmaster). It sets up for this backend's access to the already-existing
147 * buffer pool.
149 * NB: this is called before InitProcess(), so we do not have a PGPROC and
150 * cannot do LWLockAcquire; hence we can't actually access stuff in
151 * shared memory yet. We are only initializing local data here.
152 * (See also InitBufferPoolBackend, over in bufmgr.c.)
154 void
155 InitBufferPoolAccess(void)
158 * Allocate and zero local arrays of per-buffer info.
160 PrivateRefCount = (int32 *) calloc(NBuffers, sizeof(int32));
161 if (!PrivateRefCount)
162 ereport(FATAL,
163 (errcode(ERRCODE_OUT_OF_MEMORY),
164 errmsg("out of memory")));
168 * BufferShmemSize
170 * compute the size of shared memory for the buffer pool including
171 * data pages, buffer descriptors, hash tables, etc.
173 Size
174 BufferShmemSize(void)
176 Size size = 0;
178 /* size of buffer descriptors */
179 size = add_size(size, mul_size(NBuffers, sizeof(BufferDesc)));
181 /* size of data pages */
182 size = add_size(size, mul_size(NBuffers, BLCKSZ));
184 /* size of stuff controlled by freelist.c */
185 size = add_size(size, StrategyShmemSize());
187 return size;