1package module23import (4 "encoding/json"5 "fmt"6 "sync"7)89// ModSpecificData is a container that allows modules to attach10// additional context data to framework objects such as SMTP connections11// without conflicting with each other and ensuring each module12// gets its own namespace.13//14// It must not be used to store stateful objects that may need15// a specific cleanup routine as ModSpecificData does not provide16// any lifetime management.17//18// Stored data must be serializable to JSON for state persistence19// e.g. when message is stored in a on-disk queue.20type ModSpecificData struct {21 modDataLck sync.RWMutex22 modData map[string]interface{}23}2425func (msd *ModSpecificData) modKey(m Module, perInstance bool) string {26 if !perInstance {27 return m.Name()28 }29 instName := m.InstanceName()30 if instName == "" {31 instName = fmt.Sprintf("%x", m)32 }33 return m.Name() + "/" + instName34}3536func (msd *ModSpecificData) MarshalJSON() ([]byte, error) {37 msd.modDataLck.RLock()38 defer msd.modDataLck.RUnlock()39 return json.Marshal(msd.modData)40}4142func (msd *ModSpecificData) UnmarshalJSON(b []byte) error {43 msd.modDataLck.Lock()44 defer msd.modDataLck.Unlock()45 return json.Unmarshal(b, &msd.modData)46}4748func (msd *ModSpecificData) Set(m Module, perInstance bool, value interface{}) {49 key := msd.modKey(m, perInstance)50 msd.modDataLck.Lock()51 defer msd.modDataLck.Unlock()52 if msd.modData == nil {53 msd.modData = make(map[string]interface{})54 }55 msd.modData[key] = value56}5758func (msd *ModSpecificData) Get(m Module, perInstance bool) interface{} {59 key := msd.modKey(m, perInstance)60 msd.modDataLck.RLock()61 defer msd.modDataLck.RUnlock()62 return msd.modData[key]63}