summary refs log tree commit diff stats
path: root/lib/pure/memfiles.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/memfiles.nim')
-rw-r--r--lib/pure/memfiles.nim38
1 files changed, 34 insertions, 4 deletions
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index e5345e645..810223d72 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -36,11 +36,12 @@ type
     size*: int       ## size of the memory mapped file
 
     when defined(windows):
-      fHandle: Handle
-      mapHandle: Handle
-      wasOpened: bool   ## only close if wasOpened
+      fHandle*: Handle     ## **Caution**: Windows specific public field to allow
+                           ## even more low level trickery.
+      mapHandle*: Handle   ## **Caution**: Windows specific public field.
+      wasOpened*: bool     ## **Caution**: Windows specific public field.
     else:
-      handle: cint
+      handle*: cint        ## **Caution**: Posix specific public field.
 
 proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
              mappedSize = -1, offset = 0): pointer =
@@ -281,6 +282,35 @@ proc flush*(f: var MemFile; attempts: Natural = 3) =
       if lastErr != EBUSY.OSErrorCode:
         raiseOSError(lastErr, "error flushing mapping")
 
+when defined(posix) or defined(nimdoc):
+  proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} =
+    ## 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.
+    ## **Note**: This is not (yet) avaiable on Windows.
+    when defined(posix):
+      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.
s='oid'>7687dd8d ^
d35bac82 ^
fa704bab ^




fa704bab ^
0115ab10 ^
ea87d005 ^
fa704bab ^
d35bac82 ^

fa704bab ^
ea87d005 ^
fa704bab ^
d35bac82 ^



0115ab10 ^


ea87d005 ^
586f0006 ^













ea87d005 ^
586f0006 ^














fa704bab ^

d35bac82 ^



fd39b80a ^









fa704bab ^

0115ab10 ^
0115ab10 ^
fa704bab ^
d35bac82 ^

fa704bab ^
fa704bab ^
0115ab10 ^
fa704bab ^
0115ab10 ^
8e327137 ^
c8d84d00 ^
a986e2bd ^
ea87d005 ^
0115ab10 ^
d35bac82 ^
0115ab10 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127