-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
direct_io.go
57 lines (53 loc) · 1.6 KB
/
direct_io.go
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
// This is library for the Go language to enable use of Direct IO under
// all supported OSes of Go.
//
// Direct IO does IO to and from disk without buffering data in the OS.
// It is useful when you are reading or writing lots of data you don't
// want to fill the OS cache up with.
//
// Instead of using os.OpenFile use directio.OpenFile
//
// in, err := directio.OpenFile(file, os.O_RDONLY, 0666)
//
// And when reading or writing blocks, make sure you do them in chunks of
// directio.BlockSize using memory allocated by directio.AlignedBlock
//
// block := directio.AlignedBlock(BlockSize)
// _, err := io.ReadFull(in, block)
package directio
import (
"log"
"unsafe"
)
// alignment returns alignment of the block in memory
// with reference to AlignSize
//
// Can't check alignment of a zero sized block as &block[0] is invalid
func alignment(block []byte, AlignSize int) int {
return int(uintptr(unsafe.Pointer(&block[0])) & uintptr(AlignSize-1))
}
// IsAligned checks wether passed byte slice is aligned
func IsAligned(block []byte) bool {
return alignment(block, AlignSize) == 0
}
// AlignedBlock returns []byte of size BlockSize aligned to a multiple
// of AlignSize in memory (must be power of two)
func AlignedBlock(BlockSize int) []byte {
block := make([]byte, BlockSize+AlignSize)
if AlignSize == 0 {
return block
}
a := alignment(block, AlignSize)
offset := 0
if a != 0 {
offset = AlignSize - a
}
block = block[offset : offset+BlockSize]
// Can't check alignment of a zero sized block
if BlockSize != 0 {
if !IsAligned(block) {
log.Fatal("Failed to align block")
}
}
return block
}