diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/memfiles.nim | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index e5345e645..d2beb629a 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -281,6 +281,35 @@ proc flush*(f: var MemFile; attempts: Natural = 3) = if lastErr != EBUSY.OSErrorCode: raiseOSError(lastErr, "error flushing mapping") +proc resize*(f: var MemFile, newFileSize: int) = + ## resize and re-map the file underlying an ``allowRemap MemFile``. NOTE: + ## this assumes the entire file is mapped read-write at offset zero. Also, + ## the value of ``.mem`` will probably change. + when defined(windows): + discard #TODO This needs to be implemented. + else: + if f.handle == -1: + raise newException(IOError, + "Cannot resize MemFile opened with allowRemap=false") + if ftruncate(f.handle, newFileSize) == -1: + raiseOSError(osLastError()) + when defined(linux): #Maybe NetBSD, too? + #On Linux this can be over 100 times faster than a munmap,mmap cycle. + proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {. + importc: "mremap", header: "<sys/mman.h>" .} + let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + else: + if munmap(f.mem, f.size) != 0: + raiseOSError(osLastError()) + let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE, + MAP_SHARED or MAP_POPULATE, f.handle, 0) + if newAddr == cast[pointer](MAP_FAILED): + raiseOSError(osLastError()) + f.mem = newAddr + f.size = newFileSize + proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the ## file system, if `f` was opened with write access. |