This commit is contained in:
2026-06-13 22:43:17 +00:00
parent 1d1fdb1f0b
commit 685c48f94f
28 changed files with 2492 additions and 2657 deletions

View File

@@ -11,12 +11,11 @@ import (
"gordenko.dev/dima/qb/atree"
"gordenko.dev/dima/qb/bufreader"
"gordenko.dev/dima/qb/proto"
"gordenko.dev/dima/qb/storage"
"gordenko.dev/dima/qb/transform"
"gordenko.dev/dima/qb/worker"
)
var (
ErrNoValueBug = errors.New("has timestamp but no value")
ErrWrongResultCodeBug = errors.New("bug: wrong result code")
successMsg = []byte{
@@ -215,7 +214,7 @@ func (s *Database) AddMetric(req proto.AddMetricReq) uint16 {
fmt.Println("add job")
s.worker.AddJobToQueue(tryAddMetricReq{
s.workerInbox.Push(worker.AddMetricReq{
MetricID: req.MetricID,
ResultCh: resultCh,
})
@@ -225,7 +224,7 @@ func (s *Database) AddMetric(req proto.AddMetricReq) uint16 {
resultCode := <-resultCh
switch resultCode {
case Succeed:
case worker.Succeed:
fmt.Println("OK")
// s.storage.Append(storage.MetricAddRecord{
// MetricID: req.MetricID,
@@ -234,7 +233,7 @@ func (s *Database) AddMetric(req proto.AddMetricReq) uint16 {
// })
//<-waitCh
case MetricDuplicate:
case worker.MetricDuplicate:
fmt.Println("ErrDuplicate")
return proto.ErrDuplicate
@@ -245,16 +244,10 @@ func (s *Database) AddMetric(req proto.AddMetricReq) uint16 {
return 0
}
type Metric struct {
MetricType qb.MetricType
FracDigits byte
ResultCode byte
}
func (s *Database) GetMetric(conn io.Writer, req proto.GetMetricReq) error {
resultCh := make(chan Metric, 1)
resultCh := make(chan worker.GetMetricResult, 1)
s.worker.AddJobToQueue(tryGetMetricReq{
s.workerInbox.Push(worker.GetMetricReq{
MetricID: req.MetricID,
ResultCh: resultCh,
})
@@ -262,7 +255,7 @@ func (s *Database) GetMetric(conn io.Writer, req proto.GetMetricReq) error {
result := <-resultCh
switch result.ResultCode {
case Succeed:
case worker.Succeed:
answer := []byte{
proto.RespValue,
0, 0, 0, 0, // metricID
@@ -276,7 +269,7 @@ func (s *Database) GetMetric(conn io.Writer, req proto.GetMetricReq) error {
return err
}
case NoMetric:
case worker.NoMetric:
reply(conn, proto.ErrNoMetric)
default:
@@ -285,15 +278,10 @@ func (s *Database) GetMetric(conn io.Writer, req proto.GetMetricReq) error {
return nil
}
type tryDeleteMetricResult struct {
ResultCode byte
RootPageNo uint32
}
func (s *Database) DeleteMetric(req proto.DeleteMetricReq) uint16 {
resultCh := make(chan tryDeleteMetricResult, 1)
resultCh := make(chan worker.DeleteMetricResult, 1)
s.worker.AddJobToQueue(tryDeleteMetricReq{
s.workerInbox.Push(worker.DeleteMetricReq{
MetricID: req.MetricID,
ResultCh: resultCh,
})
@@ -301,7 +289,7 @@ func (s *Database) DeleteMetric(req proto.DeleteMetricReq) uint16 {
result := <-resultCh
switch result.ResultCode {
case Succeed:
case worker.Succeed:
// var (
// //freePageNumbers []uint32
// )
@@ -318,7 +306,7 @@ func (s *Database) DeleteMetric(req proto.DeleteMetricReq) uint16 {
// })
//<-waitCh
case NoMetric:
case worker.NoMetric:
return proto.ErrNoMetric
default:
@@ -337,127 +325,10 @@ type FilledPage struct {
ValuesSize uint16
}
// type tryAppendMeasureResult struct {
// MetricID uint32
// Timestamp uint32
// Value float64
// FilledPage *FilledPage
// ResultCode byte
// }
// func (s *Database) AppendMeasure(req proto.AppendMeasureReq) uint16 {
// resultCh := make(chan tryAppendMeasureResult, 1)
// s.appendJobToWorkerQueue(tryAppendMeasureReq{
// MetricID: req.MetricID,
// Timestamp: req.Timestamp,
// Value: req.Value,
// ResultCh: resultCh,
// })
// result := <-resultCh
// switch result.ResultCode {
// case CanAppend:
// waitCh := s.storage.Append(storage.AppendedMeasure{
// MetricID: req.MetricID,
// Timestamp: req.Timestamp,
// Value: req.Value,
// })
// <-waitCh
// case NewPage:
// filled := result.FilledPage
// var path atree.PathToDataPage
// if filled.RootPageNo > 0 {
// path, err := s.atree.FindPathToLastPage(filled.RootPageNo)
// if err != nil {
// // FIX
// qb.Abort(qb.WriteToAtreeFailed, err)
// }
// // for _, leg := range path.Legs {
// // pagesToRelease = append(pagesToRelease, leg.PageNo)
// // }
// if path.LastPageNo != filled.PrevPageNo {
// qb.Abort(
// qb.WrongPrevPageNo,
// fmt.Errorf("bug: last pageNo %d in tree != prev pageNo %d in _metric",
// path.LastPageNo, filled.PrevPageNo),
// )
// }
// }
// // report, err := s.atree.AppendDataPages(atree.AppendDataPageReq{
// // MetricID: req.MetricID,
// // Timestamp: req.Timestamp,
// // Value: req.Value,
// // Since: filled.Since,
// // RootPageNo: filled.RootPageNo,
// // PrevPageNo: filled.PrevPageNo,
// // TimestampsChunks: filled.TimestampsChunks,
// // TimestampsSize: filled.TimestampsSize,
// // ValuesChunks: filled.ValuesChunks,
// // ValuesSize: filled.ValuesSize,
// // })
// // if err != nil {
// // qb.Abort(qb.WriteToAtreeFailed, err)
// // }
// // _ = report
// //waitCh := s.storage.WriteAppended(path, report)
// waitCh := s.storage.Append(storage.AppendedPagesReq{
// Legs: path.Legs,
// MetricID: req.MetricID,
// Timestamp: req.Timestamp,
// Value: req.Value,
// LastPageNo: filled.PrevPageNo,
// //Pages: ,
// TimestampsChunks: filled.TimestampsChunks,
// TimestampsSize: filled.TimestampsSize,
// ValuesChunks: filled.ValuesChunks,
// ValuesSize: filled.ValuesSize,
// },
// )
// <-waitCh
// case NoMetric:
// return proto.ErrNoMetric
// case ExpiredMeasure:
// return proto.ErrExpiredMeasure
// case NonMonotonicValue:
// return proto.ErrNonMonotonicValue
// default:
// qb.Abort(qb.WrongResultCodeBug, ErrWrongResultCodeBug)
// }
// return 0
// }
type tryAppendMeasuresResult struct {
ResultCode byte
Written int
// MetricType qb.MetricType
// FracDigits byte
// Since uint32
// Until uint32
// UntilValue float64
// RootPageNo uint32
// PrevPageNo uint32
// TimestampsBuf *conbuf.ContinuousBuffer
// ValuesBuf *conbuf.ContinuousBuffer
// Timestamps qb.TimestampCompressor
// Values qb.ValueCompressor
}
func (s *Database) AppendMeasures(req proto.AppendMeasuresReq) uint16 {
resultCh := make(chan tryAppendMeasuresResult, 1)
resultCh := make(chan worker.AppendMeasuresResult, 1)
s.worker.AddJobToQueue(tryAppendMeasuresReq{
s.workerInbox.Push(worker.AppendMeasuresReq{
MetricID: req.MetricID,
Measures: req.Measures,
ResultCh: resultCh,
@@ -466,7 +337,7 @@ func (s *Database) AppendMeasures(req proto.AppendMeasuresReq) uint16 {
result := <-resultCh
switch result.ResultCode {
case CanAppend:
case worker.CanAppend:
// report, err := s.atree.AppendDataPage(atree.AppendDataPageReq{})
// if err != nil {
@@ -485,7 +356,7 @@ func (s *Database) AppendMeasures(req proto.AppendMeasuresReq) uint16 {
// <-waitCh
// }
case NoMetric:
case worker.NoMetric:
return proto.ErrNoMetric
default:
@@ -494,15 +365,10 @@ func (s *Database) AppendMeasures(req proto.AppendMeasuresReq) uint16 {
return 0
}
type tryDeleteMeasuresResult struct {
ResultCode byte
RootPageNo uint32
}
func (s *Database) DeleteMeasures(req proto.DeleteMeasuresReq) uint16 {
resultCh := make(chan tryDeleteMeasuresResult, 1)
resultCh := make(chan worker.DeleteMeasuresResult, 1)
s.worker.AddJobToQueue(tryDeleteMeasuresReq{
s.workerInbox.Push(worker.DeleteMeasuresReq{
MetricID: req.MetricID,
Since: req.Since,
ResultCh: resultCh,
@@ -511,17 +377,17 @@ func (s *Database) DeleteMeasures(req proto.DeleteMeasuresReq) uint16 {
result := <-resultCh
switch result.ResultCode {
case NoMeasuresToDelete:
case worker.NoMeasuresToDelete:
// ok
case DeleteFromAtreeNotNeeded:
case worker.DeleteFromAtreeNotNeeded:
// регистрирую удаление в TransactionLog
s.storage.Append(storage.MeasuresDeleteRecord{
MetricID: req.MetricID,
})
// s.storage.Append(storage.MeasuresDeleteRecord{
// MetricID: req.MetricID,
// })
//<-waitCh
case DeleteFromAtreeRequired:
case worker.DeleteFromAtreeRequired:
// собираю номера всех data и index страниц метрики (типа запись REDO лога).
// pageNumbers, err := s.atree.GetAllPages(req.MetricID)
// if err != nil {
@@ -534,7 +400,7 @@ func (s *Database) DeleteMeasures(req proto.DeleteMeasuresReq) uint16 {
// })
//<-waitCh
case NoMetric:
case worker.NoMetric:
return proto.ErrNoMetric
default:
@@ -545,12 +411,6 @@ func (s *Database) DeleteMeasures(req proto.DeleteMeasuresReq) uint16 {
// SELECT
type fullScanResult struct {
ResultCode byte
FracDigits byte
LastPageNo uint32
}
func (s *Database) ListAllInstantMeasures(conn net.Conn, req proto.ListAllInstantMetricMeasuresReq) error {
responseWriter := transform.NewInstantMeasureWriter(conn, 0)
@@ -609,13 +469,6 @@ func (s *Database) ListCumulativeMeasures(conn net.Conn, req proto.ListCumulativ
})
}
type rangeScanResult struct {
ResultCode byte
FracDigits byte
RootPageNo uint32
LastPageNo uint32
}
func (s *Database) ListInstantPeriods(conn net.Conn, req proto.ListInstantPeriodsReq) error {
since, until := timeBoundsOfAggregation(req.Since, req.Until, req.GroupBy, req.FirstHourOfDay)
if since.After(until) {
@@ -681,9 +534,9 @@ type rangeScanReq struct {
}
func (s *Database) rangeScan(req rangeScanReq) error {
resultCh := make(chan rangeScanResult, 1)
resultCh := make(chan worker.RangeScanResult, 1)
s.worker.AddJobToQueue(tryRangeScanReq{
s.workerInbox.Push(worker.RangeScanReq{
MetricID: req.MetricID,
Since: req.Since,
Until: req.Until,
@@ -695,44 +548,44 @@ func (s *Database) rangeScan(req rangeScanReq) error {
result := <-resultCh
switch result.ResultCode {
case QueryDone:
case worker.QueryDone:
req.ResponseWriter.Close()
case UntilFound:
err := s.atree.ContinueRangeScan(atree.ContinueRangeScanReq{
FracDigits: result.FracDigits,
ResponseWriter: req.ResponseWriter,
LastPageNo: result.LastPageNo,
Since: req.Since,
})
case worker.UntilFound:
// err := s.atree.ContinueRangeScan(atree.ContinueRangeScanReq{
// FracDigits: result.FracDigits,
// ResponseWriter: req.ResponseWriter,
// LastPageNo: result.LastPageNo,
// Since: req.Since,
// })
//s.metricRUnlock(req.MetricID)
if err != nil {
reply(req.Conn, proto.ErrUnexpected)
} else {
req.ResponseWriter.Close()
}
// if err != nil {
// reply(req.Conn, proto.ErrUnexpected)
// } else {
// req.ResponseWriter.Close()
// }
case UntilNotFound:
err := s.atree.RangeScan(atree.RangeScanReq{
FracDigits: result.FracDigits,
ResponseWriter: req.ResponseWriter,
RootPageNo: result.RootPageNo,
Since: req.Since,
Until: req.Until,
})
case worker.UntilNotFound:
// err := s.atree.RangeScan(atree.RangeScanReq{
// FracDigits: result.FracDigits,
// ResponseWriter: req.ResponseWriter,
// RootPageNo: result.RootPageNo,
// Since: req.Since,
// Until: req.Until,
// })
//s.metricRUnlock(req.MetricID)
if err != nil {
reply(req.Conn, proto.ErrUnexpected)
} else {
req.ResponseWriter.Close()
}
// if err != nil {
// reply(req.Conn, proto.ErrUnexpected)
// } else {
// req.ResponseWriter.Close()
// }
case NoMetric:
case worker.NoMetric:
reply(req.Conn, proto.ErrNoMetric)
case WrongMetricType:
case worker.WrongMetricType:
reply(req.Conn, proto.ErrWrongMetricType)
default:
@@ -749,9 +602,9 @@ type fullScanReq struct {
}
func (s *Database) fullScan(req fullScanReq) error {
resultCh := make(chan fullScanResult, 1)
resultCh := make(chan worker.FullScanResult, 1)
s.worker.AddJobToQueue(tryFullScanReq{
s.workerInbox.Push(worker.FullScanReq{
MetricID: req.MetricID,
MetricType: req.MetricType,
ResponseWriter: req.ResponseWriter,
@@ -761,26 +614,26 @@ func (s *Database) fullScan(req fullScanReq) error {
result := <-resultCh
switch result.ResultCode {
case QueryDone:
case worker.QueryDone:
req.ResponseWriter.Close()
case UntilFound:
err := s.atree.ContinueFullScan(atree.ContinueFullScanReq{
FracDigits: result.FracDigits,
ResponseWriter: req.ResponseWriter,
LastPageNo: result.LastPageNo,
})
s.worker.AddJobToQueue(req.MetricID)
if err != nil {
reply(req.Conn, proto.ErrUnexpected)
} else {
req.ResponseWriter.Close()
}
case worker.UntilFound:
// err := s.atree.ContinueFullScan(atree.ContinueFullScanReq{
// FracDigits: result.FracDigits,
// ResponseWriter: req.ResponseWriter,
// LastPageNo: result.LastPageNo,
// })
// s.worker.AddJobToQueue(req.MetricID)
// if err != nil {
// reply(req.Conn, proto.ErrUnexpected)
// } else {
// req.ResponseWriter.Close()
// }
case NoMetric:
case worker.NoMetric:
reply(req.Conn, proto.ErrNoMetric)
case WrongMetricType:
case worker.WrongMetricType:
reply(req.Conn, proto.ErrWrongMetricType)
default:
@@ -795,7 +648,7 @@ func (s *Database) ListCurrentValues(conn net.Conn, req proto.ListCurrentValuesR
resultCh := make(chan struct{})
s.worker.AddJobToQueue(tryListCurrentValuesReq{
s.workerInbox.Push(worker.ListCurrentValuesReq{
MetricIDs: req.MetricIDs,
ResponseWriter: responseWriter,
ResultCh: resultCh,