github.com/gofiber/fiber/v2@v2.47.0/internal/gopsutil/mem/mem_solaris.go (about)

     1  package mem
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os/exec"
     8  	"regexp"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/gofiber/fiber/v2/internal/gopsutil/common"
    13  )
    14  
    15  // VirtualMemory for Solaris is a minimal implementation which only returns
    16  // what Nomad needs. It does take into account global vs zone, however.
    17  func VirtualMemory() (*VirtualMemoryStat, error) {
    18  	return VirtualMemoryWithContext(context.Background())
    19  }
    20  
    21  func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
    22  	result := &VirtualMemoryStat{}
    23  
    24  	zoneName, err := zoneName()
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	if zoneName == "global" {
    30  		cap, err := globalZoneMemoryCapacity()
    31  		if err != nil {
    32  			return nil, err
    33  		}
    34  		result.Total = cap
    35  	} else {
    36  		cap, err := nonGlobalZoneMemoryCapacity()
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  		result.Total = cap
    41  	}
    42  
    43  	return result, nil
    44  }
    45  
    46  func SwapMemory() (*SwapMemoryStat, error) {
    47  	return SwapMemoryWithContext(context.Background())
    48  }
    49  
    50  func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
    51  	return nil, common.ErrNotImplementedError
    52  }
    53  
    54  func zoneName() (string, error) {
    55  	zonename, err := exec.LookPath("zonename")
    56  	if err != nil {
    57  		return "", err
    58  	}
    59  
    60  	ctx := context.Background()
    61  	out, err := invoke.CommandWithContext(ctx, zonename)
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  
    66  	return strings.TrimSpace(string(out)), nil
    67  }
    68  
    69  var globalZoneMemoryCapacityMatch = regexp.MustCompile(`memory size: ([\d]+) Megabytes`)
    70  
    71  func globalZoneMemoryCapacity() (uint64, error) {
    72  	prtconf, err := exec.LookPath("prtconf")
    73  	if err != nil {
    74  		return 0, err
    75  	}
    76  
    77  	ctx := context.Background()
    78  	out, err := invoke.CommandWithContext(ctx, prtconf)
    79  	if err != nil {
    80  		return 0, err
    81  	}
    82  
    83  	match := globalZoneMemoryCapacityMatch.FindAllStringSubmatch(string(out), -1)
    84  	if len(match) != 1 {
    85  		return 0, errors.New("memory size not contained in output of /usr/sbin/prtconf")
    86  	}
    87  
    88  	totalMB, err := strconv.ParseUint(match[0][1], 10, 64)
    89  	if err != nil {
    90  		return 0, err
    91  	}
    92  
    93  	return totalMB * 1024 * 1024, nil
    94  }
    95  
    96  var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`)
    97  
    98  func nonGlobalZoneMemoryCapacity() (uint64, error) {
    99  	kstat, err := exec.LookPath("kstat")
   100  	if err != nil {
   101  		return 0, err
   102  	}
   103  
   104  	ctx := context.Background()
   105  	out, err := invoke.CommandWithContext(ctx, kstat, "-p", "-c", "zone_memory_cap", "memory_cap:*:*:physcap")
   106  	if err != nil {
   107  		return 0, err
   108  	}
   109  
   110  	kstats := kstatMatch.FindAllStringSubmatch(string(out), -1)
   111  	if len(kstats) != 1 {
   112  		return 0, fmt.Errorf("expected 1 kstat, found %d", len(kstats))
   113  	}
   114  
   115  	memSizeBytes, err := strconv.ParseUint(kstats[0][2], 10, 64)
   116  	if err != nil {
   117  		return 0, err
   118  	}
   119  
   120  	return memSizeBytes, nil
   121  }