Final changes to circular buffer
This commit is contained in:
parent
084e809507
commit
86fc57b5ef
@ -15,7 +15,6 @@
|
|||||||
package memory
|
package memory
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ import (
|
|||||||
// containerStorage is used to store per-container information
|
// containerStorage is used to store per-container information
|
||||||
type containerStorage struct {
|
type containerStorage struct {
|
||||||
ref info.ContainerReference
|
ref info.ContainerReference
|
||||||
recentStats *list.List
|
recentStats *StatsBuffer
|
||||||
maxNumStats int
|
maxNumStats int
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
@ -37,46 +36,32 @@ func (self *containerStorage) AddStats(stats *info.ContainerStats) error {
|
|||||||
defer self.lock.Unlock()
|
defer self.lock.Unlock()
|
||||||
|
|
||||||
// Add the stat to storage.
|
// Add the stat to storage.
|
||||||
if self.recentStats.Len() >= self.maxNumStats {
|
self.recentStats.Add(stats)
|
||||||
self.recentStats.Remove(self.recentStats.Back())
|
|
||||||
}
|
|
||||||
self.recentStats.PushFront(stats)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *containerStorage) RecentStats(numStats int) ([]*info.ContainerStats, error) {
|
func (self *containerStorage) RecentStats(numStats int) ([]*info.ContainerStats, error) {
|
||||||
self.lock.RLock()
|
self.lock.RLock()
|
||||||
defer self.lock.RUnlock()
|
defer self.lock.RUnlock()
|
||||||
if self.recentStats.Len() < numStats || numStats < 0 {
|
if self.recentStats.Size() < numStats || numStats < 0 {
|
||||||
numStats = self.recentStats.Len()
|
numStats = self.recentStats.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats in the recentStats list are stored in reverse chronological
|
// Stats in the recentStats list are stored in reverse chronological
|
||||||
// order, i.e. most recent stats is in the front.
|
// order, i.e. most recent stats is in the front.
|
||||||
// numStats will always <= recentStats.Len() so that there will be
|
// numStats will always <= recentStats.Size() so that there will be
|
||||||
// always at least numStats available stats to retrieve. We traverse
|
// always at least numStats available stats to retrieve. We traverse
|
||||||
// the recentStats list from its head and fill the ret slice in
|
// the recentStats list from its head so that the returned slice will be in chronological
|
||||||
// reverse order so that the returned slice will be in chronological
|
|
||||||
// order. The order of the returned slice is not specified by the
|
// order. The order of the returned slice is not specified by the
|
||||||
// StorageDriver interface, so it is not necessary for other storage
|
// StorageDriver interface, so it is not necessary for other storage
|
||||||
// drivers to return the slice in the same order.
|
// drivers to return the slice in the same order.
|
||||||
ret := make([]*info.ContainerStats, numStats)
|
return self.recentStats.FirstN(numStats), nil
|
||||||
e := self.recentStats.Front()
|
|
||||||
for i := numStats - 1; i >= 0; i-- {
|
|
||||||
data, ok := e.Value.(*info.ContainerStats)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("The %vth element is not a ContainerStats", i)
|
|
||||||
}
|
|
||||||
ret[i] = data
|
|
||||||
e = e.Next()
|
|
||||||
}
|
|
||||||
return ret, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContainerStore(ref info.ContainerReference, maxNumStats int) *containerStorage {
|
func newContainerStore(ref info.ContainerReference, maxNumStats int) *containerStorage {
|
||||||
return &containerStorage{
|
return &containerStorage{
|
||||||
ref: ref,
|
ref: ref,
|
||||||
recentStats: list.New(),
|
recentStats: NewStatsBuffer(maxNumStats),
|
||||||
maxNumStats: maxNumStats,
|
maxNumStats: maxNumStats,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ func (self *StatsBuffer) Add(item *info.ContainerStats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the first N elements in the buffer. If N > size of buffer, size of buffer elements are returned.
|
// Returns the first N elements in the buffer. If N > size of buffer, size of buffer elements are returned.
|
||||||
func (self *StatsBuffer) FirstN(n int) []info.ContainerStats {
|
func (self *StatsBuffer) FirstN(n int) []*info.ContainerStats {
|
||||||
// Cap n at the number of elements we have.
|
// Cap n at the number of elements we have.
|
||||||
if n > self.size {
|
if n > self.size {
|
||||||
n = self.size
|
n = self.size
|
||||||
@ -43,10 +43,10 @@ func (self *StatsBuffer) FirstN(n int) []info.ContainerStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy the elements.
|
// Copy the elements.
|
||||||
res := make([]info.ContainerStats, n)
|
res := make([]*info.ContainerStats, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
index := (start + i) % len(self.buffer)
|
index := (start + i) % len(self.buffer)
|
||||||
res[i] = self.buffer[index]
|
res[i] = &self.buffer[index]
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/cadvisor/info"
|
"github.com/google/cadvisor/info"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func createStats(id int32) *info.ContainerStats {
|
func createStats(id int32) *info.ContainerStats {
|
||||||
|
Loading…
Reference in New Issue
Block a user