LCOV - code coverage report
Current view: top level - src/backend/storage/smgr - smgr.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 147 169 87.0 %
Date: 2017-09-29 15:12:54 Functions: 24 27 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * smgr.c
       4             :  *    public interface routines to storage manager switch.
       5             :  *
       6             :  *    All file system operations in POSTGRES dispatch through these
       7             :  *    routines.
       8             :  *
       9             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
      10             :  * Portions Copyright (c) 1994, Regents of the University of California
      11             :  *
      12             :  *
      13             :  * IDENTIFICATION
      14             :  *    src/backend/storage/smgr/smgr.c
      15             :  *
      16             :  *-------------------------------------------------------------------------
      17             :  */
      18             : #include "postgres.h"
      19             : 
      20             : #include "commands/tablespace.h"
      21             : #include "storage/bufmgr.h"
      22             : #include "storage/ipc.h"
      23             : #include "storage/smgr.h"
      24             : #include "utils/hsearch.h"
      25             : #include "utils/inval.h"
      26             : 
      27             : 
      28             : /*
      29             :  * This struct of function pointers defines the API between smgr.c and
      30             :  * any individual storage manager module.  Note that smgr subfunctions are
      31             :  * generally expected to report problems via elog(ERROR).  An exception is
      32             :  * that smgr_unlink should use elog(WARNING), rather than erroring out,
      33             :  * because we normally unlink relations during post-commit/abort cleanup,
      34             :  * and so it's too late to raise an error.  Also, various conditions that
      35             :  * would normally be errors should be allowed during bootstrap and/or WAL
      36             :  * recovery --- see comments in md.c for details.
      37             :  */
      38             : typedef struct f_smgr
      39             : {
      40             :     void        (*smgr_init) (void);    /* may be NULL */
      41             :     void        (*smgr_shutdown) (void);    /* may be NULL */
      42             :     void        (*smgr_close) (SMgrRelation reln, ForkNumber forknum);
      43             :     void        (*smgr_create) (SMgrRelation reln, ForkNumber forknum,
      44             :                                 bool isRedo);
      45             :     bool        (*smgr_exists) (SMgrRelation reln, ForkNumber forknum);
      46             :     void        (*smgr_unlink) (RelFileNodeBackend rnode, ForkNumber forknum,
      47             :                                 bool isRedo);
      48             :     void        (*smgr_extend) (SMgrRelation reln, ForkNumber forknum,
      49             :                                 BlockNumber blocknum, char *buffer, bool skipFsync);
      50             :     void        (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
      51             :                                   BlockNumber blocknum);
      52             :     void        (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
      53             :                               BlockNumber blocknum, char *buffer);
      54             :     void        (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
      55             :                                BlockNumber blocknum, char *buffer, bool skipFsync);
      56             :     void        (*smgr_writeback) (SMgrRelation reln, ForkNumber forknum,
      57             :                                    BlockNumber blocknum, BlockNumber nblocks);
      58             :     BlockNumber (*smgr_nblocks) (SMgrRelation reln, ForkNumber forknum);
      59             :     void        (*smgr_truncate) (SMgrRelation reln, ForkNumber forknum,
      60             :                                   BlockNumber nblocks);
      61             :     void        (*smgr_immedsync) (SMgrRelation reln, ForkNumber forknum);
      62             :     void        (*smgr_pre_ckpt) (void);    /* may be NULL */
      63             :     void        (*smgr_sync) (void);    /* may be NULL */
      64             :     void        (*smgr_post_ckpt) (void);   /* may be NULL */
      65             : } f_smgr;
      66             : 
      67             : 
      68             : static const f_smgr smgrsw[] = {
      69             :     /* magnetic disk */
      70             :     {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend,
      71             :         mdprefetch, mdread, mdwrite, mdwriteback, mdnblocks, mdtruncate,
      72             :         mdimmedsync, mdpreckpt, mdsync, mdpostckpt
      73             :     }
      74             : };
      75             : 
      76             : static const int NSmgr = lengthof(smgrsw);
      77             : 
      78             : 
      79             : /*
      80             :  * Each backend has a hashtable that stores all extant SMgrRelation objects.
      81             :  * In addition, "unowned" SMgrRelation objects are chained together in a list.
      82             :  */
      83             : static HTAB *SMgrRelationHash = NULL;
      84             : 
      85             : static SMgrRelation first_unowned_reln = NULL;
      86             : 
      87             : /* local function prototypes */
      88             : static void smgrshutdown(int code, Datum arg);
      89             : static void add_to_unowned_list(SMgrRelation reln);
      90             : static void remove_from_unowned_list(SMgrRelation reln);
      91             : 
      92             : 
      93             : /*
      94             :  *  smgrinit(), smgrshutdown() -- Initialize or shut down storage
      95             :  *                                managers.
      96             :  *
      97             :  * Note: smgrinit is called during backend startup (normal or standalone
      98             :  * case), *not* during postmaster start.  Therefore, any resources created
      99             :  * here or destroyed in smgrshutdown are backend-local.
     100             :  */
     101             : void
     102         344 : smgrinit(void)
     103             : {
     104             :     int         i;
     105             : 
     106         688 :     for (i = 0; i < NSmgr; i++)
     107             :     {
     108         344 :         if (smgrsw[i].smgr_init)
     109         344 :             (*(smgrsw[i].smgr_init)) ();
     110             :     }
     111             : 
     112             :     /* register the shutdown proc */
     113         344 :     on_proc_exit(smgrshutdown, 0);
     114         344 : }
     115             : 
     116             : /*
     117             :  * on_proc_exit hook for smgr cleanup during backend shutdown
     118             :  */
     119             : static void
     120         344 : smgrshutdown(int code, Datum arg)
     121             : {
     122             :     int         i;
     123             : 
     124         688 :     for (i = 0; i < NSmgr; i++)
     125             :     {
     126         344 :         if (smgrsw[i].smgr_shutdown)
     127           0 :             (*(smgrsw[i].smgr_shutdown)) ();
     128             :     }
     129         344 : }
     130             : 
     131             : /*
     132             :  *  smgropen() -- Return an SMgrRelation object, creating it if need be.
     133             :  *
     134             :  *      This does not attempt to actually open the underlying file.
     135             :  */
     136             : SMgrRelation
     137       47746 : smgropen(RelFileNode rnode, BackendId backend)
     138             : {
     139             :     RelFileNodeBackend brnode;
     140             :     SMgrRelation reln;
     141             :     bool        found;
     142             : 
     143       47746 :     if (SMgrRelationHash == NULL)
     144             :     {
     145             :         /* First time through: initialize the hash table */
     146             :         HASHCTL     ctl;
     147             : 
     148         339 :         MemSet(&ctl, 0, sizeof(ctl));
     149         339 :         ctl.keysize = sizeof(RelFileNodeBackend);
     150         339 :         ctl.entrysize = sizeof(SMgrRelationData);
     151         339 :         SMgrRelationHash = hash_create("smgr relation table", 400,
     152             :                                        &ctl, HASH_ELEM | HASH_BLOBS);
     153         339 :         first_unowned_reln = NULL;
     154             :     }
     155             : 
     156             :     /* Look up or create an entry */
     157       47746 :     brnode.node = rnode;
     158       47746 :     brnode.backend = backend;
     159       47746 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     160             :                                       (void *) &brnode,
     161             :                                       HASH_ENTER, &found);
     162             : 
     163             :     /* Initialize it if not present before */
     164       47746 :     if (!found)
     165             :     {
     166             :         int         forknum;
     167             : 
     168             :         /* hash_search already filled in the lookup key */
     169       34514 :         reln->smgr_owner = NULL;
     170       34514 :         reln->smgr_targblock = InvalidBlockNumber;
     171       34514 :         reln->smgr_fsm_nblocks = InvalidBlockNumber;
     172       34514 :         reln->smgr_vm_nblocks = InvalidBlockNumber;
     173       34514 :         reln->smgr_which = 0;    /* we only have md.c at present */
     174             : 
     175             :         /* mark it not open */
     176      172570 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     177      138056 :             reln->md_num_open_segs[forknum] = 0;
     178             : 
     179             :         /* it has no owner yet */
     180       34514 :         add_to_unowned_list(reln);
     181             :     }
     182             : 
     183       47746 :     return reln;
     184             : }
     185             : 
     186             : /*
     187             :  * smgrsetowner() -- Establish a long-lived reference to an SMgrRelation object
     188             :  *
     189             :  * There can be only one owner at a time; this is sufficient since currently
     190             :  * the only such owners exist in the relcache.
     191             :  */
     192             : void
     193       30411 : smgrsetowner(SMgrRelation *owner, SMgrRelation reln)
     194             : {
     195             :     /* We don't support "disowning" an SMgrRelation here, use smgrclearowner */
     196       30411 :     Assert(owner != NULL);
     197             : 
     198             :     /*
     199             :      * First, unhook any old owner.  (Normally there shouldn't be any, but it
     200             :      * seems possible that this can happen during swap_relation_files()
     201             :      * depending on the order of processing.  It's ok to close the old
     202             :      * relcache entry early in that case.)
     203             :      *
     204             :      * If there isn't an old owner, then the reln should be in the unowned
     205             :      * list, and we need to remove it.
     206             :      */
     207       30411 :     if (reln->smgr_owner)
     208           0 :         *(reln->smgr_owner) = NULL;
     209             :     else
     210       30411 :         remove_from_unowned_list(reln);
     211             : 
     212             :     /* Now establish the ownership relationship. */
     213       30411 :     reln->smgr_owner = owner;
     214       30411 :     *owner = reln;
     215       30411 : }
     216             : 
     217             : /*
     218             :  * smgrclearowner() -- Remove long-lived reference to an SMgrRelation object
     219             :  *                     if one exists
     220             :  */
     221             : void
     222           0 : smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
     223             : {
     224             :     /* Do nothing if the SMgrRelation object is not owned by the owner */
     225           0 :     if (reln->smgr_owner != owner)
     226           0 :         return;
     227             : 
     228             :     /* unset the owner's reference */
     229           0 :     *owner = NULL;
     230             : 
     231             :     /* unset our reference to the owner */
     232           0 :     reln->smgr_owner = NULL;
     233             : 
     234           0 :     add_to_unowned_list(reln);
     235             : }
     236             : 
     237             : /*
     238             :  * add_to_unowned_list -- link an SMgrRelation onto the unowned list
     239             :  *
     240             :  * Check remove_from_unowned_list()'s comments for performance
     241             :  * considerations.
     242             :  */
     243             : static void
     244       34514 : add_to_unowned_list(SMgrRelation reln)
     245             : {
     246             :     /* place it at head of the list (to make smgrsetowner cheap) */
     247       34514 :     reln->next_unowned_reln = first_unowned_reln;
     248       34514 :     first_unowned_reln = reln;
     249       34514 : }
     250             : 
     251             : /*
     252             :  * remove_from_unowned_list -- unlink an SMgrRelation from the unowned list
     253             :  *
     254             :  * If the reln is not present in the list, nothing happens.  Typically this
     255             :  * would be caller error, but there seems no reason to throw an error.
     256             :  *
     257             :  * In the worst case this could be rather slow; but in all the cases that seem
     258             :  * likely to be performance-critical, the reln being sought will actually be
     259             :  * first in the list.  Furthermore, the number of unowned relns touched in any
     260             :  * one transaction shouldn't be all that high typically.  So it doesn't seem
     261             :  * worth expending the additional space and management logic needed for a
     262             :  * doubly-linked list.
     263             :  */
     264             : static void
     265       33994 : remove_from_unowned_list(SMgrRelation reln)
     266             : {
     267             :     SMgrRelation *link;
     268             :     SMgrRelation cur;
     269             : 
     270       83438 :     for (link = &first_unowned_reln, cur = *link;
     271             :          cur != NULL;
     272       15450 :          link = &cur->next_unowned_reln, cur = *link)
     273             :     {
     274       49444 :         if (cur == reln)
     275             :         {
     276       33994 :             *link = cur->next_unowned_reln;
     277       33994 :             cur->next_unowned_reln = NULL;
     278       33994 :             break;
     279             :         }
     280             :     }
     281       33994 : }
     282             : 
     283             : /*
     284             :  *  smgrexists() -- Does the underlying file for a fork exist?
     285             :  */
     286             : bool
     287       10547 : smgrexists(SMgrRelation reln, ForkNumber forknum)
     288             : {
     289       10547 :     return (*(smgrsw[reln->smgr_which].smgr_exists)) (reln, forknum);
     290             : }
     291             : 
     292             : /*
     293             :  *  smgrclose() -- Close and delete an SMgrRelation object.
     294             :  */
     295             : void
     296       16802 : smgrclose(SMgrRelation reln)
     297             : {
     298             :     SMgrRelation *owner;
     299             :     ForkNumber  forknum;
     300             : 
     301       84010 :     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     302       67208 :         (*(smgrsw[reln->smgr_which].smgr_close)) (reln, forknum);
     303             : 
     304       16802 :     owner = reln->smgr_owner;
     305             : 
     306       16802 :     if (!owner)
     307        3583 :         remove_from_unowned_list(reln);
     308             : 
     309       16802 :     if (hash_search(SMgrRelationHash,
     310       16802 :                     (void *) &(reln->smgr_rnode),
     311             :                     HASH_REMOVE, NULL) == NULL)
     312           0 :         elog(ERROR, "SMgrRelation hashtable corrupted");
     313             : 
     314             :     /*
     315             :      * Unhook the owner pointer, if any.  We do this last since in the remote
     316             :      * possibility of failure above, the SMgrRelation object will still exist.
     317             :      */
     318       16802 :     if (owner)
     319       13219 :         *owner = NULL;
     320       16802 : }
     321             : 
     322             : /*
     323             :  *  smgrcloseall() -- Close all existing SMgrRelation objects.
     324             :  */
     325             : void
     326         140 : smgrcloseall(void)
     327             : {
     328             :     HASH_SEQ_STATUS status;
     329             :     SMgrRelation reln;
     330             : 
     331             :     /* Nothing to do if hashtable not set up */
     332         140 :     if (SMgrRelationHash == NULL)
     333         144 :         return;
     334             : 
     335         136 :     hash_seq_init(&status, SMgrRelationHash);
     336             : 
     337         537 :     while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
     338         265 :         smgrclose(reln);
     339             : }
     340             : 
     341             : /*
     342             :  *  smgrclosenode() -- Close SMgrRelation object for given RelFileNode,
     343             :  *                     if one exists.
     344             :  *
     345             :  * This has the same effects as smgrclose(smgropen(rnode)), but it avoids
     346             :  * uselessly creating a hashtable entry only to drop it again when no
     347             :  * such entry exists already.
     348             :  */
     349             : void
     350       20294 : smgrclosenode(RelFileNodeBackend rnode)
     351             : {
     352             :     SMgrRelation reln;
     353             : 
     354             :     /* Nothing to do if hashtable not set up */
     355       20294 :     if (SMgrRelationHash == NULL)
     356       20303 :         return;
     357             : 
     358       20285 :     reln = (SMgrRelation) hash_search(SMgrRelationHash,
     359             :                                       (void *) &rnode,
     360             :                                       HASH_FIND, NULL);
     361       20285 :     if (reln != NULL)
     362         494 :         smgrclose(reln);
     363             : }
     364             : 
     365             : /*
     366             :  *  smgrcreate() -- Create a new relation.
     367             :  *
     368             :  *      Given an already-created (but presumably unused) SMgrRelation,
     369             :  *      cause the underlying disk file or other storage for the fork
     370             :  *      to be created.
     371             :  *
     372             :  *      If isRedo is true, it is okay for the underlying file to exist
     373             :  *      already because we are in a WAL replay sequence.
     374             :  */
     375             : void
     376        4479 : smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
     377             : {
     378             :     /*
     379             :      * Exit quickly in WAL replay mode if we've already opened the file. If
     380             :      * it's open, it surely must exist.
     381             :      */
     382        4479 :     if (isRedo && reln->md_num_open_segs[forknum] > 0)
     383        4479 :         return;
     384             : 
     385             :     /*
     386             :      * We may be using the target table space for the first time in this
     387             :      * database, so create a per-database subdirectory if needed.
     388             :      *
     389             :      * XXX this is a fairly ugly violation of module layering, but this seems
     390             :      * to be the best place to put the check.  Maybe TablespaceCreateDbspace
     391             :      * should be here and not in commands/tablespace.c?  But that would imply
     392             :      * importing a lot of stuff that smgr.c oughtn't know, either.
     393             :      */
     394        4479 :     TablespaceCreateDbspace(reln->smgr_rnode.node.spcNode,
     395             :                             reln->smgr_rnode.node.dbNode,
     396             :                             isRedo);
     397             : 
     398        4479 :     (*(smgrsw[reln->smgr_which].smgr_create)) (reln, forknum, isRedo);
     399             : }
     400             : 
     401             : /*
     402             :  *  smgrdounlink() -- Immediately unlink all forks of a relation.
     403             :  *
     404             :  *      All forks of the relation are removed from the store.  This should
     405             :  *      not be used during transactional operations, since it can't be undone.
     406             :  *
     407             :  *      If isRedo is true, it is okay for the underlying file(s) to be gone
     408             :  *      already.
     409             :  *
     410             :  *      This is equivalent to calling smgrdounlinkfork for each fork, but
     411             :  *      it's significantly quicker so should be preferred when possible.
     412             :  */
     413             : void
     414           1 : smgrdounlink(SMgrRelation reln, bool isRedo)
     415             : {
     416           1 :     RelFileNodeBackend rnode = reln->smgr_rnode;
     417           1 :     int         which = reln->smgr_which;
     418             :     ForkNumber  forknum;
     419             : 
     420             :     /* Close the forks at smgr level */
     421           5 :     for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     422           4 :         (*(smgrsw[which].smgr_close)) (reln, forknum);
     423             : 
     424             :     /*
     425             :      * Get rid of any remaining buffers for the relation.  bufmgr will just
     426             :      * drop them without bothering to write the contents.
     427             :      */
     428           1 :     DropRelFileNodesAllBuffers(&rnode, 1);
     429             : 
     430             :     /*
     431             :      * It'd be nice to tell the stats collector to forget it immediately, too.
     432             :      * But we can't because we don't know the OID (and in cases involving
     433             :      * relfilenode swaps, it's not always clear which table OID to forget,
     434             :      * anyway).
     435             :      */
     436             : 
     437             :     /*
     438             :      * Send a shared-inval message to force other backends to close any
     439             :      * dangling smgr references they may have for this rel.  We should do this
     440             :      * before starting the actual unlinking, in case we fail partway through
     441             :      * that step.  Note that the sinval message will eventually come back to
     442             :      * this backend, too, and thereby provide a backstop that we closed our
     443             :      * own smgr rel.
     444             :      */
     445           1 :     CacheInvalidateSmgr(rnode);
     446             : 
     447             :     /*
     448             :      * Delete the physical file(s).
     449             :      *
     450             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     451             :      * ERROR, because we've already decided to commit or abort the current
     452             :      * xact.
     453             :      */
     454           1 :     (*(smgrsw[which].smgr_unlink)) (rnode, InvalidForkNumber, isRedo);
     455           1 : }
     456             : 
     457             : /*
     458             :  *  smgrdounlinkall() -- Immediately unlink all forks of all given relations
     459             :  *
     460             :  *      All forks of all given relations are removed from the store.  This
     461             :  *      should not be used during transactional operations, since it can't be
     462             :  *      undone.
     463             :  *
     464             :  *      If isRedo is true, it is okay for the underlying file(s) to be gone
     465             :  *      already.
     466             :  *
     467             :  *      This is equivalent to calling smgrdounlink for each relation, but it's
     468             :  *      significantly quicker so should be preferred when possible.
     469             :  */
     470             : void
     471        1031 : smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
     472             : {
     473        1031 :     int         i = 0;
     474             :     RelFileNodeBackend *rnodes;
     475             :     ForkNumber  forknum;
     476             : 
     477        1031 :     if (nrels == 0)
     478        1031 :         return;
     479             : 
     480             :     /*
     481             :      * create an array which contains all relations to be dropped, and close
     482             :      * each relation's forks at the smgr level while at it
     483             :      */
     484        1031 :     rnodes = palloc(sizeof(RelFileNodeBackend) * nrels);
     485        4211 :     for (i = 0; i < nrels; i++)
     486             :     {
     487        3180 :         RelFileNodeBackend rnode = rels[i]->smgr_rnode;
     488        3180 :         int         which = rels[i]->smgr_which;
     489             : 
     490        3180 :         rnodes[i] = rnode;
     491             : 
     492             :         /* Close the forks at smgr level */
     493       15900 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     494       12720 :             (*(smgrsw[which].smgr_close)) (rels[i], forknum);
     495             :     }
     496             : 
     497             :     /*
     498             :      * Get rid of any remaining buffers for the relations.  bufmgr will just
     499             :      * drop them without bothering to write the contents.
     500             :      */
     501        1031 :     DropRelFileNodesAllBuffers(rnodes, nrels);
     502             : 
     503             :     /*
     504             :      * It'd be nice to tell the stats collector to forget them immediately,
     505             :      * too. But we can't because we don't know the OIDs.
     506             :      */
     507             : 
     508             :     /*
     509             :      * Send a shared-inval message to force other backends to close any
     510             :      * dangling smgr references they may have for these rels.  We should do
     511             :      * this before starting the actual unlinking, in case we fail partway
     512             :      * through that step.  Note that the sinval messages will eventually come
     513             :      * back to this backend, too, and thereby provide a backstop that we
     514             :      * closed our own smgr rel.
     515             :      */
     516        4211 :     for (i = 0; i < nrels; i++)
     517        3180 :         CacheInvalidateSmgr(rnodes[i]);
     518             : 
     519             :     /*
     520             :      * Delete the physical file(s).
     521             :      *
     522             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     523             :      * ERROR, because we've already decided to commit or abort the current
     524             :      * xact.
     525             :      */
     526             : 
     527        4211 :     for (i = 0; i < nrels; i++)
     528             :     {
     529        3180 :         int         which = rels[i]->smgr_which;
     530             : 
     531       15900 :         for (forknum = 0; forknum <= MAX_FORKNUM; forknum++)
     532       12720 :             (*(smgrsw[which].smgr_unlink)) (rnodes[i], forknum, isRedo);
     533             :     }
     534             : 
     535        1031 :     pfree(rnodes);
     536             : }
     537             : 
     538             : /*
     539             :  *  smgrdounlinkfork() -- Immediately unlink one fork of a relation.
     540             :  *
     541             :  *      The specified fork of the relation is removed from the store.  This
     542             :  *      should not be used during transactional operations, since it can't be
     543             :  *      undone.
     544             :  *
     545             :  *      If isRedo is true, it is okay for the underlying file to be gone
     546             :  *      already.
     547             :  */
     548             : void
     549           0 : smgrdounlinkfork(SMgrRelation reln, ForkNumber forknum, bool isRedo)
     550             : {
     551           0 :     RelFileNodeBackend rnode = reln->smgr_rnode;
     552           0 :     int         which = reln->smgr_which;
     553             : 
     554             :     /* Close the fork at smgr level */
     555           0 :     (*(smgrsw[which].smgr_close)) (reln, forknum);
     556             : 
     557             :     /*
     558             :      * Get rid of any remaining buffers for the fork.  bufmgr will just drop
     559             :      * them without bothering to write the contents.
     560             :      */
     561           0 :     DropRelFileNodeBuffers(rnode, forknum, 0);
     562             : 
     563             :     /*
     564             :      * It'd be nice to tell the stats collector to forget it immediately, too.
     565             :      * But we can't because we don't know the OID (and in cases involving
     566             :      * relfilenode swaps, it's not always clear which table OID to forget,
     567             :      * anyway).
     568             :      */
     569             : 
     570             :     /*
     571             :      * Send a shared-inval message to force other backends to close any
     572             :      * dangling smgr references they may have for this rel.  We should do this
     573             :      * before starting the actual unlinking, in case we fail partway through
     574             :      * that step.  Note that the sinval message will eventually come back to
     575             :      * this backend, too, and thereby provide a backstop that we closed our
     576             :      * own smgr rel.
     577             :      */
     578           0 :     CacheInvalidateSmgr(rnode);
     579             : 
     580             :     /*
     581             :      * Delete the physical file(s).
     582             :      *
     583             :      * Note: smgr_unlink must treat deletion failure as a WARNING, not an
     584             :      * ERROR, because we've already decided to commit or abort the current
     585             :      * xact.
     586             :      */
     587           0 :     (*(smgrsw[which].smgr_unlink)) (rnode, forknum, isRedo);
     588           0 : }
     589             : 
     590             : /*
     591             :  *  smgrextend() -- Add a new block to a file.
     592             :  *
     593             :  *      The semantics are nearly the same as smgrwrite(): write at the
     594             :  *      specified position.  However, this is to be used for the case of
     595             :  *      extending a relation (i.e., blocknum is at or beyond the current
     596             :  *      EOF).  Note that we assume writing a block beyond current EOF
     597             :  *      causes intervening file space to become filled with zeroes.
     598             :  */
     599             : void
     600       18586 : smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     601             :            char *buffer, bool skipFsync)
     602             : {
     603       18586 :     (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, forknum, blocknum,
     604             :                                                buffer, skipFsync);
     605       18586 : }
     606             : 
     607             : /*
     608             :  *  smgrprefetch() -- Initiate asynchronous read of the specified block of a relation.
     609             :  */
     610             : void
     611           0 : smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
     612             : {
     613           0 :     (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum);
     614           0 : }
     615             : 
     616             : /*
     617             :  *  smgrread() -- read a particular block from a relation into the supplied
     618             :  *                buffer.
     619             :  *
     620             :  *      This routine is called from the buffer manager in order to
     621             :  *      instantiate pages in the shared buffer cache.  All storage managers
     622             :  *      return pages in the format that POSTGRES expects.
     623             :  */
     624             : void
     625        4439 : smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     626             :          char *buffer)
     627             : {
     628        4439 :     (*(smgrsw[reln->smgr_which].smgr_read)) (reln, forknum, blocknum, buffer);
     629        4439 : }
     630             : 
     631             : /*
     632             :  *  smgrwrite() -- Write the supplied buffer out.
     633             :  *
     634             :  *      This is to be used only for updating already-existing blocks of a
     635             :  *      relation (ie, those before the current EOF).  To extend a relation,
     636             :  *      use smgrextend().
     637             :  *
     638             :  *      This is not a synchronous write -- the block is not necessarily
     639             :  *      on disk at return, only dumped out to the kernel.  However,
     640             :  *      provisions will be made to fsync the write before the next checkpoint.
     641             :  *
     642             :  *      skipFsync indicates that the caller will make other provisions to
     643             :  *      fsync the relation, so we needn't bother.  Temporary relations also
     644             :  *      do not require fsync.
     645             :  */
     646             : void
     647        8838 : smgrwrite(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     648             :           char *buffer, bool skipFsync)
     649             : {
     650        8838 :     (*(smgrsw[reln->smgr_which].smgr_write)) (reln, forknum, blocknum,
     651             :                                               buffer, skipFsync);
     652        8838 : }
     653             : 
     654             : 
     655             : /*
     656             :  *  smgrwriteback() -- Trigger kernel writeback for the supplied range of
     657             :  *                     blocks.
     658             :  */
     659             : void
     660        1477 : smgrwriteback(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
     661             :               BlockNumber nblocks)
     662             : {
     663        1477 :     (*(smgrsw[reln->smgr_which].smgr_writeback)) (reln, forknum, blocknum,
     664             :                                                   nblocks);
     665        1477 : }
     666             : 
     667             : /*
     668             :  *  smgrnblocks() -- Calculate the number of blocks in the
     669             :  *                   supplied relation.
     670             :  */
     671             : BlockNumber
     672       84151 : smgrnblocks(SMgrRelation reln, ForkNumber forknum)
     673             : {
     674       84151 :     return (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln, forknum);
     675             : }
     676             : 
     677             : /*
     678             :  *  smgrtruncate() -- Truncate supplied relation to the specified number
     679             :  *                    of blocks
     680             :  *
     681             :  * The truncation is done immediately, so this can't be rolled back.
     682             :  */
     683             : void
     684          46 : smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
     685             : {
     686             :     /*
     687             :      * Get rid of any buffers for the about-to-be-deleted blocks. bufmgr will
     688             :      * just drop them without bothering to write the contents.
     689             :      */
     690          46 :     DropRelFileNodeBuffers(reln->smgr_rnode, forknum, nblocks);
     691             : 
     692             :     /*
     693             :      * Send a shared-inval message to force other backends to close any smgr
     694             :      * references they may have for this rel.  This is useful because they
     695             :      * might have open file pointers to segments that got removed, and/or
     696             :      * smgr_targblock variables pointing past the new rel end.  (The inval
     697             :      * message will come back to our backend, too, causing a
     698             :      * probably-unnecessary local smgr flush.  But we don't expect that this
     699             :      * is a performance-critical path.)  As in the unlink code, we want to be
     700             :      * sure the message is sent before we start changing things on-disk.
     701             :      */
     702          46 :     CacheInvalidateSmgr(reln->smgr_rnode);
     703             : 
     704             :     /*
     705             :      * Do the truncation.
     706             :      */
     707          46 :     (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, forknum, nblocks);
     708          46 : }
     709             : 
     710             : /*
     711             :  *  smgrimmedsync() -- Force the specified relation to stable storage.
     712             :  *
     713             :  *      Synchronously force all previous writes to the specified relation
     714             :  *      down to disk.
     715             :  *
     716             :  *      This is useful for building completely new relations (eg, new
     717             :  *      indexes).  Instead of incrementally WAL-logging the index build
     718             :  *      steps, we can just write completed index pages to disk with smgrwrite
     719             :  *      or smgrextend, and then fsync the completed index file before
     720             :  *      committing the transaction.  (This is sufficient for purposes of
     721             :  *      crash recovery, since it effectively duplicates forcing a checkpoint
     722             :  *      for the completed index.  But it is *not* sufficient if one wishes
     723             :  *      to use the WAL log for PITR or replication purposes: in that case
     724             :  *      we have to make WAL entries as well.)
     725             :  *
     726             :  *      The preceding writes should specify skipFsync = true to avoid
     727             :  *      duplicative fsyncs.
     728             :  *
     729             :  *      Note that you need to do FlushRelationBuffers() first if there is
     730             :  *      any possibility that there are dirty buffers for the relation;
     731             :  *      otherwise the sync is not very meaningful.
     732             :  */
     733             : void
     734        1264 : smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
     735             : {
     736        1264 :     (*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln, forknum);
     737        1264 : }
     738             : 
     739             : 
     740             : /*
     741             :  *  smgrpreckpt() -- Prepare for checkpoint.
     742             :  */
     743             : void
     744          11 : smgrpreckpt(void)
     745             : {
     746             :     int         i;
     747             : 
     748          22 :     for (i = 0; i < NSmgr; i++)
     749             :     {
     750          11 :         if (smgrsw[i].smgr_pre_ckpt)
     751          11 :             (*(smgrsw[i].smgr_pre_ckpt)) ();
     752             :     }
     753          11 : }
     754             : 
     755             : /*
     756             :  *  smgrsync() -- Sync files to disk during checkpoint.
     757             :  */
     758             : void
     759          11 : smgrsync(void)
     760             : {
     761             :     int         i;
     762             : 
     763          22 :     for (i = 0; i < NSmgr; i++)
     764             :     {
     765          11 :         if (smgrsw[i].smgr_sync)
     766          11 :             (*(smgrsw[i].smgr_sync)) ();
     767             :     }
     768          11 : }
     769             : 
     770             : /*
     771             :  *  smgrpostckpt() -- Post-checkpoint cleanup.
     772             :  */
     773             : void
     774          11 : smgrpostckpt(void)
     775             : {
     776             :     int         i;
     777             : 
     778          22 :     for (i = 0; i < NSmgr; i++)
     779             :     {
     780          11 :         if (smgrsw[i].smgr_post_ckpt)
     781          11 :             (*(smgrsw[i].smgr_post_ckpt)) ();
     782             :     }
     783          11 : }
     784             : 
     785             : /*
     786             :  * AtEOXact_SMgr
     787             :  *
     788             :  * This routine is called during transaction commit or abort (it doesn't
     789             :  * particularly care which).  All transient SMgrRelation objects are closed.
     790             :  *
     791             :  * We do this as a compromise between wanting transient SMgrRelations to
     792             :  * live awhile (to amortize the costs of blind writes of multiple blocks)
     793             :  * and needing them to not live forever (since we're probably holding open
     794             :  * a kernel file descriptor for the underlying file, and we need to ensure
     795             :  * that gets closed reasonably soon if the file gets deleted).
     796             :  */
     797             : void
     798       26218 : AtEOXact_SMgr(void)
     799             : {
     800             :     /*
     801             :      * Zap all unowned SMgrRelations.  We rely on smgrclose() to remove each
     802             :      * one from the list.
     803             :      */
     804       52436 :     while (first_unowned_reln != NULL)
     805             :     {
     806           0 :         Assert(first_unowned_reln->smgr_owner == NULL);
     807           0 :         smgrclose(first_unowned_reln);
     808             :     }
     809       26218 : }

Generated by: LCOV version 1.11