Add cross-platform fsync() primitive and improve Direct mode. (#228)
This commit is contained in:
parent
fc09b2e023
commit
4d4dfb7b32
34
stew/io2.nim
34
stew/io2.nim
|
@ -35,6 +35,7 @@ when defined(windows):
|
|||
FILE_APPEND_DATA = 0x00000004'u32
|
||||
|
||||
FILE_FLAG_NO_BUFFERING = 0x20000000'u32
|
||||
FILE_FLAG_WRITE_THROUGH = 0x80000000'u32
|
||||
FILE_ATTRIBUTE_READONLY = 0x00000001'u32
|
||||
FILE_ATTRIBUTE_DIRECTORY = 0x00000010'u32
|
||||
|
||||
|
@ -200,6 +201,8 @@ when defined(windows):
|
|||
sideEffect.}
|
||||
proc getTempPathW(nBufferLength: uint32, lpBuffer: WideCString): uint32 {.
|
||||
importc: "GetTempPathW", dynlib: "kernel32", stdcall, sideEffect.}
|
||||
proc flushFileBuffers(hFile: uint): int32 {.
|
||||
importc: "FlushFileBuffers", dynlib: "kernel32", stdcall, sideEffect.}
|
||||
|
||||
const
|
||||
NO_ERROR = IoErrorCode(0)
|
||||
|
@ -1024,15 +1027,16 @@ proc openFile*(pathName: string, flags: set[OpenFlags],
|
|||
when defined(linux) or defined(freebsd) or defined(netbsd) or
|
||||
defined(dragonflybsd):
|
||||
if OpenFlags.Direct in flags:
|
||||
cflags = cflags or O_DIRECT
|
||||
cflags = cflags or O_DIRECT or O_SYNC
|
||||
if OpenFlags.Inherit notin flags:
|
||||
cflags = cflags or O_CLOEXEC
|
||||
if OpenFlags.NonBlock in flags:
|
||||
cflags = cflags or posix.O_NONBLOCK
|
||||
|
||||
while true:
|
||||
let omask = setUmask(0)
|
||||
let ores = posix.open(cstring(pathName), cflags, Mode(createMode))
|
||||
let
|
||||
omask = setUmask(0)
|
||||
ores = posix.open(cstring(pathName), cflags, Mode(createMode))
|
||||
discard setUmask(omask)
|
||||
if ores == -1:
|
||||
let errCode = ioLastError()
|
||||
|
@ -1041,7 +1045,7 @@ proc openFile*(pathName: string, flags: set[OpenFlags],
|
|||
else:
|
||||
return err(errCode)
|
||||
else:
|
||||
when defined(macosx):
|
||||
when defined(macosx) or defined(macos):
|
||||
if OpenFlags.Direct in flags:
|
||||
while true:
|
||||
let fres = posix.fcntl(cint(ores), F_NOCACHE, 1)
|
||||
|
@ -1105,7 +1109,7 @@ proc openFile*(pathName: string, flags: set[OpenFlags],
|
|||
if OpenFlags.NonBlock in flags:
|
||||
dwFlags = dwFlags or FILE_FLAG_OVERLAPPED
|
||||
if OpenFlags.Direct in flags:
|
||||
dwFlags = dwFlags or FILE_FLAG_NO_BUFFERING
|
||||
dwFlags = dwFlags or FILE_FLAG_NO_BUFFERING or FILE_FLAG_WRITE_THROUGH
|
||||
if OpenFlags.Inherit in flags:
|
||||
sa.bInheritHandle = 1
|
||||
|
||||
|
@ -1391,6 +1395,26 @@ proc truncate*(pathName: string, length: int64): IoResult[void] =
|
|||
else:
|
||||
ok()
|
||||
|
||||
proc fsync*(handle: IoHandle): IoResult[void] =
|
||||
## Ensure that all data for the open file descriptor named by ``handle``
|
||||
## is to be transferred to the storage device associated with the file.
|
||||
when defined(windows):
|
||||
let res = flushFileBuffers(uint(handle))
|
||||
if res == 0:
|
||||
return err(ioLastError())
|
||||
ok()
|
||||
else:
|
||||
while true:
|
||||
let res = posix.fsync(cint(handle))
|
||||
if res == -1:
|
||||
let errCode = ioLastError()
|
||||
if errCode == EINTR:
|
||||
continue
|
||||
else:
|
||||
return err(errCode)
|
||||
else:
|
||||
return ok()
|
||||
|
||||
proc checkFileSize*(value: int64): IoResult[int] =
|
||||
## Checks if ``value`` fits into supported by Nim string/sequence indexing
|
||||
## mechanism.
|
||||
|
|
Loading…
Reference in New Issue