X-Git-Url: https://git.octo.it/?p=otsdb-go.git;a=blobdiff_plain;f=ots_timeseries.go;fp=ots_timeseries.go;h=fd22468f2e6a4fb82ae0aae9de681efee5f44d32;hp=efa8931f268198ec2efba20f8c39edd00139ad6b;hb=977787ef46f4aa56ab39b331ecd0969decd701df;hpb=c440adb8c05c78b612296b8f08f0ef7b727eb5e7 diff --git a/ots_timeseries.go b/ots_timeseries.go index efa8931..fd22468 100644 --- a/ots_timeseries.go +++ b/ots_timeseries.go @@ -16,6 +16,11 @@ type OTS_TimeSeries struct { DataPoints []OTS_DataPoint } +func timestampToInterval (a float64, b float64) float64 { + tmp := int (a / b) + return b * float64 (tmp) +} + /* Functions for the sort interface. */ func (obj *OTS_TimeSeries) Len () int { return (len (obj.DataPoints)) @@ -29,14 +34,7 @@ func (obj *OTS_TimeSeries) Less (i, j int) bool { } func (obj *OTS_TimeSeries) Swap (i, j int) { - tmp := obj.DataPoints[i] - obj.DataPoints[i] = obj.DataPoints[j] - obj.DataPoints[j] = tmp -} - -func Fmod64 (a float64, b float64) float64 { - tmp := int (a / b) - return b * float64 (tmp) + obj.DataPoints[i], obj.DataPoints[j] = obj.DataPoints[j], obj.DataPoints[i] } func (obj *OTS_TimeSeries) Write (name string) os.Error { @@ -56,6 +54,45 @@ func (obj *OTS_TimeSeries) Write (name string) os.Error { return nil } +func (obj *OTS_TimeSeries) AddDataPoint (timestamp, rate float64) int { + if math.IsNaN (timestamp) || (timestamp < 0.0) { + return -1 + } + + /* Handle the usual case first. */ + if (timestamp > obj.TimestampLast ()) || (obj.DataPoints == nil) { + obj.DataPoints = append (obj.DataPoints, OTS_DataPoint{timestamp, rate}) + return 0 + } + + /* Find the first index where the timestamp is greater than or equal to the + * new timestamp. This is an O(log n) operation. */ + index := sort.Search (len (obj.DataPoints), func (i int) bool { + if obj.DataPoints[i].TimeStamp >= timestamp { + return true + } + return false + }) + + /* Check for a duplicate time. */ + if obj.DataPoints[index].TimeStamp == timestamp { + obj.DataPoints[index].Rate = rate + return 0 + } + + /* Insert the new datapoint at "index". Currently, this is a O(n) operation. + * First, add the new datapoint at the end. */ + obj.DataPoints = append (obj.DataPoints, OTS_DataPoint{timestamp, rate}) + /* Now move the datapoint to the position "index". */ + for i := len (obj.DataPoints) - 2; i >= index; i-- { + /* TODO: Is there a faster way to manipulate arrays in Go than to move + * elements in bubblesort fashion? */ + obj.Swap (i, i + 1) + } + + return 0 +} + func ReadFile (name string) (obj *OTS_TimeSeries, err os.Error) { fd, err := os.Open (name) if err != nil { @@ -65,7 +102,7 @@ func ReadFile (name string) (obj *OTS_TimeSeries, err os.Error) { /* dp_list := make ([]OTS_DataPoint, intervals_num */ obj = new (OTS_TimeSeries) - for ;; { + for { var timestamp float64 var rate float64 @@ -78,7 +115,7 @@ func ReadFile (name string) (obj *OTS_TimeSeries, err os.Error) { fmt.Printf ("timestamp = %.3f; rate = %g;\n", timestamp, rate) - obj.DataPoints = append (obj.DataPoints, OTS_DataPoint{timestamp, rate}) + obj.AddDataPoint (timestamp, rate) } fd.Close () @@ -157,6 +194,20 @@ func (obj *OTS_TimeSeries) ConsolidatePointAverage (ts_start, ts_end float64) OT return dp } /* ConsolidatePointAverage */ +func (obj *OTS_TimeSeries) TimestampFirst () float64 { + if obj.DataPoints == nil { + return math.NaN () + } + return obj.DataPoints[0].TimeStamp +} + +func (obj *OTS_TimeSeries) TimestampLast () float64 { + if obj.DataPoints == nil { + return math.NaN () + } + return obj.DataPoints[len (obj.DataPoints) - 1].TimeStamp +} + func (obj *OTS_TimeSeries) ConsolidateAverage (interval float64) *OTS_TimeSeries { if interval <= 0.0 { return nil @@ -169,8 +220,8 @@ func (obj *OTS_TimeSeries) ConsolidateAverage (interval float64) *OTS_TimeSeries ts_raw_first, ts_raw_last) /* Determine the timespan the consolidated data will span. */ - ts_csl_first := Fmod64 (ts_raw_first, interval) - ts_csl_last := Fmod64 (ts_raw_last, interval) + ts_csl_first := timestampToInterval (ts_raw_first, interval) + ts_csl_last := timestampToInterval (ts_raw_last, interval) if ts_csl_first < ts_raw_first { ts_csl_first += interval }