github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/acm/acmstate/metadata_cache.go (about)

     1  package acmstate
     2  
     3  import (
     4  	"sync"
     5  )
     6  
     7  type metadataInfo struct {
     8  	metadata string
     9  	updated  bool
    10  }
    11  
    12  type MetadataCache struct {
    13  	backend MetadataReader
    14  	m       sync.Map
    15  }
    16  
    17  func NewMetadataCache(backend MetadataReader) *MetadataCache {
    18  	return &MetadataCache{
    19  		backend: backend,
    20  	}
    21  }
    22  
    23  func (cache *MetadataCache) SetMetadata(metahash MetadataHash, metadata string) error {
    24  	cache.m.Store(metahash, &metadataInfo{updated: true, metadata: metadata})
    25  	return nil
    26  }
    27  
    28  func (cache *MetadataCache) GetMetadata(metahash MetadataHash) (string, error) {
    29  	metaInfo, err := cache.getMetadata(metahash)
    30  	if err != nil {
    31  		return "", err
    32  	}
    33  
    34  	return metaInfo.metadata, nil
    35  }
    36  
    37  // Syncs changes to the backend in deterministic order. Sends storage updates before updating
    38  // the account they belong so that storage values can be taken account of in the update.
    39  func (cache *MetadataCache) Sync(st MetadataWriter) error {
    40  	var err error
    41  	cache.m.Range(func(key, value interface{}) bool {
    42  		hash := key.(MetadataHash)
    43  		info := value.(*metadataInfo)
    44  		if info.updated {
    45  			err = st.SetMetadata(hash, info.metadata)
    46  			if err != nil {
    47  				return false
    48  			}
    49  		}
    50  		return true
    51  	})
    52  	if err != nil {
    53  		return err
    54  	}
    55  	return nil
    56  }
    57  
    58  func (cache *MetadataCache) Reset(backend MetadataReader) {
    59  	cache.backend = backend
    60  	cache.m = sync.Map{}
    61  }
    62  
    63  // Get the cache accountInfo item creating it if necessary
    64  func (cache *MetadataCache) getMetadata(metahash MetadataHash) (*metadataInfo, error) {
    65  	value, ok := cache.m.Load(metahash)
    66  	if !ok {
    67  		metadata, err := cache.backend.GetMetadata(metahash)
    68  		if err != nil {
    69  			return nil, err
    70  		}
    71  		metaInfo := &metadataInfo{
    72  			metadata: metadata,
    73  		}
    74  		cache.m.Store(metahash, metaInfo)
    75  		return metaInfo, nil
    76  	}
    77  	return value.(*metadataInfo), nil
    78  }