From a047b135ca416584178a6adde64cc156ab637431 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 27 Jan 2020 19:35:32 -0500 Subject: Have RRD.UnmarshalBinary() avoid parsing things repeatedly --- rrdformat/unmarshal_binary.go | 79 +++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 29 deletions(-) (limited to 'rrdformat/unmarshal_binary.go') diff --git a/rrdformat/unmarshal_binary.go b/rrdformat/unmarshal_binary.go index b9bafde..70c06b7 100644 --- a/rrdformat/unmarshal_binary.go +++ b/rrdformat/unmarshal_binary.go @@ -2,6 +2,7 @@ package rrdformat import ( "encoding" + "fmt" "git.lukeshu.com/go/librrd/rrdformat/rrdbinary" ) @@ -16,44 +17,64 @@ func (rrd *RRD) UnmarshalBinary(data []byte) error { if err != nil { return err } - var header Header - if err := rrdbinary.Unmarshal(arch, data, &header); err != nil { - return err - } + decoder := rrdbinary.NewDecoder(arch, data) var parsed RRDv0005 - parsed.DSDefs = make([]DSDef, header.DSCnt) - parsed.DSDefs = make([]DSDef, header.DSCnt) - parsed.RRADefs = make([]RRADef, header.RRACnt) - //LastUpdated - parsed.PDPPreps = make([]PDPPrep, header.DSCnt) - parsed.CDPPreps = make([]CDPPrep, header.DSCnt*header.RRACnt) - parsed.RRAPtrs = make([]RRAPtr, header.RRACnt) - //Values - switch header.Version { + if err := decoder.Decode(&parsed.Header, ""); err != nil { + return fmt.Errorf("field %s: %w", "Header", err) + } + // allocate memory based on .Header values + parsed.DSDefs = make([]DSDef, parsed.Header.DSCnt) + parsed.DSDefs = make([]DSDef, parsed.Header.DSCnt) + parsed.RRADefs = make([]RRADef, parsed.Header.RRACnt) + parsed.PDPPreps = make([]PDPPrep, parsed.Header.DSCnt) + parsed.CDPPreps = make([]CDPPrep, parsed.Header.DSCnt*parsed.Header.RRACnt) + parsed.RRAPtrs = make([]RRAPtr, parsed.Header.RRACnt) + // resume decoding + if err := decoder.Decode(&parsed.DSDefs, ""); err != nil { + return fmt.Errorf("field %s: %w", "DSDefs", err) + } + if err := decoder.Decode(&parsed.RRADefs, ""); err != nil { + return fmt.Errorf("field %s: %w", "RRADefs", err) + } + // allocate memory based on .RRADefs + val_cnt := 0 + for i := range parsed.RRADefs { + val_cnt += int(parsed.RRADefs[i].RowCnt * parsed.Header.DSCnt) + } + parsed.Values = make([]RRDValue, val_cnt) + // resume decoding + var lastUpdatedPtr interface{} + switch parsed.Header.Version { case "0001", "0002": - _parsed := &RRDv0001{} //(*RRDv0001)(&parsed) - if err := rrdbinary.Unmarshal(arch, data, _parsed); err != nil { - return err - } + lastUpdatedPtr = &parsed.LastUpdated.Sec case "0003", "0004", "0005": - if err := rrdbinary.Unmarshal(arch, data, &parsed); err != nil { - return err - } + lastUpdatedPtr = &parsed.LastUpdated default: - // version number already validated by - // SniffArchitecture + // version number already validated by SniffArchitecture panic("should not happen") } - - val_cnt := 0 - for i := range parsed.RRADefs { - val_cnt += int(parsed.RRADefs[i].RowCnt * header.DSCnt) + if err := decoder.Decode(lastUpdatedPtr, ""); err != nil { + return fmt.Errorf("field %s: %w", "LastUpdated", err) } - parsed.Values = make([]RRDValue, val_cnt) - if err := rrdbinary.Unmarshal(arch, data, &parsed.Values); err != nil { - return err + if err := decoder.Decode(&parsed.LastUpdated, ""); err != nil { + return fmt.Errorf("field %s: %w", "LastUpdated", err) + } + if err := decoder.Decode(&parsed.PDPPreps, ""); err != nil { + return fmt.Errorf("field %s: %w", "PDPPreps", err) + } + if err := decoder.Decode(&parsed.CDPPreps, ""); err != nil { + return fmt.Errorf("field %s: %w", "CDPPreps", err) + } + if err := decoder.Decode(&parsed.RRAPtrs, ""); err != nil { + return fmt.Errorf("field %s: %w", "RRAPtrs", err) + } + if err := decoder.Decode(&parsed.Values, ""); err != nil { + return fmt.Errorf("field %s: %w", "Values", err) + } + if err := decoder.Decode(&rrdbinary.EOF{}, ""); err != nil { + return fmt.Errorf("field %s: %w", "EOF", err) } *rrd = RRD{ -- cgit v1.2.3