Files
qb/atree/io.go

168 lines
3.2 KiB
Go
Raw Normal View History

2026-02-10 14:02:11 +00:00
package atree
import (
"fmt"
2026-06-10 06:18:45 +03:00
bin "gordenko.dev/dima/bin/little"
2026-02-23 11:02:29 +00:00
"gordenko.dev/dima/qb"
2026-06-15 05:32:15 +03:00
"gordenko.dev/dima/qb/storage"
2026-05-21 23:38:52 +03:00
"gordenko.dev/dima/qb/util"
2026-02-10 14:02:11 +00:00
)
type readResult struct {
Data []byte
Err error
}
// INDEX PAGES
2026-02-23 19:37:05 +00:00
func (s *Atree) DeletePages(pageNumbers []uint32) {
2026-02-10 14:02:11 +00:00
s.mutex.Lock()
for _, pageNo := range pageNumbers {
2026-02-23 19:37:05 +00:00
delete(s.pages, pageNo)
2026-02-10 14:02:11 +00:00
}
s.mutex.Unlock()
}
func (s *Atree) fetchIndexPage(pageNo uint32) ([]byte, error) {
2026-06-10 06:18:45 +03:00
// buf, err := s.fetchPage(pageNo)
// if err != nil {
// return nil, err
// }
// if buf[pageTypeIdx] != PageTypeIndex {
// return nil, fmt.Errorf("wrong pageType %d instead of %d", buf[pageTypeIdx], PageTypeIndex)
// }
// return buf, nil
return nil, nil
2026-02-23 19:37:05 +00:00
}
func (s *Atree) fetchDataPage(pageNo uint32) ([]byte, error) {
2026-06-15 05:32:15 +03:00
buf, err := s.fetchPage(pageNo)
if err != nil {
return nil, err
}
return buf, nil
2026-02-23 19:37:05 +00:00
}
2026-05-10 00:59:47 +00:00
func (s *Atree) fetchPage(pageNo uint32) ([]byte, error) {
2026-06-15 05:32:15 +03:00
s.mutex.Lock()
p, ok := s.pages[pageNo]
if ok {
p.ReferenceCount++
s.mutex.Unlock()
return p.Buf, nil
}
2026-06-10 06:18:45 +03:00
2026-06-15 05:32:15 +03:00
resultCh := make(chan readResult, 1)
s.pageWaits[pageNo] = append(s.pageWaits[pageNo], resultCh)
if len(s.pageWaits[pageNo]) == 1 {
s.pagesToRead = append(s.pagesToRead, pageNo)
s.mutex.Unlock()
2026-06-10 06:18:45 +03:00
2026-06-15 05:32:15 +03:00
select {
case s.readSignalCh <- struct{}{}:
default:
}
} else {
s.mutex.Unlock()
}
2026-06-10 06:18:45 +03:00
2026-06-15 05:32:15 +03:00
result := <-resultCh
if result.Err == nil {
result.Err = s.verifyCRC(result.Data, storage.DataPageSize)
}
return result.Data, result.Err
2026-02-10 14:02:11 +00:00
}
2026-02-23 19:37:05 +00:00
func (s *Atree) releasePage(pageNo uint32) {
2026-02-10 14:02:11 +00:00
s.mutex.Lock()
defer s.mutex.Unlock()
2026-02-23 19:37:05 +00:00
p, ok := s.pages[pageNo]
2026-02-10 14:02:11 +00:00
if ok {
if p.ReferenceCount > 0 {
p.ReferenceCount--
return
} else {
2026-02-23 11:02:29 +00:00
qb.Abort(
qb.ReferenceCountBug,
2026-02-23 19:37:05 +00:00
fmt.Errorf("call releasePage on page %d with reference count = %d",
2026-02-10 14:02:11 +00:00
pageNo, p.ReferenceCount),
)
}
}
}
2026-02-23 19:37:05 +00:00
// DATA PAGES
2026-02-10 14:02:11 +00:00
// READ
func (s *Atree) pageReader() {
for {
select {
case <-s.readSignalCh:
s.readPages()
}
}
}
func (s *Atree) readPages() {
2026-06-15 05:32:15 +03:00
s.mutex.Lock()
if len(s.pagesToRead) == 0 {
s.mutex.Unlock()
2026-02-10 14:02:11 +00:00
return
}
2026-06-15 05:32:15 +03:00
pagesToRead := s.pagesToRead
s.pagesToRead = nil
s.mutex.Unlock()
2026-02-10 14:02:11 +00:00
2026-06-15 05:32:15 +03:00
for _, pageNo := range pagesToRead {
buf := make([]byte, storage.DataPageSize)
off := int(pageNo-1) * storage.DataPageSize
n, err := s.file.ReadAt(buf, int64(off))
if n != storage.DataPageSize {
err = fmt.Errorf("read %d instead of %d", n, storage.DataPageSize)
}
2026-02-10 14:02:11 +00:00
2026-06-15 05:32:15 +03:00
s.mutex.Lock()
resultChannels := s.pageWaits[pageNo]
delete(s.pageWaits, pageNo)
if err != nil {
s.mutex.Unlock()
for _, resultCh := range resultChannels {
resultCh <- readResult{
Err: err,
}
}
} else {
s.pages[pageNo] = &_page{
PageNo: pageNo,
Buf: buf,
ReferenceCount: len(resultChannels),
}
s.mutex.Unlock()
for _, resultCh := range resultChannels {
resultCh <- readResult{
Data: buf,
}
}
}
2026-02-10 14:02:11 +00:00
}
}
2026-06-15 05:32:15 +03:00
// WRITE
2026-02-10 14:02:11 +00:00
func (s *Atree) verifyCRC(data []byte, pageSize int) error {
var (
pos = pageSize - 4
2026-06-13 08:01:42 +03:00
calculatedCRC = util.CalculateCRC32(data[:pos])
2026-06-10 06:18:45 +03:00
storedCRC, _ = bin.GetUint32(data[pos:])
2026-02-10 14:02:11 +00:00
)
if calculatedCRC != storedCRC {
return fmt.Errorf("calculatedCRC %d not equal storedCRC %d",
calculatedCRC, storedCRC)
}
return nil
}