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
  [EMAIL PROTECTED]               |  (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 */
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to