From 036f7ab20b7bdcddcdbac4071e359602b1a0728f Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 28 Jan 2020 08:58:49 -0500 Subject: wip xml --- rrdformat/format.go | 29 ++++++++------- rrdformat/marshal_xml.go | 84 ++++++++++++++++++++++++++++++++++++++++--- rrdformat/rrdbinary/types.go | 10 ++++++ rrdformat/unmarshal_binary.go | 11 ++++-- 4 files changed, 111 insertions(+), 23 deletions(-) diff --git a/rrdformat/format.go b/rrdformat/format.go index 91e5669..a2d95af 100644 --- a/rrdformat/format.go +++ b/rrdformat/format.go @@ -39,9 +39,7 @@ import ( // // - "0001" (the original in rrdtool 1.0.0, 1999-07-15) -const XMLNS = "https://oss.oetiker.ch/rrdtool/rrdtool-dump.xml" - -type RRDValue = rrdbinary.Float +type Value = rrdbinary.Float type Header struct { Cookie rrdbinary.String `rrdbinary:"size=4" xml:"-"` @@ -60,10 +58,11 @@ type DSDef struct { } type RRADef struct { - CFName rrdbinary.String `rrdbinary:"size=20"` - RowCnt rrdbinary.Uint - PDPCnt rrdbinary.Uint - Paameters [10]rrdbinary.Unival + CFName rrdbinary.String `rrdbinary:"size=20"` + RowCnt rrdbinary.Uint + PDPCnt rrdbinary.Uint + Parameters [10]rrdbinary.Unival + Values []Value `rrdbinary:"-"` } type TimeWithUsec struct { @@ -104,10 +103,10 @@ type RRDv0003 struct { DSDefs []DSDef // .Header.DSCnt RRADefs []RRADef // .Header.RRACnt LastUpdated TimeWithUsec - PDPPreps []PDPPrep // .Header.DSCnt - CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt - RRAPtrs []RRAPtr // .Header.RRACnt - Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DSCnt + PDPPreps []PDPPrep // .Header.DSCnt + CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt + RRAPtrs []RRAPtr // .Header.RRACnt + Values []Value // Σ .RRADefs[i].RowCnt*.Header.DSCnt } type RRDv0002 = RRDv0001 @@ -117,8 +116,8 @@ type RRDv0001 struct { DSDefs []DSDef // .Header.DSCnt RRADefs []RRADef // .Header.RRACnt LastUpdated TimeWithoutUsec - PDPPreps []PDPPrep // .Header.DSCnt - CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt - RRAPtrs []RRAPtr // .Header.RRACnt - Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DSCnt + PDPPreps []PDPPrep // .Header.DSCnt + CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt + RRAPtrs []RRAPtr // .Header.RRACnt + Values []Value // Σ .RRADefs[i].RowCnt*.Header.DSCnt } diff --git a/rrdformat/marshal_xml.go b/rrdformat/marshal_xml.go index dfb0556..7263810 100644 --- a/rrdformat/marshal_xml.go +++ b/rrdformat/marshal_xml.go @@ -1,19 +1,93 @@ package rrdformat import ( + "strconv" "encoding/xml" ) -func (h *Header) MarshalXML(e *xml.Encoder, start xml.StartElement) error { - if err := e.EncodeElement(h.Version, xml.StartElement{Name: xml.Name{Local: "version", Space: XMLNS}}); err != nil { +//const XMLNS = "https://oss.oetiker.ch/rrdtool/rrdtool-dump.xml" + +func (rrd RRD) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return e.Encode(rrd.Data) +} + +func xmlStart(name string) xml.StartElement { + return xml.StartElement{ + Name: xml.Name{ + Local: name, + }, + } +} + +func (rrd RRDv0005) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + if err := e.EncodeToken(xml.Comment(" Round Robin Database Dump ")); err != nil { + return err + } + if err := e.EncodeToken(xml.CharData("\n")); err != nil { + return err + } + if err := e.EncodeToken(start); err != nil { + return err + } + + // 1. Header + if err := e.Encode(rrd.Header); err != nil { + return err + } + // 2 + if err := e.Encode(rrd.LastUpdated); err != nil { return err } - if err := e.EncodeElement(h.PDPStep, xml.StartElement{Name: xml.Name{Local: "step", Space: XMLNS}}); err != nil { + if err := e.EncodeToken(xml.CharData("\n")); err != nil { + return err + } + for _, ds := range rrd.DSDefs { + if err := e.Encode(ds); err != nil { + return err + } + } + + if err := e.EncodeToken(start.End()); err != nil { return err } return nil } -var _ xml.Marshaler = &Header{} +func (t TimeWithUsec) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + return TimeWithoutUsec{Sec: t.Sec}.MarshalXML(e, start) +} -//var _ xml.Unmarshaler = &Header{} +func (t TimeWithoutUsec) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + if err := e.EncodeToken(start); err != nil { + return err + } + if err := e.EncodeToken(xml.CharData(strconv.FormatInt(int64(t.Sec), 10))); err != nil { + return err + } + if err := e.EncodeToken(start.End()); err != nil { + return err + } + if err := e.EncodeToken(xml.CharData(" ")); err != nil { + return err + } + if err := e.EncodeToken(xml.Comment(t.Time().Format(" 2006-01-02 15:04:05 MST "))); err != nil { + return err + } + return nil +} + +func (h Header) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + if err := e.EncodeElement(h.Version, xmlStart("version")); err != nil { + return err + } + if err := e.EncodeElement(h.PDPStep, xmlStart("step")); err != nil { + return err + } + if err := e.EncodeToken(xml.CharData(" ")); err != nil { + return err + } + if err := e.EncodeToken(xml.Comment(" Seconds ")); err != nil { + return err + } + return nil +} diff --git a/rrdformat/rrdbinary/types.go b/rrdformat/rrdbinary/types.go index 0bf4913..a6fa881 100644 --- a/rrdformat/rrdbinary/types.go +++ b/rrdformat/rrdbinary/types.go @@ -2,6 +2,7 @@ package rrdbinary import ( "encoding/binary" + "encoding/json" "math" ) @@ -32,6 +33,15 @@ type EOF struct{} // 0 bytes func (u Unival) AsUint64() uint64 { return uint64(u) } func (u Unival) AsFloat64() float64 { return math.Float64frombits(uint64(u)) } +// MarshalJSON is for my own debugging. +func (f Float) MarshalJSON() ([]byte, error) { + raw := float64(f) + if math.IsNaN(raw) { + return json.Marshal("NaN") + } + return json.Marshal(raw) +} + // Statically assert that each of the above types implements the // 'unmarshaler' interface. var _ unmarshaler = func() *String { return nil }() diff --git a/rrdformat/unmarshal_binary.go b/rrdformat/unmarshal_binary.go index 923ccb1..bd4c005 100644 --- a/rrdformat/unmarshal_binary.go +++ b/rrdformat/unmarshal_binary.go @@ -8,8 +8,8 @@ import ( ) type RRD struct { - Architecture rrdbinary.Architecture - Data RRDv0005 + Architecture rrdbinary.Architecture `xml:"-"` + Data RRDv0005 `xml:",innerxml"` } func (rrd *RRD) UnmarshalBinary(data []byte) error { @@ -42,7 +42,12 @@ func (rrd *RRD) UnmarshalBinary(data []byte) error { for i := range parsed.RRADefs { val_cnt += int(parsed.RRADefs[i].RowCnt * parsed.Header.DSCnt) } - parsed.Values = make([]RRDValue, val_cnt) + vals := make([]Value, val_cnt) + parsed.Values = vals + for i := range parsed.RRADefs { + parsed.RRADefs[i].Values = vals[:parsed.RRADefs[i].RowCnt*parsed.Header.DSCnt] + vals = vals[parsed.RRADefs[i].RowCnt*parsed.Header.DSCnt:] + } // resume decoding var lastUpdatedPtr interface{} switch parsed.Header.Version { -- cgit v1.2.3