mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 02:04:11 +01:00 
			
		
		
		
	* Update blevesearch v0.8.1 -> v1.0.7 * make vendor Co-authored-by: zeripath <art27@cantab.net>
		
			
				
	
	
		
			179 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
package bbolt
 | 
						|
 | 
						|
import "sort"
 | 
						|
 | 
						|
// hashmapFreeCount returns count of free pages(hashmap version)
 | 
						|
func (f *freelist) hashmapFreeCount() int {
 | 
						|
	// use the forwardmap to get the total count
 | 
						|
	count := 0
 | 
						|
	for _, size := range f.forwardMap {
 | 
						|
		count += int(size)
 | 
						|
	}
 | 
						|
	return count
 | 
						|
}
 | 
						|
 | 
						|
// hashmapAllocate serves the same purpose as arrayAllocate, but use hashmap as backend
 | 
						|
func (f *freelist) hashmapAllocate(txid txid, n int) pgid {
 | 
						|
	if n == 0 {
 | 
						|
		return 0
 | 
						|
	}
 | 
						|
 | 
						|
	// if we have a exact size match just return short path
 | 
						|
	if bm, ok := f.freemaps[uint64(n)]; ok {
 | 
						|
		for pid := range bm {
 | 
						|
			// remove the span
 | 
						|
			f.delSpan(pid, uint64(n))
 | 
						|
 | 
						|
			f.allocs[pid] = txid
 | 
						|
 | 
						|
			for i := pgid(0); i < pgid(n); i++ {
 | 
						|
				delete(f.cache, pid+i)
 | 
						|
			}
 | 
						|
			return pid
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// lookup the map to find larger span
 | 
						|
	for size, bm := range f.freemaps {
 | 
						|
		if size < uint64(n) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		for pid := range bm {
 | 
						|
			// remove the initial
 | 
						|
			f.delSpan(pid, uint64(size))
 | 
						|
 | 
						|
			f.allocs[pid] = txid
 | 
						|
 | 
						|
			remain := size - uint64(n)
 | 
						|
 | 
						|
			// add remain span
 | 
						|
			f.addSpan(pid+pgid(n), remain)
 | 
						|
 | 
						|
			for i := pgid(0); i < pgid(n); i++ {
 | 
						|
				delete(f.cache, pid+pgid(i))
 | 
						|
			}
 | 
						|
			return pid
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
// hashmapReadIDs reads pgids as input an initial the freelist(hashmap version)
 | 
						|
func (f *freelist) hashmapReadIDs(pgids []pgid) {
 | 
						|
	f.init(pgids)
 | 
						|
 | 
						|
	// Rebuild the page cache.
 | 
						|
	f.reindex()
 | 
						|
}
 | 
						|
 | 
						|
// hashmapGetFreePageIDs returns the sorted free page ids
 | 
						|
func (f *freelist) hashmapGetFreePageIDs() []pgid {
 | 
						|
	count := f.free_count()
 | 
						|
	if count == 0 {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
 | 
						|
	m := make([]pgid, 0, count)
 | 
						|
	for start, size := range f.forwardMap {
 | 
						|
		for i := 0; i < int(size); i++ {
 | 
						|
			m = append(m, start+pgid(i))
 | 
						|
		}
 | 
						|
	}
 | 
						|
	sort.Sort(pgids(m))
 | 
						|
 | 
						|
	return m
 | 
						|
}
 | 
						|
 | 
						|
// hashmapMergeSpans try to merge list of pages(represented by pgids) with existing spans
 | 
						|
func (f *freelist) hashmapMergeSpans(ids pgids) {
 | 
						|
	for _, id := range ids {
 | 
						|
		// try to see if we can merge and update
 | 
						|
		f.mergeWithExistingSpan(id)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// mergeWithExistingSpan merges pid to the existing free spans, try to merge it backward and forward
 | 
						|
func (f *freelist) mergeWithExistingSpan(pid pgid) {
 | 
						|
	prev := pid - 1
 | 
						|
	next := pid + 1
 | 
						|
 | 
						|
	preSize, mergeWithPrev := f.backwardMap[prev]
 | 
						|
	nextSize, mergeWithNext := f.forwardMap[next]
 | 
						|
	newStart := pid
 | 
						|
	newSize := uint64(1)
 | 
						|
 | 
						|
	if mergeWithPrev {
 | 
						|
		//merge with previous span
 | 
						|
		start := prev + 1 - pgid(preSize)
 | 
						|
		f.delSpan(start, preSize)
 | 
						|
 | 
						|
		newStart -= pgid(preSize)
 | 
						|
		newSize += preSize
 | 
						|
	}
 | 
						|
 | 
						|
	if mergeWithNext {
 | 
						|
		// merge with next span
 | 
						|
		f.delSpan(next, nextSize)
 | 
						|
		newSize += nextSize
 | 
						|
	}
 | 
						|
 | 
						|
	f.addSpan(newStart, newSize)
 | 
						|
}
 | 
						|
 | 
						|
func (f *freelist) addSpan(start pgid, size uint64) {
 | 
						|
	f.backwardMap[start-1+pgid(size)] = size
 | 
						|
	f.forwardMap[start] = size
 | 
						|
	if _, ok := f.freemaps[size]; !ok {
 | 
						|
		f.freemaps[size] = make(map[pgid]struct{})
 | 
						|
	}
 | 
						|
 | 
						|
	f.freemaps[size][start] = struct{}{}
 | 
						|
}
 | 
						|
 | 
						|
func (f *freelist) delSpan(start pgid, size uint64) {
 | 
						|
	delete(f.forwardMap, start)
 | 
						|
	delete(f.backwardMap, start+pgid(size-1))
 | 
						|
	delete(f.freemaps[size], start)
 | 
						|
	if len(f.freemaps[size]) == 0 {
 | 
						|
		delete(f.freemaps, size)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// initial from pgids using when use hashmap version
 | 
						|
// pgids must be sorted
 | 
						|
func (f *freelist) init(pgids []pgid) {
 | 
						|
	if len(pgids) == 0 {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	size := uint64(1)
 | 
						|
	start := pgids[0]
 | 
						|
 | 
						|
	if !sort.SliceIsSorted([]pgid(pgids), func(i, j int) bool { return pgids[i] < pgids[j] }) {
 | 
						|
		panic("pgids not sorted")
 | 
						|
	}
 | 
						|
 | 
						|
	f.freemaps = make(map[uint64]pidSet)
 | 
						|
	f.forwardMap = make(map[pgid]uint64)
 | 
						|
	f.backwardMap = make(map[pgid]uint64)
 | 
						|
 | 
						|
	for i := 1; i < len(pgids); i++ {
 | 
						|
		// continuous page
 | 
						|
		if pgids[i] == pgids[i-1]+1 {
 | 
						|
			size++
 | 
						|
		} else {
 | 
						|
			f.addSpan(start, size)
 | 
						|
 | 
						|
			size = 1
 | 
						|
			start = pgids[i]
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// init the tail
 | 
						|
	if size != 0 && start != 0 {
 | 
						|
		f.addSpan(start, size)
 | 
						|
	}
 | 
						|
}
 |