@@ -22,22 +22,6 @@ import (
2222 "google.golang.org/api/iterator"
2323)
2424
25- type FilesRecord struct {
26- Session string
27- FilePath string
28- Instrumented int64
29- Covered int64
30- LinesInstrumented []int64
31- HitCounts []int64
32- Manager string // "*" means "collected from all managers"
33- }
34-
35- type FileSubsystems struct {
36- Namespace string
37- FilePath string
38- Subsystems []string
39- }
40-
4125type HistoryRecord struct {
4226 Session string
4327 Time time.Time
@@ -49,6 +33,25 @@ type HistoryRecord struct {
4933 TotalRows int64
5034}
5135
36+ type MergedCoverageRecord struct {
37+ Manager string
38+ FilePath string
39+ FileData * Coverage
40+ }
41+
42+ // FuncLines represents the 'functions' table records.
43+ // It could be used to maps 'hitcounts' from 'files' table to the function names.
44+ type FuncLines struct {
45+ FilePath string
46+ FuncName string
47+ Lines []int64 // List of lines we know belong to this function name according to the addr2line output.
48+ }
49+
50+ type JSONLWrapper struct {
51+ MCR * MergedCoverageRecord
52+ FL * FuncLines
53+ }
54+
5255type Coverage struct {
5356 Instrumented int64
5457 Covered int64
@@ -65,23 +68,27 @@ func (c *Coverage) AddLineHitCount(line int, hitCount int64) {
6568 }
6669}
6770
68- type MergedCoverageRecord struct {
69- Manager string
70- FilePath string
71- FileData * Coverage
71+ type filesRecord struct {
72+ Session string
73+ FilePath string
74+ Instrumented int64
75+ Covered int64
76+ LinesInstrumented []int64
77+ HitCounts []int64
78+ Manager string // "*" means "collected from all managers"
7279}
7380
74- // FuncLines represents the 'functions' table records.
75- // It could be used to maps 'hitcounts' from 'files' table to the function names.
76- type FuncLines struct {
81+ type functionsRecord struct {
82+ Session string
7783 FilePath string
7884 FuncName string
79- Lines []int64 // List of lines we know belong to this function name according to the addr2line output.
85+ Lines []int64
8086}
8187
82- type JSONLWrapper struct {
83- MCR * MergedCoverageRecord
84- FL * FuncLines
88+ type fileSubsystems struct {
89+ Namespace string
90+ FilePath string
91+ Subsystems []string
8592}
8693
8794func SaveMergeResult (ctx context.Context , client spannerclient.SpannerClient , descr * HistoryRecord , dec * json.Decoder ,
@@ -94,23 +101,26 @@ func SaveMergeResult(ctx context.Context, client spannerclient.SpannerClient, de
94101 ssCache := make (map [string ][]string )
95102
96103 session := uuid .New ().String ()
97- mutations := []* spanner.Mutation {}
104+ var mutations []* spanner.Mutation
98105
99106 for {
100- var mcr MergedCoverageRecord
101- err := dec .Decode (& mcr )
107+ var wr JSONLWrapper
108+ err := dec .Decode (& wr )
102109 if err == io .EOF {
103110 break
104111 }
105112 if err != nil {
106113 return rowsCreated , fmt .Errorf ("dec.Decode(MergedCoverageRecord): %w" , err )
107114 }
108- if mcr .FileData == nil {
109- return rowsCreated , errors .New ("field MergedCoverageRecord.FileData can't be nil" )
115+ if mcr := wr .MCR ; mcr != nil {
116+ mutations = append (mutations , fileRecordMutation (session , mcr ))
117+ subsystems := getFileSubsystems (mcr .FilePath , ssMatcher , ssCache )
118+ mutations = append (mutations , fileSubsystemsMutation (descr .Namespace , mcr .FilePath , subsystems ))
119+ } else if fl := wr .FL ; fl != nil {
120+ mutations = append (mutations , fileFunctionsMutation (session , fl ))
121+ } else {
122+ return rowsCreated , errors .New ("JSONLWrapper can't be empty" )
110123 }
111- mutations = append (mutations , fileRecordMutation (session , & mcr ))
112- subsystems := fileSubsystems (mcr .FilePath , ssMatcher , ssCache )
113- mutations = append (mutations , fileSubsystemsMutation (descr .Namespace , mcr .FilePath , subsystems ))
114124 // There is a limit on the number of mutations per transaction (80k) imposed by the DB.
115125 // This includes both explicit mutations of the fields (6 fields * 1k records = 6k mutations)
116126 // and implicit index mutations.
@@ -203,8 +213,21 @@ func historyMutation(session string, template *HistoryRecord) *spanner.Mutation
203213 return historyInsert
204214}
205215
216+ func fileFunctionsMutation (session string , fl * FuncLines ) * spanner.Mutation {
217+ insert , err := spanner .InsertOrUpdateStruct ("functions" , & functionsRecord {
218+ Session : session ,
219+ FilePath : fl .FilePath ,
220+ FuncName : fl .FuncName ,
221+ Lines : fl .Lines ,
222+ })
223+ if err != nil {
224+ panic (fmt .Sprintf ("failed to fileFunctionsMutation: %v" , err ))
225+ }
226+ return insert
227+ }
228+
206229func fileRecordMutation (session string , mcr * MergedCoverageRecord ) * spanner.Mutation {
207- insert , err := spanner .InsertOrUpdateStruct ("files" , & FilesRecord {
230+ insert , err := spanner .InsertOrUpdateStruct ("files" , & filesRecord {
208231 Session : session ,
209232 FilePath : mcr .FilePath ,
210233 Instrumented : mcr .FileData .Instrumented ,
@@ -220,7 +243,7 @@ func fileRecordMutation(session string, mcr *MergedCoverageRecord) *spanner.Muta
220243}
221244
222245func fileSubsystemsMutation (ns , filePath string , subsystems []string ) * spanner.Mutation {
223- insert , err := spanner .InsertOrUpdateStruct ("file_subsystems" , & FileSubsystems {
246+ insert , err := spanner .InsertOrUpdateStruct ("file_subsystems" , & fileSubsystems {
224247 Namespace : ns ,
225248 FilePath : filePath ,
226249 Subsystems : subsystems ,
@@ -231,7 +254,7 @@ func fileSubsystemsMutation(ns, filePath string, subsystems []string) *spanner.M
231254 return insert
232255}
233256
234- func fileSubsystems (filePath string , ssMatcher * subsystem.PathMatcher , ssCache map [string ][]string ) []string {
257+ func getFileSubsystems (filePath string , ssMatcher * subsystem.PathMatcher , ssCache map [string ][]string ) []string {
235258 sss , cached := ssCache [filePath ]
236259 if ! cached {
237260 for _ , match := range ssMatcher .Match (filePath ) {
0 commit comments