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
|
package bytewriter
import (
"os"
"path/filepath"
mmap "github.com/edsrzf/mmap-go"
"github.com/pkg/errors"
)
// MemoryMappedWriter is a ByteBuffer that is also mapped into memory
type MemoryMappedWriter struct {
*ByteWriter
handle *os.File // file handle
loc string // location of the memory mapped file
size int // size in bytes
}
// NewMemoryMappedWriter will create and return a new instance of a MemoryMappedWriter
func NewMemoryMappedWriter(loc string, size int) (*MemoryMappedWriter, error) {
if _, err := os.Stat(loc); err == nil {
err = os.Remove(loc)
if err != nil {
return nil, err
}
}
// ensure destination directory exists
dir := filepath.Dir(loc)
err := os.MkdirAll(dir, 0700)
if err != nil {
return nil, err
}
f, err := os.OpenFile(loc, os.O_CREATE|os.O_RDWR|os.O_EXCL, 0644)
if err != nil {
return nil, err
}
l, err := f.Write(make([]byte, size))
if err != nil {
return nil, err
}
if l < size {
return nil, errors.Errorf("Could not initialize %d bytes", size)
}
b, err := mmap.Map(f, mmap.RDWR, 0)
if err != nil {
return nil, err
}
return &MemoryMappedWriter{
NewByteWriterSlice(b),
f,
loc,
size,
}, nil
}
// Unmap will manually delete the memory mapping of a mapped buffer
func (b *MemoryMappedWriter) Unmap(removefile bool) error {
m := mmap.MMap(b.buffer)
if err := m.Unmap(); err != nil {
return err
}
if err := b.handle.Close(); err != nil {
return err
}
if removefile {
if err := os.Remove(b.loc); err != nil {
return err
}
}
return nil
}
|