forked from nutsdb/nutsdb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecovery_reader.go
More file actions
85 lines (74 loc) · 1.68 KB
/
recovery_reader.go
File metadata and controls
85 lines (74 loc) · 1.68 KB
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
package nutsdb
import (
"bufio"
"encoding/binary"
"io"
"os"
)
// fileRecovery use bufio.Reader to read entry
type fileRecovery struct {
fd *os.File
reader *bufio.Reader
}
func newFileRecovery(path string, bufSize int) (fr *fileRecovery, err error) {
fd, err := os.OpenFile(path, os.O_RDWR, os.ModePerm)
if err != nil {
return nil, err
}
bufSize = calBufferSize(bufSize)
return &fileRecovery{
fd: fd,
reader: bufio.NewReaderSize(fd, bufSize),
}, nil
}
// readEntry will read an Entry from disk.
func (fr *fileRecovery) readEntry() (e *Entry, err error) {
buf := make([]byte, DataEntryHeaderSize)
_, err = io.ReadFull(fr.reader, buf)
if err != nil {
return nil, err
}
e = &Entry{
crc: binary.LittleEndian.Uint32(buf[0:4]),
}
err = e.ParseMeta(buf)
if err != nil {
return nil, err
}
if e.IsZero() {
return nil, nil
}
meta := e.Meta
dataSize := meta.BucketSize + meta.KeySize + meta.ValueSize
dataBuf := make([]byte, dataSize)
_, err = io.ReadFull(fr.reader, dataBuf)
if err != nil {
return nil, err
}
err = e.ParsePayload(dataBuf)
if err != nil {
return nil, err
}
crc := e.GetCrc(buf)
if crc != e.crc {
return nil, ErrCrc
}
return e, nil
}
// calBufferSize calculates the buffer size of bufio.Reader
// if the size < 4 * KB, use 4 * KB as the size of buffer in bufio.Reader
// if the size > 4 * KB, use the nearly blockSize buffer as the size of buffer in bufio.Reader
func calBufferSize(size int) int {
blockSize := 4 * KB
if size < blockSize {
return blockSize
}
hasRest := (size%blockSize == 0)
if hasRest {
return (size/blockSize + 1) * blockSize
}
return size
}
func (fr *fileRecovery) release() error {
return fr.fd.Close()
}