github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/query/metadata/unrotatedmeta.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package metadata 18 19 import ( 20 "sync" 21 "sync/atomic" 22 23 dtu "github.com/siglens/siglens/pkg/common/dtypeutils" 24 "github.com/siglens/siglens/pkg/segment/query/summary" 25 "github.com/siglens/siglens/pkg/segment/structs" 26 "github.com/siglens/siglens/pkg/segment/utils" 27 segutils "github.com/siglens/siglens/pkg/segment/utils" 28 "github.com/siglens/siglens/pkg/segment/writer" 29 log "github.com/sirupsen/logrus" 30 ) 31 32 // returns the search request. The bool will tell if the request is valid or not 33 func createSearchRequestForUnrotated(fileName string, tableName string, 34 filteredBlocks map[uint16]map[string]bool, 35 unrotatedInfo *writer.UnrotatedSegmentInfo) (*structs.SegmentSearchRequest, bool) { 36 if len(filteredBlocks) == 0 { 37 return nil, false 38 } 39 40 blkSum, blkMeta, unrotatedCols := unrotatedInfo.GetUnrotatedBlockInfoForQuery() 41 42 searchMeta := make(map[uint16]*structs.BlockMetadataHolder) 43 for blkNum := range filteredBlocks { 44 currBlkMeta, ok := blkMeta[blkNum] 45 if !ok { 46 log.Warnf("createSearchRequestForUnrotated: block %d does not exist in unrotated block list but passed initial filtering", 47 blkNum) 48 continue 49 } 50 searchMeta[blkNum] = currBlkMeta 51 } 52 53 finalReq := &structs.SegmentSearchRequest{ 54 SegmentKey: fileName, 55 SearchMetadata: &structs.SearchMetadataHolder{ 56 BlockSummaries: blkSum, 57 }, 58 VirtualTableName: tableName, 59 AllBlocksToSearch: searchMeta, 60 AllPossibleColumns: unrotatedCols, 61 LatestEpochMS: unrotatedInfo.GetTimeRange().EndEpochMs, 62 CmiPassedCnames: filteredBlocks, 63 } 64 return finalReq, true 65 } 66 67 // filters unrotated blocks based on search conditions 68 // returns the final search request, total blocks, sum of filtered blocks, and any errors 69 func CheckMicroIndicesForUnrotated(currQuery *structs.SearchQuery, lookupTimeRange *dtu.TimeRange, indexNames []string, 70 allBlocksToSearch map[string]map[string]*structs.BlockTracker, bloomWords map[string]bool, bloomOp utils.LogicalOperator, rangeFilter map[string]string, 71 rangeOp utils.FilterOperator, isRange bool, wildcardValue bool, qid uint64) (map[string]*structs.SegmentSearchRequest, uint64, uint64, error) { 72 73 writer.UnrotatedInfoLock.RLock() 74 defer writer.UnrotatedInfoLock.RUnlock() 75 res := make(map[string]*structs.SegmentSearchRequest) 76 matchedFiles := make(chan *structs.SegmentSearchRequest) 77 var err error 78 var wg sync.WaitGroup 79 totalUnrotatedBlocks := uint64(0) 80 totalFilteredBlocks := uint64(0) 81 82 for _, rawSearchKeys := range allBlocksToSearch { 83 for segKey, blkTracker := range rawSearchKeys { 84 usi, ok := writer.AllUnrotatedSegmentInfo[segKey] 85 if !ok { 86 log.Errorf("qid=%d, CheckMicroIndicesForUnrotated: SegKey %+v does not exist in unrotated information", qid, segKey) 87 continue 88 } 89 wg.Add(1) 90 go func(sKey string, store *writer.UnrotatedSegmentInfo, blkT *structs.BlockTracker) { 91 defer wg.Done() 92 93 filteredBlocks, maxBlocks, numFiltered, err := store.DoCMICheckForUnrotated(currQuery, lookupTimeRange, 94 blkT, bloomWords, bloomOp, rangeFilter, rangeOp, isRange, wildcardValue, qid) 95 atomic.AddUint64(&totalUnrotatedBlocks, maxBlocks) 96 atomic.AddUint64(&totalFilteredBlocks, numFiltered) 97 if err != nil { 98 log.Errorf("qid=%d, CheckMicroIndicesForUnrotated: Error getting block summaries from vtable %s and segfile %s err=%v", 99 qid, store.TableName, sKey, err) 100 } else { 101 finalReq, valid := createSearchRequestForUnrotated(sKey, store.TableName, 102 filteredBlocks, store) 103 if valid && finalReq != nil { 104 matchedFiles <- finalReq 105 } 106 } 107 }(segKey, usi, blkTracker) 108 } 109 } 110 111 go func() { 112 wg.Wait() 113 close(matchedFiles) 114 }() 115 for readRequest := range matchedFiles { 116 res[readRequest.SegmentKey] = readRequest 117 } 118 return res, totalUnrotatedBlocks, totalFilteredBlocks, err 119 120 } 121 122 func ExtractUnrotatedSSRFromSearchNode(node *structs.SearchNode, timeRange *dtu.TimeRange, indexNames []string, 123 rawSearchKeys map[string]map[string]*structs.BlockTracker, querySummary *summary.QuerySummary, qid uint64) map[string]*structs.SegmentSearchRequest { 124 // todo: better joining of intermediate results of block summaries 125 finalList := make(map[string]*structs.SegmentSearchRequest) 126 127 if node.AndSearchConditions != nil { 128 andSegmentFiles := extractUnrotatedSSRFromCondition(node.AndSearchConditions, segutils.And, timeRange, indexNames, 129 rawSearchKeys, querySummary, qid) 130 for fileName, searchReq := range andSegmentFiles { 131 if _, ok := finalList[fileName]; !ok { 132 finalList[fileName] = searchReq 133 continue 134 } 135 finalList[fileName].JoinRequest(searchReq, segutils.And) 136 } 137 } 138 139 if node.OrSearchConditions != nil { 140 orSegmentFiles := extractUnrotatedSSRFromCondition(node.OrSearchConditions, segutils.Or, timeRange, indexNames, 141 rawSearchKeys, querySummary, qid) 142 for fileName, searchReq := range orSegmentFiles { 143 if _, ok := finalList[fileName]; !ok { 144 finalList[fileName] = searchReq 145 continue 146 } 147 finalList[fileName].JoinRequest(searchReq, segutils.Or) 148 } 149 } 150 // for exclusion, only join the column info for files that exist and not the actual search request info 151 // exclusion conditions should not influence raw blocks to search 152 if node.ExclusionSearchConditions != nil { 153 exclustionSegmentFiles := extractUnrotatedSSRFromCondition(node.ExclusionSearchConditions, segutils.And, timeRange, indexNames, 154 rawSearchKeys, querySummary, qid) 155 for fileName, searchReq := range exclustionSegmentFiles { 156 if _, ok := finalList[fileName]; !ok { 157 continue 158 } 159 finalList[fileName].JoinColumnInfo(searchReq) 160 } 161 } 162 163 return finalList 164 } 165 166 func extractUnrotatedSSRFromCondition(condition *structs.SearchCondition, op segutils.LogicalOperator, timeRange *dtu.TimeRange, 167 indexNames []string, rawSearchKeys map[string]map[string]*structs.BlockTracker, querySummary *summary.QuerySummary, 168 qid uint64) map[string]*structs.SegmentSearchRequest { 169 finalSegFiles := make(map[string]*structs.SegmentSearchRequest) 170 if condition.SearchQueries != nil { 171 172 for _, query := range condition.SearchQueries { 173 rangeFilter, rangeOp, isRange := query.ExtractRangeFilterFromQuery(qid) 174 bloomWords, wildcardBloom, bloomOp := query.GetAllBlockBloomKeysToSearch() 175 res, totalUnrotatedBlocks, filteredUnrotatedBlocks, err := CheckMicroIndicesForUnrotated(query, timeRange, indexNames, 176 rawSearchKeys, bloomWords, bloomOp, rangeFilter, rangeOp, isRange, wildcardBloom, qid) 177 178 if err != nil { 179 log.Errorf("qid=%d, extractUnrotatedSSRFromCondition: an error occurred while checking unrotated data %+v", qid, err) 180 continue 181 } 182 querySummary.UpdateCMIResults(totalUnrotatedBlocks, filteredUnrotatedBlocks) 183 for fileName, searchReq := range res { 184 if _, ok := finalSegFiles[fileName]; !ok { 185 finalSegFiles[fileName] = searchReq 186 } else { 187 finalSegFiles[fileName].JoinRequest(searchReq, op) 188 } 189 } 190 } 191 } 192 193 if condition.SearchNode != nil { 194 for _, node := range condition.SearchNode { 195 segmentFiles := ExtractUnrotatedSSRFromSearchNode(node, timeRange, indexNames, rawSearchKeys, querySummary, qid) 196 for fileName, searchReq := range segmentFiles { 197 if _, ok := finalSegFiles[fileName]; !ok { 198 finalSegFiles[fileName] = searchReq 199 continue 200 } 201 finalSegFiles[fileName].JoinRequest(searchReq, op) 202 } 203 } 204 } 205 return finalSegFiles 206 }