lang: funcs: Send empty values when appropriate

I seem to have forgotten to differentiate between the empty string and
no data because the zero value for the stored result was the empty
string. This turns it into a pointer so that we don't block the function
engine if a template or one of the other patched functions sends an
empty string as the first value.
This commit is contained in:
James Shubin
2019-12-30 12:35:08 -05:00
parent ff20e67d07
commit 762c53fb8d
10 changed files with 39 additions and 32 deletions

View File

@@ -44,7 +44,7 @@ type AbsPathFunc struct {
last types.Value // last value received to use for diff last types.Value // last value received to use for diff
path string // the active path path string // the active path
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -130,10 +130,10 @@ func (obj *AbsPathFunc) Stream() error {
} }
result += obj.path result += obj.path
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -141,7 +141,7 @@ func (obj *AbsPathFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -41,7 +41,7 @@ type ReadFileFunc struct {
last types.Value // last value received to use for diff last types.Value // last value received to use for diff
filename string // the active filename filename string // the active filename
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -139,10 +139,10 @@ func (obj *ReadFileFunc) Stream() error {
result := string(content) // convert to string result := string(content) // convert to string
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -150,7 +150,7 @@ func (obj *ReadFileFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -41,7 +41,7 @@ type ReadFileAbsFunc struct {
last types.Value // last value received to use for diff last types.Value // last value received to use for diff
filename string // the active filename filename string // the active filename
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -125,10 +125,10 @@ func (obj *ReadFileAbsFunc) Stream() error {
result := string(content) // convert to string result := string(content) // convert to string
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -136,7 +136,7 @@ func (obj *ReadFileAbsFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -45,7 +45,7 @@ type VUMeterFunc struct {
multiplier int64 multiplier int64
peak float64 peak float64
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -153,10 +153,10 @@ func (obj *VUMeterFunc) Stream() error {
return errwrap.Wrapf(err, "could not generate visual") return errwrap.Wrapf(err, "could not generate visual")
} }
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -164,7 +164,7 @@ func (obj *VUMeterFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -51,7 +51,7 @@ type PrintfFunc struct {
init *interfaces.Init init *interfaces.Init
last types.Value // last value received to use for diff last types.Value // last value received to use for diff
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -224,10 +224,10 @@ func (obj *PrintfFunc) Stream() error {
return err // no errwrap needed b/c helper func return err // no errwrap needed b/c helper func
} }
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -235,7 +235,7 @@ func (obj *PrintfFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -46,7 +46,7 @@ type ReadFileFunc struct {
events chan error // internal events events chan error // internal events
wg *sync.WaitGroup wg *sync.WaitGroup
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -195,10 +195,10 @@ func (obj *ReadFileFunc) Stream() error {
} }
result := string(content) // convert to string result := string(content) // convert to string
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -206,7 +206,7 @@ func (obj *ReadFileFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -89,6 +89,8 @@ func (obj CPUCountFact) Stream() error {
closeChan := make(chan struct{}) // channel to unblock selects in goroutine closeChan := make(chan struct{}) // channel to unblock selects in goroutine
defer close(closeChan) defer close(closeChan)
var once bool // did we send at least once?
// wait for kernel to poke us about new device changes on the system // wait for kernel to poke us about new device changes on the system
wg.Add(1) wg.Add(1)
go func() { go func() {
@@ -121,6 +123,8 @@ func (obj CPUCountFact) Stream() error {
if err != nil { if err != nil {
obj.init.Logf("Could not get initial CPU count. Setting to zero.") obj.init.Logf("Could not get initial CPU count. Setting to zero.")
} }
// TODO: would we rather error instead of sending zero?
case event, ok := <-eventChan: case event, ok := <-eventChan:
if !ok { if !ok {
continue continue
@@ -142,7 +146,7 @@ func (obj CPUCountFact) Stream() error {
return nil return nil
} }
if newCount == cpuCount { if once && newCount == cpuCount {
continue continue
} }
cpuCount = newCount cpuCount = newCount
@@ -151,6 +155,7 @@ func (obj CPUCountFact) Stream() error {
case obj.init.Output <- &types.IntValue{ case obj.init.Output <- &types.IntValue{
V: cpuCount, V: cpuCount,
}: }:
once = true
// send // send
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -68,7 +68,7 @@ type TemplateFunc struct {
init *interfaces.Init init *interfaces.Init
last types.Value // last value received to use for diff last types.Value // last value received to use for diff
result string // last calculated output result *string // last calculated output
closeChan chan struct{} closeChan chan struct{}
} }
@@ -353,10 +353,10 @@ func (obj *TemplateFunc) Stream() error {
return err // no errwrap needed b/c helper func return err // no errwrap needed b/c helper func
} }
if obj.result == result { if obj.result != nil && *obj.result == result {
continue // result didn't change continue // result didn't change
} }
obj.result = result // store new result obj.result = &result // store new result
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil
@@ -364,7 +364,7 @@ func (obj *TemplateFunc) Stream() error {
select { select {
case obj.init.Output <- &types.StrValue{ case obj.init.Output <- &types.StrValue{
V: obj.result, V: *obj.result,
}: }:
case <-obj.closeChan: case <-obj.closeChan:
return nil return nil

View File

@@ -140,6 +140,7 @@ func (obj *WrappedFunc) Stream() error {
return errwrap.Wrapf(err, "simple function errored") return errwrap.Wrapf(err, "simple function errored")
} }
// TODO: do we want obj.result to be a pointer instead?
if obj.result == result { if obj.result == result {
continue // result didn't change continue // result didn't change
} }

View File

@@ -280,6 +280,7 @@ func (obj *WrappedFunc) Stream() error {
obj.init.Logf("Function returned with: %+v", values) obj.init.Logf("Function returned with: %+v", values)
} }
// TODO: do we want obj.result to be a pointer instead?
if obj.result == result { if obj.result == result {
continue // result didn't change continue // result didn't change
} }