@@ -33,77 +33,94 @@ package maxminddb
33
33
import (
34
34
"errors"
35
35
"os"
36
- "reflect"
37
36
"sync"
38
37
"unsafe"
39
38
40
39
"golang.org/x/sys/windows"
41
40
)
42
41
43
- type memoryMap []byte
44
-
45
42
// Windows
46
43
var (
47
44
handleLock sync.Mutex
48
45
handleMap = map [uintptr ]windows.Handle {}
49
46
)
50
47
51
- func mmap (fd int , length int ) (data []byte , err error ) {
52
- h , errno := windows .CreateFileMapping (windows .Handle (fd ), nil ,
53
- uint32 (windows .PAGE_READONLY ), 0 , uint32 (length ), nil )
54
- if h == 0 {
55
- return nil , os .NewSyscallError ("CreateFileMapping" , errno )
48
+ // mmap maps a file into memory and returns a byte slice.
49
+ func mmap (fd int , length int ) ([]byte , error ) {
50
+ // Create a file mapping
51
+ handle , err := windows .CreateFileMapping (
52
+ windows .Handle (fd ),
53
+ nil ,
54
+ windows .PAGE_READONLY ,
55
+ 0 ,
56
+ uint32 (length ),
57
+ nil ,
58
+ )
59
+ if err != nil {
60
+ return nil , os .NewSyscallError ("CreateFileMapping" , err )
56
61
}
57
62
58
- addr , errno := windows .MapViewOfFile (h , uint32 (windows .FILE_MAP_READ ), 0 ,
59
- 0 , uintptr (length ))
60
- if addr == 0 {
61
- return nil , os .NewSyscallError ("MapViewOfFile" , errno )
63
+ // Map the file into memory
64
+ addr , err := windows .MapViewOfFile (
65
+ handle ,
66
+ windows .FILE_MAP_READ ,
67
+ 0 ,
68
+ 0 ,
69
+ uintptr (length ),
70
+ )
71
+ if err != nil {
72
+ windows .CloseHandle (handle )
73
+ return nil , os .NewSyscallError ("MapViewOfFile" , err )
62
74
}
75
+
76
+ // Store the handle in the map
63
77
handleLock .Lock ()
64
- handleMap [addr ] = h
78
+ handleMap [addr ] = handle
65
79
handleLock .Unlock ()
66
80
67
- m := memoryMap {}
68
- dh := m .header ()
69
- dh .Data = addr
70
- dh .Len = length
71
- dh .Cap = dh .Len
72
-
73
- return m , nil
74
- }
75
-
76
- func (m * memoryMap ) header () * reflect.SliceHeader {
77
- return (* reflect .SliceHeader )(unsafe .Pointer (m ))
81
+ data := unsafe .Slice ((* byte )(unsafe .Pointer (addr )), length )
82
+ return data , nil
78
83
}
79
84
80
- func flush (addr , len uintptr ) error {
81
- errno := windows .FlushViewOfFile (addr , len )
82
- return os .NewSyscallError ("FlushViewOfFile" , errno )
85
+ // flush ensures changes to a memory-mapped region are written to disk.
86
+ func flush (addr , length uintptr ) error {
87
+ err := windows .FlushViewOfFile (addr , length )
88
+ if err != nil {
89
+ return os .NewSyscallError ("FlushViewOfFile" , err )
90
+ }
91
+ return nil
83
92
}
84
93
85
- func munmap ( b [] byte ) ( err error ) {
86
- m := memoryMap ( b )
87
- dh := m . header ()
88
-
89
- addr := dh . Data
90
- length := uintptr (dh . Len )
94
+ // munmap unmaps a memory-mapped file and releases associated resources.
95
+ func munmap ( b [] byte ) error {
96
+ // Convert slice to base address and length
97
+ data := unsafe . SliceData ( b )
98
+ addr := uintptr ( unsafe . Pointer ( data ))
99
+ length := uintptr (len ( b ) )
91
100
92
- flush (addr , length )
93
- err = windows .UnmapViewOfFile (addr )
94
- if err != nil {
101
+ // Flush the memory region
102
+ if err := flush (addr , length ); err != nil {
95
103
return err
96
104
}
97
105
106
+ // Unmap the memory
107
+ if err := windows .UnmapViewOfFile (addr ); err != nil {
108
+ return os .NewSyscallError ("UnmapViewOfFile" , err )
109
+ }
110
+
111
+ // Remove the handle from the map and close it
98
112
handleLock .Lock ()
99
113
defer handleLock .Unlock ()
114
+
100
115
handle , ok := handleMap [addr ]
101
116
if ! ok {
102
117
// should be impossible; we would've errored above
103
118
return errors .New ("unknown base address" )
104
119
}
105
120
delete (handleMap , addr )
106
121
107
- e := windows .CloseHandle (windows .Handle (handle ))
108
- return os .NewSyscallError ("CloseHandle" , e )
122
+ if err := windows .CloseHandle (handle ); err != nil {
123
+ return os .NewSyscallError ("CloseHandle" , err )
124
+ }
125
+ return nil
109
126
}
0 commit comments