This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git


The following commit(s) were added to refs/heads/main by this push:
     new 215f4bbe0 fix: avoid pooling arena-owned migration tag values (#1203)
215f4bbe0 is described below

commit 215f4bbe028ed041e00407de58071894be2fb0aa
Author: Huang Youliang <[email protected]>
AuthorDate: Tue Jul 7 16:15:48 2026 +0800

    fix: avoid pooling arena-owned migration tag values (#1203)
    
    Co-authored-by: Hongtao Gao <[email protected]>
---
 banyand/stream/test_helper.go | 110 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 93 insertions(+), 17 deletions(-)

diff --git a/banyand/stream/test_helper.go b/banyand/stream/test_helper.go
index e3cf88c67..1a36d2014 100644
--- a/banyand/stream/test_helper.go
+++ b/banyand/stream/test_helper.go
@@ -29,6 +29,7 @@ import (
        "github.com/apache/skywalking-banyandb/pkg/convert"
        "github.com/apache/skywalking-banyandb/pkg/fs"
        "github.com/apache/skywalking-banyandb/pkg/index"
+       pbv1 "github.com/apache/skywalking-banyandb/pkg/pb/v1"
 )
 
 // DumpTag describes one tag of a stream row for the dump test builder. Value 
is a
@@ -61,10 +62,14 @@ func BuildPartForDump(tmpPath string, fileSystem 
fs.FileSystem, partID uint64, r
                if r.Entity != "" {
                        r.SeriesID = 
common.SeriesID(convert.Hash([]byte(r.Entity)))
                }
+       }
+       projections := collectDumpTagProjections(rows)
+       for i := range rows {
+               r := &rows[i]
                es.seriesIDs = append(es.seriesIDs, r.SeriesID)
                es.timestamps = append(es.timestamps, r.Timestamp)
                es.elementIDs = append(es.elementIDs, r.ElementID)
-               es.tagFamilies = append(es.tagFamilies, 
buildDumpTagFamilies(r.Tags))
+               es.tagFamilies = append(es.tagFamilies, 
buildDumpTagFamilies(r.Tags, projections[r.SeriesID]))
        }
 
        mp := generateMemPart()
@@ -146,35 +151,106 @@ func EntityDumpRows(entities []string) []DumpRow {
        return rows
 }
 
-func buildDumpTagFamilies(tags []DumpTag) []tagValues {
-       order := make([]string, 0)
-       byFamily := make(map[string][]*tagValue)
-       for _, tg := range tags {
-               if _, ok := byFamily[tg.Family]; !ok {
-                       order = append(order, tg.Family)
+type dumpTagProjection struct {
+       Family string
+       Tags   []dumpProjectedTag
+}
+
+type dumpProjectedTag struct {
+       Name string
+       Type databasev1.TagType
+}
+
+func collectDumpTagProjections(rows []DumpRow) 
map[common.SeriesID][]dumpTagProjection {
+       projections := make(map[common.SeriesID][]dumpTagProjection)
+       familyIndexes := make(map[common.SeriesID]map[string]int)
+       tagIndexes := make(map[common.SeriesID]map[string]map[string]int)
+       for _, row := range rows {
+               projection := projections[row.SeriesID]
+               if familyIndexes[row.SeriesID] == nil {
+                       familyIndexes[row.SeriesID] = make(map[string]int)
+                       tagIndexes[row.SeriesID] = 
make(map[string]map[string]int)
+               }
+               for _, tag := range row.Tags {
+                       familyIdx, familyExists := 
familyIndexes[row.SeriesID][tag.Family]
+                       if !familyExists {
+                               familyIdx = len(projection)
+                               familyIndexes[row.SeriesID][tag.Family] = 
familyIdx
+                               tagIndexes[row.SeriesID][tag.Family] = 
make(map[string]int)
+                               projection = append(projection, 
dumpTagProjection{Family: tag.Family})
+                       }
+                       tagType := dumpTagType(tag.Value)
+                       if tagIdx, tagExists := 
tagIndexes[row.SeriesID][tag.Family][tag.Name]; tagExists {
+                               if projection[familyIdx].Tags[tagIdx].Type != 
tagType {
+                                       panic(fmt.Sprintf("dump tag %s.%s 
changes type from %s to %s", tag.Family, tag.Name, 
projection[familyIdx].Tags[tagIdx].Type, tagType))
+                               }
+                               continue
+                       }
+                       tagIndexes[row.SeriesID][tag.Family][tag.Name] = 
len(projection[familyIdx].Tags)
+                       projection[familyIdx].Tags = 
append(projection[familyIdx].Tags, dumpProjectedTag{Name: tag.Name, Type: 
tagType})
                }
-               byFamily[tg.Family] = append(byFamily[tg.Family], 
encodeDumpTag(tg.Name, tg.Value))
+               projections[row.SeriesID] = projection
        }
-       out := make([]tagValues, 0, len(order))
-       for _, family := range order {
-               out = append(out, tagValues{tag: family, values: 
byFamily[family]})
+       return projections
+}
+
+func buildDumpTagFamilies(tags []DumpTag, projection []dumpTagProjection) 
[]tagValues {
+       byFamily := make(map[string]map[string]*tagValue)
+       for _, tag := range tags {
+               if byFamily[tag.Family] == nil {
+                       byFamily[tag.Family] = make(map[string]*tagValue)
+               }
+               byFamily[tag.Family][tag.Name] = encodeDumpTag(tag.Name, 
tag.Value)
+       }
+       out := make([]tagValues, 0, len(projection))
+       for _, family := range projection {
+               values := make([]*tagValue, 0, len(family.Tags))
+               for _, tag := range family.Tags {
+                       if value := byFamily[family.Family][tag.Name]; value != 
nil {
+                               values = append(values, value)
+                               continue
+                       }
+                       values = append(values, encodeTagValue(tag.Name, 
tag.Type, pbv1.NullTagValue))
+               }
+               out = append(out, tagValues{tag: family.Family, values: values})
        }
        return out
 }
 
 func encodeDumpTag(name string, value any) *tagValue {
-       switch v := value.(type) {
+       return encodeTagValue(name, dumpTagType(value), dumpTagValue(name, 
value))
+}
+
+func dumpTagType(value any) databasev1.TagType {
+       switch value.(type) {
        case string:
-               return encodeTagValue(name, databasev1.TagType_TAG_TYPE_STRING, 
&modelv1.TagValue{Value: &modelv1.TagValue_Str{Str: &modelv1.Str{Value: v}}})
+               return databasev1.TagType_TAG_TYPE_STRING
        case int64:
-               return encodeTagValue(name, databasev1.TagType_TAG_TYPE_INT, 
&modelv1.TagValue{Value: &modelv1.TagValue_Int{Int: &modelv1.Int{Value: v}}})
+               return databasev1.TagType_TAG_TYPE_INT
        case []string:
-               return encodeTagValue(name, 
databasev1.TagType_TAG_TYPE_STRING_ARRAY, &modelv1.TagValue{Value: 
&modelv1.TagValue_StrArray{StrArray: &modelv1.StrArray{Value: v}}})
+               return databasev1.TagType_TAG_TYPE_STRING_ARRAY
        case []int64:
-               return encodeTagValue(name, 
databasev1.TagType_TAG_TYPE_INT_ARRAY, &modelv1.TagValue{Value: 
&modelv1.TagValue_IntArray{IntArray: &modelv1.IntArray{Value: v}}})
+               return databasev1.TagType_TAG_TYPE_INT_ARRAY
        case []byte:
-               return encodeTagValue(name, 
databasev1.TagType_TAG_TYPE_DATA_BINARY, &modelv1.TagValue{Value: 
&modelv1.TagValue_BinaryData{BinaryData: v}})
+               return databasev1.TagType_TAG_TYPE_DATA_BINARY
        default:
                panic(fmt.Sprintf("unsupported dump tag value type %T", value))
        }
 }
+
+func dumpTagValue(name string, value any) *modelv1.TagValue {
+       switch v := value.(type) {
+       case string:
+               return &modelv1.TagValue{Value: &modelv1.TagValue_Str{Str: 
&modelv1.Str{Value: v}}}
+       case int64:
+               return &modelv1.TagValue{Value: &modelv1.TagValue_Int{Int: 
&modelv1.Int{Value: v}}}
+       case []string:
+               return &modelv1.TagValue{Value: 
&modelv1.TagValue_StrArray{StrArray: &modelv1.StrArray{Value: v}}}
+       case []int64:
+               return &modelv1.TagValue{Value: 
&modelv1.TagValue_IntArray{IntArray: &modelv1.IntArray{Value: v}}}
+       case []byte:
+               return &modelv1.TagValue{Value: 
&modelv1.TagValue_BinaryData{BinaryData: v}}
+       default:
+               panic(fmt.Sprintf("unsupported dump tag %s value type %T", 
name, value))
+       }
+}

Reply via email to