예제 #1
0
파일: cache.go 프로젝트: pombredanne/hts
// Put inserts a Block into the Cache, returning the Block that was evicted or
// nil if no eviction was necessary and the Block was retained. Unused Blocks
// are not retained but are returned if the Cache is full.
func (c *FIFO) Put(b bgzf.Block) (evicted bgzf.Block, retained bool) {
	c.mu.Lock()
	defer c.mu.Unlock()

	var d bgzf.Block
	if _, ok := c.table[b.Base()]; ok {
		return b, false
	}
	used := b.Used()
	if len(c.table) == c.cap {
		if !used {
			return b, false
		}
		d = c.root.prev.b
		remove(c.root.prev, c.table)
	}
	n := &node{b: b}
	c.table[b.Base()] = n
	if used {
		insertAfter(&c.root, n)
	} else {
		insertAfter(c.root.prev, n)
	}
	return d, true
}
예제 #2
0
파일: cache.go 프로젝트: pombredanne/hts
// Put inserts a Block into the Cache, returning the Block that was evicted or
// nil if no eviction was necessary and the Block was retained. Unused Blocks
// are not retained but are returned if the Cache is full.
func (c *Random) Put(b bgzf.Block) (evicted bgzf.Block, retained bool) {
	c.mu.Lock()
	defer c.mu.Unlock()

	var d bgzf.Block
	if _, ok := c.table[b.Base()]; ok {
		return b, false
	}
	if len(c.table) == c.cap {
		if !b.Used() {
			return b, false
		}
		for k, v := range c.table {
			if v.Used() {
				continue
			}
			delete(c.table, k)
			d = v
			goto done
		}
		for k, v := range c.table {
			delete(c.table, k)
			d = v
			break
		}
	done:
	}
	c.table[b.Base()] = b
	return d, true
}

// StatsRecorder allows a bgzf.Cache to capture cache statistics.
type StatsRecorder struct {
	bgzf.Cache

	mu    sync.RWMutex
	stats Stats
}

// Stats represents statistics of a bgzf.Cache.
type Stats struct {
	Gets      int // number of Get operations
	Misses    int // number of cache misses
	Puts      int // number of Put operations
	Retains   int // number of times a Put has resulted in Block retention
	Evictions int // number of times a Put has resulted in a Block eviction
}

// Stats returns the current statistics for the cache.
func (s *StatsRecorder) Stats() Stats {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.stats
}

// Reset zeros the statistics kept by the StatsRecorder.
func (s *StatsRecorder) Reset() {
	s.mu.Lock()
	s.stats = Stats{}
	s.mu.Unlock()
}

// Get returns the Block in the underlying Cache with the specified base or a nil
// Block if it does not exist. It updates the gets and misses statistics.
func (s *StatsRecorder) Get(base int64) bgzf.Block {
	s.mu.Lock()
	s.stats.Gets++
	blk := s.Cache.Get(base)
	if blk == nil {
		s.stats.Misses++
	}
	s.mu.Unlock()
	return blk
}

// Put inserts a Block into the underlying Cache, returning the Block and eviction
// status according to the underlying cache behavior. It updates the puts, retains and
// evictions statistics.
func (s *StatsRecorder) Put(b bgzf.Block) (evicted bgzf.Block, retained bool) {
	s.mu.Lock()
	s.stats.Puts++
	blk, retained := s.Cache.Put(b)
	if retained {
		s.stats.Retains++
		if blk != nil {
			s.stats.Evictions++
		}
	}
	s.mu.Unlock()
	return blk, retained
}