-
Notifications
You must be signed in to change notification settings - Fork 1
/
packets.go
160 lines (150 loc) · 3.67 KB
/
packets.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package chotki
import (
"errors"
"github.com/cockroachdb/pebble"
"github.com/drpcorg/chotki/protocol"
"github.com/drpcorg/chotki/rdx"
)
func (cho *Chotki) UpdateVTree(id, ref rdx.ID, pb *pebble.Batch) (err error) {
v := protocol.Record('V', id.ZipBytes())
err = pb.Merge(VKey(ref), v, cho.opts.PebbleWriteOptions)
if err == nil {
err = pb.Merge(VKey0, v, cho.opts.PebbleWriteOptions)
}
return
}
func (cho *Chotki) ApplyD(id, ref rdx.ID, body []byte, batch *pebble.Batch) (err error) {
rest := body
var rdt byte
for len(rest) > 0 && err == nil {
var dzip, bare []byte
dzip, rest = protocol.Take('F', rest)
d := rdx.UnzipUint64(dzip)
at := ref + rdx.ID(d) // fixme
rdt, bare, rest = protocol.TakeAny(rest)
err = batch.Merge(OKey(at, rdt), bare, cho.opts.PebbleWriteOptions)
}
return
}
func (cho *Chotki) ApplyH(id, ref rdx.ID, body []byte, batch *pebble.Batch) (err error) {
_, rest := protocol.Take('M', body)
var vbody []byte
vbody, _ = protocol.Take('V', rest)
err = batch.Merge(VKey0, vbody, cho.opts.PebbleWriteOptions)
return
}
func (cho *Chotki) ApplyV(id, ref rdx.ID, body []byte, batch *pebble.Batch) (err error) {
rest := body
for len(rest) > 0 {
var rec, idb []byte
rec, rest = protocol.Take('V', rest)
idb, rec = protocol.Take('R', rec)
id := rdx.IDFromZipBytes(idb)
key := VKey(id)
if !rdx.VValid(rec) {
err = ErrBadVPacket
} else {
err = batch.Merge(key, rec, cho.opts.PebbleWriteOptions)
}
}
return
}
func (cho *Chotki) ApplyC(id, ref rdx.ID, body []byte, batch *pebble.Batch) (err error) {
err = batch.Merge(
OKey(id, 'C'),
body,
cho.opts.PebbleWriteOptions)
if err == nil {
err = cho.UpdateVTree(id, ref, batch)
}
return
}
func (cho *Chotki) ApplyOY(lot byte, id, ref rdx.ID, body []byte, batch *pebble.Batch) (err error) {
err = batch.Merge(
OKey(id, lot),
ref.ZipBytes(),
cho.opts.PebbleWriteOptions)
rest := body
var fid rdx.ID
for fno := rdx.ID(1); len(rest) > 0 && err == nil; fno++ {
lit, hlen, blen := protocol.ProbeHeader(rest)
if lit == 0 || lit == '-' {
return rdx.ErrBadPacket
}
var bare, rebar []byte
rlen := hlen + blen
if len(rest) < rlen {
return ErrBadOPacket
}
bare = rest[hlen:rlen]
fid = id + fno
fkey := OKey(fid, lit)
switch lit {
case 'F', 'I', 'R', 'S', 'T':
rebar, err = rdx.SetSourceFIRST(bare, id.Src())
case 'E', 'L', 'M':
rebar, err = rdx.MelReSource(bare, id.Src())
default:
rebar = bare
}
if err != nil {
break
}
err = batch.Merge(
fkey,
rebar,
cho.opts.PebbleWriteOptions)
rest = rest[rlen:]
}
if err == nil {
err = cho.UpdateVTree(fid, id, batch)
}
return
}
var ErrOffsetOpId = errors.New("op id is offset")
func (cho *Chotki) ApplyE(id, r rdx.ID, body []byte, batch *pebble.Batch, calls *[]CallHook) (err error) {
if id.Off() != 0 || r.Off() != 0 {
return ErrOffsetOpId
}
rest := body
for len(rest) > 0 && err == nil {
var fint, bare, rebar []byte
var lit byte
fint, rest = protocol.Take('F', rest)
if fint == nil {
return ErrBadEPacket
}
field := rdx.UnzipUint64(fint)
if field > uint64(rdx.OffMask) {
return ErrBadEPacket
}
lit, bare, rest = protocol.TakeAny(rest)
switch lit {
case 'F', 'I', 'R', 'S', 'T':
rebar, err = rdx.SetSourceFIRST(bare, id.Src())
case 'E', 'L', 'M':
rebar, err = rdx.MelReSource(bare, id.Src())
default:
rebar = bare
}
if err != nil {
break
}
fid := r + rdx.ID(field)
fkey := OKey(fid, lit)
err = batch.Merge(
fkey,
rebar,
cho.opts.PebbleWriteOptions)
hook, ok := cho.hooks.Load(fid)
if ok {
for _, h := range hook {
(*calls) = append((*calls), CallHook{h, fid})
}
}
}
if err == nil {
err = cho.UpdateVTree(id, r, batch)
}
return
}