[ARVADOS] updated: 75b8b796ee88196ca1b99dcfed0533565c52dce7

git at public.curoverse.com git at public.curoverse.com
Thu Oct 16 10:52:44 EDT 2014


Summary of changes:
 services/crunchstat/crunchstat.go | 161 ++++++++++++++++++--------------------
 1 file changed, 76 insertions(+), 85 deletions(-)

       via  75b8b796ee88196ca1b99dcfed0533565c52dce7 (commit)
       via  90057cfa2c19091b0d627a1df978014998e187c6 (commit)
       via  becd16125599abeefa3d2d1203279bf7eee69669 (commit)
      from  2b08ab24b496f14d2ef97167a2e78e92b179f226 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 75b8b796ee88196ca1b99dcfed0533565c52dce7
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu Oct 16 10:52:05 2014 -0400

    3826: Fix up formatting cf. gofmt

diff --git a/services/crunchstat/crunchstat.go b/services/crunchstat/crunchstat.go
index 7d19a9e..6b35570 100644
--- a/services/crunchstat/crunchstat.go
+++ b/services/crunchstat/crunchstat.go
@@ -3,8 +3,8 @@ package main
 import (
 	"bufio"
 	"bytes"
-	"flag"
 	"errors"
+	"flag"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -24,6 +24,7 @@ import (
 #include <stdlib.h>
 */
 import "C"
+
 // The above block of magic allows us to look up user_hz via _SC_CLK_TCK.
 
 type Cgroup struct {
@@ -95,7 +96,7 @@ func OpenStatFile(stderr chan<- string, cgroup Cgroup, statgroup string, stat st
 	if err != nil {
 		file = nil
 		path = ""
-	} 
+	}
 	if pathWas, ok := reportedStatFile[stat]; !ok || pathWas != path {
 		// Log whenever we start using a new/different cgroup
 		// stat file for a given statistic. This typically
@@ -174,8 +175,8 @@ func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoS
 		if prev, ok := lastSample[dev]; ok {
 			delta = fmt.Sprintf(" -- interval %.4f seconds %d write %d read",
 				sample.sampleTime.Sub(prev.sampleTime).Seconds(),
-				sample.txBytes - prev.txBytes,
-				sample.rxBytes - prev.rxBytes)
+				sample.txBytes-prev.txBytes,
+				sample.rxBytes-prev.rxBytes)
 		}
 		stderr <- fmt.Sprintf("crunchstat: blkio:%s %d write %d read%s", dev, sample.txBytes, sample.rxBytes, delta)
 		lastSample[dev] = sample
@@ -216,10 +217,13 @@ func DoMemoryStats(stderr chan<- string, cgroup Cgroup) {
 func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) {
 	sampleTime := time.Now()
 	stats, err := GetContainerNetStats(stderr, cgroup)
-	if err != nil { return }
+	if err != nil {
+		return
+	}
 
 	scanner := bufio.NewScanner(stats)
-	Iface: for scanner.Scan() {
+Iface:
+	for scanner.Scan() {
 		var ifName string
 		var rx, tx int64
 		words := bufio.NewScanner(strings.NewReader(scanner.Text()))
@@ -254,8 +258,8 @@ func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]I
 			interval := nextSample.sampleTime.Sub(lastSample.sampleTime).Seconds()
 			delta = fmt.Sprintf(" -- interval %.4f seconds %d tx %d rx",
 				interval,
-				tx - lastSample.txBytes,
-				rx - lastSample.rxBytes)
+				tx-lastSample.txBytes,
+				rx-lastSample.rxBytes)
 		}
 		stderr <- fmt.Sprintf("crunchstat: net:%s %d tx %d rx%s",
 			ifName, tx, rx, delta)
@@ -264,7 +268,7 @@ func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]I
 }
 
 type CpuSample struct {
-	hasData    bool		// to distinguish the zero value from real data
+	hasData    bool // to distinguish the zero value from real data
 	sampleTime time.Time
 	user       float64
 	sys        float64
@@ -273,7 +277,7 @@ type CpuSample struct {
 
 // Return the number of CPUs available in the container. Return 0 if
 // we can't figure out the real number of CPUs.
-func GetCpuCount(stderr chan<- string, cgroup Cgroup) (int64) {
+func GetCpuCount(stderr chan<- string, cgroup Cgroup) int64 {
 	cpusetFile, err := OpenStatFile(stderr, cgroup, "cpuset", "cpuset.cpus")
 	if err != nil {
 		return 0
@@ -316,8 +320,8 @@ func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) {
 	if lastSample.hasData {
 		delta = fmt.Sprintf(" -- interval %.4f seconds %.4f user %.4f sys",
 			nextSample.sampleTime.Sub(lastSample.sampleTime).Seconds(),
-			nextSample.user - lastSample.user,
-			nextSample.sys - lastSample.sys)
+			nextSample.user-lastSample.user,
+			nextSample.sys-lastSample.sys)
 	}
 	stderr <- fmt.Sprintf("crunchstat: cpu %.4f user %.4f sys %d cpus%s",
 		nextSample.user, nextSample.sys, nextSample.cpus, delta)

commit 90057cfa2c19091b0d627a1df978014998e187c6
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu Oct 16 10:48:27 2014 -0400

    3826: Just modify lastSample maps in place, instead of returning the supplied pointer.

diff --git a/services/crunchstat/crunchstat.go b/services/crunchstat/crunchstat.go
index 8f698a2..7d19a9e 100644
--- a/services/crunchstat/crunchstat.go
+++ b/services/crunchstat/crunchstat.go
@@ -138,10 +138,10 @@ type IoSample struct {
 	rxBytes    int64
 }
 
-func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) (map[string]IoSample) {
+func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) {
 	c, err := OpenStatFile(stderr, cgroup, "blkio", "blkio.io_service_bytes")
 	if err != nil {
-		return lastSample
+		return
 	}
 	defer c.Close()
 	b := bufio.NewScanner(c)
@@ -166,9 +166,6 @@ func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoS
 		}
 		newSamples[device] = thisSample
 	}
-	if lastSample == nil {
-		lastSample = make(map[string]IoSample)
-	}
 	for dev, sample := range newSamples {
 		if sample.txBytes < 0 || sample.rxBytes < 0 {
 			continue
@@ -183,7 +180,6 @@ func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoS
 		stderr <- fmt.Sprintf("crunchstat: blkio:%s %d write %d read%s", dev, sample.txBytes, sample.rxBytes, delta)
 		lastSample[dev] = sample
 	}
-	return lastSample
 }
 
 type MemSample struct {
@@ -217,14 +213,11 @@ func DoMemoryStats(stderr chan<- string, cgroup Cgroup) {
 	stderr <- fmt.Sprintf("crunchstat: mem%s", outstat.String())
 }
 
-func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) (map[string]IoSample) {
+func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) {
 	sampleTime := time.Now()
 	stats, err := GetContainerNetStats(stderr, cgroup)
-	if err != nil { return lastSample }
+	if err != nil { return }
 
-	if lastSample == nil {
-		lastSample = make(map[string]IoSample)
-	}
 	scanner := bufio.NewScanner(stats)
 	Iface: for scanner.Scan() {
 		var ifName string
@@ -268,10 +261,10 @@ func DoNetworkStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]I
 			ifName, tx, rx, delta)
 		lastSample[ifName] = nextSample
 	}
-	return lastSample
 }
 
 type CpuSample struct {
+	hasData    bool		// to distinguish the zero value from real data
 	sampleTime time.Time
 	user       float64
 	sys        float64
@@ -301,18 +294,18 @@ func GetCpuCount(stderr chan<- string, cgroup Cgroup) (int64) {
 	return cpus
 }
 
-func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) (*CpuSample) {
+func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) {
 	statFile, err := OpenStatFile(stderr, cgroup, "cpuacct", "cpuacct.stat")
 	if err != nil {
-		return lastSample
+		return
 	}
 	defer statFile.Close()
 	b, err := ReadAllOrWarn(statFile, stderr)
 	if err != nil {
-		return lastSample
+		return
 	}
 
-	nextSample := &CpuSample{time.Now(), 0, 0, GetCpuCount(stderr, cgroup)}
+	nextSample := CpuSample{true, time.Now(), 0, 0, GetCpuCount(stderr, cgroup)}
 	var userTicks, sysTicks int64
 	fmt.Sscanf(string(b), "user %d\nsystem %d", &userTicks, &sysTicks)
 	user_hz := float64(C.sysconf(C._SC_CLK_TCK))
@@ -320,7 +313,7 @@ func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) (*Cp
 	nextSample.sys = float64(sysTicks) / user_hz
 
 	delta := ""
-	if lastSample != nil {
+	if lastSample.hasData {
 		delta = fmt.Sprintf(" -- interval %.4f seconds %.4f user %.4f sys",
 			nextSample.sampleTime.Sub(lastSample.sampleTime).Seconds(),
 			nextSample.user - lastSample.user,
@@ -328,13 +321,13 @@ func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) (*Cp
 	}
 	stderr <- fmt.Sprintf("crunchstat: cpu %.4f user %.4f sys %d cpus%s",
 		nextSample.user, nextSample.sys, nextSample.cpus, delta)
-	return nextSample
+	*lastSample = nextSample
 }
 
 func PollCgroupStats(cgroup Cgroup, stderr chan string, poll int64, stop_poll_chan <-chan bool) {
-	var lastNetSample map[string]IoSample = nil
-	var lastDiskSample map[string]IoSample = nil
-	var lastCpuSample *CpuSample = nil
+	var lastNetSample = map[string]IoSample{}
+	var lastDiskSample = map[string]IoSample{}
+	var lastCpuSample = CpuSample{}
 
 	poll_chan := make(chan bool, 1)
 	go func() {
@@ -353,9 +346,9 @@ func PollCgroupStats(cgroup Cgroup, stderr chan string, poll int64, stop_poll_ch
 			// Emit stats, then select again.
 		}
 		DoMemoryStats(stderr, cgroup)
-		lastCpuSample = DoCpuStats(stderr, cgroup, lastCpuSample)
-		lastDiskSample = DoBlkIoStats(stderr, cgroup, lastDiskSample)
-		lastNetSample = DoNetworkStats(stderr, cgroup, lastNetSample)
+		DoCpuStats(stderr, cgroup, &lastCpuSample)
+		DoBlkIoStats(stderr, cgroup, lastDiskSample)
+		DoNetworkStats(stderr, cgroup, lastNetSample)
 	}
 }
 

commit becd16125599abeefa3d2d1203279bf7eee69669
Author: Tom Clegg <tom at curoverse.com>
Date:   Thu Oct 16 10:36:34 2014 -0400

    3826: Change FindStat to OpenStatFile to eliminate redundant Stat()
    calls and races. Log every time we change our mind about where to read
    a given statistic.

diff --git a/services/crunchstat/crunchstat.go b/services/crunchstat/crunchstat.go
index 2b4571d..8f698a2 100644
--- a/services/crunchstat/crunchstat.go
+++ b/services/crunchstat/crunchstat.go
@@ -55,61 +55,67 @@ func OpenAndReadAll(filename string, log_chan chan<- string) ([]byte, error) {
 		return nil, err
 	}
 	defer in.Close()
-	{
-		content, err := ioutil.ReadAll(in)
-		if err != nil && log_chan != nil {
-			log_chan <- fmt.Sprintf("crunchstat: read %s: %s", filename, err)
-		}
-		return content, err
+	return ReadAllOrWarn(in, log_chan)
+}
+
+func ReadAllOrWarn(in *os.File, log_chan chan<- string) ([]byte, error) {
+	content, err := ioutil.ReadAll(in)
+	if err != nil && log_chan != nil {
+		log_chan <- fmt.Sprintf("crunchstat: read %s: %s", in.Name(), err)
 	}
+	return content, err
 }
 
-var reportedStatFile map[string]bool
-var reportedNoStatFile map[string]bool
+var reportedStatFile = map[string]string{}
 
-// Find the cgroup stats file in /sys/fs corresponding to the target
-// cgroup.
+// Open the cgroup stats file in /sys/fs corresponding to the target
+// cgroup, and return an *os.File. If no stats file is available,
+// return nil.
 //
 // TODO: Instead of trying all options, choose a process in the
 // container, and read /proc/PID/cgroup to determine the appropriate
 // cgroup root for the given statgroup. (This will avoid falling back
 // to host-level stats during container setup and teardown.)
-func FindStat(stderr chan<- string, cgroup Cgroup, statgroup string, stat string) string {
-	if reportedStatFile == nil {
-		reportedStatFile = make(map[string]bool)
-		reportedNoStatFile = make(map[string]bool)
-	}
-
+func OpenStatFile(stderr chan<- string, cgroup Cgroup, statgroup string, stat string) (*os.File, error) {
 	var path string
 	path = fmt.Sprintf("%s/%s/%s/%s/%s", cgroup.root, statgroup, cgroup.parent, cgroup.cid, stat)
-	if _, err := os.Stat(path); err != nil {
+	file, err := os.Open(path)
+	if err != nil {
 		path = fmt.Sprintf("%s/%s/%s/%s", cgroup.root, cgroup.parent, cgroup.cid, stat)
+		file, err = os.Open(path)
 	}
-	if _, err := os.Stat(path); err != nil {
+	if err != nil {
 		path = fmt.Sprintf("%s/%s/%s", cgroup.root, statgroup, stat)
+		file, err = os.Open(path)
 	}
-	if _, err := os.Stat(path); err != nil {
+	if err != nil {
 		path = fmt.Sprintf("%s/%s", cgroup.root, stat)
+		file, err = os.Open(path)
 	}
-	if _, err := os.Stat(path); err != nil {
-		if _, ok := reportedNoStatFile[stat]; !ok {
+	if err != nil {
+		file = nil
+		path = ""
+	} 
+	if pathWas, ok := reportedStatFile[stat]; !ok || pathWas != path {
+		// Log whenever we start using a new/different cgroup
+		// stat file for a given statistic. This typically
+		// happens 1 to 3 times per statistic, depending on
+		// whether we happen to collect stats [a] before any
+		// processes have been created in the container and
+		// [b] after all contained processes have exited.
+		reportedStatFile[stat] = path
+		if path == "" {
 			stderr <- fmt.Sprintf("crunchstat: did not find stats file (root %s, parent %s, cid %s, statgroup %s, stat %s)", cgroup.root, cgroup.parent, cgroup.cid, statgroup, stat)
-			reportedNoStatFile[stat] = true
+		} else {
+			stderr <- fmt.Sprintf("crunchstat: reading stats from %s", path)
 		}
-		return ""
 	}
-	if _, ok := reportedStatFile[path]; !ok {
-		stderr <- fmt.Sprintf("crunchstat: reading stats from %s", path)
-		reportedStatFile[path] = true
-	}
-	return path
+	return file, err
 }
 
 func GetContainerNetStats(stderr chan<- string, cgroup Cgroup) (io.Reader, error) {
-	procsFilename := FindStat(stderr, cgroup, "cpuacct", "cgroup.procs")
-	procsFile, err := os.Open(procsFilename)
+	procsFile, err := OpenStatFile(stderr, cgroup, "cpuacct", "cgroup.procs")
 	if err != nil {
-		stderr <- fmt.Sprintf("crunchstat: open %s: %s", procsFilename, err)
 		return nil, err
 	}
 	defer procsFile.Close()
@@ -133,14 +139,8 @@ type IoSample struct {
 }
 
 func DoBlkIoStats(stderr chan<- string, cgroup Cgroup, lastSample map[string]IoSample) (map[string]IoSample) {
-	blkio_io_service_bytes := FindStat(stderr, cgroup, "blkio", "blkio.io_service_bytes")
-	if blkio_io_service_bytes == "" {
-		return lastSample
-	}
-
-	c, err := os.Open(blkio_io_service_bytes)
+	c, err := OpenStatFile(stderr, cgroup, "blkio", "blkio.io_service_bytes")
 	if err != nil {
-		stderr <- fmt.Sprintf("crunchstat: open %s: %s", blkio_io_service_bytes, err)
 		return lastSample
 	}
 	defer c.Close()
@@ -192,13 +192,8 @@ type MemSample struct {
 }
 
 func DoMemoryStats(stderr chan<- string, cgroup Cgroup) {
-	memory_stat := FindStat(stderr, cgroup, "memory", "memory.stat")
-	if memory_stat == "" {
-		return
-	}
-	c, err := os.Open(memory_stat)
+	c, err := OpenStatFile(stderr, cgroup, "memory", "memory.stat")
 	if err != nil {
-		stderr <- fmt.Sprintf("crunchstat: open %s: %s", memory_stat, err)
 		return
 	}
 	defer c.Close()
@@ -286,14 +281,12 @@ type CpuSample struct {
 // Return the number of CPUs available in the container. Return 0 if
 // we can't figure out the real number of CPUs.
 func GetCpuCount(stderr chan<- string, cgroup Cgroup) (int64) {
-	cpuset_cpus := FindStat(stderr, cgroup, "cpuset", "cpuset.cpus")
-	if cpuset_cpus == "" {
-		return 0
-	}
-	b, err := OpenAndReadAll(cpuset_cpus, stderr)
+	cpusetFile, err := OpenStatFile(stderr, cgroup, "cpuset", "cpuset.cpus")
 	if err != nil {
 		return 0
 	}
+	defer cpusetFile.Close()
+	b, err := ReadAllOrWarn(cpusetFile, stderr)
 	sp := strings.Split(string(b), ",")
 	cpus := int64(0)
 	for _, v := range sp {
@@ -309,11 +302,12 @@ func GetCpuCount(stderr chan<- string, cgroup Cgroup) (int64) {
 }
 
 func DoCpuStats(stderr chan<- string, cgroup Cgroup, lastSample *CpuSample) (*CpuSample) {
-	cpuacct_stat := FindStat(stderr, cgroup, "cpuacct", "cpuacct.stat")
-	if cpuacct_stat == "" {
+	statFile, err := OpenStatFile(stderr, cgroup, "cpuacct", "cpuacct.stat")
+	if err != nil {
 		return lastSample
 	}
-	b, err := OpenAndReadAll(cpuacct_stat, stderr)
+	defer statFile.Close()
+	b, err := ReadAllOrWarn(statFile, stderr)
 	if err != nil {
 		return lastSample
 	}

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list