github.com/a4a881d4/docker@v1.9.0-rc2/pkg/ulimit/ulimit.go (about)

     1  // Package ulimit provides structure and helper function to parse and represent
     2  // resource limits (Rlimit and Ulimit, its human friendly version).
     3  package ulimit
     4  
     5  import (
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // Ulimit is a human friendly version of Rlimit.
    12  type Ulimit struct {
    13  	Name string
    14  	Hard int64
    15  	Soft int64
    16  }
    17  
    18  // Rlimit specifies the resource limits, such as max open files.
    19  type Rlimit struct {
    20  	Type int    `json:"type,omitempty"`
    21  	Hard uint64 `json:"hard,omitempty"`
    22  	Soft uint64 `json:"soft,omitempty"`
    23  }
    24  
    25  const (
    26  	// magic numbers for making the syscall
    27  	// some of these are defined in the syscall package, but not all.
    28  	// Also since Windows client doesn't get access to the syscall package, need to
    29  	//	define these here
    30  	rlimitAs         = 9
    31  	rlimitCore       = 4
    32  	rlimitCPU        = 0
    33  	rlimitData       = 2
    34  	rlimitFsize      = 1
    35  	rlimitLocks      = 10
    36  	rlimitMemlock    = 8
    37  	rlimitMsgqueue   = 12
    38  	rlimitNice       = 13
    39  	rlimitNofile     = 7
    40  	rlimitNproc      = 6
    41  	rlimitRss        = 5
    42  	rlimitRtprio     = 14
    43  	rlimitRttime     = 15
    44  	rlimitSigpending = 11
    45  	rlimitStack      = 3
    46  )
    47  
    48  var ulimitNameMapping = map[string]int{
    49  	//"as":         rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
    50  	"core":       rlimitCore,
    51  	"cpu":        rlimitCPU,
    52  	"data":       rlimitData,
    53  	"fsize":      rlimitFsize,
    54  	"locks":      rlimitLocks,
    55  	"memlock":    rlimitMemlock,
    56  	"msgqueue":   rlimitMsgqueue,
    57  	"nice":       rlimitNice,
    58  	"nofile":     rlimitNofile,
    59  	"nproc":      rlimitNproc,
    60  	"rss":        rlimitRss,
    61  	"rtprio":     rlimitRtprio,
    62  	"rttime":     rlimitRttime,
    63  	"sigpending": rlimitSigpending,
    64  	"stack":      rlimitStack,
    65  }
    66  
    67  // Parse parses and returns a Ulimit from the specified string.
    68  func Parse(val string) (*Ulimit, error) {
    69  	parts := strings.SplitN(val, "=", 2)
    70  	if len(parts) != 2 {
    71  		return nil, fmt.Errorf("invalid ulimit argument: %s", val)
    72  	}
    73  
    74  	if _, exists := ulimitNameMapping[parts[0]]; !exists {
    75  		return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
    76  	}
    77  
    78  	limitVals := strings.SplitN(parts[1], ":", 2)
    79  	if len(limitVals) > 2 {
    80  		return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
    81  	}
    82  
    83  	soft, err := strconv.ParseInt(limitVals[0], 10, 64)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	hard := soft // in case no hard was set
    89  	if len(limitVals) == 2 {
    90  		hard, err = strconv.ParseInt(limitVals[1], 10, 64)
    91  	}
    92  	if soft > hard {
    93  		return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, hard)
    94  	}
    95  
    96  	return &Ulimit{Name: parts[0], Soft: soft, Hard: hard}, nil
    97  }
    98  
    99  // GetRlimit returns the RLimit corresponding to Ulimit.
   100  func (u *Ulimit) GetRlimit() (*Rlimit, error) {
   101  	t, exists := ulimitNameMapping[u.Name]
   102  	if !exists {
   103  		return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
   104  	}
   105  
   106  	return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
   107  }
   108  
   109  func (u *Ulimit) String() string {
   110  	return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
   111  }