summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rrdformat/format.go47
-rw-r--r--rrdformat/marshal_xml.go19
-rw-r--r--rrdformat/rrdbinary/types.go1
-rw-r--r--rrdformat/rrdbinary/unmarshal.go21
-rw-r--r--rrdformat/unmarshal_binary.go67
5 files changed, 120 insertions, 35 deletions
diff --git a/rrdformat/format.go b/rrdformat/format.go
index 8898ffd..f9b8504 100644
--- a/rrdformat/format.go
+++ b/rrdformat/format.go
@@ -1,9 +1,6 @@
package rrdformat
import (
- //"encoding"
- "encoding/xml"
-
"git.lukeshu.com/go/librrd/rrdformat/rrdbinary"
)
@@ -66,11 +63,16 @@ type RRADef struct {
PDPCnt rrdbinary.Uint
}
-type Time struct {
+type TimeWithUsec struct {
Sec rrdbinary.Time
Usec rrdbinary.Int // signed, but always >= 0
}
+type TimeWithoutUsec struct {
+ Sec rrdbinary.Time
+ Usec rrdbinary.Int `rrdbinary:"-"`
+}
+
type PDPPrep struct {
LastDS rrdbinary.String `rrdbinary:"size=30"`
Scratch [10]rrdbinary.Unival
@@ -91,11 +93,11 @@ type RRDv0003 struct {
Header Header
DSDefs []DSDef // .Header.DSCnt
RRADefs []RRADef // .Header.RRACnt
- LastUpdated Time
- PDPPrep []PDPPrep // .Header.DSCnt
- CDPPrep []CDPPrep // .Header.DSCnt * .Header.RRACnt
- RRAPtr []RRAPtr // .Header.RRACnt
- Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DsCnt
+ LastUpdated TimeWithUsec
+ PDPPreps []PDPPrep // .Header.DSCnt
+ CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt
+ RRAPtrs []RRAPtr // .Header.RRACnt
+ Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DSCnt
}
type RRDv0002 = RRDv0001
@@ -104,26 +106,9 @@ type RRDv0001 struct {
Header Header
DSDefs []DSDef // .Header.DSCnt
RRADefs []RRADef // .Header.RRACnt
- LastUpdated rrdbinary.Time
- PDPPrep []PDPPrep // .Header.DSCnt
- CDPPrep []CDPPrep // .Header.DSCnt * .Header.RRACnt
- RRAPtr []RRAPtr // .Header.RRACnt
- Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DsCnt
+ LastUpdated TimeWithoutUsec
+ PDPPreps []PDPPrep // .Header.DSCnt
+ CDPPreps []CDPPrep // .Header.DSCnt * .Header.RRACnt
+ RRAPtrs []RRAPtr // .Header.RRACnt
+ Values []RRDValue // Σ .RRADefs[i].RowCnt*.Header.DSCnt
}
-
-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 {
- return err
- }
- if err := e.EncodeElement(h.PDPStep, xml.StartElement{Name: xml.Name{Local: "step", Space: XMLNS}}); err != nil {
- return err
- }
- return nil
-}
-
-//var _ encoding.BinaryMarshaler = &Header{}
-//var _ encoding.BinaryUnmarshaler = &Header{}
-
-var _ xml.Marshaler = &Header{}
-
-//var _ xml.Unmarshaler = &Header{}
diff --git a/rrdformat/marshal_xml.go b/rrdformat/marshal_xml.go
new file mode 100644
index 0000000..dfb0556
--- /dev/null
+++ b/rrdformat/marshal_xml.go
@@ -0,0 +1,19 @@
+package rrdformat
+
+import (
+ "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 {
+ return err
+ }
+ if err := e.EncodeElement(h.PDPStep, xml.StartElement{Name: xml.Name{Local: "step", Space: XMLNS}}); err != nil {
+ return err
+ }
+ return nil
+}
+
+var _ xml.Marshaler = &Header{}
+
+//var _ xml.Unmarshaler = &Header{}
diff --git a/rrdformat/rrdbinary/types.go b/rrdformat/rrdbinary/types.go
index a036d5d..006af3c 100644
--- a/rrdformat/rrdbinary/types.go
+++ b/rrdformat/rrdbinary/types.go
@@ -27,6 +27,7 @@ type Uint uint64 // 4 or 8 bytes
type Int int64 // 4 or 8 bytes
type Unival uint64 // 8 bytes
type Time int64 // 4 or 8 bytes, only has second-precision
+type EOF struct{} // 0 bytes
func (u Unival) AsUint64() uint64 { return uint64(u) }
func (u Unival) AsFloat64() float64 { return math.Float64frombits(uint64(u)) }
diff --git a/rrdformat/rrdbinary/unmarshal.go b/rrdformat/rrdbinary/unmarshal.go
index 1cfee34..142ee9f 100644
--- a/rrdformat/rrdbinary/unmarshal.go
+++ b/rrdformat/rrdbinary/unmarshal.go
@@ -50,12 +50,14 @@ func (d *unmarshaler) unmarshal(v reflect.Value, tag string) error {
return d.unmarshalUnival(v, tag)
case reflect.TypeOf(Time(0)):
return d.unmarshalTime(v, tag)
+ case reflect.TypeOf(EOF{}):
+ return d.unmarshalEOF(v, tag)
default:
switch v.Type().Kind() {
case reflect.Struct:
return d.unmarshalStruct(v, tag)
- case reflect.Array:
- return d.unmarshalArray(v, tag)
+ case reflect.Array, reflect.Slice:
+ return d.unmarshalList(v, tag)
default:
return typeErrorf("invalid type for rrdbinary.Unmarshal: %v", v.Type())
}
@@ -83,8 +85,8 @@ func (d *unmarshaler) unmarshalStruct(v reflect.Value, tag string) error {
return nil
}
-func (d *unmarshaler) unmarshalArray(v reflect.Value, tag string) error {
- panicUnless(v.Kind() == reflect.Array)
+func (d *unmarshaler) unmarshalList(v reflect.Value, tag string) error {
+ panicUnless(v.Kind() == reflect.Array || v.Kind() == reflect.Slice)
panicUnless(v.CanSet())
for i := 0; i < v.Len(); i++ {
@@ -314,3 +316,14 @@ func (d *unmarshaler) unmarshalTime(v reflect.Value, tag string) error {
d.pos += padding + d.arch.TimeWidth
return nil
}
+
+func (d *unmarshaler) unmarshalEOF(v reflect.Value, tag string) error {
+ panicUnless(v.Type() == reflect.TypeOf(EOF{}))
+
+ data := d.data[d.pos:]
+ if len(data) > 0 {
+ return d.binErrorf(16, "extra %d bytes of data after expected end-of-file", len(data))
+ }
+
+ return nil
+}
diff --git a/rrdformat/unmarshal_binary.go b/rrdformat/unmarshal_binary.go
new file mode 100644
index 0000000..b9bafde
--- /dev/null
+++ b/rrdformat/unmarshal_binary.go
@@ -0,0 +1,67 @@
+package rrdformat
+
+import (
+ "encoding"
+
+ "git.lukeshu.com/go/librrd/rrdformat/rrdbinary"
+)
+
+type RRD struct {
+ Architecture rrdbinary.Architecture
+ Data RRDv0005
+}
+
+func (rrd *RRD) UnmarshalBinary(data []byte) error {
+ arch, err := SniffArchitecture(data)
+ if err != nil {
+ return err
+ }
+ var header Header
+ if err := rrdbinary.Unmarshal(arch, data, &header); err != nil {
+ return err
+ }
+
+ 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 {
+ case "0001", "0002":
+ _parsed := &RRDv0001{} //(*RRDv0001)(&parsed)
+ if err := rrdbinary.Unmarshal(arch, data, _parsed); err != nil {
+ return err
+ }
+ case "0003", "0004", "0005":
+ if err := rrdbinary.Unmarshal(arch, data, &parsed); err != nil {
+ return err
+ }
+ default:
+ // 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)
+ }
+ parsed.Values = make([]RRDValue, val_cnt)
+ if err := rrdbinary.Unmarshal(arch, data, &parsed.Values); err != nil {
+ return err
+ }
+
+ *rrd = RRD{
+ Architecture: arch,
+ Data: parsed,
+ }
+ return nil
+}
+
+//var _ encoding.BinaryMarshaler = &RRD{}
+var _ encoding.BinaryUnmarshaler = &RRD{}