Thread: Win32 and fsync()

Win32 and fsync()

From
"Dann Corbit"
Date:
For Win32, in order to emulate fsync() we will need to call
FlushFileBuffers():
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/
base/flushfilebuffers.asp


Re: Win32 and fsync()

From
"Andrew Dunstan"
Date:
I'm having difficulty digging up the reference, but I think I recall seeing
something that said, roughly, on W32 there are 2 sets of buffers - those in
the user level library and those in the kernel level driver, and
FlushFileBuffers drains the first, while _commit drains both (it includes a
call to FlushFileBuffers).

I'm also fairly sure I saw something like   #define fsync _commit
in the Berkeley DB sources the other day, which might be a clue.

I'll be happy to be corrected, though.

cheers

andrew


----- Original Message -----
From: "Dann Corbit" <DCorbit@connx.com>
To: "PostgreSQL Hackers" <pgsql-hackers@postgresql.org>
Sent: Monday, February 03, 2003 3:15 PM
Subject: [HACKERS] Win32 and fsync()


> For Win32, in order to emulate fsync() we will need to call
> FlushFileBuffers():
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/
> base/flushfilebuffers.asp
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org



Re: Win32 and fsync()

From
"Merlin Moncure"
Date:
>> For Win32, in order to emulate fsync() we will need to call
>> FlushFileBuffers():
The supplied link does not work.  FlushFileBuffers() is for flushing
files opened with CreateFile() etc.

For files opened with fopen(), call fflush().

For files opened with _open(), call _commit().

Likekly the win32 port code, which I have yet to inspect, will use the
second version.

Merlin




Re: Win32 and fsync()

From
"Dave Page"
Date:

> -----Original Message-----
> From: Andrew Dunstan [mailto:andrew@dunslane.net]
> Sent: 03 February 2003 22:47
> To: PostgreSQL Hackers
> Subject: Re: [HACKERS] Win32 and fsync()
>
>
> I'm having difficulty digging up the reference, but I think I
> recall seeing something that said, roughly, on W32 there are
> 2 sets of buffers - those in the user level library and those
> in the kernel level driver, and FlushFileBuffers drains the
> first, while _commit drains both (it includes a call to
> FlushFileBuffers).
>
> I'm also fairly sure I saw something like
>     #define fsync _commit
> in the Berkeley DB sources the other day, which might be a clue.
>
> I'll be happy to be corrected, though.

I too have yet to look at the Win32 patces, but if they have used
FlushFileBuffers, perhaps that would explain my powerfail test
results...

Regards, Dave.


Re: Win32 and fsync()

From
"Merlin Moncure"
Date:
>I'm having difficulty digging up the reference, but I think I recall
seeing >something that said, roughly, on W32 there are 2 sets of buffers
- those in >the user level library and those in the kernel level driver,
and >FlushFileBuffers drains the first, while _commit drains both (it
includes a >call to FlushFileBuffers).

You were correct: here is the source.


int __cdecl _commit (       int filedes       )
{       int retval;
       /* if filedes out of range, complain */       if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
!(_osfile(filedes)& FOPEN) )       {               errno = EBADF;               return (-1);       } 
       _lock_fh(filedes);
       /* if filedes open, try to commit, else fall through to bad */       if (_osfile(filedes) & FOPEN) {
               if ( !FlushFileBuffers((HANDLE)_get_osfhandle(filedes))
) {                       retval = GetLastError();               } else {                       retval = 0;     /*
returnsuccess */               } 
               /* map the OS return code to C errno value and return
code */               if (retval == 0) {                       goto good;               } else {
_doserrno= retval;                       goto bad;               } 
       }

bad :       errno = EBADF;       retval = -1;
good :       _unlock_fh(filedes);       return (retval);
}


Re: Win32 and fsync()

From
Gavin Sherry
Date:
On Mon, 3 Feb 2003, Andrew Dunstan wrote:

> I'm also fairly sure I saw something like
>     #define fsync _commit
> in the Berkeley DB sources the other day, which might be a clue.
> 
> I'll be happy to be corrected, though.

You'd be right:

/** Win32 has fsync, getcwd, snprintf and vsnprintf, but under different names.*/
#define fsync(fd)       _commit(fd)

Funny Win32-ism

Still not sure if it has the same semantics as Unix fsync() but sleepycat
(Berkeley) DB seems to think so.

Gavin



Re: Win32 and fsync()

From
"Dann Corbit"
Date:
> -----Original Message-----
> From: Merlin Moncure [mailto:merlin.moncure@rcsonline.com]
> Sent: Monday, February 03, 2003 3:00 PM
> To: Andrew Dunstan
> Cc: pgsql-hackers@postgresql.org
> Subject: Re: [HACKERS] Win32 and fsync()
>
>
> >I'm having difficulty digging up the reference, but I think I recall
> seeing >something that said, roughly, on W32 there are 2 sets
> of buffers
> - those in >the user level library and those in the kernel
> level driver, and >FlushFileBuffers drains the first, while
> _commit drains both (it includes a >call to FlushFileBuffers).
>
> You were correct: here is the source.
>
>
> int __cdecl _commit (
>         int filedes
>         )
> {
>         int retval;
>
>         /* if filedes out of range, complain */
>         if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
>              !(_osfile(filedes) & FOPEN) )
>         {
>                 errno = EBADF;
>                 return (-1);
>         }
>
>         _lock_fh(filedes);
>
>         /* if filedes open, try to commit, else fall through to bad */
>         if (_osfile(filedes) & FOPEN) {
>
>                 if (
> !FlushFileBuffers((HANDLE)_get_osfhandle(filedes))
> ) {
>                         retval = GetLastError();
>                 } else {
>                         retval = 0;     /* return success */
>                 }
>
>                 /* map the OS return code to C errno value
> and return code */
>                 if (retval == 0) {
>                         goto good;
>                 } else {
>                         _doserrno = retval;
>                         goto bad;
>                 }
>
>         }
>
> bad :
>         errno = EBADF;
>         retval = -1;
> good :
>         _unlock_fh(filedes);
>         return (retval);
> }

Where is the "other" flush besides FlushFileBuffers()?


Re: Win32 and fsync()

From
Gavin Sherry
Date:
On Mon, 3 Feb 2003, Dann Corbit wrote:

> > -----Original Message-----
> > From: Merlin Moncure [mailto:merlin.moncure@rcsonline.com] 
> > Sent: Monday, February 03, 2003 3:00 PM
> > To: Andrew Dunstan
> > Cc: pgsql-hackers@postgresql.org
> > Subject: Re: [HACKERS] Win32 and fsync()
> > 
> > 
> > >I'm having difficulty digging up the reference, but I think I recall
> > seeing >something that said, roughly, on W32 there are 2 sets 
> > of buffers
> > - those in >the user level library and those in the kernel 
> > level driver, and >FlushFileBuffers drains the first, while 
> > _commit drains both (it includes a >call to FlushFileBuffers).
> > 
> > You were correct: here is the source.
> > 
> > 
> > int __cdecl _commit (
> >         int filedes
> >         )
> > {
> >         int retval;
> > 
> >         /* if filedes out of range, complain */
> >         if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
> >              !(_osfile(filedes) & FOPEN) )
> >         {
> >                 errno = EBADF;
> >                 return (-1);
> >         }
> > 
> >         _lock_fh(filedes);
> > 
> >         /* if filedes open, try to commit, else fall through to bad */
> >         if (_osfile(filedes) & FOPEN) {
> > 
> >                 if ( 
> > !FlushFileBuffers((HANDLE)_get_osfhandle(filedes))
> > ) {
> >                         retval = GetLastError();
> >                 } else {
> >                         retval = 0;     /* return success */
> >                 }
> > 
> >                 /* map the OS return code to C errno value 
> > and return code */
> >                 if (retval == 0) {
> >                         goto good;
> >                 } else {
> >                         _doserrno = retval;
> >                         goto bad;
> >                 }
> > 
> >         }
> > 
> > bad :
> >         errno = EBADF;
> >         retval = -1;
> > good :
> >         _unlock_fh(filedes);
> >         return (retval);
> > }
> 
> Where is the "other" flush besides FlushFileBuffers()?

The only real code there is, it seems, an exclusive look on the file
descriptor. (Provided of course that that is what _lock_fh(filedes) does).

Gavin




Re: Win32 and fsync()

From
"Andrew Dunstan"
Date:
I'm not sure what the provenance of this code for _commit is - I thought it
was in the standard MS libs - have they finally seen the light and open
sourced it? ;-)

andrew

----- Original Message -----
From: "Dann Corbit" <DCorbit@connx.com>
To: "Merlin Moncure" <merlin.moncure@rcsonline.com>; "Andrew Dunstan"
<andrew@dunslane.net>
Cc: <pgsql-hackers@postgresql.org>
Sent: Monday, February 03, 2003 6:24 PM
Subject: Re: [HACKERS] Win32 and fsync()


> > -----Original Message-----
> > From: Merlin Moncure [mailto:merlin.moncure@rcsonline.com]
> > Sent: Monday, February 03, 2003 3:00 PM
> > To: Andrew Dunstan
> > Cc: pgsql-hackers@postgresql.org
> > Subject: Re: [HACKERS] Win32 and fsync()
> >
> >
> > >I'm having difficulty digging up the reference, but I think I recall
> > seeing >something that said, roughly, on W32 there are 2 sets
> > of buffers
> > - those in >the user level library and those in the kernel
> > level driver, and >FlushFileBuffers drains the first, while
> > _commit drains both (it includes a >call to FlushFileBuffers).
> >
> > You were correct: here is the source.
> >
> >
> > int __cdecl _commit (
> >         int filedes
> >         )
> > {
> >         int retval;
> >
> >         /* if filedes out of range, complain */
> >         if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
> >              !(_osfile(filedes) & FOPEN) )
> >         {
> >                 errno = EBADF;
> >                 return (-1);
> >         }
> >
> >         _lock_fh(filedes);
> >
> >         /* if filedes open, try to commit, else fall through to bad */
> >         if (_osfile(filedes) & FOPEN) {
> >
> >                 if (
> > !FlushFileBuffers((HANDLE)_get_osfhandle(filedes))
> > ) {
> >                         retval = GetLastError();
> >                 } else {
> >                         retval = 0;     /* return success */
> >                 }
> >
> >                 /* map the OS return code to C errno value
> > and return code */
> >                 if (retval == 0) {
> >                         goto good;
> >                 } else {
> >                         _doserrno = retval;
> >                         goto bad;
> >                 }
> >
> >         }
> >
> > bad :
> >         errno = EBADF;
> >         retval = -1;
> > good :
> >         _unlock_fh(filedes);
> >         return (retval);
> > }
>
> Where is the "other" flush besides FlushFileBuffers()?
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org



Re: Win32 and fsync()

From
"Dann Corbit"
Date:
> -----Original Message-----
> From: Andrew Dunstan [mailto:andrew@dunslane.net]
> Sent: Monday, February 03, 2003 3:31 PM
> To: Dann Corbit; Merlin Moncure
> Cc: pgsql-hackers@postgresql.org
> Subject: Re: [HACKERS] Win32 and fsync()
>
>
> I'm not sure what the provenance of this code for _commit is
> - I thought it was in the standard MS libs - have they
> finally seen the light and open sourced it? ;-)

MS has always shipped the source code to their standard libraries on the
CD.  However, the compiler source remains closed.  This seems
insignificant, but sometimes functions are totally inlined within the
compiler (e.g. math functions like sin() and exp()).


Re: Win32 and fsync()

From
"Andrew Dunstan"
Date:
----- Original Message -----
From: "Gavin Sherry" <swm@linuxworld.com.au>
[snip]
> > Where is the "other" flush besides FlushFileBuffers()?
>
> The only real code there is, it seems, an exclusive look on the file
> descriptor. (Provided of course that that is what _lock_fh(filedes) does).
>

yes, it looks that way.

I wonder what whould happen to reliability and performance if the files were
opened using Windows' write through cache flag (FILE_FLAG_WRITE_THROUGH).
Also, this article might be relevant:

http://support.microsoft.com/default.aspx?scid=kb;en-us;332023

although I see the Windows tests were done on W2000/SP3, so maybe not.

andrew




Re: Win32 and fsync()

From
"Merlin Moncure"
Date:
I think the fopen or _open family of functions all map directly to the
win32 API.  They add a little cruft, which generally makes using them
pointless, because you have less control over security, caching, and
other such things when opening the file.  There is the slight overhead
of the extra call, and the conversion of the C handle to the win32
handle.  However, all you get with the api is readfile() and
writefile(), which means workhorses like fprintf() and especially
fgets() and must be reimplemented (in lieu of using the C++ runtime).

> MS has always shipped the source code to their standard libraries on
the
> CD.  However, the compiler source remains closed.  This seems
> insignificant, but sometimes functions are totally inlined within the
> compiler (e.g. math functions like sin() and exp()).

They have a special calling convention __dllspec(naked), which strips
the function prolog and epilog and allows you to write your own in
assembly.  You can use that to write very fast functions when you don't
trust the optimizer to inline your functions.  I think your are correct
some of the math functions are written this way.

Merlin