Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
wlin committed Oct 18, 2024
2 parents 9309ae7 + b7044f6 commit f94f74d
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 150 deletions.
9 changes: 4 additions & 5 deletions agent/probe/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -2675,12 +2675,11 @@ func (p *Probe) addProcHistory(id string, proc *procInternal, bFromMonitor bool)
p.procHistoryMap[id] = histProc
}

if dbgError := histProc.Write(proc); dbgError != nil {
log.WithFields(log.Fields{"dbgError": dbgError}).Debug()
}
histProc.Write(proc)

// Verification section, test only
// log.WithFields(log.Fields{"path": proc.path, "id": id, "cnt": histProc.Leng()}).Debug("PROC: ")
// if histProc.Leng() == 400 {
// log.WithFields(log.Fields{"path": proc.path, "id": id, "cnt": histProc.Length()}).Debug("PROC: ")
// if histProc.Length()() == 400 {
// var list []*procInternal
// elements := histProc.DumpExt()
// for i := 0; i < len(elements); i++ {
Expand Down
51 changes: 0 additions & 51 deletions agent/probe/ringbuffer/dump.go

This file was deleted.

129 changes: 35 additions & 94 deletions agent/probe/ringbuffer/ringbuffer.go
Original file line number Diff line number Diff line change
@@ -1,113 +1,54 @@
// package ringbuffer implements a sequential compact FIFO and LILO. Also called a Queue.
// To Use:
//
// type myThing ringbuffer.RingElement
// var whatever == myThing("whatever") // Assuming a conversion from string.
// rb := RingBuffer.New(40)
// rb.Write(myThing) // Et cetera
// aThing := rb.Read()
// for 0 < rb.Size() {
// doSomethingWith(rb.Read())
// }
//
// THIS IS NOT CONCURRENT —— ONE GOROUTINE ONLY.
// THIS IS NOT CONCURRENT —— ONE GOROUTINE ONLY.
package ringbuffer

import (
"fmt"
)

// A ring buffer is stored in an array of ringbuffer.RingElement, of the size requested.
type RingElement interface{}

type Element interface{}
type RingBuffer struct {
data []RingElement
in, out int // Place of next in (Write). Place of next out (Read). These are subscripts.
size int // Number of items currenly in the ring buffer.
}

type RingBufferError struct {
What string
}

// "Convert" ringbuffer.RingBufferError into a string.
func (e *RingBufferError) Error() string {
return e.What
}

// /// Inspect the internal state of the ring buffer and complain if not ok. ////
var invNum int // invNum is an error code.

// New() allocates and initializes a new ring buffer of specified size
func New(n int) *RingBuffer {
b := &RingBuffer{data: make([]RingElement, n), // Contents
in: 0, out: 0, size: 0}
return b
}

// next() does a 'wrapping increment' of a subscript to point to the next element.
func (b *RingBuffer) next(subscript int) int {
subscript++
if subscript >= cap(b.data) { // I suspect this is quicker than a modulus calculation.
subscript = 0
data []Element
head int
tail int
size int
}

func New(capacity int) *RingBuffer {
return &RingBuffer{
data: make([]Element, capacity+1), // +1
head: 0,
tail: 0, // empty
size: capacity + 1,
}
return subscript
}

// Write inserts an element into the ring buffer.
func (b *RingBuffer) Write(datum RingElement) error {
if b.size >= cap(b.data) {
//fmt.Printf("!Full b %p, size %d, cap %d\n", b, b.size, cap(b.data))
b.Read() // dump the oldest element
}

b.data[b.in] = datum
b.in = b.next(b.in)
b.size++
if 0 >= b.size {
fmt.Printf("\n\tError: b.size %d, b %p, cap(b.data) %d\n", b.size, b, cap(b.data))
func (r *RingBuffer) Write(value Element) {
r.data[r.tail] = value
r.tail = (r.tail + 1) % r.size
if r.tail == r.head {
r.head = (r.head + 1) % r.size // next
}

return nil
}

// Read fetches the next element from the ring buffer.
func (b *RingBuffer) Read() RingElement {
if 0 >= b.size {
return nil // Nil is our EOF. Could use an error return, too.
//return &RingBufferError{"RingBuffer is empty\n"}
func (r *RingBuffer) Read(i int) Element {
if r.head == r.tail {
return nil // Buffer is empty
}
b.size--
tmp := b.data[b.out]
b.out = b.next(b.out)
return tmp
}

// Number of slots currently in use. Total writes - Total reads.
func (b *RingBuffer) Leng() int {
return b.size
return r.data[(r.head+i)%r.size]
}

// Is the buffer currently full?
func (b *RingBuffer) Full() bool {
if nil == b {
return true // best we can do? Even Possible?
func (r *RingBuffer) Length() int {
if r.tail >= r.head {
return r.tail - r.head
}
return (nil != b.data) &&
(b.size >= cap(b.data))
return r.tail + r.size - r.head
}

// Any left to read?
func (b *RingBuffer) HasAny() bool {
return b.size > 0
func (r *RingBuffer) Clear() {
r.head, r.tail, r.size = 0, 0, 0
clear(r.data)
}

// Obliterate, Purge, and Remove the contents of the ring buffer.
// Support your local Garbage Collector!
func (b *RingBuffer) Clear() {
b.in, b.out, b.size = 0, 0, 0
for i := 0; i < len(b.data); i++ { // Remove dangling references to avoid leaks.
b.data[i] = nil
func (r *RingBuffer) DumpExt() []Element {
var elements []Element
for i := 0; i < r.Length(); i++ {
elements = append(elements, r.Read(i)) // starts from head
}
b.data = nil // Let GC collect the array.
return elements
}
56 changes: 56 additions & 0 deletions agent/probe/ringbuffer/ringbuffer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ringbuffer

import (
"testing"
// log "github.com/sirupsen/logrus"
)

func TestRingBuffer_empty(t *testing.T) {
r := New(8)

history := r.DumpExt()
// log.WithFields(log.Fields{"len": len(history)}).Info("empty")
if len(history) != 0 {
t.Errorf("Error length[%d]: %d\n", 0, len(history))
}
}

func TestRingBuffer_in_range(t *testing.T) {
r := New(8)
for i := 0; i < 3; i++ {
r.Write(i)
}

history := r.DumpExt()
// log.WithFields(log.Fields{"len": len(history)}).Info("in range")
if len(history) != 3 {
t.Errorf("Error length[%d]: %d\n", 3, len(history))
}

for i, item := range history {
//log.WithFields(log.Fields{"i": i, "item": item}).Info()
if item != i {
t.Errorf("Error[%d]: [%v,%v]\n", i, i, item)
}
}
}

func TestRingBuffer_wrap_around(t *testing.T) {
r := New(8)
for i := 0; i < 128; i++ {
r.Write(i)
}

history := r.DumpExt()
// log.WithFields(log.Fields{"len": len(history)}).Info("wrap around")
if len(history) != 8 {
t.Errorf("Error length[%d]: %d\n", 3, len(history))
}

for i, item := range history {
// log.WithFields(log.Fields{"i": i, "item": item}).Info()
if item != (i + 120) {
t.Errorf("Error[%d]: [%v,%v]\n", i, i+120, item)
}
}
}

0 comments on commit f94f74d

Please sign in to comment.