diff --git a/metrics/metrics.go b/metrics/metrics.go index 1739f600..9180ef35 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -106,20 +106,11 @@ type StatWriter interface { func GetOrRegisterStatItem(group, groupSuffix string, service string) StatItem { k := group + groupSuffix + service - itemsLock.RLock() - item := items[k] - itemsLock.RUnlock() + item := safeGet(k) if item != nil { return item } - itemsLock.Lock() - item = items[k] - if item == nil { - item = NewStatItem(group, groupSuffix, service) - items[k] = item - } - itemsLock.Unlock() - return item + return safePutAbsent(k, group, groupSuffix, service) } func GetStatItem(group, groupSuffix string, service string) StatItem { @@ -134,22 +125,16 @@ func NewDefaultStatItem(group, groupSuffix string, service string) StatItem { } func RMStatItem(group, groupSuffix string, service string) { - itemsLock.RLock() - i := items[group+groupSuffix+service] - itemsLock.RUnlock() - if i != nil { - i.Clear() - itemsLock.Lock() - delete(items, group+groupSuffix+service) - itemsLock.Unlock() + k := group + groupSuffix + service + item := safeGet(k) + if item != nil { + safeDelete(k) + item.Clear() } } func ClearStatItems() { - itemsLock.Lock() - old := items - items = make(map[string]StatItem, 64) - itemsLock.Unlock() + old := safeExchangeNew() for _, item := range old { item.Clear() } @@ -173,6 +158,37 @@ func StatItemSize() int { return len(items) } +func safeGet(k string) StatItem { + itemsLock.RLock() + defer itemsLock.RUnlock() + return items[k] +} + +func safePutAbsent(k, group, groupSuffix, service string) StatItem { + itemsLock.Lock() + defer itemsLock.Unlock() + item := items[k] + if item == nil { + item = NewStatItem(group, groupSuffix, service) + items[k] = item + } + return item +} + +func safeDelete(k string) { + itemsLock.Lock() + defer itemsLock.Unlock() + delete(items, k) +} + +func safeExchangeNew() map[string]StatItem { + itemsLock.Lock() + defer itemsLock.Unlock() + old := items + items = make(map[string]StatItem, 64) + return old +} + // Escape the string avoid invalid graphite key func Escape(s string) string { if v, ok := escapeCache.Load(s); ok { diff --git a/protocol/motanProtocol.go b/protocol/motanProtocol.go index 8b102c16..ea9321ec 100644 --- a/protocol/motanProtocol.go +++ b/protocol/motanProtocol.go @@ -411,7 +411,7 @@ func DecodeWithTime(reader *bufio.Reader, buf *[]byte, maxContentLength int) (ms // get a message from pool msg = AcquireMessage() defer func() { - if err != nil { + if err != nil && msg != nil { msg.SetCanRelease() ReleaseMessage(msg) }