github.com/khulnasoft-lab/gopkg@v0.0.0-20240121181808-81b44d894093/cache/memory.go (about)

     1  package cache
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/Khulnasoft-lab/gopkg/msg"
     7  )
     8  
     9  // Provide an in memory cache of imported project information.
    10  
    11  var defaultMemCache = newMemCache()
    12  
    13  // MemPut put a version into the in memory cache for a name.
    14  // This will silently ignore non-semver and make sure the latest
    15  // is stored.
    16  func MemPut(name, version string) {
    17  	defaultMemCache.put(name, version)
    18  }
    19  
    20  // MemTouched returns true if the cache was touched for a name.
    21  func MemTouched(name string) bool {
    22  	return defaultMemCache.touched(name)
    23  }
    24  
    25  // MemTouch notes if a name has been looked at.
    26  func MemTouch(name string) {
    27  	defaultMemCache.touch(name)
    28  }
    29  
    30  // MemLatest returns the latest, that is most recent, semver release. This
    31  // may be a blank string if no put value
    32  func MemLatest(name string) string {
    33  	return defaultMemCache.getLatest(name)
    34  }
    35  
    36  // MemSetCurrent is used to set the current version in use.
    37  func MemSetCurrent(name, version string) {
    38  	defaultMemCache.setCurrent(name, version)
    39  }
    40  
    41  // MemCurrent is used to get the current version in use.
    42  func MemCurrent(name string) string {
    43  	return defaultMemCache.current(name)
    44  }
    45  
    46  // An in memory cache.
    47  type memCache struct {
    48  	sync.RWMutex
    49  	latest   map[string]string
    50  	t        map[string]bool
    51  	versions map[string][]string
    52  	c        map[string]string
    53  }
    54  
    55  func newMemCache() *memCache {
    56  	return &memCache{
    57  		latest:   make(map[string]string),
    58  		t:        make(map[string]bool),
    59  		versions: make(map[string][]string),
    60  		c:        make(map[string]string),
    61  	}
    62  }
    63  
    64  func (m *memCache) setCurrent(name, version string) {
    65  	m.Lock()
    66  	defer m.Unlock()
    67  
    68  	if m.c[name] == "" {
    69  		m.c[name] = version
    70  	} else {
    71  		// If we already have a version try to see if the new or old one is
    72  		// semver and use that one.
    73  		_, err := semver.NewVersion(m.c[name])
    74  		if err != nil {
    75  			_, err2 := semver.NewVersion(version)
    76  			if err2 == nil {
    77  				m.c[name] = version
    78  			}
    79  		}
    80  	}
    81  }
    82  
    83  func (m *memCache) current(name string) string {
    84  	m.RLock()
    85  	defer m.RUnlock()
    86  	return m.c[name]
    87  }
    88  
    89  func (m *memCache) put(name, version string) {
    90  	m.Lock()
    91  	defer m.Unlock()
    92  	m.t[name] = true
    93  	sv, err := semver.NewVersion(version)
    94  	if err != nil {
    95  		msg.Debug("Ignoring %s version %s: %s", name, version, err)
    96  		return
    97  	}
    98  
    99  	latest, found := m.latest[name]
   100  	if found {
   101  		lv, err := semver.NewVersion(latest)
   102  		if err == nil {
   103  			if sv.GreaterThan(lv) {
   104  				m.latest[name] = version
   105  			}
   106  		}
   107  	} else {
   108  		m.latest[name] = version
   109  	}
   110  
   111  	found = false
   112  	for _, v := range m.versions[name] {
   113  		if v == version {
   114  			found = true
   115  		}
   116  	}
   117  	if !found {
   118  		m.versions[name] = append(m.versions[name], version)
   119  	}
   120  }
   121  
   122  func (m *memCache) touch(name string) {
   123  	m.Lock()
   124  	defer m.Unlock()
   125  	m.t[name] = true
   126  }
   127  
   128  func (m *memCache) touched(name string) bool {
   129  	m.RLock()
   130  	defer m.RUnlock()
   131  	return m.t[name]
   132  }
   133  
   134  func (m *memCache) getLatest(name string) string {
   135  	m.RLock()
   136  	defer m.RUnlock()
   137  	return m.latest[name]
   138  }