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
import (
"encoding/binary"
"sort"
)
// 0. Address
......@@ -1026,9 +1027,8 @@ func (p *AnswerLockedTransactions) NEOEncodedLen() int {
l := uint32(len(p.TidDict))
_ = l
size += 4
for key, v := range p.TidDict {
for key := range p.TidDict {
_ = key
_ = v
size += 16
}
}
......@@ -1040,9 +1040,14 @@ func (p *AnswerLockedTransactions) NEOEncode(data []byte) {
l := uint32(len(p.TidDict))
binary.BigEndian.PutUint32(data[0:], l)
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[8:], uint64(v))
binary.BigEndian.PutUint64(data[8:], uint64(p.TidDict[key]))
data = data[16:]
}
}
......@@ -2833,9 +2838,8 @@ func (p *AnswerObjectUndoSerial) NEOEncodedLen() int {
l := uint32(len(p.ObjectTIDDict))
_ = l
size += 4
for key, v := range p.ObjectTIDDict {
for key := range p.ObjectTIDDict {
_ = key
_ = v
size += 25
}
}
......@@ -2847,11 +2851,16 @@ func (p *AnswerObjectUndoSerial) NEOEncode(data []byte) {
l := uint32(len(p.ObjectTIDDict))
binary.BigEndian.PutUint32(data[0:], l)
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[8:], uint64(v.CurrentSerial))
binary.BigEndian.PutUint64(data[16:], uint64(v.UndoSerial))
(data[24:])[0] = bool2byte(v.IsCurrent)
binary.BigEndian.PutUint64(data[8:], uint64(p.ObjectTIDDict[key].CurrentSerial))
binary.BigEndian.PutUint64(data[16:], uint64(p.ObjectTIDDict[key].UndoSerial))
(data[24:])[0] = bool2byte(p.ObjectTIDDict[key].IsCurrent)
data = data[25:]
}
}
......@@ -3037,9 +3046,8 @@ func (p *CheckReplicas) NEOEncodedLen() int {
l := uint32(len(p.PartitionDict))
_ = l
size += 4
for key, v := range p.PartitionDict {
for key := range p.PartitionDict {
_ = key
_ = v
size += 8
}
}
......@@ -3051,9 +3059,14 @@ func (p *CheckReplicas) NEOEncode(data []byte) {
l := uint32(len(p.PartitionDict))
binary.BigEndian.PutUint32(data[0:], l)
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[4:], uint32(int32(v)))
binary.BigEndian.PutUint32(data[4:], uint32(int32(p.PartitionDict[key])))
data = data[8:]
}
}
......
......@@ -167,7 +167,6 @@ func TestPktMarshal(t *testing.T) {
hex("00000007000000030000000b000000040000000f000000030000001700000000"),
},
/*
// map[Oid]struct {Tid,Tid,bool}
{&AnswerObjectUndoSerial{
ObjectTIDDict: map[Oid]struct{
......@@ -184,10 +183,9 @@ func TestPktMarshal(t *testing.T) {
u32(4) +
u64(1) + u64(1) + u64(0) + hex("00") +
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
{&PartitionCorrupted{7, []UUID{1,3,9,4}},
......
......@@ -86,6 +86,7 @@ func main() {
package neo
import (
"encoding/binary"
"sort"
)
`)
......@@ -376,14 +377,24 @@ func (e *encoder) genMap(path string, typ *types.Map, obj types.Object) {
}
e.n = 0
// 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("v", typ.Elem(), obj, e)
codegenType(fmt.Sprintf("%s[key]", path), typ.Elem(), obj, e)
if !e.SizeOnly {
e.emit("data = data[%v:]", e.n) // XXX wrt map of map?
} else {
e.emit("_ = key") // FIXME remove
e.emit("_ = v") // FIXME remove
e.emit("size += %v", e.n)
}
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