You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
1.6 KiB
72 lines
1.6 KiB
package freelist
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/RoaringBitmap/roaring/v2"
|
|
)
|
|
|
|
type FreeList struct {
|
|
mutex sync.Mutex
|
|
free *roaring.Bitmap
|
|
reserved *roaring.Bitmap
|
|
}
|
|
|
|
func New() *FreeList {
|
|
return &FreeList{
|
|
free: roaring.New(),
|
|
reserved: roaring.New(),
|
|
}
|
|
}
|
|
|
|
func (s *FreeList) Restore(serialized []byte) error {
|
|
err := s.free.UnmarshalBinary(serialized)
|
|
if err != nil {
|
|
return fmt.Errorf("UnmarshalBinary: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *FreeList) AddPages(pageNumbers []uint32) {
|
|
if len(pageNumbers) == 0 {
|
|
return
|
|
}
|
|
s.mutex.Lock()
|
|
s.free.AddMany(pageNumbers)
|
|
s.mutex.Unlock()
|
|
}
|
|
|
|
// ReserveDataPage - аллокатор резервирует страницу, но не удаляет до визова
|
|
// DeleteFromFree, ибо транзакция может не завершится, а между віделением страници
|
|
// и падением транзакции - будет создан init файл.
|
|
func (s *FreeList) ReservePage() (pageNo uint32) {
|
|
s.mutex.Lock()
|
|
defer s.mutex.Unlock()
|
|
|
|
if s.free.IsEmpty() {
|
|
return
|
|
}
|
|
pageNo = s.free.Minimum()
|
|
s.free.Remove(pageNo)
|
|
s.reserved.Add(pageNo)
|
|
return
|
|
}
|
|
|
|
// Удаляет ранее зарезервированные страницы
|
|
func (s *FreeList) DeletePages(pageNumbers []uint32) {
|
|
s.mutex.Lock()
|
|
for _, pageNo := range pageNumbers {
|
|
s.reserved.Remove(pageNo)
|
|
s.free.Remove(pageNo) // прокрута TransactionLog
|
|
}
|
|
s.mutex.Unlock()
|
|
}
|
|
|
|
func (s *FreeList) Serialize() ([]byte, error) {
|
|
s.mutex.Lock()
|
|
defer s.mutex.Unlock()
|
|
tmp := roaring.Or(s.free, s.reserved)
|
|
tmp.RunOptimize()
|
|
return tmp.ToBytes()
|
|
}
|
|
|