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  }