203 lines
4.1 KiB
Go
203 lines
4.1 KiB
Go
package postgres
|
|
|
|
import (
|
|
"context"
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"sync/atomic"
|
|
)
|
|
|
|
const (
|
|
tbmeasurement string = "public.measurement"
|
|
)
|
|
|
|
const (
|
|
ChannelYCPrefix string = "TM"
|
|
ChannelYXPrefix string = "TS"
|
|
ChannelP string = "P"
|
|
ChannelQ string = "Q"
|
|
ChannelS string = "S"
|
|
ChannelPF string = "PF"
|
|
ChannelF string = "F"
|
|
ChannelDF string = "dF"
|
|
ChannelUPrefix string = "U"
|
|
)
|
|
|
|
type dataSource struct {
|
|
Type int `json:"type"`
|
|
Addr any `json:"io_address"`
|
|
}
|
|
|
|
func (ds *dataSource) Scan(value any) error {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
bytes, ok := value.([]byte)
|
|
if !ok {
|
|
return errors.New("type assertion to []byte failed")
|
|
}
|
|
return json.Unmarshal(bytes, ds)
|
|
}
|
|
|
|
func (ds *dataSource) Value() (driver.Value, error) {
|
|
return json.Marshal(ds)
|
|
}
|
|
|
|
type measurement struct {
|
|
ID int64 `gorm:"colunmn:id"`
|
|
Tag string `gorm:"column:tag"`
|
|
Size int `gorm:"column:size"`
|
|
DataSource *dataSource `gorm:"column:data_source;type:jsonb"`
|
|
// mapping TODO
|
|
}
|
|
|
|
type ChannelSize struct {
|
|
Station string
|
|
Device string
|
|
Channel string
|
|
Size int
|
|
}
|
|
|
|
// channel is original
|
|
var SSU2ChannelSizes atomic.Value
|
|
|
|
func init() {
|
|
SSU2ChannelSizes.Store(map[string][]ChannelSize{})
|
|
}
|
|
|
|
func LoadSSU2ChannelSizes() map[string][]ChannelSize {
|
|
v := SSU2ChannelSizes.Load()
|
|
if v == nil {
|
|
return nil
|
|
}
|
|
return v.(map[string][]ChannelSize)
|
|
}
|
|
|
|
func StoreSSU2ChannelSizes(m map[string][]ChannelSize) {
|
|
SSU2ChannelSizes.Store(m)
|
|
}
|
|
|
|
func GetSSU2ChannelSizesCopy() map[string][]ChannelSize {
|
|
src := LoadSSU2ChannelSizes()
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
out := make(map[string][]ChannelSize, len(src))
|
|
for k, v := range src {
|
|
cp := make([]ChannelSize, len(v))
|
|
copy(cp, v)
|
|
out[k] = cp
|
|
}
|
|
return out
|
|
}
|
|
|
|
func GetSSU2ChannelSizesFor(ssu string) []ChannelSize {
|
|
src := LoadSSU2ChannelSizes()
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
v, ok := src[ssu]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
cp := make([]ChannelSize, len(v))
|
|
copy(cp, v)
|
|
return cp
|
|
}
|
|
|
|
func GetMeasurements(ctx context.Context, batchSize int) ([]*measurement, error) {
|
|
var totalRecords []*measurement
|
|
|
|
id := int64(0)
|
|
for {
|
|
var records []*measurement
|
|
result := client.WithContext(ctx).Table(tbmeasurement).Where("id > ?", id).
|
|
Order("id ASC").Limit(batchSize).Find(&records)
|
|
|
|
if result.Error != nil {
|
|
return totalRecords, result.Error
|
|
}
|
|
|
|
length := len(records)
|
|
if length <= 0 {
|
|
break
|
|
}
|
|
id = records[length-1].ID
|
|
|
|
totalRecords = append(totalRecords, records...)
|
|
}
|
|
|
|
return totalRecords, nil
|
|
}
|
|
|
|
func GenSSU2ChannelSizes(ctx context.Context, batchSize int) error {
|
|
id := int64(0)
|
|
ssu2ChannelSizes := make(map[string][]ChannelSize)
|
|
for {
|
|
var records []*measurement
|
|
result := client.WithContext(ctx).Table(tbmeasurement).
|
|
Where("id > ?", id).Order("id ASC").Limit(batchSize).Find(&records)
|
|
|
|
if result.Error != nil {
|
|
return result.Error
|
|
}
|
|
|
|
length := len(records)
|
|
if length <= 0 {
|
|
break
|
|
}
|
|
|
|
for _, record := range records {
|
|
if record == nil || record.DataSource == nil {
|
|
continue
|
|
}
|
|
|
|
addrType := record.DataSource.Type
|
|
addr := record.DataSource.Addr
|
|
if err := genMappingFromAddr(ssu2ChannelSizes, addrType, addr, record.Size); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
id = records[length-1].ID
|
|
}
|
|
|
|
StoreSSU2ChannelSizes(ssu2ChannelSizes)
|
|
|
|
return nil
|
|
}
|
|
|
|
func genMappingFromAddr(ssu2ChannelSizes map[string][]ChannelSize, addrType int, addr any, size int) error {
|
|
switch addrType {
|
|
case 1:
|
|
if rawAddr, ok := addr.(map[string]interface{}); ok {
|
|
station, ok := rawAddr["station"].(string)
|
|
if !ok {
|
|
return errors.New("invalid station")
|
|
}
|
|
device, ok := rawAddr["device"].(string)
|
|
if !ok {
|
|
return errors.New("invalid device")
|
|
}
|
|
channel, ok := rawAddr["channel"].(string)
|
|
if !ok {
|
|
return errors.New("invalid channel")
|
|
}
|
|
ssu2ChannelSizes[device] = append(ssu2ChannelSizes[device], ChannelSize{
|
|
Station: station,
|
|
Device: device,
|
|
Channel: channel,
|
|
Size: size,
|
|
})
|
|
} else {
|
|
return errors.New("invalid io_address")
|
|
}
|
|
|
|
default:
|
|
return errors.New("invalid data_source.type")
|
|
}
|
|
|
|
return nil
|
|
}
|