85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
|
// Copyright (c) 2017 Arista Networks, Inc.
|
||
|
// Use of this source code is governed by the Apache License 2.0
|
||
|
// that can be found in the COPYING file.
|
||
|
|
||
|
// This code was forked from the Go project, here's the original copyright header:
|
||
|
|
||
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package monitor
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"expvar"
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
// Map is a string-to-Var map variable that satisfies the Var interface.
|
||
|
// This a streamlined, more efficient version of expvar.Map, that also
|
||
|
// supports deletion.
|
||
|
type Map struct {
|
||
|
m sync.Map // map[string]expvar.Var
|
||
|
}
|
||
|
|
||
|
func (v *Map) String() string {
|
||
|
var b bytes.Buffer
|
||
|
b.WriteByte('{')
|
||
|
first := true
|
||
|
v.m.Range(func(k, value interface{}) bool {
|
||
|
if !first {
|
||
|
b.WriteString(", ")
|
||
|
}
|
||
|
fmt.Fprintf(&b, "%q: %v", k, value)
|
||
|
first = false
|
||
|
return true
|
||
|
})
|
||
|
b.WriteByte('}')
|
||
|
return b.String()
|
||
|
}
|
||
|
|
||
|
// Get atomically returns the Var for the given key or nil.
|
||
|
func (v *Map) Get(key string) expvar.Var {
|
||
|
i, _ := v.m.Load(key)
|
||
|
av, _ := i.(expvar.Var)
|
||
|
return av
|
||
|
}
|
||
|
|
||
|
// Set atomically associates the given Var to the given key.
|
||
|
func (v *Map) Set(key string, av expvar.Var) {
|
||
|
// Before we store the value, check to see whether the key is new. Try a Load
|
||
|
// before LoadOrStore: LoadOrStore causes the key interface to escape even on
|
||
|
// the Load path.
|
||
|
if _, ok := v.m.Load(key); !ok {
|
||
|
if _, dup := v.m.LoadOrStore(key, av); !dup {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
v.m.Store(key, av)
|
||
|
}
|
||
|
|
||
|
// Delete atomically deletes the given key if it exists.
|
||
|
func (v *Map) Delete(key string) {
|
||
|
v.m.Delete(key)
|
||
|
}
|
||
|
|
||
|
// Do calls f for each entry in the map.
|
||
|
// The map is locked during the iteration,
|
||
|
// but existing entries may be concurrently updated.
|
||
|
func (v *Map) Do(f func(expvar.KeyValue)) {
|
||
|
v.m.Range(func(k, value interface{}) bool {
|
||
|
f(expvar.KeyValue{Key: k.(string), Value: value.(expvar.Var)})
|
||
|
return true
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// NewMap creates a new Map and publishes it with the given name.
|
||
|
func NewMap(name string) *Map {
|
||
|
v := new(Map)
|
||
|
expvar.Publish(name, v)
|
||
|
return v
|
||
|
}
|