Commit 1aaf1a02 authored by Geoff Simmons's avatar Geoff Simmons

Refactor log record parsing to work with no allocations.

parent 95054cbe
......@@ -43,25 +43,74 @@ import (
type existence struct{}
var (
exister = struct{}{}
spaceByte = []byte(" ")
str2type = map[string]TxType{
"sess": Sess,
"req": Req,
"bereq": BeReq,
}
str2reason = map[string]Reason{
"HTTP/1": HTTP1,
"rxreq": RxReq,
"esi": ESI,
"restart": Restart,
"pass": Pass,
"fetch": Fetch,
"bgfetch": BgFetch,
"pipe": Pipe,
}
exister = struct{}{}
sessBytes = []byte("ess")
reqBytes = []byte("eq")
bereqBytes = []byte("ereq")
http1Bytes = []byte("TTP/1")
rxreqBytes = []byte("xreq")
esiBytes = []byte("si")
restartBytes = []byte("estart")
passBytes = []byte("ass")
fetchBytes = []byte("etch")
bgFetchBytes = []byte("gfetch")
pipeBytes = []byte("ipe")
)
func bytes2Type(b []byte) (TxType, bool) {
switch b[0] {
case byte('s'):
if bytes.Equal(b[1:], sessBytes) {
return Sess, true
}
case byte('r'):
if bytes.Equal(b[1:], reqBytes) {
return Req, true
}
case byte('b'):
if bytes.Equal(b[1:], bereqBytes) {
return BeReq, true
}
}
return TxUnknown, false
}
func bytes2Reason(b []byte) (Reason, bool) {
switch b[0] {
case byte('H'):
if bytes.Equal(b[1:], http1Bytes) {
return HTTP1, true
}
case byte('r'):
if bytes.Equal(b[1:], rxreqBytes) {
return RxReq, true
}
if bytes.Equal(b[1:], restartBytes) {
return Restart, true
}
case byte('e'):
if bytes.Equal(b[1:], esiBytes) {
return ESI, true
}
case byte('p'):
if bytes.Equal(b[1:], passBytes) {
return Pass, true
}
if bytes.Equal(b[1:], pipeBytes) {
return Pipe, true
}
case byte('f'):
if bytes.Equal(b[1:], fetchBytes) {
return Fetch, true
}
case byte('b'):
if bytes.Equal(b[1:], bgFetchBytes) {
return BgFetch, true
}
}
return ReasonUnknown, false
}
type grpNode struct {
children []uint32
vxid uint32
......@@ -137,33 +186,43 @@ func (c *Cursor) NewQuery(grp Grouping, query string) (*Query, error) {
// Parses a Begin or Link record for the purposes of grouping
func (q *Query) parseRec(payload Payload) (TxType, uint32, Reason, error) {
flds := bytes.Split(payload, spaceByte)
if len(flds) != 3 {
// XXX
min, max, ok := fieldNDelims(payload, 0)
if !ok {
// XXX error handling
return TxUnknown, 0, ReasonUnknown, nil
}
txtype, exists := str2type[string(flds[0])]
if !exists {
// XXX
txtype, ok := bytes2Type(payload[min:max])
if !ok {
// XXX error handling
return TxUnknown, 0, ReasonUnknown, nil
}
vxid, ok := atoUint32(flds[1])
min, max, ok = fieldNDelims(payload, 1)
if !ok {
// XXX
// XXX error handling
return txtype, 0, ReasonUnknown, nil
}
reason, exists := str2reason[string(flds[2])]
if !exists {
// XXX
vxid, ok := atoUint32(payload[min:max])
if !ok {
// XXX error handling
return txtype, 0, ReasonUnknown, nil
}
min, max, ok = fieldNDelims(payload, 2)
if !ok {
// XXX error handling
return txtype, vxid, ReasonUnknown, nil
}
reason, ok := bytes2Reason(payload[min:max])
if !ok {
// XXX error handling
return TxUnknown, vxid, ReasonUnknown, nil
}
return txtype, vxid, reason, nil
}
func (q *Query) link(pvxid uint32, vxid uint32) {
child, cexists := q.grpNodes[vxid]
if !cexists {
child = grpNode{ vxid: vxid }
child = grpNode{vxid: vxid}
}
child.pvxid = pvxid
q.grpNodes[vxid] = child
......@@ -172,7 +231,7 @@ func (q *Query) link(pvxid uint32, vxid uint32) {
}
parent, pexists := q.grpNodes[pvxid]
if !pexists {
parent = grpNode{ vxid: pvxid }
parent = grpNode{vxid: pvxid}
}
found := false
for _, xid := range parent.children {
......
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