mirror of
https://github.com/ClusterCockpit/cc-metric-store.git
synced 2024-12-28 09:39:05 +01:00
Fix bug when reading past newest buffer
This commit is contained in:
parent
38d605b6c4
commit
0219c48e78
35
memstore.go
35
memstore.go
@ -82,12 +82,22 @@ func (b *buffer) write(ts int64, value Float) (*buffer, error) {
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return all known values from `from` to `to`. Gaps of information are
|
func (b *buffer) end() int64 {
|
||||||
// represented by NaN. If values at the start or end are missing,
|
return b.start + int64(len(b.data))*b.frequency
|
||||||
// instead of NaN values, the second and thrid return values contain
|
}
|
||||||
// the actual `from`/`to`.
|
|
||||||
// This function goes back the buffer chain if `from` is older than the
|
// func interpolate(idx int, data []Float) Float {
|
||||||
// currents buffer start.
|
// if idx == 0 || idx+1 == len(data) {
|
||||||
|
// return NaN
|
||||||
|
// }
|
||||||
|
// return (data[idx-1] + data[idx+1]) / 2.0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Return all known values from `from` to `to`. Gaps of information are represented as NaN.
|
||||||
|
// Simple linear interpolation is done between the two neighboring cells if possible.
|
||||||
|
// If values at the start or end are missing, instead of NaN values, the second and thrid
|
||||||
|
// return values contain the actual `from`/`to`.
|
||||||
|
// This function goes back the buffer chain if `from` is older than the currents buffer start.
|
||||||
// The loaded values are added to `data` and `data` is returned, possibly with a shorter length.
|
// The loaded values are added to `data` and `data` is returned, possibly with a shorter length.
|
||||||
// If `data` is not long enough to hold all values, this function will panic!
|
// If `data` is not long enough to hold all values, this function will panic!
|
||||||
func (b *buffer) read(from, to int64, data []Float) ([]Float, int64, int64, error) {
|
func (b *buffer) read(from, to int64, data []Float) ([]Float, int64, int64, error) {
|
||||||
@ -103,10 +113,10 @@ func (b *buffer) read(from, to int64, data []Float) ([]Float, int64, int64, erro
|
|||||||
for ; t < to; t += b.frequency {
|
for ; t < to; t += b.frequency {
|
||||||
idx := int((t - b.start) / b.frequency)
|
idx := int((t - b.start) / b.frequency)
|
||||||
if idx >= cap(b.data) {
|
if idx >= cap(b.data) {
|
||||||
b = b.next
|
if b.next == nil {
|
||||||
if b == nil {
|
break
|
||||||
return data, from, t, nil
|
|
||||||
}
|
}
|
||||||
|
b = b.next
|
||||||
idx = 0
|
idx = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +127,8 @@ func (b *buffer) read(from, to int64, data []Float) ([]Float, int64, int64, erro
|
|||||||
data[i] += NaN
|
data[i] += NaN
|
||||||
} else if t < b.start {
|
} else if t < b.start {
|
||||||
data[i] += NaN
|
data[i] += NaN
|
||||||
|
// } else if b.data[idx].IsNaN() {
|
||||||
|
// data[i] += interpolate(idx, b.data)
|
||||||
} else {
|
} else {
|
||||||
data[i] += b.data[idx]
|
data[i] += b.data[idx]
|
||||||
}
|
}
|
||||||
@ -129,7 +141,7 @@ func (b *buffer) read(from, to int64, data []Float) ([]Float, int64, int64, erro
|
|||||||
// Free up and free all buffers in the chain only containing data
|
// Free up and free all buffers in the chain only containing data
|
||||||
// older than `t`.
|
// older than `t`.
|
||||||
func (b *buffer) free(t int64) (int, error) {
|
func (b *buffer) free(t int64) (int, error) {
|
||||||
end := b.start + int64(len(b.data))*b.frequency
|
end := b.end()
|
||||||
if end < t && b.next != nil {
|
if end < t && b.next != nil {
|
||||||
b.next.prev = nil
|
b.next.prev = nil
|
||||||
n := 0
|
n := 0
|
||||||
@ -167,8 +179,7 @@ func (b *buffer) iterFromTo(from, to int64, callback func(b *buffer) error) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
end := b.start + int64(len(b.data))*b.frequency
|
if from <= b.end() && b.start <= to {
|
||||||
if from <= end && b.start <= to {
|
|
||||||
return callback(b)
|
return callback(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,18 @@ func TestMemoryStoreOutOfBounds(t *testing.T) {
|
|||||||
t.Fatalf("Wrong data (got: %d, %f, %f, expected: %d, %f, %f)",
|
t.Fatalf("Wrong data (got: %d, %f, %f, expected: %d, %f, %f)",
|
||||||
len(data), data[0], data[len(data)-1], count, 0., Float(count-1))
|
len(data), data[0], data[len(data)-1], count, 0., Float(count-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testfrom, testlen := int64(100000000), int64(10000)
|
||||||
|
data, from, to, err = store.Read(sel, "a", testfrom, testfrom+testlen)
|
||||||
|
if len(data) != 0 || from != testfrom || to != testfrom || err != nil {
|
||||||
|
t.Fatal("Unexpected data returned when reading range after valid data")
|
||||||
|
}
|
||||||
|
|
||||||
|
testfrom, testlen = 0, 10
|
||||||
|
data, from, to, err = store.Read(sel, "a", testfrom, testfrom+testlen)
|
||||||
|
if len(data) != 0 || from != int64(toffset) || to != int64(toffset) || err != nil {
|
||||||
|
t.Fatal("Unexpected data returned when reading range before valid data")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMemoryStoreMissingDatapoints(t *testing.T) {
|
func TestMemoryStoreMissingDatapoints(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user