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.
469 lines
10 KiB
469 lines
10 KiB
package proto
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
octopus "gordenko.dev/dima/diploma"
|
|
"gordenko.dev/dima/diploma/bin"
|
|
"gordenko.dev/dima/diploma/bufreader"
|
|
)
|
|
|
|
const (
|
|
TypeDeleteMeasures byte = 1
|
|
TypeListCurrentValues byte = 2
|
|
TypeListInstantMeasures byte = 3
|
|
TypeListCumulativeMeasures byte = 33
|
|
TypeListInstantPeriods byte = 4
|
|
TypeListCumulativePeriods byte = 44
|
|
TypeGetMetric byte = 5
|
|
TypeAddMetric byte = 6
|
|
TypeListAllInstantMeasures byte = 8
|
|
TypeListAllCumulativeMeasures byte = 88
|
|
TypeRangeTotal byte = 9
|
|
TypeAppendMeasure byte = 10
|
|
TypeAppendMeasures byte = 11
|
|
TypeDeleteMetric byte = 12
|
|
|
|
RespPartOfValue byte = 255
|
|
RespEndOfValue byte = 254
|
|
RespError byte = 253
|
|
RespSuccess byte = 252
|
|
RespValue byte = 251
|
|
|
|
ErrNoMetric = 1
|
|
ErrDuplicate = 2
|
|
ErrWrongMetricType = 3
|
|
ErrWrongFracDigits = 4
|
|
ErrExpiredMeasure = 5
|
|
ErrNonMonotonicValue = 6
|
|
ErrEmptyMetricID = 7
|
|
ErrInvalidRange = 8
|
|
ErrUnexpected = 9
|
|
)
|
|
|
|
func ErrorCodeToText(code uint16) string {
|
|
switch code {
|
|
case ErrNoMetric:
|
|
return "NoMetric"
|
|
case ErrDuplicate:
|
|
return "Duplicate"
|
|
case ErrWrongMetricType:
|
|
return "WrongMetricType"
|
|
case ErrWrongFracDigits:
|
|
return "WrongFracDigits"
|
|
case ErrExpiredMeasure:
|
|
return "ExpiredMeasure"
|
|
case ErrNonMonotonicValue:
|
|
return "NonMonotonicValue"
|
|
case ErrEmptyMetricID:
|
|
return "EmptyMetricID"
|
|
case ErrInvalidRange:
|
|
return "InvalidRange"
|
|
case ErrUnexpected:
|
|
return "Unexpected"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
type GetMetricReq struct {
|
|
MetricID uint32
|
|
}
|
|
|
|
type ListCurrentValuesReq struct {
|
|
MetricIDs []uint32
|
|
}
|
|
|
|
type AddMetricReq struct {
|
|
MetricID uint32
|
|
MetricType octopus.MetricType
|
|
FracDigits int
|
|
}
|
|
|
|
type UpdateMetricReq struct {
|
|
MetricID uint32
|
|
MetricType octopus.MetricType
|
|
FracDigits int
|
|
}
|
|
|
|
type DeleteMetricReq struct {
|
|
MetricID uint32
|
|
}
|
|
|
|
type DeleteMeasuresReq struct {
|
|
MetricID uint32
|
|
Since uint32 // timestamp (optional)
|
|
}
|
|
|
|
type AppendMeasureReq struct {
|
|
MetricID uint32
|
|
Timestamp uint32
|
|
Value float64
|
|
}
|
|
|
|
type ListAllInstantMetricMeasuresReq struct {
|
|
MetricID uint32
|
|
}
|
|
|
|
type ListAllCumulativeMeasuresReq struct {
|
|
MetricID uint32
|
|
}
|
|
|
|
type ListInstantMeasuresReq struct {
|
|
MetricID uint32
|
|
Since uint32
|
|
Until uint32
|
|
FirstHourOfDay int
|
|
}
|
|
|
|
type ListCumulativeMeasuresReq struct {
|
|
MetricID uint32
|
|
Since uint32
|
|
Until uint32
|
|
FirstHourOfDay int
|
|
}
|
|
|
|
type ListInstantPeriodsReq struct {
|
|
MetricID uint32
|
|
Since uint32
|
|
Until uint32
|
|
GroupBy octopus.GroupBy
|
|
AggregateFuncs byte
|
|
FirstHourOfDay int
|
|
}
|
|
|
|
type ListCumulativePeriodsReq struct {
|
|
MetricID uint32
|
|
Since uint32
|
|
Until uint32
|
|
GroupBy octopus.GroupBy
|
|
FirstHourOfDay int
|
|
}
|
|
|
|
type Metric struct {
|
|
MetricID uint32
|
|
MetricType octopus.MetricType
|
|
FracDigits int
|
|
}
|
|
|
|
type RangeTotalReq struct {
|
|
MetricID uint32
|
|
Since uint32
|
|
Until uint32
|
|
}
|
|
|
|
func PackAddMetricReq(req AddMetricReq) []byte {
|
|
arr := []byte{
|
|
TypeAddMetric,
|
|
0, 0, 0, 0, //
|
|
byte(req.MetricType),
|
|
byte(req.FracDigits),
|
|
}
|
|
bin.PutUint32(arr[1:], req.MetricID)
|
|
return arr
|
|
}
|
|
|
|
func PackDeleteMetricReq(req DeleteMetricReq) []byte {
|
|
arr := []byte{
|
|
TypeDeleteMetric,
|
|
0, 0, 0, 0, // metricID
|
|
}
|
|
bin.PutUint32(arr[1:], req.MetricID)
|
|
return arr
|
|
}
|
|
|
|
func PackAppendMeasure(req AppendMeasureReq) []byte {
|
|
arr := []byte{
|
|
TypeAppendMeasure,
|
|
0, 0, 0, 0, // metricID
|
|
0, 0, 0, 0, // timestamp
|
|
0, 0, 0, 0, 0, 0, 0, 0, // value
|
|
}
|
|
bin.PutUint32(arr[1:], req.MetricID)
|
|
bin.PutUint32(arr[5:], uint32(req.Timestamp))
|
|
bin.PutFloat64(arr[9:], req.Value)
|
|
return arr
|
|
}
|
|
|
|
func PackDeleteMeasuresReq(req DeleteMeasuresReq) []byte {
|
|
arr := []byte{
|
|
TypeDeleteMeasures,
|
|
0, 0, 0, 0, // metricID
|
|
0, 0, 0, 0, // since
|
|
}
|
|
bin.PutUint32(arr[1:], req.MetricID)
|
|
bin.PutUint32(arr[5:], uint32(req.Since))
|
|
return arr
|
|
}
|
|
|
|
// UNPACK reqs
|
|
|
|
func UnpackAddMetricReq(arr []byte) (m AddMetricReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.MetricType = octopus.MetricType(arr[4])
|
|
m.FracDigits = int(arr[5])
|
|
return
|
|
}
|
|
|
|
func UnpackUpdateMetricReq(arr []byte) (m UpdateMetricReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.MetricType = octopus.MetricType(arr[4])
|
|
m.FracDigits = int(arr[5])
|
|
return
|
|
}
|
|
|
|
func UnpackDeleteMetricReq(arr []byte) (m DeleteMetricReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
return
|
|
}
|
|
|
|
func UnpackAppendMeasureReq(arr []byte) (m AppendMeasureReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.Timestamp = bin.GetUint32(arr[4:])
|
|
m.Value = bin.GetFloat64(arr[8:])
|
|
return
|
|
}
|
|
|
|
func UnpackDeleteMeasuresReq(arr []byte) (m DeleteMeasuresReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
return
|
|
}
|
|
|
|
func UnpackListInstantMeasuresReq(arr []byte) (m ListInstantMeasuresReq) {
|
|
m.MetricID = bin.GetUint32(arr[0:])
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
m.Until = bin.GetUint32(arr[8:])
|
|
m.FirstHourOfDay = int(arr[12])
|
|
return
|
|
}
|
|
|
|
func UnpackListCumulativeMeasuresReq(arr []byte) (m ListCumulativeMeasuresReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
m.Until = bin.GetUint32(arr[8:])
|
|
m.FirstHourOfDay = int(arr[12])
|
|
return
|
|
}
|
|
|
|
func UnpackListInstantPeriodsReq(arr []byte) (m ListInstantPeriodsReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
m.Until = bin.GetUint32(arr[8:])
|
|
m.GroupBy = octopus.GroupBy(arr[12])
|
|
m.AggregateFuncs = arr[13]
|
|
m.FirstHourOfDay = int(arr[14])
|
|
return
|
|
}
|
|
|
|
func UnpackListCumulativePeriodsReq(arr []byte) (m ListCumulativePeriodsReq) {
|
|
m.MetricID = bin.GetUint32(arr[0:])
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
m.Until = bin.GetUint32(arr[8:])
|
|
m.GroupBy = octopus.GroupBy(arr[12])
|
|
m.FirstHourOfDay = int(arr[13])
|
|
return
|
|
}
|
|
|
|
func UnpackRangeTotalReq(arr []byte) (m RangeTotalReq) {
|
|
m.MetricID = bin.GetUint32(arr)
|
|
m.Since = bin.GetUint32(arr[4:])
|
|
m.Until = bin.GetUint32(arr[8:])
|
|
return
|
|
}
|
|
|
|
// READ reqs
|
|
|
|
func ReadGetMetricReq(r *bufreader.BufferedReader) (m GetMetricReq, err error) {
|
|
m.MetricID, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadAddMetricReq(r *bufreader.BufferedReader) (m AddMetricReq, err error) {
|
|
arr, err := r.ReadN(6)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackAddMetricReq(arr), nil
|
|
}
|
|
|
|
func ReadUpdateMetricReq(r *bufreader.BufferedReader) (m UpdateMetricReq, err error) {
|
|
arr, err := r.ReadN(6)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackUpdateMetricReq(arr), nil
|
|
}
|
|
|
|
func ReadDeleteMetricReq(r *bufreader.BufferedReader) (m DeleteMetricReq, err error) {
|
|
m.MetricID, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadAppendMeasureReq(r *bufreader.BufferedReader) (m AppendMeasureReq, err error) {
|
|
arr, err := r.ReadN(16)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackAppendMeasureReq(arr), nil
|
|
}
|
|
|
|
func ReadDeleteMeasuresReq(r *bufreader.BufferedReader) (m DeleteMeasuresReq, err error) {
|
|
arr, err := r.ReadN(8)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackDeleteMeasuresReq(arr), nil
|
|
}
|
|
|
|
func ReadListAllInstantMeasuresReq(r *bufreader.BufferedReader) (m ListAllInstantMetricMeasuresReq, err error) {
|
|
m.MetricID, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadListAllCumulativeMeasuresReq(r *bufreader.BufferedReader) (m ListAllCumulativeMeasuresReq, err error) {
|
|
m.MetricID, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func ReadListInstantMeasuresReq(r *bufreader.BufferedReader) (m ListInstantMeasuresReq, err error) {
|
|
arr, err := r.ReadN(13)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackListInstantMeasuresReq(arr), nil
|
|
}
|
|
|
|
func ReadListCumulativeMeasuresReq(r *bufreader.BufferedReader) (m ListCumulativeMeasuresReq, err error) {
|
|
arr, err := r.ReadN(13)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackListCumulativeMeasuresReq(arr), nil
|
|
}
|
|
|
|
func ReadListInstantPeriodsReq(r *bufreader.BufferedReader) (m ListInstantPeriodsReq, err error) {
|
|
arr, err := r.ReadN(15)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackListInstantPeriodsReq(arr), nil
|
|
}
|
|
|
|
func ReadListCumulativePeriodsReq(r *bufreader.BufferedReader) (m ListCumulativePeriodsReq, err error) {
|
|
arr, err := r.ReadN(14)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackListCumulativePeriodsReq(arr), nil
|
|
}
|
|
|
|
func ReadRangeTotalReq(r *bufreader.BufferedReader) (m RangeTotalReq, err error) {
|
|
arr, err := r.ReadN(12)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
return UnpackRangeTotalReq(arr), nil
|
|
}
|
|
|
|
func ReadListCurrentValuesReq(r *bufreader.BufferedReader) (m ListCurrentValuesReq, err error) {
|
|
qty, err := bin.ReadUint16(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read req: %s", err)
|
|
return
|
|
}
|
|
|
|
for i := range int(qty) {
|
|
var metricID uint32
|
|
metricID, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read metricID (#%d): %s", i, err)
|
|
return
|
|
}
|
|
m.MetricIDs = append(m.MetricIDs, metricID)
|
|
}
|
|
return
|
|
}
|
|
|
|
type AppendMeasuresReq struct {
|
|
MetricID uint32
|
|
Measures []Measure
|
|
}
|
|
|
|
type Measure struct {
|
|
Timestamp uint32
|
|
Value float64
|
|
}
|
|
|
|
func PackAppendMeasures(req AppendMeasuresReq) []byte {
|
|
if len(req.Measures) > 65535 {
|
|
panic(fmt.Errorf("wrong measures qty: %d", len(req.Measures)))
|
|
}
|
|
var (
|
|
prefixSize = 7
|
|
recordSize = 12
|
|
arr = make([]byte, prefixSize+len(req.Measures)*recordSize)
|
|
)
|
|
arr[0] = TypeAppendMeasures
|
|
bin.PutUint32(arr[1:], req.MetricID)
|
|
bin.PutUint16(arr[5:], uint16(len(req.Measures)))
|
|
pos := prefixSize
|
|
for _, measure := range req.Measures {
|
|
bin.PutUint32(arr[pos:], measure.Timestamp)
|
|
bin.PutFloat64(arr[pos+4:], measure.Value)
|
|
pos += recordSize
|
|
}
|
|
return arr
|
|
}
|
|
|
|
func ReadAppendMeasuresReq(r *bufreader.BufferedReader) (m AppendMeasuresReq, err error) {
|
|
prefix, err := bin.ReadN(r, 6) // metricID + measures qty
|
|
if err != nil {
|
|
err = fmt.Errorf("read prefix: %s", err)
|
|
return
|
|
}
|
|
|
|
m.MetricID = bin.GetUint32(prefix[0:])
|
|
qty := bin.GetUint16(prefix[4:])
|
|
|
|
for i := range int(qty) {
|
|
var measure Measure
|
|
measure.Timestamp, err = bin.ReadUint32(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read timestamp (#%d): %s", i, err)
|
|
return
|
|
}
|
|
measure.Value, err = bin.ReadFloat64(r)
|
|
if err != nil {
|
|
err = fmt.Errorf("read value (#%d): %s", i, err)
|
|
return
|
|
}
|
|
m.Measures = append(m.Measures, measure)
|
|
}
|
|
return
|
|
}
|
|
|