revendor containerd/cgroups
Note: now vndr >= v0.10 is required (https://github.com/containerd/cgroups/issues/139) Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
5
vendor/github.com/coreos/go-systemd/v22/NOTICE
generated
vendored
Normal file
5
vendor/github.com/coreos/go-systemd/v22/NOTICE
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CoreOS Project
|
||||
Copyright 2018 CoreOS, Inc
|
||||
|
||||
This product includes software developed at CoreOS, Inc.
|
||||
(http://www.coreos.com/).
|
||||
@@ -2,13 +2,17 @@
|
||||
|
||||
[](https://travis-ci.org/coreos/go-systemd)
|
||||
[](http://godoc.org/github.com/coreos/go-systemd)
|
||||

|
||||
|
||||
|
||||
Go bindings to systemd. The project has several packages:
|
||||
|
||||
- `activation` - for writing and using socket activation from Go
|
||||
- `daemon` - for notifying systemd of service status changes
|
||||
- `dbus` - for starting/stopping/inspecting running services and units
|
||||
- `journal` - for writing to systemd's logging service, journald
|
||||
- `sdjournal` - for reading from journald by wrapping its C API
|
||||
- `login1` - for integration with the systemd logind API
|
||||
- `machine1` - for registering machines/containers with systemd
|
||||
- `unit` - for (de)serialization and comparison of unit files
|
||||
|
||||
@@ -18,10 +22,9 @@ An example HTTP server using socket activation can be quickly set up by followin
|
||||
|
||||
https://github.com/coreos/go-systemd/tree/master/examples/activation/httpserver
|
||||
|
||||
## Journal
|
||||
## systemd Service Notification
|
||||
|
||||
Using the pure-Go `journal` package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry.
|
||||
The `sdjournal` package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available.
|
||||
The `daemon` package is an implementation of the [sd_notify protocol](https://www.freedesktop.org/software/systemd/man/sd_notify.html#Description). It can be used to inform systemd of service start-up completion, watchdog events, and other status changes.
|
||||
|
||||
## D-Bus
|
||||
|
||||
@@ -45,6 +48,20 @@ Create `/etc/dbus-1/system-local.conf` that looks like this:
|
||||
</busconfig>
|
||||
```
|
||||
|
||||
## Journal
|
||||
|
||||
### Writing to the Journal
|
||||
|
||||
Using the pure-Go `journal` package you can submit journal entries directly to systemd's journal, taking advantage of features like indexed key/value pairs for each log entry.
|
||||
|
||||
### Reading from the Journal
|
||||
|
||||
The `sdjournal` package provides read access to the journal by wrapping around journald's native C API; consequently it requires cgo and the journal headers to be available.
|
||||
|
||||
## logind
|
||||
|
||||
The `login1` package provides functions to integrate with the [systemd logind API](http://www.freedesktop.org/wiki/Software/systemd/logind/).
|
||||
|
||||
## machined
|
||||
|
||||
The `machine1` package allows interaction with the [systemd machined D-Bus API](http://www.freedesktop.org/wiki/Software/systemd/machined/).
|
||||
@@ -16,13 +16,14 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -60,6 +61,27 @@ func PathBusEscape(path string) string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
// pathBusUnescape is the inverse of PathBusEscape.
|
||||
func pathBusUnescape(path string) string {
|
||||
if path == "_" {
|
||||
return ""
|
||||
}
|
||||
n := []byte{}
|
||||
for i := 0; i < len(path); i++ {
|
||||
c := path[i]
|
||||
if c == '_' && i+2 < len(path) {
|
||||
res, err := hex.DecodeString(path[i+1 : i+3])
|
||||
if err == nil {
|
||||
n = append(n, res...)
|
||||
}
|
||||
i += 2
|
||||
} else {
|
||||
n = append(n, c)
|
||||
}
|
||||
}
|
||||
return string(n)
|
||||
}
|
||||
|
||||
// Conn is a connection to systemd's dbus endpoint.
|
||||
type Conn struct {
|
||||
// sysconn/sysobj are only used to call dbus methods
|
||||
@@ -74,13 +96,18 @@ type Conn struct {
|
||||
jobs map[dbus.ObjectPath]chan<- string
|
||||
sync.Mutex
|
||||
}
|
||||
subscriber struct {
|
||||
subStateSubscriber struct {
|
||||
updateCh chan<- *SubStateUpdate
|
||||
errCh chan<- error
|
||||
sync.Mutex
|
||||
ignore map[dbus.ObjectPath]int64
|
||||
cleanIgnore int64
|
||||
}
|
||||
propertiesSubscriber struct {
|
||||
updateCh chan<- *PropertiesUpdate
|
||||
errCh chan<- error
|
||||
sync.Mutex
|
||||
}
|
||||
}
|
||||
|
||||
// New establishes a connection to any available bus and authenticates.
|
||||
@@ -116,7 +143,7 @@ func NewUserConnection() (*Conn, error) {
|
||||
func NewSystemdConnection() (*Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
// We skip Hello when talking directly to systemd.
|
||||
return dbusAuthConnection(func() (*dbus.Conn, error) {
|
||||
return dbusAuthConnection(func(opts ...dbus.ConnOption) (*dbus.Conn, error) {
|
||||
return dbus.Dial("unix:path=/run/systemd/private")
|
||||
})
|
||||
})
|
||||
@@ -152,7 +179,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||
sigobj: systemdObject(sigconn),
|
||||
}
|
||||
|
||||
c.subscriber.ignore = make(map[dbus.ObjectPath]int64)
|
||||
c.subStateSubscriber.ignore = make(map[dbus.ObjectPath]int64)
|
||||
c.jobListener.jobs = make(map[dbus.ObjectPath]chan<- string)
|
||||
|
||||
// Setup the listeners on jobs so that we can get completions
|
||||
@@ -174,7 +201,7 @@ func (c *Conn) GetManagerProperty(prop string) (string, error) {
|
||||
return variant.String(), nil
|
||||
}
|
||||
|
||||
func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := createBus()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -194,7 +221,7 @@ func dbusAuthConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func dbusAuthHelloConnection(createBus func() (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
func dbusAuthHelloConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := dbusAuthConnection(createBus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015 CoreOS, Inc.
|
||||
// Copyright 2015, 2018 CoreOS, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,11 @@ package dbus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
func (c *Conn) jobComplete(signal *dbus.Signal) {
|
||||
@@ -116,13 +117,13 @@ func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int,
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// ReloadOrRestart attempts a reload if the unit supports it and use a restart
|
||||
// ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart
|
||||
// otherwise.
|
||||
func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// ReloadOrTryRestart attempts a reload if the unit supports it and use a "Try"
|
||||
// ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try"
|
||||
// flavored restart otherwise.
|
||||
func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
|
||||
@@ -148,14 +149,27 @@ func (c *Conn) ResetFailedUnit(name string) error {
|
||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
||||
}
|
||||
|
||||
// getProperties takes the unit name and returns all of its dbus object properties, for the given dbus interface
|
||||
func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]interface{}, error) {
|
||||
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
|
||||
func (c *Conn) SystemState() (*Property, error) {
|
||||
var err error
|
||||
var prop dbus.Variant
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
|
||||
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Property{Name: "SystemState", Value: prop}, nil
|
||||
}
|
||||
|
||||
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface
|
||||
func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
|
||||
var err error
|
||||
var props map[string]dbus.Variant
|
||||
|
||||
path := unitPath(unit)
|
||||
if !path.IsValid() {
|
||||
return nil, errors.New("invalid unit name: " + unit)
|
||||
return nil, fmt.Errorf("invalid unit name: %v", path)
|
||||
}
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||
@@ -172,9 +186,21 @@ func (c *Conn) getProperties(unit string, dbusInterface string) (map[string]inte
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetUnitProperties takes the unit name and returns all of its dbus object properties.
|
||||
// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
||||
return c.getProperties(unit, "org.freedesktop.systemd1.Unit")
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
// GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties.
|
||||
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
// GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||
func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "")
|
||||
}
|
||||
|
||||
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||
@@ -208,7 +234,8 @@ func (c *Conn) GetServiceProperty(service string, propertyName string) (*Propert
|
||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
||||
return c.getProperties(unit, "org.freedesktop.systemd1."+unitType)
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1."+unitType)
|
||||
}
|
||||
|
||||
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
||||
@@ -270,6 +297,8 @@ func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
|
||||
// ListUnits returns an array with all currently loaded units. Note that
|
||||
// units may be known by multiple names at the same time, and hence there might
|
||||
// be more unit names loaded than actual units behind them.
|
||||
// Also note that a unit is only loaded if it is active and/or enabled.
|
||||
// Units that are both disabled and inactive will thus not be returned.
|
||||
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
|
||||
}
|
||||
@@ -292,6 +321,7 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt
|
||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||
// method, this method returns statuses even for inactive or non-existing
|
||||
// units. Input array should contain exact unit names, but not patterns.
|
||||
// Note: Requires systemd v230 or higher
|
||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||
}
|
||||
@@ -563,3 +593,8 @@ func (c *Conn) Reload() error {
|
||||
func unitPath(name string) dbus.ObjectPath {
|
||||
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
||||
}
|
||||
|
||||
// unitName returns the unescaped base element of the supplied escaped path
|
||||
func unitName(dpath dbus.ObjectPath) string {
|
||||
return pathBusUnescape(path.Base(string(dpath)))
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"github.com/godbus/dbus"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
// From the systemd docs:
|
||||
@@ -56,7 +56,7 @@ type execStart struct {
|
||||
// http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
|
||||
func PropExecStart(command []string, uncleanIsFailure bool) Property {
|
||||
execStarts := []execStart{
|
||||
execStart{
|
||||
{
|
||||
Path: command[0],
|
||||
Args: command,
|
||||
UncleanIsFailure: uncleanIsFailure,
|
||||
@@ -36,7 +36,7 @@ func (s *set) Length() int {
|
||||
}
|
||||
|
||||
func (s *set) Values() (values []string) {
|
||||
for val, _ := range s.data {
|
||||
for val := range s.data {
|
||||
values = append(values, val)
|
||||
}
|
||||
return
|
||||
@@ -16,9 +16,10 @@ package dbus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -36,22 +37,12 @@ func (c *Conn) Subscribe() error {
|
||||
c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0,
|
||||
"type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'")
|
||||
|
||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store()
|
||||
}
|
||||
|
||||
// Unsubscribe this connection from systemd dbus events.
|
||||
func (c *Conn) Unsubscribe() error {
|
||||
err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store()
|
||||
}
|
||||
|
||||
func (c *Conn) dispatch() {
|
||||
@@ -70,7 +61,8 @@ func (c *Conn) dispatch() {
|
||||
c.jobComplete(signal)
|
||||
}
|
||||
|
||||
if c.subscriber.updateCh == nil {
|
||||
if c.subStateSubscriber.updateCh == nil &&
|
||||
c.propertiesSubscriber.updateCh == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -84,6 +76,12 @@ func (c *Conn) dispatch() {
|
||||
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
||||
if signal.Body[0].(string) == "org.freedesktop.systemd1.Unit" {
|
||||
unitPath = signal.Path
|
||||
|
||||
if len(signal.Body) >= 2 {
|
||||
if changed, ok := signal.Body[1].(map[string]dbus.Variant); ok {
|
||||
c.sendPropertiesUpdate(unitPath, changed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +94,7 @@ func (c *Conn) dispatch() {
|
||||
}()
|
||||
}
|
||||
|
||||
// Returns two unbuffered channels which will receive all changed units every
|
||||
// SubscribeUnits returns two unbuffered channels which will receive all changed units every
|
||||
// interval. Deleted units are sent as nil.
|
||||
func (c *Conn) SubscribeUnits(interval time.Duration) (<-chan map[string]*UnitStatus, <-chan error) {
|
||||
return c.SubscribeUnitsCustom(interval, 0, func(u1, u2 *UnitStatus) bool { return *u1 != *u2 }, nil)
|
||||
@@ -169,42 +167,80 @@ type SubStateUpdate struct {
|
||||
// is full, it attempts to write an error to errCh; if errCh is full, the error
|
||||
// passes silently.
|
||||
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
|
||||
c.subscriber.Lock()
|
||||
defer c.subscriber.Unlock()
|
||||
c.subscriber.updateCh = updateCh
|
||||
c.subscriber.errCh = errCh
|
||||
}
|
||||
|
||||
func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
||||
c.subscriber.Lock()
|
||||
defer c.subscriber.Unlock()
|
||||
|
||||
if c.shouldIgnore(path) {
|
||||
if c == nil {
|
||||
msg := "nil receiver"
|
||||
select {
|
||||
case errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
info, err := c.GetUnitProperties(string(path))
|
||||
if err != nil {
|
||||
select {
|
||||
case c.subscriber.errCh <- err:
|
||||
default:
|
||||
}
|
||||
c.subStateSubscriber.Lock()
|
||||
defer c.subStateSubscriber.Unlock()
|
||||
c.subStateSubscriber.updateCh = updateCh
|
||||
c.subStateSubscriber.errCh = errCh
|
||||
}
|
||||
|
||||
func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
|
||||
c.subStateSubscriber.Lock()
|
||||
defer c.subStateSubscriber.Unlock()
|
||||
|
||||
if c.subStateSubscriber.updateCh == nil {
|
||||
return
|
||||
}
|
||||
|
||||
name := info["Id"].(string)
|
||||
substate := info["SubState"].(string)
|
||||
isIgnored := c.shouldIgnore(unitPath)
|
||||
defer c.cleanIgnore()
|
||||
if isIgnored {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := c.GetUnitPathProperties(unitPath)
|
||||
if err != nil {
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- err:
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
defer c.updateIgnore(unitPath, info)
|
||||
|
||||
name, ok := info["Id"].(string)
|
||||
if !ok {
|
||||
msg := "failed to cast info.Id"
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
substate, ok := info["SubState"].(string)
|
||||
if !ok {
|
||||
msg := "failed to cast info.SubState"
|
||||
select {
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
update := &SubStateUpdate{name, substate}
|
||||
select {
|
||||
case c.subscriber.updateCh <- update:
|
||||
case c.subStateSubscriber.updateCh <- update:
|
||||
default:
|
||||
msg := "update channel is full"
|
||||
select {
|
||||
case c.subscriber.errCh <- errors.New("update channel full!"):
|
||||
case c.subStateSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.updateIgnore(path, info)
|
||||
}
|
||||
|
||||
// The ignore functions work around a wart in the systemd dbus interface.
|
||||
@@ -222,29 +258,76 @@ func (c *Conn) sendSubStateUpdate(path dbus.ObjectPath) {
|
||||
// the properties).
|
||||
|
||||
func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
|
||||
t, ok := c.subscriber.ignore[path]
|
||||
t, ok := c.subStateSubscriber.ignore[path]
|
||||
return ok && t >= time.Now().UnixNano()
|
||||
}
|
||||
|
||||
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
|
||||
c.cleanIgnore()
|
||||
loadState, ok := info["LoadState"].(string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
// unit is unloaded - it will trigger bad systemd dbus behavior
|
||||
if info["LoadState"].(string) == "not-found" {
|
||||
c.subscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||
if loadState == "not-found" {
|
||||
c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
|
||||
}
|
||||
}
|
||||
|
||||
// without this, ignore would grow unboundedly over time
|
||||
func (c *Conn) cleanIgnore() {
|
||||
now := time.Now().UnixNano()
|
||||
if c.subscriber.cleanIgnore < now {
|
||||
c.subscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||
if c.subStateSubscriber.cleanIgnore < now {
|
||||
c.subStateSubscriber.cleanIgnore = now + cleanIgnoreInterval
|
||||
|
||||
for p, t := range c.subscriber.ignore {
|
||||
for p, t := range c.subStateSubscriber.ignore {
|
||||
if t < now {
|
||||
delete(c.subscriber.ignore, p)
|
||||
delete(c.subStateSubscriber.ignore, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PropertiesUpdate holds a map of a unit's changed properties
|
||||
type PropertiesUpdate struct {
|
||||
UnitName string
|
||||
Changed map[string]dbus.Variant
|
||||
}
|
||||
|
||||
// SetPropertiesSubscriber writes to updateCh when any unit's properties
|
||||
// change. Every property change reported by systemd will be sent; that is, no
|
||||
// transitions will be "missed" (as they might be with SetSubStateSubscriber).
|
||||
// However, state changes will only be written to the channel with non-blocking
|
||||
// writes. If updateCh is full, it attempts to write an error to errCh; if
|
||||
// errCh is full, the error passes silently.
|
||||
func (c *Conn) SetPropertiesSubscriber(updateCh chan<- *PropertiesUpdate, errCh chan<- error) {
|
||||
c.propertiesSubscriber.Lock()
|
||||
defer c.propertiesSubscriber.Unlock()
|
||||
c.propertiesSubscriber.updateCh = updateCh
|
||||
c.propertiesSubscriber.errCh = errCh
|
||||
}
|
||||
|
||||
// we don't need to worry about shouldIgnore() here because
|
||||
// sendPropertiesUpdate doesn't call GetProperties()
|
||||
func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[string]dbus.Variant) {
|
||||
c.propertiesSubscriber.Lock()
|
||||
defer c.propertiesSubscriber.Unlock()
|
||||
|
||||
if c.propertiesSubscriber.updateCh == nil {
|
||||
return
|
||||
}
|
||||
|
||||
update := &PropertiesUpdate{unitName(unitPath), changedProps}
|
||||
|
||||
select {
|
||||
case c.propertiesSubscriber.updateCh <- update:
|
||||
default:
|
||||
msg := "update channel is full"
|
||||
select {
|
||||
case c.propertiesSubscriber.errCh <- errors.New(msg):
|
||||
default:
|
||||
log.Printf("full error channel while reporting: %s\n", msg)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
5
vendor/github.com/coreos/go-systemd/v22/go.mod
generated
vendored
Normal file
5
vendor/github.com/coreos/go-systemd/v22/go.mod
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/coreos/go-systemd/v22
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/godbus/dbus/v5 v5.0.3
|
||||
Reference in New Issue
Block a user