From 8a1807ae2fb748cbc99724ae9b9e2a388564db5b Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 17 Dec 2013 15:33:03 -0500 Subject: [PATCH] adding cgroup and controller bits, and comments too --- cg.go | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 161 insertions(+), 10 deletions(-) diff --git a/cg.go b/cg.go index 5eb0a79..d27f968 100644 --- a/cg.go +++ b/cg.go @@ -1,13 +1,155 @@ package cgroup -// #include -// #cgo LDFLAGS: -lcgroup +/* +#include +#cgo LDFLAGS: -lcgroup + +// work around for the 'type' special word +enum cgroup_file_type type_from_file_info(struct cgroup_file_info fi) { + return fi.type; +} +*/ import "C" import ( "errors" + "runtime" "unsafe" ) +/* + * Structure describing one or more control groups. The structure is opaque to + * applications. + */ +type Cgroup struct { + g *C.struct_group +} + +func NewCgroup(name string) Cgroup { + cg := Cgroup{ + C.cgroup_new_cgroup(C.CString(name)), + } + runtime.SetFinalizer(cg, freeCgroup) + return cg +} + +func (cg *Cgroup) AddController(name string) Controller { + return Controller{ + C.cgroup_add_controller(cg.g, C.CString(name)), + } +} +func (cg Cgroup) GetController(name string) Controller { + return Controller{ + C.cgroup_get_controller(cg.g, C.CString(name)), + } +} + +func freeCgroup(cg Cgroup) { + C.cgroup_free(&cg.g) +} + +/* + * Structure describing a controller attached to one struct @c cgroup, including + * parameters of the group and their values. The structure is opaque to + * applications. + */ +type Controller struct { + c *C.struct_cgroup_controller +} + +/** + * Initialize libcgroup. Information about mounted hierarchies are examined + * and cached internally (just what's mounted where, not the groups themselves). + */ +func Init() error { + return _err(C.cgroup_init()) +} + +/* + * Load configuration file and mount and create control groups described there. + * See cgconfig.conf man page for format of the file. + */ +func LoadConfig(filename string) error { + return _err(C.cgroup_config_load_config(C.CString(filename))) +} + +/** + * Delete all control groups and unmount all hierarchies. + */ +func Unload() error { + return _err(C.cgroup_unload_cgroups()) +} + +type DeleteFlag int + +const ( + /** + * Ignore errors caused by migration of tasks to parent group. + */ + DeleteIgnoreMigration = DeleteFlag(C.CGFLAG_DELETE_IGNORE_MIGRATION) + + /** + * Recursively delete all child groups. + */ + DeleteRecursive = DeleteFlag(C.CGFLAG_DELETE_RECURSIVE) + + /** + * Delete the cgroup only if it is empty, i.e. it has no subgroups and + * no processes inside. This flag cannot be used with + * DeleteRecursive + */ + DeleteEmptyOnly = DeleteFlag(C.CGFLAG_DELETE_EMPTY_ONLY) +) + +/** + * Delete all cgroups and unmount all mount points defined in specified config + * file. + * + * The groups are either removed recursively or only the empty ones, based + * on given flags. Mount point are always umounted only if they are empty, + * regardless of any flags. + * + * The groups are sorted before they are removed, so the removal of empty ones + * actually works (i.e. subgroups are removed first). + */ +func UnloadFromConfig(filename string, flags DeleteFlag) error { + return _err(C.cgroup_config_unload_config(C.CString(filename), C.int(flags))) +} + +type FileInfo struct { + Type FileType + Path string + Parent string + FullPath string + Depth int8 +} + +func fromCFileInfo(cData C.struct_cgroup_file_info) FileInfo { + return FileInfo{ + Type: FileType(C.type_from_file_info(cData)), + Path: C.GoString(cData.path), + Parent: C.GoString(cData.parent), + FullPath: C.GoString(cData.full_path), + Depth: int8(cData.depth), + } +} + +type FileType int + +const ( + FileTypeFile = FileType(C.CGROUP_FILE_TYPE_FILE) + FileTypeDir = FileType(C.CGROUP_FILE_TYPE_DIR) + FileTypeOther = FileType(C.CGROUP_FILE_TYPE_OTHER) +) + +/* +int cgroup_walk_tree_begin(const char *controller, const char *base_path, int depth, + void **handle, struct cgroup_file_info *info, + int *base_level); +*/ + +/* +Information model for Controllers available +*/ type ControllerData struct { Name string Hierarchy int @@ -16,10 +158,11 @@ type ControllerData struct { } func fromCControllerData(cData C.struct_controller_data) ControllerData { - name := C.GoString(&cData.name[0]) return ControllerData{ - Name: name, - Hierarchy: int(cData.hierarchy), + Name: C.GoString(&cData.name[0]), + Hierarchy: int(cData.hierarchy), + NumCgroups: int(cData.num_cgroups), + Enabled: int(cData.enabled), } } @@ -58,19 +201,27 @@ func GetSubSysMountPoint(controller string) (string, error) { } var ( - ECGEOF = errors.New(C.GoString(C.cgroup_strerror(C.ECGEOF))) + // End-of-file for iterators + ECGEOF = errors.New(C.GoString(C.cgroup_strerror(C.ECGEOF))) + ECGOTHER = errors.New(C.GoString(C.cgroup_strerror(C.ECGOTHER))) ) +/* + * Return last errno, which caused ECGOTHER error. + */ +func LastError() error { + return _err(C.cgroup_get_last_errno()) +} + func _err(num C.int) error { switch num { case 0: return nil case C.ECGEOF: return ECGEOF + case C.ECGOTHER: + return ECGOTHER } + // There's a lot. We'll create them as they come return errors.New(C.GoString(C.cgroup_strerror(num))) } - -func Init() error { - return _err(C.cgroup_init()) -}