Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Typedefs | Functions | Variables

smgr.c File Reference

#include "postgres.h"
#include "commands/tablespace.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
#include "storage/smgr.h"
#include "utils/hsearch.h"
#include "utils/inval.h"
Include dependency graph for smgr.c:

Go to the source code of this file.

Data Structures

struct  f_smgr

Typedefs

typedef struct f_smgr f_smgr

Functions

static void smgrshutdown (int code, Datum arg)
static void remove_from_unowned_list (SMgrRelation reln)
void smgrinit (void)
SMgrRelation smgropen (RelFileNode rnode, BackendId backend)
void smgrsetowner (SMgrRelation *owner, SMgrRelation reln)
bool smgrexists (SMgrRelation reln, ForkNumber forknum)
void smgrclose (SMgrRelation reln)
void smgrcloseall (void)
void smgrclosenode (RelFileNodeBackend rnode)
void smgrcreate (SMgrRelation reln, ForkNumber forknum, bool isRedo)
void smgrdounlink (SMgrRelation reln, bool isRedo)
void smgrdounlinkall (SMgrRelation *rels, int nrels, bool isRedo)
void smgrdounlinkfork (SMgrRelation reln, ForkNumber forknum, bool isRedo)
void smgrextend (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
void smgrprefetch (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
void smgrread (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
void smgrwrite (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
BlockNumber smgrnblocks (SMgrRelation reln, ForkNumber forknum)
void smgrtruncate (SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
void smgrimmedsync (SMgrRelation reln, ForkNumber forknum)
void smgrpreckpt (void)
void smgrsync (void)
void smgrpostckpt (void)
void AtEOXact_SMgr (void)

Variables

static const f_smgr smgrsw []
static const int NSmgr = lengthof(smgrsw)
static HTABSMgrRelationHash = NULL
static SMgrRelation first_unowned_reln = NULL

Typedef Documentation

typedef struct f_smgr f_smgr

Function Documentation

void AtEOXact_SMgr ( void   ) 

Definition at line 749 of file smgr.c.

References Assert, NULL, SMgrRelationData::smgr_owner, and smgrclose().

Referenced by AbortTransaction(), BackgroundWriterMain(), CheckpointerMain(), CommitTransaction(), PrepareTransaction(), and WalWriterMain().

{
    /*
     * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
     * one from the list.
     */
    while (first_unowned_reln != NULL)
    {
        Assert(first_unowned_reln->smgr_owner == NULL);
        smgrclose(first_unowned_reln);
    }
}

static void remove_from_unowned_list ( SMgrRelation  reln  )  [static]

Definition at line 230 of file smgr.c.

References cur, and SMgrRelationData::next_unowned_reln.

Referenced by smgrclose(), and smgrsetowner().

{
    SMgrRelation *link;
    SMgrRelation cur;

    for (link = &first_unowned_reln, cur = *link;
         cur != NULL;
         link = &cur->next_unowned_reln, cur = *link)
    {
        if (cur == reln)
        {
            *link = cur->next_unowned_reln;
            cur->next_unowned_reln = NULL;
            break;
        }
    }
}

void smgrclose ( SMgrRelation  reln  ) 

Definition at line 261 of file smgr.c.

References elog, ERROR, HASH_REMOVE, hash_search(), NULL, remove_from_unowned_list(), f_smgr::smgr_close, SMgrRelationData::smgr_owner, SMgrRelationData::smgr_rnode, and SMgrRelationData::smgr_which.

Referenced by AtEOXact_SMgr(), ATExecSetTableSpace(), FinishPreparedTransaction(), smgrcloseall(), smgrclosenode(), smgrDoPendingDeletes(), xact_redo_abort(), and xact_redo_commit_internal().

{
    SMgrRelation *owner;
    ForkNumber  forknum;

    for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
        (*(smgrsw[reln->smgr_which].smgr_close)) (reln, forknum);

    owner = reln->smgr_owner;

    if (!owner)
        remove_from_unowned_list(reln);

    if (hash_search(SMgrRelationHash,
                    (void *) &(reln->smgr_rnode),
                    HASH_REMOVE, NULL) == NULL)
        elog(ERROR, "SMgrRelation hashtable corrupted");

    /*
     * Unhook the owner pointer, if any.  We do this last since in the remote
     * possibility of failure above, the SMgrRelation object will still exist.
     */
    if (owner)
        *owner = NULL;
}

void smgrcloseall ( void   ) 

Definition at line 291 of file smgr.c.

References hash_seq_init(), hash_seq_search(), NULL, and smgrclose().

Referenced by BackgroundWriterMain(), CheckpointerMain(), RelationCacheInvalidate(), RequestCheckpoint(), WalWriterMain(), and XLogDropDatabase().

{
    HASH_SEQ_STATUS status;
    SMgrRelation reln;

    /* Nothing to do if hashtable not set up */
    if (SMgrRelationHash == NULL)
        return;

    hash_seq_init(&status, SMgrRelationHash);

    while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
        smgrclose(reln);
}

void smgrclosenode ( RelFileNodeBackend  rnode  ) 

Definition at line 315 of file smgr.c.

References hash_search(), NULL, and smgrclose().

Referenced by LocalExecuteInvalidationMessage(), and RelationSetNewRelfilenode().

{
    SMgrRelation reln;

    /* Nothing to do if hashtable not set up */
    if (SMgrRelationHash == NULL)
        return;

    reln = (SMgrRelation) hash_search(SMgrRelationHash,
                                      (void *) &rnode,
                                      HASH_FIND, NULL);
    if (reln != NULL)
        smgrclose(reln);
}

void smgrcreate ( SMgrRelation  reln,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 341 of file smgr.c.

References RelFileNode::dbNode, SMgrRelationData::md_fd, RelFileNodeBackend::node, NULL, f_smgr::smgr_create, SMgrRelationData::smgr_rnode, SMgrRelationData::smgr_which, RelFileNode::spcNode, and TablespaceCreateDbspace().

Referenced by ATExecSetTableSpace(), fsm_extend(), heap_create_init_fork(), index_build(), RelationCreateStorage(), smgr_redo(), vm_extend(), and XLogReadBufferExtended().

{
    /*
     * 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_fd[forknum] != NULL)
        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);
}

void smgrdounlink ( SMgrRelation  reln,
bool  isRedo 
)

Definition at line 379 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodesAllBuffers(), SMgrRelationData::smgr_rnode, f_smgr::smgr_unlink, and SMgrRelationData::smgr_which.

Referenced by FinishPreparedTransaction(), xact_redo_abort(), and xact_redo_commit_internal().

{
    RelFileNodeBackend rnode = reln->smgr_rnode;
    int         which = reln->smgr_which;
    ForkNumber  forknum;

    /* Close the forks at smgr level */
    for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
        (*(smgrsw[which].smgr_close)) (reln, forknum);

    /*
     * Get rid of any remaining buffers for the relation.  bufmgr will just
     * drop them without bothering to write the contents.
     */
    DropRelFileNodesAllBuffers(&rnode, 1);

    /*
     * It'd be nice to tell the stats collector to forget it immediately, too.
     * But we can't because we don't know the OID (and in cases involving
     * relfilenode swaps, it's not always clear which table OID to forget,
     * anyway).
     */

    /*
     * Send a shared-inval message to force other backends to close any
     * dangling smgr references they may have for this rel.  We should do this
     * before starting the actual unlinking, in case we fail partway through
     * that step.  Note that the sinval message will eventually come back to
     * this backend, too, and thereby provide a backstop that we closed our
     * own smgr rel.
     */
    CacheInvalidateSmgr(rnode);

    /*
     * Delete the physical file(s).
     *
     * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     * ERROR, because we've already decided to commit or abort the current
     * xact.
     */
    (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
}

void smgrdounlinkall ( SMgrRelation rels,
int  nrels,
bool  isRedo 
)

Definition at line 436 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodesAllBuffers(), i, palloc(), pfree(), SMgrRelationData::smgr_rnode, and SMgrRelationData::smgr_which.

Referenced by smgrDoPendingDeletes().

{
    int     i = 0;
    RelFileNodeBackend *rnodes;
    ForkNumber  forknum;

    if (nrels == 0)
        return;

    /*
     * create an array which contains all relations to be dropped, and
     * close each relation's forks at the smgr level while at it
     */
    rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
    for (i = 0; i < nrels; i++)
    {
        RelFileNodeBackend rnode = rels[i]->smgr_rnode;
        int         which = rels[i]->smgr_which;

        rnodes[i] = rnode;

        /* Close the forks at smgr level */
        for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
            (*(smgrsw[which].smgr_close)) (rels[i], forknum);
    }

    /*
     * Get rid of any remaining buffers for the relations.  bufmgr will just
     * drop them without bothering to write the contents.
     */
    DropRelFileNodesAllBuffers(rnodes, nrels);

    /*
     * It'd be nice to tell the stats collector to forget them immediately, too.
     * But we can't because we don't know the OIDs.
     */

    /*
     * Send a shared-inval message to force other backends to close any
     * dangling smgr references they may have for these rels.  We should do
     * this before starting the actual unlinking, in case we fail partway
     * through that step.  Note that the sinval messages will eventually come
     * back to this backend, too, and thereby provide a backstop that we closed
     * our own smgr rel.
     */
    for (i = 0; i < nrels; i++)
        CacheInvalidateSmgr(rnodes[i]);

    /*
     * Delete the physical file(s).
     *
     * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     * ERROR, because we've already decided to commit or abort the current
     * xact.
     */

    for (i = 0; i < nrels; i++)
    {
        int which = rels[i]->smgr_which;
        for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
            (*(smgrsw[which].smgr_unlink)) (rnodes[i], forknum, isRedo);
    }

    pfree(rnodes);
}

void smgrdounlinkfork ( SMgrRelation  reln,
ForkNumber  forknum,
bool  isRedo 
)

Definition at line 513 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodeBuffers(), f_smgr::smgr_close, SMgrRelationData::smgr_rnode, f_smgr::smgr_unlink, and SMgrRelationData::smgr_which.

{
    RelFileNodeBackend rnode = reln->smgr_rnode;
    int         which = reln->smgr_which;

    /* Close the fork at smgr level */
    (*(smgrsw[which].smgr_close)) (reln, forknum);

    /*
     * Get rid of any remaining buffers for the fork.  bufmgr will just drop
     * them without bothering to write the contents.
     */
    DropRelFileNodeBuffers(rnode, forknum, 0);

    /*
     * It'd be nice to tell the stats collector to forget it immediately, too.
     * But we can't because we don't know the OID (and in cases involving
     * relfilenode swaps, it's not always clear which table OID to forget,
     * anyway).
     */

    /*
     * Send a shared-inval message to force other backends to close any
     * dangling smgr references they may have for this rel.  We should do this
     * before starting the actual unlinking, in case we fail partway through
     * that step.  Note that the sinval message will eventually come back to
     * this backend, too, and thereby provide a backstop that we closed our
     * own smgr rel.
     */
    CacheInvalidateSmgr(rnode);

    /*
     * Delete the physical file(s).
     *
     * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     * ERROR, because we've already decided to commit or abort the current
     * xact.
     */
    (*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
}

bool smgrexists ( SMgrRelation  reln,
ForkNumber  forknum 
)
void smgrextend ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)
void smgrimmedsync ( SMgrRelation  reln,
ForkNumber  forknum 
)
void smgrinit ( void   ) 

Definition at line 99 of file smgr.c.

References i, NSmgr, on_proc_exit(), f_smgr::smgr_init, and smgrshutdown().

Referenced by BaseInit().

{
    int         i;

    for (i = 0; i < NSmgr; i++)
    {
        if (smgrsw[i].smgr_init)
            (*(smgrsw[i].smgr_init)) ();
    }

    /* register the shutdown proc */
    on_proc_exit(smgrshutdown, 0);
}

BlockNumber smgrnblocks ( SMgrRelation  reln,
ForkNumber  forknum 
)
SMgrRelation smgropen ( RelFileNode  rnode,
BackendId  backend 
)

Definition at line 134 of file smgr.c.

References RelFileNodeBackend::backend, HASHCTL::entrysize, HASHCTL::hash, hash_create(), HASH_ELEM, HASH_FUNCTION, hash_search(), HASHCTL::keysize, SMgrRelationData::md_fd, MemSet, SMgrRelationData::next_unowned_reln, RelFileNodeBackend::node, NULL, SMgrRelationData::smgr_fsm_nblocks, SMgrRelationData::smgr_owner, SMgrRelationData::smgr_targblock, SMgrRelationData::smgr_vm_nblocks, and SMgrRelationData::smgr_which.

Referenced by ATExecSetTableSpace(), FinishPreparedTransaction(), FlushBuffer(), LocalBufferAlloc(), mdsync(), ReadBufferWithoutRelcache(), RelationCreateStorage(), smgr_redo(), smgrDoPendingDeletes(), xact_redo_abort(), xact_redo_commit_internal(), and XLogReadBufferExtended().

{
    RelFileNodeBackend brnode;
    SMgrRelation reln;
    bool        found;

    if (SMgrRelationHash == NULL)
    {
        /* First time through: initialize the hash table */
        HASHCTL     ctl;

        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(RelFileNodeBackend);
        ctl.entrysize = sizeof(SMgrRelationData);
        ctl.hash = tag_hash;
        SMgrRelationHash = hash_create("smgr relation table", 400,
                                       &ctl, HASH_ELEM | HASH_FUNCTION);
        first_unowned_reln = NULL;
    }

    /* Look up or create an entry */
    brnode.node = rnode;
    brnode.backend = backend;
    reln = (SMgrRelation) hash_search(SMgrRelationHash,
                                      (void *) &brnode,
                                      HASH_ENTER, &found);

    /* Initialize it if not present before */
    if (!found)
    {
        int         forknum;

        /* hash_search already filled in the lookup key */
        reln->smgr_owner = NULL;
        reln->smgr_targblock = InvalidBlockNumber;
        reln->smgr_fsm_nblocks = InvalidBlockNumber;
        reln->smgr_vm_nblocks = InvalidBlockNumber;
        reln->smgr_which = 0;   /* we only have md.c at present */

        /* mark it not open */
        for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
            reln->md_fd[forknum] = NULL;

        /* place it at head of unowned list (to make smgrsetowner cheap) */
        reln->next_unowned_reln = first_unowned_reln;
        first_unowned_reln = reln;
    }

    return reln;
}

void smgrpostckpt ( void   ) 

Definition at line 725 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_post_ckpt.

Referenced by CreateCheckPoint().

{
    int         i;

    for (i = 0; i < NSmgr; i++)
    {
        if (smgrsw[i].smgr_post_ckpt)
            (*(smgrsw[i].smgr_post_ckpt)) ();
    }
}

void smgrpreckpt ( void   ) 

Definition at line 695 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_pre_ckpt.

Referenced by CreateCheckPoint().

{
    int         i;

    for (i = 0; i < NSmgr; i++)
    {
        if (smgrsw[i].smgr_pre_ckpt)
            (*(smgrsw[i].smgr_pre_ckpt)) ();
    }
}

void smgrprefetch ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum 
)

Definition at line 575 of file smgr.c.

References f_smgr::smgr_prefetch, and SMgrRelationData::smgr_which.

Referenced by LocalPrefetchBuffer(), and PrefetchBuffer().

{
    (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum);
}

void smgrread ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer 
)

Definition at line 589 of file smgr.c.

References f_smgr::smgr_read, and SMgrRelationData::smgr_which.

Referenced by copy_relation_data(), and ReadBuffer_common().

{
    (*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
}

void smgrsetowner ( SMgrRelation owner,
SMgrRelation  reln 
)

Definition at line 192 of file smgr.c.

References Assert, NULL, remove_from_unowned_list(), and SMgrRelationData::smgr_owner.

{
    /* We don't currently support "disowning" an SMgrRelation here */
    Assert(owner != NULL);

    /*
     * First, unhook any old owner.  (Normally there shouldn't be any, but it
     * seems possible that this can happen during swap_relation_files()
     * depending on the order of processing.  It's ok to close the old
     * relcache entry early in that case.)
     *
     * If there isn't an old owner, then the reln should be in the unowned
     * list, and we need to remove it.
     */
    if (reln->smgr_owner)
        *(reln->smgr_owner) = NULL;
    else
        remove_from_unowned_list(reln);

    /* Now establish the ownership relationship. */
    reln->smgr_owner = owner;
    *owner = reln;
}

static void smgrshutdown ( int  code,
Datum  arg 
) [static]

Definition at line 117 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_shutdown.

Referenced by smgrinit().

{
    int         i;

    for (i = 0; i < NSmgr; i++)
    {
        if (smgrsw[i].smgr_shutdown)
            (*(smgrsw[i].smgr_shutdown)) ();
    }
}

void smgrsync ( void   ) 

Definition at line 710 of file smgr.c.

References i, NSmgr, and f_smgr::smgr_sync.

Referenced by CheckPointBuffers().

{
    int         i;

    for (i = 0; i < NSmgr; i++)
    {
        if (smgrsw[i].smgr_sync)
            (*(smgrsw[i].smgr_sync)) ();
    }
}

void smgrtruncate ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  nblocks 
)

Definition at line 635 of file smgr.c.

References CacheInvalidateSmgr(), DropRelFileNodeBuffers(), SMgrRelationData::smgr_rnode, f_smgr::smgr_truncate, and SMgrRelationData::smgr_which.

Referenced by FreeSpaceMapTruncateRel(), RelationTruncate(), smgr_redo(), and visibilitymap_truncate().

{
    /*
     * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
     * just drop them without bothering to write the contents.
     */
    DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);

    /*
     * Send a shared-inval message to force other backends to close any smgr
     * references they may have for this rel.  This is useful because they
     * might have open file pointers to segments that got removed, and/or
     * smgr_targblock variables pointing past the new rel end.  (The inval
     * message will come back to our backend, too, causing a
     * probably-unnecessary local smgr flush.  But we don't expect that this
     * is a performance-critical path.)  As in the unlink code, we want to be
     * sure the message is sent before we start changing things on-disk.
     */
    CacheInvalidateSmgr(reln->smgr_rnode);

    /*
     * Do the truncation.
     */
    (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks);
}

void smgrwrite ( SMgrRelation  reln,
ForkNumber  forknum,
BlockNumber  blocknum,
char *  buffer,
bool  skipFsync 
)

Definition at line 611 of file smgr.c.

References SMgrRelationData::smgr_which, and f_smgr::smgr_write.

Referenced by _bt_blwritepage(), btbuildempty(), FlushBuffer(), FlushRelationBuffers(), LocalBufferAlloc(), and spgbuildempty().

{
    (*(smgrsw[reln->smgr_which].smgr_write)) (reln, forknum, blocknum,
                                              buffer, skipFsync);
}


Variable Documentation

Definition at line 83 of file smgr.c.

const int NSmgr = lengthof(smgrsw) [static]

Definition at line 74 of file smgr.c.

Referenced by smgrinit(), smgrpostckpt(), smgrpreckpt(), smgrshutdown(), and smgrsync().

HTAB* SMgrRelationHash = NULL [static]

Definition at line 81 of file smgr.c.

const f_smgr smgrsw[] [static]
Initial value:
 {
    
    {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend,
        mdprefetch, mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync,
        mdpreckpt, mdsync, mdpostckpt
    }
}

Definition at line 66 of file smgr.c.