/
abstractblockpackedwriter.go
112 lines (94 loc) · 2.29 KB
/
abstractblockpackedwriter.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
package packed
import (
"context"
"errors"
"sync/atomic"
"github.com/geange/lucene-go/core/store"
)
const (
ABP_MIN_BLOCK_SIZE = 64
ABP_MAX_BLOCK_SIZE = 1 << (30 - 3)
ABP_MIN_VALUE_EQUALS_0 = 1 << 0
ABP_BPV_SHIFT = 1
)
type abstractBlockPackedWriter struct {
out store.DataOutput
values []uint64
blocks []byte
off int
ord int
finished *atomic.Bool
flusher BlockPackedFlusher
}
func newAbstractBlockPackedWriter(out store.DataOutput, blockSize int) *abstractBlockPackedWriter {
writer := &abstractBlockPackedWriter{
finished: new(atomic.Bool),
}
writer.reset(out)
writer.values = make([]uint64, blockSize)
return writer
}
// Reset this writer to wrap out. The block size remains unchanged.
func (a *abstractBlockPackedWriter) reset(out store.DataOutput) {
a.out = out
a.off = 0
a.ord = 0
a.finished.Store(false)
}
func (a *abstractBlockPackedWriter) checkNotFinished() error {
if a.finished.Load() {
return errors.New("already finished")
}
return nil
}
// add
// Append a new long.
func (a *abstractBlockPackedWriter) add(ctx context.Context, v uint64) error {
if err := a.checkNotFinished(); err != nil {
return err
}
if a.off == len(a.values) {
if err := a.flush(ctx); err != nil {
return err
}
}
a.values[a.off] = v
a.off++
a.ord++
return nil
}
func (a *abstractBlockPackedWriter) Finish(ctx context.Context) error {
if a.off > 0 {
if err := a.flush(ctx); err != nil {
return err
}
}
a.finished.Store(true)
return nil
}
type BlockPackedFlusher interface {
Flush(ctx context.Context) error
}
func (a *abstractBlockPackedWriter) flush(ctx context.Context) error {
return a.flusher.Flush(ctx)
}
func (a *abstractBlockPackedWriter) writeValues(bitsRequired int) error {
encoder, err := GetEncoder(FormatPacked, VERSION_CURRENT, bitsRequired)
if err != nil {
return err
}
iterations := len(a.values) / encoder.ByteValueCount()
blockSize := encoder.ByteBlockCount() * iterations
if len(a.blocks) < blockSize {
a.blocks = make([]byte, blockSize)
}
if a.off < len(a.values) {
clear(a.values[a.off:])
}
encoder.EncodeBytes(a.values, a.blocks, iterations)
blockCount := FormatPacked.ByteCount(VERSION_CURRENT, a.off, bitsRequired)
if _, err := a.out.Write(a.blocks[:blockCount]); err != nil {
return err
}
return nil
}