Commit dfd0121d authored by Thomas Munro's avatar Thomas Munro

Move some md.c-specific logic from smgr.c to md.c.

Potential future SMGR implementations may not want to create
tablespace directories when creating an SMGR relation.  Move that
logic to mdcreate().  Move the initialization of md-specific
data structures from smgropen() to a new callback mdopen().

Author: Thomas Munro
Reviewed-by: Shawn Debnath (as part of an earlier patch set)
Discussion: https://postgr.es/m/CA%2BhUKG%2BOZqOiOuDm5tC5DyQZtJ3FH4%2BFSVMqtdC4P1atpJ%2Bqhg%40mail.gmail.com
parent 3093eb2b
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "access/xlogutils.h" #include "access/xlogutils.h"
#include "access/xlog.h" #include "access/xlog.h"
#include "commands/tablespace.h"
#include "pgstat.h" #include "pgstat.h"
#include "postmaster/bgwriter.h" #include "postmaster/bgwriter.h"
#include "storage/fd.h" #include "storage/fd.h"
...@@ -120,7 +121,7 @@ static MemoryContext MdCxt; /* context for all MdfdVec objects */ ...@@ -120,7 +121,7 @@ static MemoryContext MdCxt; /* context for all MdfdVec objects */
/* local routines */ /* local routines */
static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum, static void mdunlinkfork(RelFileNodeBackend rnode, ForkNumber forkNum,
bool isRedo); bool isRedo);
static MdfdVec *mdopen(SMgrRelation reln, ForkNumber forknum, int behavior); static MdfdVec *mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior);
static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum, static void register_dirty_segment(SMgrRelation reln, ForkNumber forknum,
MdfdVec *seg); MdfdVec *seg);
static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum, static void register_unlink_segment(RelFileNodeBackend rnode, ForkNumber forknum,
...@@ -165,7 +166,7 @@ mdexists(SMgrRelation reln, ForkNumber forkNum) ...@@ -165,7 +166,7 @@ mdexists(SMgrRelation reln, ForkNumber forkNum)
*/ */
mdclose(reln, forkNum); mdclose(reln, forkNum);
return (mdopen(reln, forkNum, EXTENSION_RETURN_NULL) != NULL); return (mdopenfork(reln, forkNum, EXTENSION_RETURN_NULL) != NULL);
} }
/* /*
...@@ -185,6 +186,19 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) ...@@ -185,6 +186,19 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
Assert(reln->md_num_open_segs[forkNum] == 0); Assert(reln->md_num_open_segs[forkNum] == 0);
/*
* We may be using the target table space for the first time in this
* database, so create a per-database subdirectory if needed.
*
* XXX this is a fairly ugly violation of module layering, but this seems
* to be the best place to put the check. Maybe TablespaceCreateDbspace
* should be here and not in commands/tablespace.c? But that would imply
* importing a lot of stuff that smgr.c oughtn't know, either.
*/
TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode,
reln->smgr_rnode.node.dbNode,
isRedo);
path = relpath(reln->smgr_rnode, forkNum); path = relpath(reln->smgr_rnode, forkNum);
fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY); fd = PathNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY);
...@@ -425,7 +439,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -425,7 +439,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
} }
/* /*
* mdopen() -- Open the specified relation. * mdopenfork() -- Open one fork of the specified relation.
* *
* Note we only open the first segment, when there are multiple segments. * Note we only open the first segment, when there are multiple segments.
* *
...@@ -435,7 +449,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -435,7 +449,7 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
* invent one out of whole cloth. * invent one out of whole cloth.
*/ */
static MdfdVec * static MdfdVec *
mdopen(SMgrRelation reln, ForkNumber forknum, int behavior) mdopenfork(SMgrRelation reln, ForkNumber forknum, int behavior)
{ {
MdfdVec *mdfd; MdfdVec *mdfd;
char *path; char *path;
...@@ -474,6 +488,17 @@ mdopen(SMgrRelation reln, ForkNumber forknum, int behavior) ...@@ -474,6 +488,17 @@ mdopen(SMgrRelation reln, ForkNumber forknum, int behavior)
return mdfd; return mdfd;
} }
/*
* mdopen() -- Initialize newly-opened relation.
*/
void
mdopen(SMgrRelation reln)
{
/* mark it not open */
for (int forknum = 0; forknum <= MAX_FORKNUM; forknum++)
reln->md_num_open_segs[forknum] = 0;
}
/* /*
* mdclose() -- Close the specified relation, if it isn't closed already. * mdclose() -- Close the specified relation, if it isn't closed already.
*/ */
...@@ -713,7 +738,7 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, ...@@ -713,7 +738,7 @@ mdwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
BlockNumber BlockNumber
mdnblocks(SMgrRelation reln, ForkNumber forknum) mdnblocks(SMgrRelation reln, ForkNumber forknum)
{ {
MdfdVec *v = mdopen(reln, forknum, EXTENSION_FAIL); MdfdVec *v = mdopenfork(reln, forknum, EXTENSION_FAIL);
BlockNumber nblocks; BlockNumber nblocks;
BlockNumber segno = 0; BlockNumber segno = 0;
...@@ -1137,7 +1162,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno, ...@@ -1137,7 +1162,7 @@ _mdfd_getseg(SMgrRelation reln, ForkNumber forknum, BlockNumber blkno,
v = &reln->md_seg_fds[forknum][reln->md_num_open_segs[forknum] - 1]; v = &reln->md_seg_fds[forknum][reln->md_num_open_segs[forknum] - 1];
else else
{ {
v = mdopen(reln, forknum, behavior); v = mdopenfork(reln, forknum, behavior);
if (!v) if (!v)
return NULL; /* if behavior & EXTENSION_RETURN_NULL */ return NULL; /* if behavior & EXTENSION_RETURN_NULL */
} }
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "commands/tablespace.h"
#include "lib/ilist.h" #include "lib/ilist.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/ipc.h" #include "storage/ipc.h"
...@@ -41,6 +40,7 @@ typedef struct f_smgr ...@@ -41,6 +40,7 @@ typedef struct f_smgr
{ {
void (*smgr_init) (void); /* may be NULL */ void (*smgr_init) (void); /* may be NULL */
void (*smgr_shutdown) (void); /* may be NULL */ void (*smgr_shutdown) (void); /* may be NULL */
void (*smgr_open) (SMgrRelation reln);
void (*smgr_close) (SMgrRelation reln, ForkNumber forknum); void (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
void (*smgr_create) (SMgrRelation reln, ForkNumber forknum, void (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
bool isRedo); bool isRedo);
...@@ -68,6 +68,7 @@ static const f_smgr smgrsw[] = { ...@@ -68,6 +68,7 @@ static const f_smgr smgrsw[] = {
{ {
.smgr_init = mdinit, .smgr_init = mdinit,
.smgr_shutdown = NULL, .smgr_shutdown = NULL,
.smgr_open = mdopen,
.smgr_close = mdclose, .smgr_close = mdclose,
.smgr_create = mdcreate, .smgr_create = mdcreate,
.smgr_exists = mdexists, .smgr_exists = mdexists,
...@@ -170,8 +171,6 @@ smgropen(RelFileNode rnode, BackendId backend) ...@@ -170,8 +171,6 @@ smgropen(RelFileNode rnode, BackendId backend)
/* Initialize it if not present before */ /* Initialize it if not present before */
if (!found) if (!found)
{ {
int forknum;
/* hash_search already filled in the lookup key */ /* hash_search already filled in the lookup key */
reln->smgr_owner = NULL; reln->smgr_owner = NULL;
reln->smgr_targblock = InvalidBlockNumber; reln->smgr_targblock = InvalidBlockNumber;
...@@ -179,9 +178,8 @@ smgropen(RelFileNode rnode, BackendId backend) ...@@ -179,9 +178,8 @@ smgropen(RelFileNode rnode, BackendId backend)
reln->smgr_vm_nblocks = InvalidBlockNumber; reln->smgr_vm_nblocks = InvalidBlockNumber;
reln->smgr_which = 0; /* we only have md.c at present */ reln->smgr_which = 0; /* we only have md.c at present */
/* mark it not open */ /* implementation-specific initialization */
for (forknum = 0; forknum <= MAX_FORKNUM; forknum++) smgrsw[reln->smgr_which].smgr_open(reln);
reln->md_num_open_segs[forknum] = 0;
/* it has no owner yet */ /* it has no owner yet */
dlist_push_tail(&unowned_relns, &reln->node); dlist_push_tail(&unowned_relns, &reln->node);
...@@ -330,33 +328,10 @@ smgrclosenode(RelFileNodeBackend rnode) ...@@ -330,33 +328,10 @@ smgrclosenode(RelFileNodeBackend rnode)
* Given an already-created (but presumably unused) SMgrRelation, * Given an already-created (but presumably unused) SMgrRelation,
* cause the underlying disk file or other storage for the fork * cause the underlying disk file or other storage for the fork
* to be created. * to be created.
*
* If isRedo is true, it is okay for the underlying file to exist
* already because we are in a WAL replay sequence.
*/ */
void void
smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
{ {
/*
* Exit quickly in WAL replay mode if we've already opened the file. If
* it's open, it surely must exist.
*/
if (isRedo && reln->md_num_open_segs[forknum] > 0)
return;
/*
* We may be using the target table space for the first time in this
* database, so create a per-database subdirectory if needed.
*
* XXX this is a fairly ugly violation of module layering, but this seems
* to be the best place to put the check. Maybe TablespaceCreateDbspace
* should be here and not in commands/tablespace.c? But that would imply
* importing a lot of stuff that smgr.c oughtn't know, either.
*/
TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode,
reln->smgr_rnode.node.dbNode,
isRedo);
smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo); smgrsw[reln->smgr_which].smgr_create(reln, forknum, isRedo);
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
/* md storage manager functionality */ /* md storage manager functionality */
extern void mdinit(void); extern void mdinit(void);
extern void mdopen(SMgrRelation reln);
extern void mdclose(SMgrRelation reln, ForkNumber forknum); extern void mdclose(SMgrRelation reln, ForkNumber forknum);
extern void mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo); extern void mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo);
extern bool mdexists(SMgrRelation reln, ForkNumber forknum); extern bool mdexists(SMgrRelation reln, ForkNumber forknum);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment