SRA Win32 sync() code

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема SRA Win32 sync() code
Дата
Msg-id 200311160500.hAG50u701539@candle.pha.pa.us
обсуждение исходный текст
Ответы Re: SRA Win32 sync() code  (Tom Lane <tgl@sss.pgh.pa.us>)
Список 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 по дате отправления:

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: minor release note improvements
Следующее
От: Andrew Dunstan
Дата:
Сообщение: Re: improve overcommit docs