-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshard_binary.go
141 lines (121 loc) · 3.72 KB
/
shard_binary.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
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package main
import (
"bufio"
"bytes"
"encoding/binary"
"errors"
"os"
)
// Byte writer to a shard
// Write in-memory to bytes for disk
func (this *Shard) _toBinaryFormat() []byte {
buf := new(bytes.Buffer)
// Re-usable byte array
var b []byte = nil
// Global read lock
this.contentsMux.Lock()
// Actual file contents
if this.contents != nil {
b := this.contents.Bytes()
this.shardMeta.SetContentsLength(uint32(len(b)))
buf.Write(b)
b = nil
} else {
log.Infof("Converting empty shard %s to bytes", this.IdStr())
this.shardMeta.SetContentsLength(0)
}
// File meta
b = this.shardFileMeta.Bytes()
this.shardMeta.SetFileMetaLength(uint32(len(b)))
buf.Write(this.shardFileMeta.Bytes())
b = nil
// File index
b = this.shardIndex.Bytes()
this.shardMeta.SetIndexLength(uint32(len(b)))
buf.Write(b)
b = nil
// Shard meta
log.Infof("Writing shard meta %v", this.shardMeta)
log.Debugf("Writing shard meta %v", this.shardMeta.Bytes())
buf.Write(this.shardMeta.Bytes())
// Unlock
this.contentsMux.Unlock()
return buf.Bytes()
}
// Open file
func (this *Shard) _openFile() (*os.File, error) {
return os.Open(this.FullPath())
}
// Read to memory structure from binary on disk
func (this *Shard) _fromBinaryFormat() (bool, error) {
// Open file
f, err := this._openFile()
defer f.Close()
if err != nil {
return false, errors.New("File not found")
}
// File stat for length
fi, fierr := f.Stat()
if fierr != nil {
return false, errors.New("Failed to stat file")
}
flen := fi.Size()
// Go to last byte to determine size of metadata
f.Seek(flen-4, 0)
buf := bufio.NewReader(f)
var metadataLength uint32
binary.Read(buf, binary.BigEndian, &metadataLength)
log.Debugf("Meta is size of %d", metadataLength)
// Read metadata
f.Seek(flen-int64(metadataLength), 0)
buf = bufio.NewReader(f)
metaBytes := make([]byte, metadataLength)
metaBytesRead, _ := buf.Read(metaBytes)
if metaBytesRead != len(metaBytes) || metaBytesRead < 1 {
panic("Failed to read metadata bytes")
}
log.Debugf("Read %d metadata bytes: %v", metaBytesRead, metaBytes)
this.shardMeta = newShardMeta()
this.shardMeta.FromBytes(metaBytes)
this.contentsOffset = this.shardMeta.ContentsLength
metaBytes = nil
if this.shardMeta.MetaVersion < 1 {
panic("Failed to read metadata, could not find version")
}
log.Debugf("Metadata: %v", this.shardMeta)
// Read index
f.Seek(flen-int64(metadataLength)-int64(this.shardMeta.IndexLength), 0)
buf = bufio.NewReader(f)
indexBytes := make([]byte, int(this.shardMeta.IndexLength))
indexBytesRead, _ := buf.Read(indexBytes)
if indexBytesRead != len(indexBytes) || metaBytesRead < 1 {
panic("Failed to read index bytes")
}
log.Debugf("Read %d index bytes", indexBytesRead)
this.shardIndex = newShardIndex(this.Id)
this.shardIndex.FromBytes(indexBytes)
indexBytes = nil
if this.shardIndex.bloomFilter == nil {
panic("Bloom filter is nil")
}
log.Debugf("Shard index %v", this.shardIndex)
// Read file meta
f.Seek(flen-int64(metadataLength)-int64(this.shardMeta.IndexLength)-int64(this.shardMeta.FileMetaLength), 0)
buf = bufio.NewReader(f)
fileMetaBytes := make([]byte, int(this.shardMeta.FileMetaLength))
fileMetaBytesRead, _ := buf.Read(fileMetaBytes)
if fileMetaBytesRead != len(fileMetaBytes) || fileMetaBytesRead < 1 {
panic("Failed to read file meta bytes")
}
log.Debugf("Read %d file meta bytes", fileMetaBytesRead)
this.shardFileMeta = newShardFileMeta()
this.shardFileMeta.FromBytes(fileMetaBytes)
fileMetaBytes = nil
if this.shardFileMeta.FileMeta == nil {
panic("File meta is nil")
}
log.Debugf("Shard file meta %v", this.shardFileMeta)
// We don't read the file contents here, that's read from disk, make sure it's empty to prevent race conditions
this.SetContents(nil)
return true, nil
}