health.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package container // import "github.com/docker/docker/container"
  2. import (
  3. "context"
  4. "sync"
  5. "github.com/containerd/log"
  6. "github.com/docker/docker/api/types"
  7. )
  8. // Health holds the current container health-check state
  9. type Health struct {
  10. types.Health
  11. stop chan struct{} // Write struct{} to stop the monitor
  12. mu sync.Mutex
  13. }
  14. // String returns a human-readable description of the health-check state
  15. func (s *Health) String() string {
  16. status := s.Status()
  17. switch status {
  18. case types.Starting:
  19. return "health: starting"
  20. default: // Healthy and Unhealthy are clear on their own
  21. return status
  22. }
  23. }
  24. // Status returns the current health status.
  25. //
  26. // Note that this takes a lock and the value may change after being read.
  27. func (s *Health) Status() string {
  28. s.mu.Lock()
  29. defer s.mu.Unlock()
  30. // This happens when the monitor has yet to be setup.
  31. if s.Health.Status == "" {
  32. return types.Unhealthy
  33. }
  34. return s.Health.Status
  35. }
  36. // SetStatus writes the current status to the underlying health structure,
  37. // obeying the locking semantics.
  38. //
  39. // Status may be set directly if another lock is used.
  40. func (s *Health) SetStatus(new string) {
  41. s.mu.Lock()
  42. defer s.mu.Unlock()
  43. s.Health.Status = new
  44. }
  45. // OpenMonitorChannel creates and returns a new monitor channel. If there
  46. // already is one, it returns nil.
  47. func (s *Health) OpenMonitorChannel() chan struct{} {
  48. s.mu.Lock()
  49. defer s.mu.Unlock()
  50. if s.stop == nil {
  51. log.G(context.TODO()).Debug("OpenMonitorChannel")
  52. s.stop = make(chan struct{})
  53. return s.stop
  54. }
  55. return nil
  56. }
  57. // CloseMonitorChannel closes any existing monitor channel.
  58. func (s *Health) CloseMonitorChannel() {
  59. s.mu.Lock()
  60. defer s.mu.Unlock()
  61. if s.stop != nil {
  62. log.G(context.TODO()).Debug("CloseMonitorChannel: waiting for probe to stop")
  63. close(s.stop)
  64. s.stop = nil
  65. // unhealthy when the monitor has stopped for compatibility reasons
  66. s.Health.Status = types.Unhealthy
  67. log.G(context.TODO()).Debug("CloseMonitorChannel done")
  68. }
  69. }