225 lines
4.5 KiB
Go
225 lines
4.5 KiB
Go
package atree
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"sync"
|
|
)
|
|
|
|
const (
|
|
filePerm = 0666
|
|
)
|
|
|
|
type PeriodsWriter interface {
|
|
Feed(uint32, float64)
|
|
FeedNoSend(uint32, float64)
|
|
Close() error
|
|
}
|
|
|
|
type WorkerMeasureConsumer interface {
|
|
FeedNoSend(uint32, float64)
|
|
}
|
|
|
|
type AtreeMeasureConsumer interface {
|
|
Feed(uint32, float64)
|
|
}
|
|
|
|
//
|
|
|
|
type _page struct {
|
|
PageNo uint32
|
|
Buf []byte
|
|
ReferenceCount int
|
|
}
|
|
|
|
type Atree struct {
|
|
indexFile *os.File
|
|
dataFile *os.File
|
|
mutex sync.Mutex
|
|
pages map[uint32]*_page
|
|
pageWaits map[uint32][]chan readResult
|
|
pagesToRead []uint32
|
|
readSignalCh chan struct{}
|
|
}
|
|
|
|
type Options struct {
|
|
IndexFile *os.File
|
|
DataFile *os.File
|
|
}
|
|
|
|
func New(opt Options) (*Atree, error) {
|
|
if opt.IndexFile == nil {
|
|
return nil, errors.New("IndexFile option is required")
|
|
}
|
|
if opt.DataFile == nil {
|
|
return nil, errors.New("DataFile option is required")
|
|
}
|
|
s := &Atree{
|
|
indexFile: opt.IndexFile,
|
|
dataFile: opt.DataFile,
|
|
pages: make(map[uint32]*_page),
|
|
pageWaits: make(map[uint32][]chan readResult),
|
|
readSignalCh: make(chan struct{}, 1),
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
func (s *Atree) Run() {
|
|
//go s.pageWriter()
|
|
go s.pageReader()
|
|
}
|
|
|
|
// FIND
|
|
|
|
func (s *Atree) findDataPage(rootPageNo uint32, timestamp uint32) (uint32, []byte, error) {
|
|
// indexPageNo := rootPageNo
|
|
// for {
|
|
// buf, err := s.fetchIndexPage(indexPageNo)
|
|
// if err != nil {
|
|
// return 0, nil, fmt.Errorf("fetchIndexPage(%d): %s", indexPageNo, err)
|
|
// }
|
|
|
|
// foundPageNo := findPageNo(buf, timestamp)
|
|
// s.releasePage(indexPageNo)
|
|
|
|
// // fix
|
|
// if buf[isLastLevelIdx] == 1 {
|
|
// buf, err := s.fetchDataPage(foundPageNo)
|
|
// if err != nil {
|
|
// return 0, nil, fmt.Errorf("fetchDataPage(%d): %s", foundPageNo, err)
|
|
// }
|
|
// return foundPageNo, buf, nil
|
|
// }
|
|
// // вглубь
|
|
// indexPageNo = foundPageNo
|
|
// }
|
|
return 0, nil, nil
|
|
}
|
|
|
|
type PathLeg struct {
|
|
PageNo uint32
|
|
Data []byte
|
|
}
|
|
|
|
type PathToDataPage struct {
|
|
Legs []PathLeg
|
|
LastPageNo uint32
|
|
}
|
|
|
|
func (s *Atree) FindPathToLastPage(rootPageNo uint32) (_ PathToDataPage, err error) {
|
|
// var (
|
|
// pageNo = rootPageNo
|
|
// legs []PathLeg
|
|
// )
|
|
|
|
// for {
|
|
// var buf []byte
|
|
// buf, err = s.fetchIndexPage(pageNo)
|
|
// if err != nil {
|
|
// err = fmt.Errorf("FetchIndexPage(%d): %s", pageNo, err)
|
|
// return
|
|
// }
|
|
|
|
// legs = append(legs, PathLeg{
|
|
// PageNo: pageNo,
|
|
// Data: buf,
|
|
// // childIdx не нужен
|
|
// })
|
|
|
|
// foundPageNo := getLastPageNo(buf)
|
|
|
|
// // fix
|
|
// if buf[isLastLevelIdx] == 1 {
|
|
// return PathToDataPage{
|
|
// Legs: legs,
|
|
// LastPageNo: foundPageNo,
|
|
// }, nil
|
|
// }
|
|
// // вглубь
|
|
// pageNo = foundPageNo
|
|
// }
|
|
return
|
|
}
|
|
|
|
// DELETE
|
|
|
|
type Level struct {
|
|
PageNo uint32
|
|
PageData []byte
|
|
Idx int
|
|
ChildQty int
|
|
}
|
|
|
|
func (s *Atree) GetAllPages(rootPageNo uint32) (_ []uint32, err error) {
|
|
// var (
|
|
// pageNumbers []uint32
|
|
// levels []*Level
|
|
// )
|
|
|
|
// buf, err := s.fetchIndexPage(rootPageNo)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("fetchIndexPage(%d): %s", rootPageNo, err)
|
|
// }
|
|
// pageNumbers = append(pageNumbers, rootPageNo)
|
|
|
|
// // if buf[isDataPageNumbersIdx] == 1 {
|
|
// // pageNumbers := listPageNumbers(buf)
|
|
// // dataPages = append(dataPages, pageNumbers...)
|
|
|
|
// // s.releasePage(rootPageNo)
|
|
|
|
// // return PageLists{
|
|
// // DataPages: dataPages,
|
|
// // IndexPages: indexPages,
|
|
// // }, nil
|
|
// // }
|
|
|
|
// childQty, _ := bin.GetUint16(buf[indexRecordsQtyIdx:])
|
|
|
|
// levels = append(levels, &Level{
|
|
// PageNo: rootPageNo,
|
|
// PageData: buf,
|
|
// Idx: 0,
|
|
// ChildQty: int(childQty),
|
|
// })
|
|
|
|
// for {
|
|
// if len(levels) == 0 {
|
|
// return pageNumbers, nil
|
|
// }
|
|
|
|
// lastIdx := len(levels) - 1
|
|
// level := levels[lastIdx]
|
|
|
|
// if level.Idx < level.ChildQty {
|
|
// pageNo := getPageNo(level.PageData, level.Idx)
|
|
// level.Idx++
|
|
|
|
// var buf []byte
|
|
// buf, err = s.fetchPage(pageNo)
|
|
// if err != nil {
|
|
// return nil, fmt.Errorf("fetchPage(%d): %s", pageNo, err)
|
|
// }
|
|
// pageNumbers = append(pageNumbers, pageNo)
|
|
|
|
// if buf[pageTypeIdx] == PageTypeData {
|
|
// //pageNumbers := listPageNumbers(buf)
|
|
// //dataPages = append(dataPages, pageNumbers...)
|
|
// s.releasePage(pageNo)
|
|
// } else {
|
|
// childQty, _ = bin.GetUint16(buf[indexRecordsQtyIdx:])
|
|
// levels = append(levels, &Level{
|
|
// PageNo: pageNo,
|
|
// PageData: buf,
|
|
// Idx: 0,
|
|
// ChildQty: int(childQty),
|
|
// })
|
|
// }
|
|
// } else {
|
|
// s.releasePage(level.PageNo)
|
|
// levels = levels[:lastIdx]
|
|
// }
|
|
// }
|
|
return
|
|
}
|