PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_prewarm.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include <unistd.h>
#include "access/relation.h"
#include "catalog/index.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/read_stream.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
Include dependency graph for pg_prewarm.c:

Go to the source code of this file.

Enumerations

enum  PrewarmType { PREWARM_PREFETCH , PREWARM_READ , PREWARM_BUFFER }
 

Functions

 PG_MODULE_MAGIC_EXT (.name="pg_prewarm",.version=PG_VERSION)
 
 PG_FUNCTION_INFO_V1 (pg_prewarm)
 
Datum pg_prewarm (PG_FUNCTION_ARGS)
 

Variables

static PGIOAlignedBlock blockbuffer
 

Enumeration Type Documentation

◆ PrewarmType

Enumerator
PREWARM_PREFETCH 
PREWARM_READ 
PREWARM_BUFFER 

Definition at line 38 of file pg_prewarm.c.

39{
PrewarmType
Definition pg_prewarm.c:39
@ PREWARM_PREFETCH
Definition pg_prewarm.c:40
@ PREWARM_READ
Definition pg_prewarm.c:41
@ PREWARM_BUFFER
Definition pg_prewarm.c:42

Function Documentation

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( pg_prewarm  )

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "pg_prewarm",
version = PG_VERSION 
)

◆ pg_prewarm()

Datum pg_prewarm ( PG_FUNCTION_ARGS  )

Definition at line 60 of file pg_prewarm.c.

61{
62 Oid relOid;
64 text *type;
67 int64 nblocks;
69 int64 block;
70 Relation rel;
72 char *forkString;
73 char *ttype;
74 PrewarmType ptype;
76 char relkind;
78
79 /* Basic sanity checking. */
80 if (PG_ARGISNULL(0))
83 errmsg("relation cannot be null")));
84 relOid = PG_GETARG_OID(0);
85 if (PG_ARGISNULL(1))
88 errmsg("prewarm type cannot be null")));
90 ttype = text_to_cstring(type);
91 if (strcmp(ttype, "prefetch") == 0)
92 ptype = PREWARM_PREFETCH;
93 else if (strcmp(ttype, "read") == 0)
94 ptype = PREWARM_READ;
95 else if (strcmp(ttype, "buffer") == 0)
96 ptype = PREWARM_BUFFER;
97 else
98 {
101 errmsg("invalid prewarm type"),
102 errhint("Valid prewarm types are \"prefetch\", \"read\", and \"buffer\".")));
103 PG_RETURN_INT64(0); /* Placate compiler. */
104 }
105 if (PG_ARGISNULL(2))
108 errmsg("relation fork cannot be null")));
112
113 /*
114 * Open relation and check privileges. If the relation is an index, we
115 * must check the privileges on its parent table instead.
116 */
117 relkind = get_rel_relkind(relOid);
118 if (relkind == RELKIND_INDEX ||
119 relkind == RELKIND_PARTITIONED_INDEX)
120 {
121 privOid = IndexGetRelation(relOid, true);
122
123 /* Lock table before index to avoid deadlock. */
124 if (OidIsValid(privOid))
126 }
127 else
128 privOid = relOid;
129
130 rel = relation_open(relOid, AccessShareLock);
131
132 /*
133 * It's possible that the relation with OID "privOid" was dropped and the
134 * OID was reused before we locked it. If that happens, we could be left
135 * with the wrong parent table OID, in which case we must ERROR. It's
136 * possible that such a race would change the outcome of
137 * get_rel_relkind(), too, but the worst case scenario there is that we'll
138 * check privileges on the index instead of its parent table, which isn't
139 * too terrible.
140 */
141 if (!OidIsValid(privOid) ||
142 (privOid != relOid &&
143 privOid != IndexGetRelation(relOid, true)))
146 errmsg("could not find parent table of index \"%s\"",
148
150 if (aclresult != ACLCHECK_OK)
152
153 /* Check that the relation has storage. */
154 if (!RELKIND_HAS_STORAGE(rel->rd_rel->relkind))
157 errmsg("relation \"%s\" does not have storage",
160
161 /* Check that the fork exists. */
165 errmsg("fork \"%s\" does not exist for this relation",
166 forkString)));
167
168 /* Validate block numbers, or handle nulls. */
170 if (PG_ARGISNULL(3))
171 first_block = 0;
172 else
173 {
178 errmsg("starting block number must be between 0 and %" PRId64,
179 (nblocks - 1))));
180 }
181 if (PG_ARGISNULL(4))
182 last_block = nblocks - 1;
183 else
184 {
189 errmsg("ending block number must be between 0 and %" PRId64,
190 (nblocks - 1))));
191 }
192
193 /* Now we're ready to do the real work. */
194 if (ptype == PREWARM_PREFETCH)
195 {
196#ifdef USE_PREFETCH
197
198 /*
199 * In prefetch mode, we just hint the OS to read the blocks, but we
200 * don't know whether it really does it, and we don't wait for it to
201 * finish.
202 *
203 * It would probably be better to pass our prefetch requests in chunks
204 * of a megabyte or maybe even a whole segment at a time, but there's
205 * no practical way to do that at present without a gross modularity
206 * violation, so we just do this.
207 */
208 for (block = first_block; block <= last_block; ++block)
209 {
211 PrefetchBuffer(rel, forkNumber, block);
212 ++blocks_done;
213 }
214#else
217 errmsg("prefetch is not supported by this build")));
218#endif
219 }
220 else if (ptype == PREWARM_READ)
221 {
222 /*
223 * In read mode, we actually read the blocks, but not into shared
224 * buffers. This is more portable than prefetch mode (it works
225 * everywhere) and is synchronous.
226 */
227 for (block = first_block; block <= last_block; ++block)
228 {
231 ++blocks_done;
232 }
233 }
234 else if (ptype == PREWARM_BUFFER)
235 {
237 ReadStream *stream;
238
239 /*
240 * In buffer mode, we actually pull the data into shared_buffers.
241 */
242
243 /* Set up the private state for our streaming buffer read callback. */
246
247 /*
248 * It is safe to use batchmode as block_range_read_stream_cb takes no
249 * locks.
250 */
254 NULL,
255 rel,
258 &p,
259 0);
260
261 for (block = first_block; block <= last_block; ++block)
262 {
263 Buffer buf;
264
268 ++blocks_done;
269 }
271 read_stream_end(stream);
272 }
273
274 /* Close relation, release locks. */
276
277 if (privOid != relOid)
279
281}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4039
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
PrefetchBufferResult PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition bufmgr.c:772
BlockNumber RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
Definition bufmgr.c:4572
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5501
#define Assert(condition)
Definition c.h:873
int64_t int64
Definition c.h:543
#define OidIsValid(objectId)
Definition c.h:788
int errhint(const char *fmt,...)
Definition elog.c:1330
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_ARGISNULL(n)
Definition fmgr.h:209
#define PG_RETURN_INT64(x)
Definition fmgr.h:370
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
Oid IndexGetRelation(Oid indexId, bool missing_ok)
Definition index.c:3581
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:229
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition lmgr.c:107
#define AccessShareLock
Definition lockdefs.h:36
char * get_rel_name(Oid relid)
Definition lsyscache.c:2078
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
Oid GetUserId(void)
Definition miscinit.c:469
ObjectType get_relkind_objtype(char relkind)
#define ACL_SELECT
Definition parsenodes.h:77
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
static PGIOAlignedBlock blockbuffer
Definition pg_prewarm.c:45
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define ERRCODE_UNDEFINED_TABLE
Definition pgbench.c:79
unsigned int Oid
static int fb(int x)
Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_data)
ReadStream * read_stream_begin_relation(int flags, BufferAccessStrategy strategy, Relation rel, ForkNumber forknum, ReadStreamBlockNumberCB callback, void *callback_private_data, size_t per_buffer_data_size)
void read_stream_end(ReadStream *stream)
BlockNumber block_range_read_stream_cb(ReadStream *stream, void *callback_private_data, void *per_buffer_data)
#define READ_STREAM_MAINTENANCE
Definition read_stream.h:28
#define READ_STREAM_USE_BATCHING
Definition read_stream.h:64
#define READ_STREAM_FULL
Definition read_stream.h:43
static SMgrRelation RelationGetSmgr(Relation rel)
Definition rel.h:576
#define RelationGetRelationName(relation)
Definition rel.h:548
ForkNumber forkname_to_number(const char *forkName)
Definition relpath.c:50
ForkNumber
Definition relpath.h:56
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition smgr.c:462
static void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition smgr.h:124
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition relation.c:47
char data[BLCKSZ]
Definition c.h:1131
Form_pg_class rd_rel
Definition rel.h:111
Definition c.h:706
char * text_to_cstring(const text *t)
Definition varlena.c:214
const char * type

References AccessShareLock, ACL_SELECT, aclcheck_error(), ACLCHECK_OK, Assert, block_range_read_stream_cb(), blockbuffer, buf, CHECK_FOR_INTERRUPTS, BlockRangeReadStreamPrivate::current_blocknum, PGIOAlignedBlock::data, ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errdetail_relkind_not_supported(), errhint(), errmsg(), ERROR, fb(), forkname_to_number(), get_rel_name(), get_rel_relkind(), get_relkind_objtype(), GetUserId(), IndexGetRelation(), InvalidBuffer, BlockRangeReadStreamPrivate::last_exclusive, LockRelationOid(), OidIsValid, PG_ARGISNULL, pg_class_aclcheck(), PG_GETARG_INT64, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_INT64, PrefetchBuffer(), PREWARM_BUFFER, PREWARM_PREFETCH, PREWARM_READ, RelationData::rd_rel, read_stream_begin_relation(), read_stream_end(), READ_STREAM_FULL, READ_STREAM_MAINTENANCE, read_stream_next_buffer(), READ_STREAM_USE_BATCHING, relation_close(), relation_open(), RelationGetNumberOfBlocksInFork(), RelationGetRelationName, RelationGetSmgr(), ReleaseBuffer(), smgrexists(), smgrread(), text_to_cstring(), type, and UnlockRelationOid().

Variable Documentation

◆ blockbuffer

PGIOAlignedBlock blockbuffer
static

Definition at line 45 of file pg_prewarm.c.

Referenced by pg_prewarm().