public static IMergeAlgorithm GetMergeAlgo(MergeAlgo ma, Type type) { IMergeAlgorithm a; m_MergeAlgorithms.TryGetValue(new MergeAlgoKey(ma, type), out a); return(a); }
public MergeAlgoKey(MergeAlgo algo, Type ColumnDataType) { this.algo = algo; this.type = ColumnDataType; }
public override SpanQueryResult MergeResults(IList <SpanQueryResult> partialResults) { SpanQueryResult finalResult = default(SpanQueryResult); if (partialResults == null || partialResults.Count == 0) { return(finalResult); } // We have partialResults to process ByteArrayEqualityComparer byteArrayEqualityComparer = new ByteArrayEqualityComparer(); Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> completeIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); if (partialResults.Count == 1) { #region Just one cluster was targeted, so no need to merge anything finalResult = partialResults[0]; #endregion } else { #region More than one clusters was targeted List <ResultItem> completeResultItemList = new List <ResultItem>(); BaseComparer baseComparer; int totalCount = 0; int additionalAvailableItemCount = 0; foreach (SpanQueryResult partialResult in partialResults) { if (partialResult != null) { #region Compute TotalCount totalCount += partialResult.TotalCount; #endregion #region Compute PageableItemCount if (GetAdditionalAvailableItemCount) { additionalAvailableItemCount += partialResult.AdditionalAvailableItemCount; } #endregion #region Merge Results if (partialResult.ResultItemList != null && partialResult.ResultItemList.Count > 0) { baseComparer = new BaseComparer(partialResult.IsTagPrimarySort, partialResult.SortFieldName, partialResult.SortOrderList); MergeAlgo.MergeItemLists(ref completeResultItemList, partialResult.ResultItemList, MaxMergeCount, baseComparer); } #endregion #region Update IndexIdIndexHeaderMapping if (GetIndexHeaderType != GetIndexHeaderType.None && partialResult.IndexIdIndexHeaderMapping != null && partialResult.IndexIdIndexHeaderMapping.Count > 0) { foreach (KeyValuePair <byte[], IndexHeader> kvp in partialResult.IndexIdIndexHeaderMapping) { if (!completeIndexIdIndexHeaderMapping.ContainsKey(kvp.Key)) { completeIndexIdIndexHeaderMapping.Add(kvp.Key, kvp.Value); } } } #endregion } } #region Create FinalResult finalResult = new SpanQueryResult { ResultItemList = completeResultItemList, TotalCount = totalCount, AdditionalAvailableItemCount = additionalAvailableItemCount, }; if (GetIndexHeaderType != GetIndexHeaderType.None && completeIndexIdIndexHeaderMapping.Count > 0) { finalResult.IndexIdIndexHeaderMapping = completeIndexIdIndexHeaderMapping; } #endregion #endregion } #region Spanning and Update IndexIdIndexHeaderMapping if required if (ClientSideSubsetProcessingRequired && Span != 0 && finalResult != null) { #region Spanning List <ResultItem> filteredResultItemList = new List <ResultItem>(); if (finalResult.ResultItemList.Count >= Offset) { for (int i = Offset - 1; i < finalResult.ResultItemList.Count && filteredResultItemList.Count < Span; i++) { filteredResultItemList.Add(finalResult.ResultItemList[i]); } } finalResult.ResultItemList = filteredResultItemList; #endregion #region Update IndexIdIndexHeaderMapping to only include metadata relevant after paging if (partialResults.Count != 1 && GetIndexHeaderType == GetIndexHeaderType.ResultItemsIndexIds && completeIndexIdIndexHeaderMapping.Count > 0) { Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> filteredIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); foreach (ResultItem resultItem in finalResult.ResultItemList) { if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } finalResult.IndexIdIndexHeaderMapping = filteredIndexIdIndexHeaderMapping.Count > 0 ? filteredIndexIdIndexHeaderMapping : null; } #endregion } #endregion return(finalResult); }
/// <summary> /// Processes the specified query. /// </summary> /// <param name="query">The query.</param> /// <param name="messageContext">The message context.</param> /// <param name="storeContext">The store context.</param> /// <returns>Query Result</returns> internal TQueryResult Process(BaseMultiIndexIdQuery <TQueryResult> query, MessageContext messageContext, IndexStoreContext storeContext) { TQueryResult result; List <ResultItem> resultItemList = new List <ResultItem>(); Dictionary <byte[], IndexHeader> indexIdIndexHeaderMapping = null; bool isTagPrimarySort = false; string sortFieldName = null; List <SortOrder> sortOrderList = null; int totalCount = 0; int additionalAvailableItemCount = 0; GroupByResult groupByResult = null; StringBuilder exceptionInfo = new StringBuilder(); int indexCap = 0; IndexTypeMapping indexTypeMapping = storeContext.StorageConfiguration.CacheIndexV3StorageConfig.IndexTypeMappingCollection[messageContext.TypeId]; try { if (query.IndexIdList.Count > 0) { #region Validate Query ValidateQuery(indexTypeMapping, query, messageContext); #endregion #region Set sort vars Index targetIndexInfo = indexTypeMapping.IndexCollection[query.TargetIndexName]; indexCap = targetIndexInfo.MaxIndexSize; if (query.TagSort != null) { isTagPrimarySort = query.TagSort.IsTag; sortFieldName = query.TagSort.TagName; sortOrderList = new List <SortOrder>(1) { query.TagSort.SortOrder }; } else { isTagPrimarySort = targetIndexInfo.PrimarySortInfo.IsTag; sortFieldName = targetIndexInfo.PrimarySortInfo.FieldName; sortOrderList = targetIndexInfo.PrimarySortInfo.SortOrderList; } BaseComparer baseComparer = new BaseComparer(isTagPrimarySort, sortFieldName, sortOrderList); groupByResult = new GroupByResult(baseComparer); #endregion #region Prepare ResultList CacheIndexInternal targetIndex; IndexIdParams indexIdParam; int maxExtractCount; byte[] metadata; MetadataPropertyCollection metadataPropertyCollection; Dictionary <KeyValuePair <byte[], string>, CacheIndexInternal> internalIndexDictionary = new Dictionary <KeyValuePair <byte[], string>, CacheIndexInternal>(); int maxMergeCount = query.MaxMergeCount; IndexCondition queryIndexCondition = query.IndexCondition; for (int i = 0; i < query.IndexIdList.Count; i++) { #region Extract index and apply criteria indexIdParam = query.GetParamsForIndexId(query.IndexIdList[i]); maxExtractCount = ComputeMaxExtractCount(indexIdParam.MaxItems, query.GetAdditionalAvailableItemCount, indexIdParam.Filter, query.MaxMergeCount); // Note: This should be changed later and just extracted once if it is also requested in GetIndexHeader metadata = null; metadataPropertyCollection = null; if (indexTypeMapping.MetadataStoredSeperately) { IndexServerUtils.GetMetadataStoredSeperately(indexTypeMapping, messageContext.TypeId, messageContext.PrimaryId, query.IndexIdList[i], storeContext, out metadata, out metadataPropertyCollection); } targetIndex = IndexServerUtils.GetCacheIndexInternal(storeContext, messageContext.TypeId, (query.PrimaryIdList != null && i < query.PrimaryIdList.Count) ? query.PrimaryIdList[i] : IndexCacheUtils.GeneratePrimaryId(query.IndexIdList[i]), query.IndexIdList[i], targetIndexInfo.ExtendedIdSuffix, query.TargetIndexName, maxExtractCount, indexIdParam.Filter, true, queryIndexCondition, false, false, targetIndexInfo.PrimarySortInfo, targetIndexInfo.LocalIdentityTagList, targetIndexInfo.StringHashCodeDictionary, query.CapCondition, targetIndexInfo.IsMetadataPropertyCollection, metadataPropertyCollection, query.DomainSpecificProcessingType, storeContext.DomainSpecificConfig, null, query.GroupBy, false); #endregion if (targetIndex != null) { totalCount += targetIndex.OutDeserializationContext.TotalCount; additionalAvailableItemCount += targetIndex.Count; internalIndexDictionary.Add(new KeyValuePair <byte[], string>(query.IndexIdList[i], query.TargetIndexName), targetIndex); SetItemCounter(messageContext.TypeId, targetIndex.OutDeserializationContext); #region Dynamic tag sort if (query.TagSort != null) { targetIndex.Sort(query.TagSort); } #endregion #region Get items from index and merge if (query.GroupBy == null) { MergeAlgo.MergeItemLists(ref resultItemList, CacheIndexInternalAdapter.GetResultItemList(targetIndex, 1, int.MaxValue), query.MaxMergeCount, baseComparer); } else { MergeAlgo.MergeGroupResult(ref groupByResult, targetIndex.GroupByResult, query.MaxMergeCount, baseComparer); } if ((i != query.IndexIdList.Count - 1) && (resultItemList.Count == maxMergeCount)) { AdjustIndexCondition(GetConditionBoundaryBytes(resultItemList, groupByResult, query.GroupBy, isTagPrimarySort, sortFieldName), ref queryIndexCondition, baseComparer); } #endregion } } #endregion #region Subset Processing ProcessSubsets(query, ref resultItemList, ref groupByResult, baseComparer); #endregion #region Get Extra Tags for IndexIds in the list //Note: Getting extra tags from GroupByResult not supported for now if (query.TagsFromIndexes != null && query.TagsFromIndexes.Count != 0) { KeyValuePair <byte[] /*IndexId */, string /*IndexName*/> kvp; CacheIndexInternal additionalCacheIndexInternal; #region Form IndexId - PrimaryId Mapping Dictionary <byte[] /*IndexId */, int /*PrimaryId*/> indexIdPrimaryIdMapping = new Dictionary <byte[] /*IndexId */, int /*PrimaryId*/>(query.IndexIdList.Count, new ByteArrayEqualityComparer()); if (query.PrimaryIdList != null && query.PrimaryIdList.Count > 0) { //Form dictionary of IndexIdPrimaryIdMapping for (int i = 0; i < query.IndexIdList.Count && i < query.PrimaryIdList.Count; i++) { indexIdPrimaryIdMapping.Add(query.IndexIdList[i], query.PrimaryIdList[i]); } } #endregion int indexPrimaryId; foreach (ResultItem resultItem in resultItemList) { foreach (string indexName in query.TagsFromIndexes) { Index indexInfo = indexTypeMapping.IndexCollection[indexName]; kvp = new KeyValuePair <byte[], string>(resultItem.IndexId, indexName); if (!internalIndexDictionary.ContainsKey(kvp)) { additionalCacheIndexInternal = IndexServerUtils.GetCacheIndexInternal(storeContext, messageContext.TypeId, indexIdPrimaryIdMapping.TryGetValue(resultItem.IndexId, out indexPrimaryId) ? indexPrimaryId : IndexCacheUtils.GeneratePrimaryId(resultItem.IndexId), resultItem.IndexId, indexInfo.ExtendedIdSuffix, indexName, 0, null, true, null, false, false, indexInfo.PrimarySortInfo, indexInfo.LocalIdentityTagList, indexInfo.StringHashCodeDictionary, null, indexInfo.IsMetadataPropertyCollection, null, query.DomainSpecificProcessingType, storeContext.DomainSpecificConfig, null, null, false); if (additionalCacheIndexInternal != null) { SetItemCounter(messageContext.TypeId, additionalCacheIndexInternal.OutDeserializationContext); internalIndexDictionary.Add(kvp, additionalCacheIndexInternal); try { IndexServerUtils.GetTags(additionalCacheIndexInternal, resultItem, resultItem); } catch (Exception ex) { LoggingUtil.Log.Error(ex.ToString()); exceptionInfo.Append(" | " + ex.Message); } } } } } } #endregion #region Get IndexHeader if (query.GetIndexHeaderType == GetIndexHeaderType.AllIndexIds) { //Get IndexHeader for all IndexIds indexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(new ByteArrayEqualityComparer()); for (int i = 0; i < query.IndexIdList.Count; i++) { byte[] indexId = query.IndexIdList[i]; CacheIndexInternal targetIndexCacheIndexInternal; if (!indexIdIndexHeaderMapping.ContainsKey(indexId) && internalIndexDictionary.TryGetValue(new KeyValuePair <byte[], string>(indexId, query.TargetIndexName), out targetIndexCacheIndexInternal)) { indexIdIndexHeaderMapping.Add(indexId, GetIndexHeader(internalIndexDictionary, targetIndexCacheIndexInternal, indexId, query, indexTypeMapping, messageContext.TypeId, storeContext, i)); } } } else if (query.GetIndexHeaderType == GetIndexHeaderType.ResultItemsIndexIds) { //Get IndexHeader just for IndexIds present in the result indexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(new ByteArrayEqualityComparer()); if (query.GroupBy == null) { for (int i = 0; i < resultItemList.Count; i++) { ResultItem resultItem = resultItemList[i]; if (!indexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { CacheIndexInternal targetIndexCacheIndexInternal; internalIndexDictionary.TryGetValue(new KeyValuePair <byte[], string>(resultItem.IndexId, query.TargetIndexName), out targetIndexCacheIndexInternal); indexIdIndexHeaderMapping.Add(resultItem.IndexId, GetIndexHeader(internalIndexDictionary, targetIndexCacheIndexInternal, resultItem.IndexId, query, indexTypeMapping, messageContext.TypeId, storeContext, i)); } } } else { foreach (ResultItemBag resultItemBag in groupByResult) { for (int i = 0; i < resultItemBag.Count; i++) { ResultItem resultItem = resultItemBag[i]; if (!indexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { CacheIndexInternal targetIndexCacheIndexInternal; internalIndexDictionary.TryGetValue(new KeyValuePair <byte[], string>(resultItem.IndexId, query.TargetIndexName), out targetIndexCacheIndexInternal); indexIdIndexHeaderMapping.Add(resultItem.IndexId, GetIndexHeader(internalIndexDictionary, targetIndexCacheIndexInternal, resultItem.IndexId, query, indexTypeMapping, messageContext.TypeId, storeContext, i)); } } } } } #endregion #region Get data if (!query.ExcludeData) { DataTierUtil.GetData(resultItemList, groupByResult, storeContext, messageContext, indexTypeMapping.FullDataIdFieldList, query.FullDataIdInfo); } #endregion } result = new TQueryResult { ResultItemList = resultItemList, IndexIdIndexHeaderMapping = indexIdIndexHeaderMapping, TotalCount = totalCount, AdditionalAvailableItemCount = additionalAvailableItemCount, IsTagPrimarySort = isTagPrimarySort, SortFieldName = sortFieldName, SortOrderList = sortOrderList, IndexCap = indexCap, GroupByResult = groupByResult, ExceptionInfo = exceptionInfo.ToString() }; #region Log Potentially Bad Queries if (indexTypeMapping.QueryOverrideSettings != null && indexTypeMapping.QueryOverrideSettings.MaxResultItemsThresholdLog > 0 && resultItemList != null && resultItemList.Count > indexTypeMapping.QueryOverrideSettings.MaxResultItemsThresholdLog) { LoggingUtil.Log.ErrorFormat("Encountered potentially Bad Paged Query with Large Result Set of {0}. AddressHistory: {1}. Query Info: {2}", resultItemList.Count, IndexServerUtils.FormatAddressHistory(messageContext.AddressHistory), FormatQueryInfo(query)); } LoggingUtil.Log.DebugFormat("QueryInfo: {0}, AddressHistory: {1}", FormatQueryInfo(query), IndexServerUtils.FormatAddressHistory(messageContext.AddressHistory)); #endregion SetIndexIdListCounter(messageContext.TypeId, query); } catch (Exception ex) { exceptionInfo.Append(" | " + ex.Message); result = new TQueryResult { ExceptionInfo = exceptionInfo.ToString() }; LoggingUtil.Log.ErrorFormat("TypeId {0} -- Error processing PagedIndexQuery : {1}", messageContext.TypeId, ex); } return(result); }
public override PagedIndexQueryResult MergeResults(IList <PagedIndexQueryResult> partialResults) { PagedIndexQueryResult finalResult = default(PagedIndexQueryResult); if (partialResults == null || partialResults.Count == 0) { return(finalResult); } // We have partialResults to process BaseComparer baseComparer = null; ByteArrayEqualityComparer byteArrayEqualityComparer = new ByteArrayEqualityComparer(); Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> completeIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); // resultVer required to determine if server is correctly performing paging logic int resultVer = 0; if (partialResults.Count == 1) { #region Just one cluster was targeted, so no need to merge anything finalResult = partialResults[0]; if (finalResult != null) { resultVer = finalResult.CurrentVersion; } #endregion } else { #region More than one clusters was targeted List <ResultItem> completeResultItemList = new List <ResultItem>(); GroupByResult completeGroupByResult = new GroupByResult(null); int totalCount = 0; int pageableItemCount = 0; StringBuilder exceptionStringBuilder = new StringBuilder(); bool indexCapSet = false; int indexCap = 0; foreach (PagedIndexQueryResult partialResult in partialResults) { if (partialResult != null) { #region Update resultVer if (resultVer == 0) { resultVer = partialResult.CurrentVersion; } #endregion #region Assign IndexCap if (!indexCapSet) { indexCap = partialResult.IndexCap; indexCapSet = true; } #endregion #region Compute TotalCount totalCount += partialResult.TotalCount; #endregion #region Compute PageableItemCount if (GetPageableItemCount) { pageableItemCount += partialResult.AdditionalAvailableItemCount; } #endregion #region Merge Results if ((partialResult.ResultItemList != null && partialResult.ResultItemList.Count > 0) || (partialResult.GroupByResult != null && partialResult.GroupByResult.Count > 0)) { if (baseComparer == null) { baseComparer = new BaseComparer(partialResult.IsTagPrimarySort, partialResult.SortFieldName, partialResult.SortOrderList); completeGroupByResult = new GroupByResult(baseComparer); } if (GroupBy == null) { MergeAlgo.MergeItemLists(ref completeResultItemList, partialResult.ResultItemList, MaxMergeCount, baseComparer); } else { MergeAlgo.MergeGroupResult(ref completeGroupByResult, partialResult.GroupByResult, MaxMergeCount, baseComparer); } } #endregion #region Update IndexIdIndexHeaderMapping if (GetIndexHeaderType != GetIndexHeaderType.None && partialResult.IndexIdIndexHeaderMapping != null && partialResult.IndexIdIndexHeaderMapping.Count > 0) { foreach (KeyValuePair <byte[], IndexHeader> kvp in partialResult.IndexIdIndexHeaderMapping) { if (!completeIndexIdIndexHeaderMapping.ContainsKey(kvp.Key)) { completeIndexIdIndexHeaderMapping.Add(kvp.Key, kvp.Value); } } } #endregion #region Update exceptionInfo if (!String.IsNullOrEmpty(partialResult.ExceptionInfo)) { exceptionStringBuilder.Append(partialResult.ExceptionInfo); exceptionStringBuilder.Append(" "); } #endregion } } #region Create FinalResult finalResult = new PagedIndexQueryResult { ResultItemList = completeResultItemList, GroupByResult = completeGroupByResult, TotalCount = totalCount, AdditionalAvailableItemCount = pageableItemCount, IndexCap = indexCap, }; //Assign sort fields for use in GroupBy remote queries if (baseComparer != null) { finalResult.IsTagPrimarySort = baseComparer.IsTagPrimarySort; finalResult.SortFieldName = baseComparer.SortFieldName; finalResult.SortOrderList = baseComparer.SortOrderList; } if (GetIndexHeaderType != GetIndexHeaderType.None && completeIndexIdIndexHeaderMapping.Count > 0) { finalResult.IndexIdIndexHeaderMapping = completeIndexIdIndexHeaderMapping; } if (exceptionStringBuilder.Length > 0) { finalResult.ExceptionInfo = exceptionStringBuilder.ToString(); } #endregion #endregion } #region Determine whether client side paging is required bool performClientSidePaging; if (resultVer < PagedIndexQueryResult.CORRECT_SERVERSIDE_PAGING_LOGIC_VERSION) { // this.ClientSidePaging cannot be trusted performClientSidePaging = numClustersInGroup > 1 && PageNum != 0; } else { // this.ClientSidePaging can be trusted performClientSidePaging = ClientSidePaging && PageNum != 0; } #endregion #region Perform Paging and Update IndexIdIndexHeaderMapping if required if (performClientSidePaging && finalResult != null) { #region Paging Logic int start = (PageNum - 1) * PageSize; if (GroupBy == null) { int end = (PageNum * PageSize) < finalResult.ResultItemList.Count ? (PageNum * PageSize) : finalResult.ResultItemList.Count; List <ResultItem> filteredResultItemList = new List <ResultItem>(); for (int i = start; i < end; i++) { filteredResultItemList.Add(finalResult.ResultItemList[i]); } finalResult.ResultItemList = filteredResultItemList; } else if (finalResult.GroupByResult != null && finalResult.GroupByResult.Count > 0) { int end = (PageNum * PageSize) < finalResult.GroupByResult.Count ? (PageNum * PageSize) : finalResult.GroupByResult.Count; GroupByResult filteredGroupByResult = new GroupByResult(baseComparer); for (int i = start; i < end; i++) { filteredGroupByResult.Add(finalResult.GroupByResult[i].CompositeKey, finalResult.GroupByResult[i]); } finalResult.GroupByResult = filteredGroupByResult; } #endregion #region Update IndexIdIndexHeaderMapping to only include metadata relevant after paging if (partialResults.Count != 1 && GetIndexHeaderType == GetIndexHeaderType.ResultItemsIndexIds && completeIndexIdIndexHeaderMapping.Count > 0) { Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> filteredIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); if (GroupBy == null) { foreach (ResultItem resultItem in finalResult.ResultItemList) { if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } } else if (finalResult.GroupByResult != null && finalResult.GroupByResult.Count > 0) { foreach (ResultItemBag resultItemBag in finalResult.GroupByResult) { for (int i = 0; i < resultItemBag.Count; i++) { ResultItem resultItem = resultItemBag[i]; if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } } } finalResult.IndexIdIndexHeaderMapping = filteredIndexIdIndexHeaderMapping.Count > 0 ? filteredIndexIdIndexHeaderMapping : null; } #endregion } #endregion return(finalResult); }
public override SpanQueryResult MergeResults(IList <SpanQueryResult> partialResults) { SpanQueryResult finalResult = default(SpanQueryResult); if (partialResults == null || partialResults.Count == 0) { return(finalResult); } // We have partialResults to process ByteArrayEqualityComparer byteArrayEqualityComparer = new ByteArrayEqualityComparer(); BaseComparer baseComparer = null; Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> completeIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); if (partialResults.Count == 1) { #region Just one cluster was targeted, so no need to merge anything finalResult = partialResults[0]; #endregion } else { #region More than one clusters was targeted List <ResultItem> completeResultItemList = new List <ResultItem>(); GroupByResult completeGroupByResult = new GroupByResult(null); int totalCount = 0; int additionalAvailableItemCount = 0; StringBuilder exceptionStringBuilder = new StringBuilder(); bool indexCapSet = false; int indexCap = 0; foreach (SpanQueryResult partialResult in partialResults) { if (partialResult != null) { #region Compute TotalCount totalCount += partialResult.TotalCount; #endregion #region Assign IndexCap if (!indexCapSet) { indexCap = partialResult.IndexCap; indexCapSet = true; } #endregion #region Compute PageableItemCount if (GetAdditionalAvailableItemCount) { additionalAvailableItemCount += partialResult.AdditionalAvailableItemCount; } #endregion #region Merge Results if ((partialResult.ResultItemList != null && partialResult.ResultItemList.Count > 0) || (partialResult.GroupByResult != null && partialResult.GroupByResult.Count > 0)) { if (baseComparer == null) { baseComparer = new BaseComparer(partialResult.IsTagPrimarySort, partialResult.SortFieldName, partialResult.SortOrderList); completeGroupByResult = new GroupByResult(baseComparer); } if (GroupBy == null) { MergeAlgo.MergeItemLists(ref completeResultItemList, partialResult.ResultItemList, MaxMergeCount, baseComparer); } else { MergeAlgo.MergeGroupResult(ref completeGroupByResult, partialResult.GroupByResult, MaxMergeCount, baseComparer); } } #endregion #region Update IndexIdIndexHeaderMapping if (GetIndexHeaderType != GetIndexHeaderType.None && partialResult.IndexIdIndexHeaderMapping != null && partialResult.IndexIdIndexHeaderMapping.Count > 0) { foreach (KeyValuePair <byte[], IndexHeader> kvp in partialResult.IndexIdIndexHeaderMapping) { if (!completeIndexIdIndexHeaderMapping.ContainsKey(kvp.Key)) { completeIndexIdIndexHeaderMapping.Add(kvp.Key, kvp.Value); } } } #endregion #region Update exceptionInfo if (!String.IsNullOrEmpty(partialResult.ExceptionInfo)) { exceptionStringBuilder.Append(partialResult.ExceptionInfo); exceptionStringBuilder.Append(" "); } #endregion } } #region Create FinalResult finalResult = new SpanQueryResult { ResultItemList = completeResultItemList, GroupByResult = completeGroupByResult, TotalCount = totalCount, AdditionalAvailableItemCount = additionalAvailableItemCount, IndexCap = indexCap }; //Assign sort fields for use in GroupBy remote queries if (baseComparer != null) { finalResult.IsTagPrimarySort = baseComparer.IsTagPrimarySort; finalResult.SortFieldName = baseComparer.SortFieldName; finalResult.SortOrderList = baseComparer.SortOrderList; } if (GetIndexHeaderType != GetIndexHeaderType.None && completeIndexIdIndexHeaderMapping.Count > 0) { finalResult.IndexIdIndexHeaderMapping = completeIndexIdIndexHeaderMapping; } if (exceptionStringBuilder.Length > 0) { finalResult.ExceptionInfo = exceptionStringBuilder.ToString(); } #endregion #endregion } #region Spanning and Update IndexIdIndexHeaderMapping if required if (ClientSideSubsetProcessingRequired && Span != 0 && finalResult != null) { #region Spanning if (GroupBy == null) { List <ResultItem> filteredResultItemList = new List <ResultItem>(); if (finalResult.ResultItemList.Count >= Offset) { for (int i = Offset - 1; i < finalResult.ResultItemList.Count && filteredResultItemList.Count < Span; i++) { filteredResultItemList.Add(finalResult.ResultItemList[i]); } } finalResult.ResultItemList = filteredResultItemList; } else if (finalResult.GroupByResult != null && finalResult.GroupByResult.Count > 0) { GroupByResult filteredGroupByResult = new GroupByResult(baseComparer); if (finalResult.GroupByResult.Count >= Offset) { for (int i = Offset - 1; i < finalResult.GroupByResult.Count && filteredGroupByResult.Count < Span; i++) { filteredGroupByResult.Add(finalResult.GroupByResult[i].CompositeKey, finalResult.GroupByResult[i]); } } finalResult.GroupByResult = filteredGroupByResult; } #endregion #region Update IndexIdIndexHeaderMapping to only include metadata relevant after paging if (partialResults.Count != 1 && GetIndexHeaderType == GetIndexHeaderType.ResultItemsIndexIds && completeIndexIdIndexHeaderMapping.Count > 0) { Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> filteredIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); if (GroupBy == null) { foreach (ResultItem resultItem in finalResult.ResultItemList) { if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } } else if (finalResult.GroupByResult != null && finalResult.GroupByResult.Count > 0) { foreach (ResultItemBag resultItemBag in finalResult.GroupByResult) { for (int i = 0; i < resultItemBag.Count; i++) { ResultItem resultItem = resultItemBag[i]; if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } } } finalResult.IndexIdIndexHeaderMapping = filteredIndexIdIndexHeaderMapping.Count > 0 ? filteredIndexIdIndexHeaderMapping : null; } #endregion } #endregion return(finalResult); }
public override PagedIndexQueryResult MergeResults(IList <PagedIndexQueryResult> partialResults) { PagedIndexQueryResult finalResult = default(PagedIndexQueryResult); if (partialResults == null || partialResults.Count == 0) { return(finalResult); } // We have partialResults to process ByteArrayEqualityComparer byteArrayEqualityComparer = new ByteArrayEqualityComparer(); Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> completeIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); // resultVer required to determine if server is correctly performing paging logic int resultVer = 0; if (partialResults.Count == 1) { #region Just one cluster was targeted, so no need to merge anything finalResult = partialResults[0]; if (finalResult != null) { resultVer = finalResult.CurrentVersion; } #endregion } else { #region More than one clusters was targeted List <ResultItem> completeResultItemList = new List <ResultItem>(); BaseComparer baseComparer; int totalCount = 0; int pageableItemCount = 0; foreach (PagedIndexQueryResult partialResult in partialResults) { if (partialResult != null) { #region Update resultVer if (resultVer == 0) { resultVer = partialResult.CurrentVersion; } #endregion #region Compute TotalCount totalCount += partialResult.TotalCount; #endregion #region Compute PageableItemCount if (GetPageableItemCount) { pageableItemCount += partialResult.AdditionalAvailableItemCount; } #endregion #region Merge Results if (partialResult.ResultItemList != null && partialResult.ResultItemList.Count > 0) { baseComparer = new BaseComparer(partialResult.IsTagPrimarySort, partialResult.SortFieldName, partialResult.SortOrderList); MergeAlgo.MergeItemLists(ref completeResultItemList, partialResult.ResultItemList, MaxMergeCount, baseComparer); } #endregion #region Update IndexIdIndexHeaderMapping if (GetIndexHeaderType != GetIndexHeaderType.None && partialResult.IndexIdIndexHeaderMapping != null && partialResult.IndexIdIndexHeaderMapping.Count > 0) { foreach (KeyValuePair <byte[], IndexHeader> kvp in partialResult.IndexIdIndexHeaderMapping) { if (!completeIndexIdIndexHeaderMapping.ContainsKey(kvp.Key)) { completeIndexIdIndexHeaderMapping.Add(kvp.Key, kvp.Value); } } } #endregion } } #region Create FinalResult finalResult = new PagedIndexQueryResult { ResultItemList = completeResultItemList, TotalCount = totalCount, AdditionalAvailableItemCount = pageableItemCount, }; if (GetIndexHeaderType != GetIndexHeaderType.None && completeIndexIdIndexHeaderMapping.Count > 0) { finalResult.IndexIdIndexHeaderMapping = completeIndexIdIndexHeaderMapping; } #endregion #endregion } #region Determine whether client side paging is required bool performClientSidePaging; if (resultVer < PagedIndexQueryResult.CORRECT_SERVERSIDE_PAGING_LOGIC_VERSION) { // this.ClientSidePaging cannot be trusted performClientSidePaging = numClustersInGroup > 1 && PageNum != 0; } else { // this.ClientSidePaging can be trusted performClientSidePaging = ClientSidePaging && PageNum != 0; } #endregion #region Perform Paging and Update IndexIdIndexHeaderMapping if required if (performClientSidePaging && finalResult != null) { #region Paging Logic int start = (PageNum - 1) * PageSize; int end = (PageNum * PageSize) < finalResult.ResultItemList.Count ? (PageNum * PageSize) : finalResult.ResultItemList.Count; List <ResultItem> filteredResultItemList = new List <ResultItem>(); for (int i = start; i < end; i++) { filteredResultItemList.Add(finalResult.ResultItemList[i]); } finalResult.ResultItemList = filteredResultItemList; #endregion #region Update IndexIdIndexHeaderMapping to only include metadata relevant after paging if (partialResults.Count != 1 && GetIndexHeaderType == GetIndexHeaderType.ResultItemsIndexIds && completeIndexIdIndexHeaderMapping.Count > 0) { Dictionary <byte[] /*IndexId*/, IndexHeader /*IndexHeader*/> filteredIndexIdIndexHeaderMapping = new Dictionary <byte[], IndexHeader>(byteArrayEqualityComparer); foreach (ResultItem resultItem in finalResult.ResultItemList) { if (!filteredIndexIdIndexHeaderMapping.ContainsKey(resultItem.IndexId)) { filteredIndexIdIndexHeaderMapping.Add(resultItem.IndexId, completeIndexIdIndexHeaderMapping[resultItem.IndexId]); } } finalResult.IndexIdIndexHeaderMapping = filteredIndexIdIndexHeaderMapping.Count > 0 ? filteredIndexIdIndexHeaderMapping : null; } #endregion } #endregion return(finalResult); }