Commit 3b04d58d authored by Geoff Simmons's avatar Geoff Simmons

Roll our own parser for XIDs from the Begin record.

strconv.Atoi(string([]byte)) causes the temporary string to escape
to the heap. This way we stay with a byte slice that does not escape.
parent cd577f41
......@@ -38,11 +38,39 @@ import "C"
import (
"bytes"
"errors"
"strconv"
)
var spaceByte = []byte(" ")
const (
cutoff = ^uint32(0) / 10
rest = byte(^uint32(0)-cutoff*10) + byte('0')
)
// Calling strconv.Atoi(string([]byte)) causes the string to escape to
// the heap.
func atoUint32(bytes []byte) (uint32, bool) {
if len(bytes) == 0 {
return 0, false
}
val := uint32(0)
for _, b := range bytes {
if val >= cutoff {
if val > cutoff {
return 0, false
}
if b > rest {
return 0, false
}
}
if b < byte('0') || b > byte('9') {
return 0, false
}
val = val*10 + uint32(b-byte('0'))
}
return val, true
}
// A Query provides the means to read aggregated transactions from the
// log. A Query must be created from a Cursor using the NewQuery
// function.
......@@ -147,9 +175,8 @@ func (q *Query) NextTxGroup() ([]Tx, Status) {
if txtype, exists := str2type[typeFromRec]; exists {
tx.Type = txtype
}
vxid := string(begin[1])
if pvxid, err := strconv.Atoi(vxid); err != nil {
tx.ParentVXID = uint32(pvxid)
if pvxid, ok := atoUint32(begin[1]); ok {
tx.ParentVXID = pvxid
}
recReason := string(begin[2])
if reason, exists := str2reason[recReason]; exists {
......
......@@ -30,6 +30,42 @@ package log
import "testing"
type atoUint32Exp struct {
val uint32
ok bool
}
func TestAtoUint32(t *testing.T) {
expMap := map[string]atoUint32Exp{
"": atoUint32Exp{val: 0, ok: false},
"0": atoUint32Exp{val: 0, ok: true},
"1": atoUint32Exp{val: 1, ok: true},
"9": atoUint32Exp{val: 9, ok: true},
"10": atoUint32Exp{val: 10, ok: true},
"101": atoUint32Exp{val: 101, ok: true},
"1009": atoUint32Exp{val: 1009, ok: true},
"foo": atoUint32Exp{val: 0, ok: false},
"4294967290": atoUint32Exp{val: 4294967290, ok: true},
"4294967291": atoUint32Exp{val: 4294967291, ok: true},
"4294967292": atoUint32Exp{val: 4294967292, ok: true},
"4294967293": atoUint32Exp{val: 4294967293, ok: true},
"4294967294": atoUint32Exp{val: 4294967294, ok: true},
"4294967295": atoUint32Exp{val: 4294967295, ok: true},
"4294967296": atoUint32Exp{val: 0, ok: false},
"4294967297": atoUint32Exp{val: 0, ok: false},
"4294967298": atoUint32Exp{val: 0, ok: false},
"4294967299": atoUint32Exp{val: 0, ok: false},
}
for str, exp := range expMap {
val, ok := atoUint32([]byte(str))
if val != exp.val || ok != exp.ok {
t.Errorf("atoUint32(%s) want=%v got=%v", str, exp,
atoUint32Exp{val: val, ok: ok})
}
}
}
func TestNewQuery(t *testing.T) {
l := New()
defer l.Release()
......
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