[ARVADOS] created: 2359eabb2e84dd9aa5109332c37b0f50aee896bc

git at public.curoverse.com git at public.curoverse.com
Tue Jul 7 16:34:07 EDT 2015


        at  2359eabb2e84dd9aa5109332c37b0f50aee896bc (commit)


commit 2359eabb2e84dd9aa5109332c37b0f50aee896bc
Author: Tom Clegg <tom at curoverse.com>
Date:   Tue Jul 7 16:31:55 2015 -0400

    6222: Add memory stats to status.json.
    
    Reduce malloc activity in status.json.
    
    Remove abandoned GetVolumeStatus, and move its tests over to
    volume_unix_test.go.

diff --git a/services/keepstore/bufferpool.go b/services/keepstore/bufferpool.go
index 373bfc7..9a35094 100644
--- a/services/keepstore/bufferpool.go
+++ b/services/keepstore/bufferpool.go
@@ -3,12 +3,15 @@ package main
 import (
 	"log"
 	"sync"
+	"sync/atomic"
 	"time"
 )
 
 type bufferPool struct {
 	// limiter has a "true" placeholder for each in-use buffer.
 	limiter chan bool
+	// allocated is the number of bytes currently allocated to buffers.
+	allocated uint64
 	// Pool has unused buffers.
 	sync.Pool
 }
@@ -16,6 +19,7 @@ type bufferPool struct {
 func newBufferPool(count int, bufSize int) *bufferPool {
 	p := bufferPool{}
 	p.New = func() interface{} {
+		atomic.AddUint64(&p.allocated, uint64(bufSize))
 		return make([]byte, bufSize)
 	}
 	p.limiter = make(chan bool, count)
@@ -42,3 +46,18 @@ func (p *bufferPool) Put(buf []byte) {
 	p.Pool.Put(buf)
 	<-p.limiter
 }
+
+// Alloc returns the number of bytes allocated to buffers.
+func (p *bufferPool) Alloc() uint64 {
+	return atomic.LoadUint64(&p.allocated)
+}
+
+// Cap returns the maximum number of buffers allowed.
+func (p *bufferPool) Cap() int {
+	return cap(p.limiter)
+}
+
+// Len returns the number of buffers in use right now.
+func (p *bufferPool) Len() int {
+	return len(p.limiter)
+}
diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go
index 3898b55..d1169d5 100644
--- a/services/keepstore/handlers.go
+++ b/services/keepstore/handlers.go
@@ -19,8 +19,9 @@ import (
 	"net/http"
 	"os"
 	"regexp"
+	"runtime"
 	"strconv"
-	"syscall"
+	"sync"
 	"time"
 )
 
@@ -185,60 +186,52 @@ type VolumeStatus struct {
 	BytesUsed  uint64 `json:"bytes_used"`
 }
 
+type PoolStatus struct {
+	Alloc uint64 `json:"BytesAllocated"`
+	Cap   int    `json:"BuffersMax"`
+	Len   int    `json:"BuffersInUse"`
+}
+
 type NodeStatus struct {
-	Volumes []*VolumeStatus `json:"volumes"`
+	Volumes    []*VolumeStatus  `json:"volumes"`
+	BufferPool PoolStatus
+	Memory     runtime.MemStats
 }
 
+var st NodeStatus
+var stLock sync.Mutex
 func StatusHandler(resp http.ResponseWriter, req *http.Request) {
-	st := GetNodeStatus()
-	if jstat, err := json.Marshal(st); err == nil {
+	stLock.Lock()
+	ReadNodeStatus(&st)
+	jstat, err := json.Marshal(&st)
+	stLock.Unlock()
+	if err == nil {
 		resp.Write(jstat)
 	} else {
 		log.Printf("json.Marshal: %s\n", err)
-		log.Printf("NodeStatus = %v\n", st)
+		log.Printf("NodeStatus = %v\n", &st)
 		http.Error(resp, err.Error(), 500)
 	}
 }
 
-// GetNodeStatus
-//     Returns a NodeStatus struct describing this Keep
-//     node's current status.
+// ReadNodeStatus populates the given NodeStatus struct with current
+// values.
 //
-func GetNodeStatus() *NodeStatus {
-	st := new(NodeStatus)
-
-	st.Volumes = make([]*VolumeStatus, len(KeepVM.AllReadable()))
-	for i, vol := range KeepVM.AllReadable() {
-		st.Volumes[i] = vol.Status()
+func ReadNodeStatus(st *NodeStatus) {
+	vols := KeepVM.AllReadable()
+	if cap(st.Volumes) < len(vols) {
+		st.Volumes = make([]*VolumeStatus, len(vols))
 	}
-	return st
-}
-
-// GetVolumeStatus
-//     Returns a VolumeStatus describing the requested volume.
-//
-func GetVolumeStatus(volume string) *VolumeStatus {
-	var fs syscall.Statfs_t
-	var devnum uint64
-
-	if fi, err := os.Stat(volume); err == nil {
-		devnum = fi.Sys().(*syscall.Stat_t).Dev
-	} else {
-		log.Printf("GetVolumeStatus: os.Stat: %s\n", err)
-		return nil
+	st.Volumes = st.Volumes[:0]
+	for _, vol := range vols {
+		if s := vol.Status(); s != nil {
+			st.Volumes = append(st.Volumes, s)
+		}
 	}
-
-	err := syscall.Statfs(volume, &fs)
-	if err != nil {
-		log.Printf("GetVolumeStatus: statfs: %s\n", err)
-		return nil
-	}
-	// These calculations match the way df calculates disk usage:
-	// "free" space is measured by fs.Bavail, but "used" space
-	// uses fs.Blocks - fs.Bfree.
-	free := fs.Bavail * uint64(fs.Bsize)
-	used := (fs.Blocks - fs.Bfree) * uint64(fs.Bsize)
-	return &VolumeStatus{volume, devnum, free, used}
+	st.BufferPool.Alloc = bufs.Alloc()
+	st.BufferPool.Cap = bufs.Cap()
+	st.BufferPool.Len = bufs.Len()
+	runtime.ReadMemStats(&st.Memory)
 }
 
 // DeleteHandler processes DELETE requests.
diff --git a/services/keepstore/keepstore_test.go b/services/keepstore/keepstore_test.go
index 811cc70..e01b013 100644
--- a/services/keepstore/keepstore_test.go
+++ b/services/keepstore/keepstore_test.go
@@ -414,43 +414,6 @@ func TestIndex(t *testing.T) {
 	}
 }
 
-// TestNodeStatus
-//     Test that GetNodeStatus returns valid info about available volumes.
-//
-//     TODO(twp): set up appropriate interfaces to permit more rigorous
-//     testing.
-//
-func TestNodeStatus(t *testing.T) {
-	defer teardown()
-
-	// Set up test Keep volumes with some blocks.
-	KeepVM = MakeTestVolumeManager(2)
-	defer KeepVM.Close()
-
-	vols := KeepVM.AllReadable()
-	vols[0].Put(TEST_HASH, TEST_BLOCK)
-	vols[1].Put(TEST_HASH_2, TEST_BLOCK_2)
-
-	// Get node status and make a basic sanity check.
-	st := GetNodeStatus()
-	for i := range vols {
-		volinfo := st.Volumes[i]
-		mtp := volinfo.MountPoint
-		if mtp != "/bogo" {
-			t.Errorf("GetNodeStatus mount_point %s, expected /bogo", mtp)
-		}
-		if volinfo.DeviceNum == 0 {
-			t.Errorf("uninitialized device_num in %v", volinfo)
-		}
-		if volinfo.BytesFree == 0 {
-			t.Errorf("uninitialized bytes_free in %v", volinfo)
-		}
-		if volinfo.BytesUsed == 0 {
-			t.Errorf("uninitialized bytes_used in %v", volinfo)
-		}
-	}
-}
-
 // ========================================
 // Helper functions for unit tests.
 // ========================================
diff --git a/services/keepstore/volume_unix.go b/services/keepstore/volume_unix.go
index 61a98b5..7c8e40c 100644
--- a/services/keepstore/volume_unix.go
+++ b/services/keepstore/volume_unix.go
@@ -141,7 +141,7 @@ func (v *UnixVolume) Put(loc string, block []byte) error {
 }
 
 // Status returns a VolumeStatus struct describing the volume's
-// current state.
+// current state, or nil if an error occurs.
 //
 func (v *UnixVolume) Status() *VolumeStatus {
 	var fs syscall.Statfs_t
diff --git a/services/keepstore/volume_unix_test.go b/services/keepstore/volume_unix_test.go
index 1320d31..6bafa7c 100644
--- a/services/keepstore/volume_unix_test.go
+++ b/services/keepstore/volume_unix_test.go
@@ -326,3 +326,23 @@ func TestIsFull(t *testing.T) {
 		t.Errorf("%s: should no longer be full", v)
 	}
 }
+
+func TestNodeStatus(t *testing.T) {
+	v := TempUnixVolume(t, false, false)
+	defer _teardown(v)
+
+	// Get node status and make a basic sanity check.
+	volinfo := v.Status()
+	if volinfo.MountPoint != v.root {
+		t.Errorf("GetNodeStatus mount_point %s, expected %s", volinfo.MountPoint, v.root)
+	}
+	if volinfo.DeviceNum == 0 {
+		t.Errorf("uninitialized device_num in %v", volinfo)
+	}
+	if volinfo.BytesFree == 0 {
+		t.Errorf("uninitialized bytes_free in %v", volinfo)
+	}
+	if volinfo.BytesUsed == 0 {
+		t.Errorf("uninitialized bytes_used in %v", volinfo)
+	}
+}

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list