package bolt import ( "encoding/json" "fmt" "git.pyer.club/kingecg/gotidb/pkg/engine" bolt "go.etcd.io/bbolt" ) // loadStats 从数据库加载统计信息 func (b *BoltEngine) loadStats() error { return b.db.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(metaBucketName)) if bucket == nil { return fmt.Errorf("meta bucket not found") } statsData := bucket.Get([]byte(statsKey)) if statsData == nil { // 没有保存的统计信息,使用默认值 return nil } if err := json.Unmarshal(statsData, &b.stats); err != nil { return fmt.Errorf("failed to unmarshal stats: %v", err) } return nil }) } // saveStats 将统计信息保存到数据库 func (b *BoltEngine) saveStats() error { return b.db.Update(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(metaBucketName)) if bucket == nil { return fmt.Errorf("meta bucket not found") } statsData, err := json.Marshal(b.stats) if err != nil { return fmt.Errorf("failed to marshal stats: %v", err) } if err := bucket.Put([]byte(statsKey), statsData); err != nil { return fmt.Errorf("failed to save stats: %v", err) } return nil }) } // updateSeriesCount 更新序列数统计信息 func (b *BoltEngine) updateSeriesCount() error { var count int64 err := b.db.View(func(tx *bolt.Tx) error { indexBucket := tx.Bucket([]byte(indexBucketName)) if indexBucket == nil { return fmt.Errorf("index bucket not found") } count = int64(indexBucket.Stats().KeyN) return nil }) if err != nil { return err } b.stats.SeriesCount = count return nil } // matchTags 检查数据点的标签是否匹配查询标签 func matchTags(pointTags, queryTags map[string]string) bool { for k, v := range queryTags { if pointTags[k] != v { return false } } return true } // calculateAggregate 计算聚合值 func calculateAggregate(points []engine.DataPoint, aggregateType engine.AggregateType) float64 { if len(points) == 0 { return 0 } switch aggregateType { case engine.AggregateTypeAvg: sum := 0.0 for _, p := range points { sum += p.Value } return sum / float64(len(points)) case engine.AggregateTypeSum: sum := 0.0 for _, p := range points { sum += p.Value } return sum case engine.AggregateTypeMin: min := points[0].Value for _, p := range points { if p.Value < min { min = p.Value } } return min case engine.AggregateTypeMax: max := points[0].Value for _, p := range points { if p.Value > max { max = p.Value } } return max case engine.AggregateTypeCount: return float64(len(points)) default: return 0 } }