96 lines
1.9 KiB
Go
96 lines
1.9 KiB
Go
package shroom_internals
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
const MAX_CACHE_POINTS = 1000
|
|
|
|
type DataCache struct {
|
|
sync.RWMutex
|
|
data []Datapoint
|
|
start int
|
|
}
|
|
|
|
func (dc *DataCache) LatestTime() int64 {
|
|
dc.Lock()
|
|
defer dc.Unlock()
|
|
|
|
if len(dc.data) == 0 {
|
|
return -1
|
|
}
|
|
if dc.start == 0 {
|
|
return int64(dc.data[len(dc.data)-1].Time)
|
|
} else {
|
|
return int64(dc.data[dc.start-1].Time)
|
|
}
|
|
}
|
|
|
|
func (dc *DataCache) Add(data *Datapoint) {
|
|
dc.Lock()
|
|
defer dc.Unlock()
|
|
|
|
if len(dc.data) < MAX_CACHE_POINTS {
|
|
dc.data = append(dc.data, *data)
|
|
} else {
|
|
dc.data[dc.start] = *data
|
|
dc.start += 1
|
|
if dc.start >= len(dc.data) {
|
|
dc.start = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
func (dc *DataCache) binarySearch(s int, e int, target uint64) int {
|
|
for s < e {
|
|
mid := (s + e) / 2
|
|
if dc.data[mid].Time < target {
|
|
s = mid + 1
|
|
} else {
|
|
e = mid
|
|
}
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (dc *DataCache) ReadSince(start_time uint64) []Datapoint {
|
|
dc.RLock()
|
|
defer dc.RUnlock()
|
|
|
|
if len(dc.data) == 0 {
|
|
return nil
|
|
}
|
|
if dc.data[dc.start].Time <= start_time {
|
|
// binary search for the point right at/after
|
|
// start_time
|
|
|
|
if len(dc.data) >= MAX_CACHE_POINTS {
|
|
// if the data is full length we've been wrapping
|
|
// around
|
|
if dc.data[0].Time <= start_time {
|
|
// it's between [0, start)
|
|
idx := dc.binarySearch(0, dc.start, start_time)
|
|
ret := []Datapoint{}
|
|
ret = append(ret, dc.data[idx:dc.start]...)
|
|
return ret
|
|
} else {
|
|
// it's between [start, len(dc.data))
|
|
// and we can always include [0, start) afterwards
|
|
idx := dc.binarySearch(dc.start, len(dc.data), start_time)
|
|
ret := []Datapoint{}
|
|
ret = append(ret, dc.data[idx:len(dc.data)]...)
|
|
ret = append(ret, dc.data[0:dc.start]...)
|
|
return ret
|
|
}
|
|
} else {
|
|
// it's between [0, len(dc.data))
|
|
idx := dc.binarySearch(0, len(dc.data), start_time)
|
|
ret := []Datapoint{}
|
|
ret = append(ret, dc.data[idx:len(dc.data)]...)
|
|
return ret
|
|
}
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|