Skip to content
This repository has been archived by the owner on Nov 8, 2019. It is now read-only.

Commit

Permalink
Adjust processing algorithm (issue #14)
Browse files Browse the repository at this point in the history
 - Saves the given script/command in a temp file; and run the file
 - Avoid line break bytes exclusion, as well as the empty line scanned (if received)
 - In error case while sending report, the process continues buffering the chunk data until next threshold
 - When sending the last pending chunk and in a scanning context error; the chunk would include the error, which is concatenated to the previous chunk if available.
 	* At any case, the chunk has to contain bytes!

See #14
  • Loading branch information
pcantera committed Nov 30, 2017
1 parent 36d5fbe commit 8a7ea5b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 25 deletions.
71 changes: 46 additions & 25 deletions cmdpolling/continuousreport.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
Expand Down Expand Up @@ -39,9 +41,9 @@ func cmdContinuousReportRun(c *cli.Context) error {
pollingSvc := cmd.WireUpPolling(c)

// cli command argument
var commandArg string
var cmdArg string
if c.Args().Present() {
commandArg = c.Args().First()
cmdArg = c.Args().First()
} else {
formatter.PrintFatal("argument missing", errors.New("a script or command is required"))
}
Expand All @@ -62,24 +64,44 @@ func cmdContinuousReportRun(c *cli.Context) error {
threshold := Threshold{lines: thresholdLines, time: thresholdTime, bytes: thresholdBytes}
log.Debug("Threshold", threshold)

if err := processCommand(pollingSvc, commandArg, threshold); err != nil {
if err := processCommand(pollingSvc, cmdArg, threshold); err != nil {
formatter.PrintFatal("cannot process continuous report command", err)
}

log.Info("completed")
return nil
}

func processCommand(pollingSvc *polling.PollingService, commandArg string, threshold Threshold) error {
func processCommand(pollingSvc *polling.PollingService, cmdArg string, threshold Threshold) error {
log.Debug("processCommand")

// Saves script/command in a temp file
cmdFileName := strings.Join([]string{time.Now().Format("20060102150405"), "_", utils.RandomString(10)}, "")
if runtime.GOOS == "windows" {
cmdFileName = strings.Join([]string{cmdFileName, ".bat"}, "")
}

// Writes content
if err := ioutil.WriteFile(cmdFileName, []byte(cmdArg), 0600); err != nil {
log.Fatalf("Error creating temp file : ", err)
}

// Creates command
var newCmd *exec.Cmd
if runtime.GOOS == "windows" {
newCmd = exec.Command("cmd", "/C", commandArg)
newCmd = exec.Command("cmd", "/C", cmdFileName)
} else {
newCmd = exec.Command("/bin/sh", "-c", commandArg)
newCmd = exec.Command("/bin/sh", cmdFileName)
}

// Removes temp file
defer func() {
err := os.Remove(cmdFileName)
if err != nil {
log.Warn("Temp file cannot be removed", err.Error())
}
}()

// Gets the pipe command
stdout, err := newCmd.StdoutPipe()
if err != nil {
Expand All @@ -92,37 +114,36 @@ func processCommand(pollingSvc *polling.PollingService, commandArg string, thres
return fmt.Errorf("cannot start the specified command %v", err)
}

line := ""
chunk := ""
nLines, nTime, nBytes := 0, 0, 0
timeStart := time.Now()

scanner := bufio.NewScanner(bufio.NewReader(stdout))
for scanner.Scan() {
line += scanner.Text()
if len(line) > 0 {
nLines++
nTime = int(time.Now().Sub(timeStart).Seconds())
nBytes = len(line)
if nLines >= threshold.lines || nTime >= threshold.time || nBytes >= threshold.bytes {
if err := sendChunks(pollingSvc, line); err != nil {
return err
} else {
line = ""
nLines, nTime, nBytes = 0, 0, 0
timeStart = time.Now()
}
chunk = strings.Join([]string{chunk, scanner.Text(), "\n"}, "")
nLines++
nTime = int(time.Now().Sub(timeStart).Seconds())
nBytes = len(chunk)
if nLines >= threshold.lines || nTime >= threshold.time || nBytes >= threshold.bytes {
if err := sendChunks(pollingSvc, chunk); err != nil {
nLines, nTime = 0, 0
timeStart = time.Now()
} else {
chunk = ""
nLines, nTime, nBytes = 0, 0, 0
timeStart = time.Now()
}
}
}

if err := scanner.Err(); err != nil {
log.Error("==> Error: ", err.Error())
if err := sendChunks(pollingSvc, "error reading standard input:"+err.Error()); err != nil {
return err
}
} else {
chunk = strings.Join([]string{chunk, err.Error()}, "")
}

if len(chunk) > 0 {
log.Debug("Sending the last pending chunk")
if err := sendChunks(pollingSvc, line); err != nil {
if err := sendChunks(pollingSvc, chunk); err != nil {
return err
}
}
Expand Down
12 changes: 12 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"archive/zip"
"fmt"
"io"
"math/rand"
"os"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/codegangsta/cli"

Expand Down Expand Up @@ -186,3 +188,13 @@ func CheckRequiredFlags(c *cli.Context, flags []string) {
os.Exit(2)
}
}

func RandomString(strlen int) string {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
const chars = "abcdefghijklmnopqrstuvwxyz0123456789"
result := make([]byte, strlen)
for i := range result {
result[i] = chars[r.Intn(len(chars))]
}
return string(result)
}

0 comments on commit 8a7ea5b

Please sign in to comment.