Commit 3d99bbc2 authored by Kirill Smelkov's avatar Kirill Smelkov

X encode: Output keys in sorted order

parent 1584a56f
...@@ -4,6 +4,7 @@ package neo ...@@ -4,6 +4,7 @@ package neo
import ( import (
"encoding/binary" "encoding/binary"
"sort"
) )
// 0. Address // 0. Address
...@@ -1026,9 +1027,8 @@ func (p *AnswerLockedTransactions) NEOEncodedLen() int { ...@@ -1026,9 +1027,8 @@ func (p *AnswerLockedTransactions) NEOEncodedLen() int {
l := uint32(len(p.TidDict)) l := uint32(len(p.TidDict))
_ = l _ = l
size += 4 size += 4
for key, v := range p.TidDict { for key := range p.TidDict {
_ = key _ = key
_ = v
size += 16 size += 16
} }
} }
...@@ -1040,9 +1040,14 @@ func (p *AnswerLockedTransactions) NEOEncode(data []byte) { ...@@ -1040,9 +1040,14 @@ func (p *AnswerLockedTransactions) NEOEncode(data []byte) {
l := uint32(len(p.TidDict)) l := uint32(len(p.TidDict))
binary.BigEndian.PutUint32(data[0:], l) binary.BigEndian.PutUint32(data[0:], l)
data = data[4:] data = data[4:]
for key, v := range p.TidDict { keyv := make([]Tid, 0, l)
for key := range p.TidDict {
keyv = append(keyv, key)
}
sort.Slice(keyv, func(i, j int) bool { return keyv[i] < keyv[j] })
for _, key := range keyv {
binary.BigEndian.PutUint64(data[0:], uint64(key)) binary.BigEndian.PutUint64(data[0:], uint64(key))
binary.BigEndian.PutUint64(data[8:], uint64(v)) binary.BigEndian.PutUint64(data[8:], uint64(p.TidDict[key]))
data = data[16:] data = data[16:]
} }
} }
...@@ -2833,9 +2838,8 @@ func (p *AnswerObjectUndoSerial) NEOEncodedLen() int { ...@@ -2833,9 +2838,8 @@ func (p *AnswerObjectUndoSerial) NEOEncodedLen() int {
l := uint32(len(p.ObjectTIDDict)) l := uint32(len(p.ObjectTIDDict))
_ = l _ = l
size += 4 size += 4
for key, v := range p.ObjectTIDDict { for key := range p.ObjectTIDDict {
_ = key _ = key
_ = v
size += 25 size += 25
} }
} }
...@@ -2847,11 +2851,16 @@ func (p *AnswerObjectUndoSerial) NEOEncode(data []byte) { ...@@ -2847,11 +2851,16 @@ func (p *AnswerObjectUndoSerial) NEOEncode(data []byte) {
l := uint32(len(p.ObjectTIDDict)) l := uint32(len(p.ObjectTIDDict))
binary.BigEndian.PutUint32(data[0:], l) binary.BigEndian.PutUint32(data[0:], l)
data = data[4:] data = data[4:]
for key, v := range p.ObjectTIDDict { keyv := make([]Oid, 0, l)
for key := range p.ObjectTIDDict {
keyv = append(keyv, key)
}
sort.Slice(keyv, func(i, j int) bool { return keyv[i] < keyv[j] })
for _, key := range keyv {
binary.BigEndian.PutUint64(data[0:], uint64(key)) binary.BigEndian.PutUint64(data[0:], uint64(key))
binary.BigEndian.PutUint64(data[8:], uint64(v.CurrentSerial)) binary.BigEndian.PutUint64(data[8:], uint64(p.ObjectTIDDict[key].CurrentSerial))
binary.BigEndian.PutUint64(data[16:], uint64(v.UndoSerial)) binary.BigEndian.PutUint64(data[16:], uint64(p.ObjectTIDDict[key].UndoSerial))
(data[24:])[0] = bool2byte(v.IsCurrent) (data[24:])[0] = bool2byte(p.ObjectTIDDict[key].IsCurrent)
data = data[25:] data = data[25:]
} }
} }
...@@ -3037,9 +3046,8 @@ func (p *CheckReplicas) NEOEncodedLen() int { ...@@ -3037,9 +3046,8 @@ func (p *CheckReplicas) NEOEncodedLen() int {
l := uint32(len(p.PartitionDict)) l := uint32(len(p.PartitionDict))
_ = l _ = l
size += 4 size += 4
for key, v := range p.PartitionDict { for key := range p.PartitionDict {
_ = key _ = key
_ = v
size += 8 size += 8
} }
} }
...@@ -3051,9 +3059,14 @@ func (p *CheckReplicas) NEOEncode(data []byte) { ...@@ -3051,9 +3059,14 @@ func (p *CheckReplicas) NEOEncode(data []byte) {
l := uint32(len(p.PartitionDict)) l := uint32(len(p.PartitionDict))
binary.BigEndian.PutUint32(data[0:], l) binary.BigEndian.PutUint32(data[0:], l)
data = data[4:] data = data[4:]
for key, v := range p.PartitionDict { keyv := make([]uint32, 0, l)
for key := range p.PartitionDict {
keyv = append(keyv, key)
}
sort.Slice(keyv, func(i, j int) bool { return keyv[i] < keyv[j] })
for _, key := range keyv {
binary.BigEndian.PutUint32(data[0:], key) binary.BigEndian.PutUint32(data[0:], key)
binary.BigEndian.PutUint32(data[4:], uint32(int32(v))) binary.BigEndian.PutUint32(data[4:], uint32(int32(p.PartitionDict[key])))
data = data[8:] data = data[8:]
} }
} }
......
...@@ -167,7 +167,6 @@ func TestPktMarshal(t *testing.T) { ...@@ -167,7 +167,6 @@ func TestPktMarshal(t *testing.T) {
hex("00000007000000030000000b000000040000000f000000030000001700000000"), hex("00000007000000030000000b000000040000000f000000030000001700000000"),
}, },
/*
// map[Oid]struct {Tid,Tid,bool} // map[Oid]struct {Tid,Tid,bool}
{&AnswerObjectUndoSerial{ {&AnswerObjectUndoSerial{
ObjectTIDDict: map[Oid]struct{ ObjectTIDDict: map[Oid]struct{
...@@ -184,10 +183,9 @@ func TestPktMarshal(t *testing.T) { ...@@ -184,10 +183,9 @@ func TestPktMarshal(t *testing.T) {
u32(4) + u32(4) +
u64(1) + u64(1) + u64(0) + hex("00") + u64(1) + u64(1) + u64(0) + hex("00") +
u64(2) + u64(7) + u64(1) + hex("01") + u64(2) + u64(7) + u64(1) + hex("01") +
u64(8) + u64(7) + u64(1) + hex("00") + u64(5) + u64(4) + u64(3) + hex("01") +
u64(5) + u64(4) + u64(3) + hex("01"), u64(8) + u64(7) + u64(1) + hex("00"),
}, },
*/
// uint32, []uint32 // uint32, []uint32
{&PartitionCorrupted{7, []UUID{1,3,9,4}}, {&PartitionCorrupted{7, []UUID{1,3,9,4}},
......
...@@ -86,6 +86,7 @@ func main() { ...@@ -86,6 +86,7 @@ func main() {
package neo package neo
import ( import (
"encoding/binary" "encoding/binary"
"sort"
) )
`) `)
...@@ -376,14 +377,24 @@ func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) { ...@@ -376,14 +377,24 @@ func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) {
} }
e.n = 0 e.n = 0
// TODO if size(item)==const - size update in one go // TODO if size(item)==const - size update in one go
e.emit("for key, v := range %s {", path) if !e.SizeOnly {
// output keys in sorted order on the wire
// (easier for debugging & deterministic for testing)
e.emit("keyv := make([]%s, 0, l)", typeName(typ.Key()))
e.emit("for key := range %s {", path)
e.emit(" keyv = append(keyv, key)")
e.emit("}")
e.emit("sort.Slice(keyv, func (i, j int) bool { return keyv[i] < keyv[j] })")
e.emit("for _, key := range keyv {")
} else {
e.emit("for key := range %s {", path)
}
codegenType("key", typ.Key(), obj, e) codegenType("key", typ.Key(), obj, e)
codegenType("v", typ.Elem(), obj, e) codegenType(fmt.Sprintf("%s[key]", path), typ.Elem(), obj, e)
if !e.SizeOnly { if !e.SizeOnly {
e.emit("data = data[%v:]", e.n) // XXX wrt map of map? e.emit("data = data[%v:]", e.n) // XXX wrt map of map?
} else { } else {
e.emit("_ = key") // FIXME remove e.emit("_ = key") // FIXME remove
e.emit("_ = v") // FIXME remove
e.emit("size += %v", e.n) e.emit("size += %v", e.n)
} }
e.emit("}") e.emit("}")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment