Commit ef3e8260 authored by Geoff Simmons's avatar Geoff Simmons

Stats only uses the global metadata map once at Attach time.

Names and descriptions are stored per object, no need to sync on the
global map after Attach.
parent 735016e9
......@@ -228,10 +228,11 @@ func mkKey() (mapKey, error) {
// A Stats instance is a client for the native statistics interface.
type Stats struct {
vsc *C.struct_vsc
vsm *vsm.VSM
rdLock sync.Mutex
dataKey mapKey
vsc *C.struct_vsc
vsm *vsm.VSM
rdLock sync.Mutex
names []string
d9ns map[string]D9n
}
// New returns a new and initialized instance of Stats. Stats
......@@ -247,8 +248,6 @@ func New() *Stats {
if stats.vsc == nil {
return nil
}
stats.vsm = nil
stats.dataKey = nil
return stats
}
......@@ -292,7 +291,7 @@ func (stats *Stats) clude(nmGlob string, exclude bool) error {
if err := stats.checkNil(); err != nil {
return err
}
if stats.dataKey != nil {
if stats.d9ns != nil || stats.names != nil {
return errors.New("already attached to a Varnish instance")
}
if err := stats.initVSM(); err != nil {
......@@ -398,30 +397,6 @@ func description(ptr unsafe.Pointer, priv unsafe.Pointer) {
data.names = append(data.names, name)
}
func (stats *Stats) getD9ns() error {
p, err := stats.vsm.Pointer()
if err != nil {
return err
}
data := new(statsData)
data.d9ns = make(map[string]D9n)
if stats.dataKey != nil {
panic("Stats data already mapped")
}
key, err := mkKey()
if err != nil {
return err
}
dataMap.Store(key, data)
stats.dataKey = key
// Don't need the read lock here, because this is only called
// for Attach.
C.descriptions(stats.vsc, (*C.struct_vsm)(p), unsafe.Pointer(key))
return nil
}
// Attach to an instance of Varnish -- varnishd with a running worker
// process.
//
......@@ -435,46 +410,49 @@ func (stats *Stats) Attach(name string) error {
if err := stats.vsm.Attach(name); err != nil {
return err
}
if err := stats.getD9ns(); err != nil {
p, err := stats.vsm.Pointer()
if err != nil {
return err
}
return nil
}
func (stats *Stats) getMetaData() (*statsData, error) {
if err := stats.checkNil(); err != nil {
return nil, err
}
if stats.vsm == nil {
return nil, errors.New("not attached to a Varnish instance")
data := new(statsData)
data.d9ns = make(map[string]D9n)
if stats.d9ns != nil || stats.names != nil {
panic("Stats data already mapped")
}
if stats.dataKey == nil {
panic("stats data not intialized")
key, err := mkKey()
if err != nil {
return err
}
dataMap.Store(key, data)
// Don't need the read lock here, because this is only called
// for Attach.
C.descriptions(stats.vsc, (*C.struct_vsm)(p), unsafe.Pointer(key))
v, ok := dataMap.Load(stats.dataKey)
if !ok {
panic("unmapped stats data")
}
data, ok := v.(*statsData)
if !ok {
panic("statsData fails type assertion")
}
return data, nil
stats.names = data.names
stats.d9ns = data.d9ns
dataMap.Delete(key)
return nil
}
// D9n (for "description") returns the Description for the stat named
// by name.
//
// Returns a non-nil error if there is no stat with that name.
// Returns a non-nil error if the Stats instance is not attached, or
// if there is no stat with that name.
func (stats *Stats) D9n(name string) (D9n, error) {
var errD9n = D9n{}
data, err := stats.getMetaData()
if err != nil {
if err := stats.checkNil(); err != nil {
return errD9n, err
}
d9n, ok := data.d9ns[name]
if stats.vsm == nil {
return errD9n, errors.New("not attached to a Varnish instance")
}
if stats.d9ns == nil {
panic("descriptions not initialized")
}
d9n, ok := stats.d9ns[name]
if !ok {
return errD9n, errors.New("no such stat: " + name)
}
......@@ -485,16 +463,19 @@ func (stats *Stats) D9n(name string) (D9n, error) {
// instance. The names in the returned slice are in the order in which
// stats are read via Read (corresponds to the order displayed by
// varnishstat).
//
// Returns a non-nil error if the Stats instance is not attached.
func (stats *Stats) Names() ([]string, error) {
data, err := stats.getMetaData()
if err != nil {
if err := stats.checkNil(); err != nil {
return nil, err
}
names := data.names
if names == nil {
panic("no stats names stored")
if stats.vsm == nil {
return nil, errors.New("not attached to a Varnish instance")
}
return names, nil
if stats.names == nil {
panic("stats names not initialized")
}
return stats.names, nil
}
// Release frees native resources associated with this client. You
......@@ -511,15 +492,6 @@ func (stats *Stats) Release() {
if stats == nil || stats.vsc == nil {
return
}
if stats.dataKey != nil {
data, err := stats.getMetaData()
if err != nil {
panic(err)
}
data.names = nil
data.d9ns = nil
dataMap.Delete(stats.dataKey)
}
if stats.vsm == nil {
C.free(unsafe.Pointer(stats.vsc))
return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment