SRA Win32 sync() code - Mailing list pgsql-patches

From Bruce Momjian
Subject SRA Win32 sync() code
Date
Msg-id 200311160500.hAG50u701539@candle.pha.pa.us
Whole thread Raw
Responses Re: SRA Win32 sync() code
List pgsql-patches
Here is the SRA sync() code for Win32.  As you might know, fsync on
Win32 is _commit, and sync() is _flushall.  However, _flushall only
flushes only _open_ kernel buffers, not dirty buffers that have been
closed.  Therefore, on Win32, during checkpoint, you have to open,
fsync(_commit), close all file that have been modified since the
previous checkpoint.

Not sure how we are going to do this in Win32, but somehow we will have
to record all open files between checkpoints in an area that the
checkpoint process can read during a checkpoint.

Here is the SRA code that records the dirty file and the code that
cycles through the list and fsync's each one.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
#ifdef POWERGRES

static Dllist *rnodes = NULL;
static volatile slock_t mylock = 0;

typedef struct {
    RelFileNode rnode;
    BlockNumber blkno;
} RelSegInfo;

#undef calloc
#undef malloc
#undef free
#undef realloc
#undef strdup

/*
 * Add segment file names to the internal table
 */
static void add_file(RelFileNode rnode, BlockNumber blkno)
{
    Dlelem *elm;
    RelSegInfo *info;

#ifndef LET_OS_MANAGE_FILESIZE
    BlockNumber segno, isegno;
#endif

    SpinLockAcquire_NoHoldoff(&mylock);

    if (rnodes == NULL)
    {
        rnodes = DLNewList();
    }

    elm = DLGetHead(rnodes);
    while (elm)
    {
        RelSegInfo *ip = (RelSegInfo *)DLE_VAL(elm);
#ifndef LET_OS_MANAGE_FILESIZE
        segno = blkno / ((BlockNumber) RELSEG_SIZE);
        isegno = ip->blkno / ((BlockNumber) RELSEG_SIZE);
#endif
        if (((ip->rnode.tblNode == (Oid)0 && rnode.tblNode == (Oid)0 && ip->rnode.relNode == rnode.relNode) ||
             (ip->rnode.tblNode == rnode.tblNode && ip->rnode.relNode == rnode.relNode))
#ifndef LET_OS_MANAGE_FILESIZE
            && segno == isegno
#endif
            )
        {
            /* already there */
            SpinLockRelease_NoHoldoff(&mylock);
            return;
        }
        elm = DLGetSucc(elm);
    }

    info = malloc(sizeof(*info));
    if (info == NULL)
    {
        elog(ERROR, "add_file: malloc failed");
    }
    else
    {
        info->rnode = rnode;
        info->blkno = blkno;
        DLAddHead(rnodes, DLNewElem(info));
    }
    SpinLockRelease_NoHoldoff(&mylock);
}

/*
 * fsync all file segments registered in the table
 */
#include <fcntl.h>
static void checkpoint_buffer_sync(void)
{
    Dllist *segs;
    Dlelem *elm;
    File fd;
    char segname[MAXPGPATH];
#ifndef LET_OS_MANAGE_FILESIZE
    BlockNumber segno;
#endif

    if (rnodes == NULL)
        return;

    SpinLockAcquire_NoHoldoff(&mylock);

    segs = DLNewList();

    elm = DLGetHead(rnodes);
    while (elm)
    {
        Dlelem *next;

        next = DLGetSucc(elm);

        DLAddHead(segs, DLNewElem(DLE_VAL(elm)));
        DLRemove(elm);
        DLFreeElem(elm);

        elm = next;
    }

    SpinLockRelease_NoHoldoff(&mylock);

    elm = DLGetHead(segs);
    while (elm)
    {
        RelSegInfo *ip = (RelSegInfo *)DLE_VAL(elm);

        if (ip->rnode.tblNode == (Oid) 0)        /* "global tablespace" */
        {
            /* Shared system relations live in {datadir}/global */
            snprintf(segname, MAXPGPATH, "%s/global/%u", DataDir, ip->rnode.relNode);
        }
        else
        {
            snprintf(segname, MAXPGPATH, "%s/base/%u/%u", DataDir, ip->rnode.tblNode, ip->rnode.relNode);
        }

#ifndef LET_OS_MANAGE_FILESIZE
        /* append the '.segno', if needed */
        segno = ip->blkno / ((BlockNumber) RELSEG_SIZE);
        if (segno > 0)
        {
            snprintf(segname, MAXPGPATH, "%s.%u", segname, segno);
        }
#endif
        fd = FileNameOpenFile(segname, O_RDWR | PG_BINARY, 0600);
        if (fd >= 0)
        {
            elog(DEBUG1,"flushing %s", segname);
            FileSync(fd);
            FileClose(fd);
        }
        elm = DLGetSucc(elm);
    }
    DLFreeList(segs);
}
#endif /* POWERGRES */

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: minor release note improvements
Next
From: Andrew Dunstan
Date:
Subject: Re: improve overcommit docs