From 4b17ac4f1ce4f916e5a8163c3904b64475949e26 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 6 Nov 2020 22:22:33 -0800 Subject: [PATCH] Fix atomic string handling for JSON output --- environment/docker/environment.go | 5 ++--- server/resources.go | 2 +- system/utils.go | 31 +++++++++++++++++++------------ 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/environment/docker/environment.go b/environment/docker/environment.go index 448cfef..d4aaf1c 100644 --- a/environment/docker/environment.go +++ b/environment/docker/environment.go @@ -48,7 +48,7 @@ type Environment struct { emitter *events.EventBus // Tracks the environment state. - st system.AtomicString + st *system.AtomicString } // Creates a new base Docker environment. The ID passed through will be the ID that is used to @@ -65,10 +65,9 @@ func New(id string, m *Metadata, c *environment.Configuration) (*Environment, er Configuration: c, meta: m, client: cli, + st: system.NewAtomicString(environment.ProcessOfflineState), } - e.st.Store(environment.ProcessOfflineState) - return e, nil } diff --git a/server/resources.go b/server/resources.go index ca52ed3..085dedc 100644 --- a/server/resources.go +++ b/server/resources.go @@ -18,7 +18,7 @@ type ResourceUsage struct { environment.Stats // The current server status. - State system.AtomicString `json:"state"` + State *system.AtomicString `json:"state" default:"{}"` // The current disk space being used by the server. This value is not guaranteed to be accurate // at all times. It is "manually" set whenever server.Proc() is called. This is kind of just a diff --git a/system/utils.go b/system/utils.go index 8a9008e..5862a0c 100644 --- a/system/utils.go +++ b/system/utils.go @@ -1,6 +1,7 @@ package system import ( + "sync" "sync/atomic" ) @@ -25,27 +26,33 @@ func (ab *AtomicBool) Get() bool { // about a potential race condition scenario. Under the hood it uses a simple sync.RWMutex // to control access to the value. type AtomicString struct { - v atomic.Value + v string + mu sync.RWMutex } -// Returns a new instance of an AtomicString. func NewAtomicString(v string) *AtomicString { - as := &AtomicString{} - if v != "" { - as.Store(v) - } - return as + return &AtomicString{v: v} } // Stores the string value passed atomically. func (as *AtomicString) Store(v string) { - as.v.Store(v) + as.mu.Lock() + as.v = v + as.mu.Unlock() } // Loads the string value and returns it. func (as *AtomicString) Load() string { - if v := as.v.Load(); v != nil { - return v.(string) - } - return "" + as.mu.RLock() + defer as.mu.RUnlock() + return as.v +} + +func (as *AtomicString) UnmarshalText(b []byte) error { + as.Store(string(b)) + return nil +} + +func (as *AtomicString) MarshalText() ([]byte, error) { + return []byte(as.Load()), nil }