Explorar o código

Add MemInfo to the system pkg.

MemInfo provides a simple API to get memory information from the
system.

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
Andrea Luzzardi %!s(int64=10) %!d(string=hai) anos
pai
achega
e0c9d7b654

+ 17 - 0
pkg/system/meminfo.go

@@ -0,0 +1,17 @@
+package system
+
+// MemInfo contains memory statistics of the host system.
+type MemInfo struct {
+	// Total usable RAM (i.e. physical RAM minus a few reserved bits and the
+	// kernel binary code).
+	MemTotal int64
+
+	// Amount of free memory.
+	MemFree int64
+
+	// Total amount of swap space available.
+	SwapTotal int64
+
+	// Amount of swap space that is currently unused.
+	SwapFree int64
+}

+ 67 - 0
pkg/system/meminfo_linux.go

@@ -0,0 +1,67 @@
+package system
+
+import (
+	"bufio"
+	"errors"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+
+	"github.com/docker/docker/pkg/units"
+)
+
+var (
+	ErrMalformed = errors.New("malformed file")
+)
+
+// Retrieve memory statistics of the host system and parse them into a MemInfo
+// type.
+func ReadMemInfo() (*MemInfo, error) {
+	file, err := os.Open("/proc/meminfo")
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+	return parseMemInfo(file)
+}
+
+func parseMemInfo(reader io.Reader) (*MemInfo, error) {
+	meminfo := &MemInfo{}
+	scanner := bufio.NewScanner(reader)
+	for scanner.Scan() {
+		// Expected format: ["MemTotal:", "1234", "kB"]
+		parts := strings.Fields(scanner.Text())
+
+		// Sanity checks: Skip malformed entries.
+		if len(parts) < 3 || parts[2] != "kB" {
+			continue
+		}
+
+		// Convert to bytes.
+		size, err := strconv.Atoi(parts[1])
+		if err != nil {
+			continue
+		}
+		bytes := int64(size) * units.KiB
+
+		switch parts[0] {
+		case "MemTotal:":
+			meminfo.MemTotal = bytes
+		case "MemFree:":
+			meminfo.MemFree = bytes
+		case "SwapTotal:":
+			meminfo.SwapTotal = bytes
+		case "SwapFree:":
+			meminfo.SwapFree = bytes
+		}
+
+	}
+
+	// Handle errors that may have occurred during the reading of the file.
+	if err := scanner.Err(); err != nil {
+		return nil, err
+	}
+
+	return meminfo, nil
+}

+ 37 - 0
pkg/system/meminfo_linux_test.go

@@ -0,0 +1,37 @@
+package system
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/docker/docker/pkg/units"
+)
+
+func TestMemInfo(t *testing.T) {
+	const input = `
+	MemTotal:      1 kB
+	MemFree:       2 kB
+	SwapTotal:     3 kB
+	SwapFree:      4 kB
+	Malformed1:
+	Malformed2:    1
+	Malformed3:    2 MB
+	Malformed4:    X kB
+	`
+	meminfo, err := parseMemInfo(strings.NewReader(input))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if meminfo.MemTotal != 1*units.KiB {
+		t.Fatalf("Unexpected MemTotal: %d", meminfo.MemTotal)
+	}
+	if meminfo.MemFree != 2*units.KiB {
+		t.Fatalf("Unexpected MemFree: %d", meminfo.MemFree)
+	}
+	if meminfo.SwapTotal != 3*units.KiB {
+		t.Fatalf("Unexpected SwapTotal: %d", meminfo.SwapTotal)
+	}
+	if meminfo.SwapFree != 4*units.KiB {
+		t.Fatalf("Unexpected SwapFree: %d", meminfo.SwapFree)
+	}
+}

+ 7 - 0
pkg/system/meminfo_unsupported.go

@@ -0,0 +1,7 @@
+// +build !linux
+
+package system
+
+func ReadMemInfo() (*MemInfo, error) {
+	return nil, ErrNotSupportedPlatform
+}