/// <summary> /// Processes the subsets. /// </summary> /// <param name="query">The query.</param> /// <param name="resultItemList">The result item list.</param> /// <param name="groupByResult">The GroupByResult</param> /// <param name="baseComparer">The BaseComparer</param> protected override void ProcessSubsets(BaseMultiIndexIdQuery <PagedIndexQueryResult> query, ref List <ResultItem> resultItemList, ref GroupByResult groupByResult, BaseComparer baseComparer) { PagedIndexQuery pagedQuery = query as PagedIndexQuery; if (!pagedQuery.ClientSideSubsetProcessingRequired && pagedQuery.PageNum != 0) { int pageSize = pagedQuery.PageSize; int start = (pagedQuery.PageNum - 1) * pageSize; int end = pagedQuery.PageNum * pageSize; if (pagedQuery.GroupBy == null) { List <ResultItem> pageFilteredResultItemList = new List <ResultItem>(); for (int i = start; i < end && i < resultItemList.Count; i++) { pageFilteredResultItemList.Add(resultItemList[i]); } resultItemList = pageFilteredResultItemList; } else { GroupByResult pageGroupByResult = new GroupByResult(baseComparer); for (int i = start; i < end && i < groupByResult.Count; i++) { pageGroupByResult.Add(groupByResult[i].CompositeKey, groupByResult[i]); } groupByResult = pageGroupByResult; } } }
/// <summary> /// Ritorna dizionario di valori raggruppati con associata la lista di elementi /// </summary> /// <param name="propertyName"></param> /// <returns></returns> public GroupByResult <TL> GroupByProperty(string propertyName) { GroupByResult <TL> ret = new GroupByResult <TL>(); Dictionary <object, TL> dicOutput = new Dictionary <object, TL>(); Property oProp = this.mObjSchema.Properties.GetPropertyByName(propertyName); object oTemp; TL oTmplist = null; //Lista originale for (int i = 0; i < this.Count; i++) { oTemp = oProp.GetValue(this[i]); //Se non esiste if (!ret.TryGetValue(oTemp, out oTmplist)) { oTmplist = this.Slot.CreateList <TL>(); ret.Add(oTemp, oTmplist); } oTmplist.mInnerList.Add(this.mInnerList[i]); } //Ritorna la lista return(ret); }
/// <summary> /// Processes the subsets. /// </summary> /// <param name="query">The query.</param> /// <param name="resultItemList">The result item list.</param> /// <param name="groupByResult">The group by result.</param> /// <param name="baseComparer">The base comparer.</param> protected override void ProcessSubsets(BaseMultiIndexIdQuery <SpanQueryResult> query, ref List <ResultItem> resultItemList, ref GroupByResult groupByResult, BaseComparer baseComparer) { SpanQuery spanQuery = query as SpanQuery; if (!spanQuery.ClientSideSubsetProcessingRequired && spanQuery.Span != 0) { if (spanQuery.GroupBy == null) { List <ResultItem> spanFilteredResultItemList = new List <ResultItem>(); if (resultItemList.Count >= spanQuery.Offset) { for (int i = spanQuery.Offset - 1; i < resultItemList.Count && spanFilteredResultItemList.Count < spanQuery.Span; i++) { spanFilteredResultItemList.Add(resultItemList[i]); } } resultItemList = spanFilteredResultItemList; } else { GroupByResult pageGroupByResult = new GroupByResult(baseComparer); for (int i = spanQuery.Offset - 1; i < groupByResult.Count && pageGroupByResult.Count < spanQuery.Span; i++) { pageGroupByResult.Add(groupByResult[i].CompositeKey, groupByResult[i]); } groupByResult = pageGroupByResult; } } }
/// <summary> /// Gets the group by result. /// </summary> /// <param name="aggregates">The aggregates.</param> /// <returns> /// GroupByResult Object /// </returns> protected GroupByResult <dynamic> GetGroupByResult(IEnumerable <dynamic> aggregates) { GroupByResult <dynamic> obj = new GroupByResult <dynamic>(); obj.Aggregates = aggregates; return(obj); }
internal static void MergeGroupResult(ref GroupByResult groupByResult1, GroupByResult groupByResult2, int maxMergeCount, BaseComparer baseComparer) { int mergedResultCount = groupByResult1.Count + groupByResult2.Count; int count1 = 0; int count2 = 0; if (mergedResultCount > maxMergeCount) { mergedResultCount = maxMergeCount; } GroupByResult newGroupResult = new GroupByResult(baseComparer); ResultItemBag resultItemBag; #region Merge until one GroupByResult ends for (int i = 0; newGroupResult.Count < mergedResultCount && count1 != groupByResult1.Count && count2 != groupByResult2.Count; i++) { resultItemBag = baseComparer.Compare(groupByResult1[count1], groupByResult2[count2]) <= 0 ? groupByResult1[count1++] : groupByResult2[count2++]; newGroupResult.Add(resultItemBag.CompositeKey, resultItemBag); } #endregion #region Append rest of the groupByResult1/groupByResult2 to newGroupResult if (count1 != groupByResult1.Count && newGroupResult.Count < mergedResultCount) { int count = groupByResult1.Count - count1; for (int i = 0; i < count && newGroupResult.Count < mergedResultCount; i++) { newGroupResult.Add(groupByResult1[count1].CompositeKey, groupByResult1[count1]); count1++; } } else if (count2 != groupByResult2.Count && newGroupResult.Count < mergedResultCount) { int count = groupByResult2.Count - count2; for (int i = 0; i < count && newGroupResult.Count < mergedResultCount; i++) { newGroupResult.Add(groupByResult2[count2].CompositeKey, groupByResult2[count2]); count2++; } } #endregion #region Update reference groupByResult1 = newGroupResult; #endregion }
public static GroupByResult GroupBy(IEnumerable <MeshRenderer> mrs, Transform parkCenter = null) { var gb = new GroupByResult(); foreach (var mr in mrs) { gb.Exec(mr, parkCenter); } return(gb); }
private static byte[] GetConditionBoundaryBytes(List <ResultItem> resultItemList, GroupByResult groupByResult, GroupBy groupBy, bool isTagPrimarySort, string sortFieldName) { ResultItem resultItem = groupBy == null ? resultItemList[resultItemList.Count - 1] : groupByResult.First.First; byte[] conditionBoundry; if (!isTagPrimarySort) // based on item id { conditionBoundry = resultItem.ItemId; } else // based on tag { resultItem.TryGetTagValue(sortFieldName, out conditionBoundry); } return(conditionBoundry); }
/// <summary> /// Processes the subsets. /// </summary> /// <param name="query">The query.</param> /// <param name="resultItemList">The result item list.</param> /// <param name="groupByResult">The GroupByResult</param> /// <param name="baseComparer">The BaseComparer</param> protected abstract void ProcessSubsets(BaseMultiIndexIdQuery <TQueryResult> query, ref List <ResultItem> resultItemList, ref GroupByResult groupByResult, BaseComparer baseComparer);
/// <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); }
/// <summary> /// Gets the data into resultItemList items. /// </summary> /// <param name="resultItemList">The result item list.</param> /// <param name="groupByResult">The groupBy result.</param> /// <param name="storeContext">The store context.</param> /// <param name="messageContext">The message context.</param> /// <param name="fullDataIdFieldList">The full data id field list.</param> /// <param name="fullDataIdInfo">The full data id info.</param> internal static void GetData(List <ResultItem> resultItemList, GroupByResult groupByResult, IndexStoreContext storeContext, MessageContext messageContext, FullDataIdFieldList fullDataIdFieldList, FullDataIdInfo fullDataIdInfo) { byte[] extendedId; List <RelayMessage> dataStoreMessages = new List <RelayMessage>(); short relatedTypeId; if (fullDataIdInfo != null && fullDataIdInfo.RelatedTypeName != null) { if (!storeContext.TryGetTypeId(fullDataIdInfo.RelatedTypeName, out relatedTypeId)) { LoggingUtil.Log.ErrorFormat("Invalid RelatedCacheTypeName - {0}", fullDataIdInfo.RelatedTypeName); throw new Exception("Invalid RelatedTypeId for TypeId - " + fullDataIdInfo.RelatedTypeName); } } else if (!storeContext.TryGetRelatedIndexTypeId(messageContext.TypeId, out relatedTypeId)) { LoggingUtil.Log.ErrorFormat("Invalid RelatedTypeId for TypeId - {0}", messageContext.TypeId); throw new Exception("Invalid RelatedTypeId for TypeId - " + messageContext.TypeId); } //Form relay messages for resultItemList if (resultItemList != null && resultItemList.Count > 0) { foreach (ResultItem resultItem in resultItemList) { extendedId = GetFullDataId(resultItem.IndexId, resultItem, fullDataIdInfo != null && fullDataIdInfo.RelatedTypeName != null ? fullDataIdInfo.FullDataIdFieldList : fullDataIdFieldList); dataStoreMessages.Add(new RelayMessage(relatedTypeId, IndexCacheUtils.GeneratePrimaryId(extendedId), extendedId, MessageType.Get)); } } //Form relay messages for GroupByResult if (groupByResult != null && groupByResult.Count > 0) { foreach (ResultItemBag resultItemBag in groupByResult) { foreach (ResultItem resultItem in resultItemBag) { extendedId = GetFullDataId(resultItem.IndexId, resultItem, fullDataIdInfo != null && fullDataIdInfo.RelatedTypeName != null ? fullDataIdInfo.FullDataIdFieldList : fullDataIdFieldList); dataStoreMessages.Add(new RelayMessage(relatedTypeId, IndexCacheUtils.GeneratePrimaryId(extendedId), extendedId, MessageType.Get)); } } } storeContext.ForwarderComponent.HandleMessages(dataStoreMessages); //Copy data to data fields in resultItemList int i = 0; if (resultItemList != null && resultItemList.Count > 0) { foreach (ResultItem resultItem in resultItemList) { if (dataStoreMessages[i].Payload != null) { resultItem.Data = dataStoreMessages[i].Payload.ByteArray; } else { LoggingUtil.Log.DebugFormat("Fetched Null Data for TypeId: {0}, IndexId: {1}, ItemId: {2}, FullDataId: {3}, PrimaryId: {4}", relatedTypeId, IndexCacheUtils.GetReadableByteArray(resultItem.IndexId), IndexCacheUtils.GetReadableByteArray(resultItem.ItemId), IndexCacheUtils.GetReadableByteArray(dataStoreMessages[i].ExtendedId), IndexCacheUtils.GeneratePrimaryId(dataStoreMessages[i].ExtendedId)); } i++; } } //Copy data to data fields in compositeKeyResultItemListMapping if (groupByResult != null && groupByResult.Count > 0) { foreach (ResultItemBag resultItemBag in groupByResult) { foreach (ResultItem resultItem in resultItemBag) { if (dataStoreMessages[i].Payload != null) { resultItem.Data = dataStoreMessages[i].Payload.ByteArray; } else { LoggingUtil.Log.DebugFormat("Fetched Null Data for TypeId: {0}, IndexId: {1}, ItemId: {2}, FullDataId: {3}, PrimaryId: {4}", relatedTypeId, IndexCacheUtils.GetReadableByteArray(resultItem.IndexId), IndexCacheUtils.GetReadableByteArray(resultItem.ItemId), IndexCacheUtils.GetReadableByteArray(dataStoreMessages[i].ExtendedId), IndexCacheUtils.GeneratePrimaryId(dataStoreMessages[i].ExtendedId)); } i++; } } } }
/// <summary> /// Deserialize the class data from a stream. /// </summary> /// <param name="reader">The <see cref="IPrimitiveReader"/> that extracts used to extra data from a stream.</param> /// <param name="version">The value of <see cref="CurrentVersion"/> that was written to the stream when it was originally serialized to a stream; /// the version of the <paramref name="reader"/> data.</param> public void Deserialize(IPrimitiveReader reader, int version) { ushort len; //Metadata or MetadataPropertyCollection if (InDeserializationContext.IsMetadataPropertyCollection) { //MetadataPropertyCollection len = reader.ReadUInt16(); if (len > 0) { MetadataPropertyCollection = new MetadataPropertyCollection(); string propertyName; byte[] propertyValue; ushort propertyValueLen; for (ushort i = 0; i < len; i++) { propertyName = reader.ReadString(); propertyValueLen = reader.ReadUInt16(); propertyValue = null; if (propertyValueLen > 0) { propertyValue = reader.ReadBytes(propertyValueLen); } MetadataPropertyCollection.Add(propertyName, propertyValue); } } } else { //Metadata len = reader.ReadUInt16(); if (len > 0) { Metadata = reader.ReadBytes(len); } } //VirtualCount if (version >= 2) { virtualCount = reader.ReadInt32(); } //Count outDeserializationContext = new OutDeserializationContext { TotalCount = reader.ReadInt32() }; if (InDeserializationContext.DeserializeHeaderOnly) { //Note: If InDeserializationContext.DeserializeHeaderOnly property is set then InDeserializationContext.PartialByteArray shall hold all CacheIndexInternal //payload except metadata and header (just virtual count for now). This code path will only be used if just //header info like virtual count needs to be updated keeping rest of the index untouched. //InDeserializationContext.PartialByteArray shall be used in Serialize code outDeserializationContext.UnserializedCacheIndexInternal = new byte[(int)reader.BaseStream.Length - (int)reader.BaseStream.Position]; reader.BaseStream.Read(outDeserializationContext.UnserializedCacheIndexInternal, 0, outDeserializationContext.UnserializedCacheIndexInternal.Length); } else { int actualItemCount = outDeserializationContext.TotalCount; //this.InDeserializationContext.MaxItemsPerIndex = 0 indicates need to extract all items //this.InDeserializationContext.MaxItemsPerIndex > 0 indicates need to extract only number of items indicated by InDeserializationContext.MaxItemsPerIndex if (InDeserializationContext.MaxItemsPerIndex > 0) { if (InDeserializationContext.MaxItemsPerIndex < outDeserializationContext.TotalCount) { actualItemCount = InDeserializationContext.MaxItemsPerIndex; } } #region Populate InternalItemList InternalItem internalItem; bool enterConditionPassed = false; InternalItemList = new InternalItemList(); GroupByResult = new GroupByResult(new BaseComparer(InDeserializationContext.PrimarySortInfo.IsTag, InDeserializationContext.PrimarySortInfo.FieldName, InDeserializationContext.PrimarySortInfo.SortOrderList)); // Note: ---- Termination condition of the loop // For full index extraction loop shall terminate because of condition : internalItemList.Count + GroupByResult.Count < actualItemCount // For partial index extraction loop shall terminate because of following conditions // a) i < InDeserializationContext.TotalCount (when no sufficient items are found) OR // b) internalItemList.Count < actualItemCount (Item extraction cap is reached) int i = 0; while (GroupByResult.Count + InternalItemList.Count < actualItemCount && i < outDeserializationContext.TotalCount) { i++; #region Deserialize ItemId len = reader.ReadUInt16(); if (len > 0) { internalItem = new InternalItem { ItemId = reader.ReadBytes(len) }; } else { throw new Exception("Invalid ItemId - is null or length is zero for IndexId : " + IndexCacheUtils.GetReadableByteArray(InDeserializationContext.IndexId)); } #endregion #region Process IndexCondition if (InDeserializationContext.EnterCondition != null || InDeserializationContext.ExitCondition != null) { #region Have Enter/Exit Condition if (InDeserializationContext.PrimarySortInfo.IsTag == false) { #region Sort by ItemId if (InDeserializationContext.EnterCondition != null && enterConditionPassed == false) { #region enter condition processing if (FilterPassed(internalItem, InDeserializationContext.EnterCondition)) { if (InDeserializationContext.ExitCondition != null && !FilterPassed(internalItem, InDeserializationContext.ExitCondition)) { // no need to search beyond this point break; } enterConditionPassed = true; DeserializeTags(internalItem, InDeserializationContext, OutDeserializationContext, reader); ApplyFilterAndAddItem(internalItem); } else { SkipDeserializeInternalItem(reader); // no filter processing required } #endregion } else if (InDeserializationContext.ExitCondition != null) { #region exit condition processing if (FilterPassed(internalItem, InDeserializationContext.ExitCondition)) { // since item passed exit filter, we keep it. DeserializeTags(internalItem, InDeserializationContext, OutDeserializationContext, reader); ApplyFilterAndAddItem(internalItem); } else { // no need to search beyond this point break; } #endregion } else if (InDeserializationContext.EnterCondition != null && enterConditionPassed && InDeserializationContext.ExitCondition == null) { #region enter condition processing when no exit condition exists DeserializeTags(internalItem, InDeserializationContext, OutDeserializationContext, reader); ApplyFilterAndAddItem(internalItem); #endregion } #endregion } else { #region Sort by Tag #region Deserialize InternalItem and fetch PrimarySortTag value byte[] tagValue; DeserializeTags(internalItem, InDeserializationContext, OutDeserializationContext, reader); if (!internalItem.TryGetTagValue(InDeserializationContext.PrimarySortInfo.FieldName, out tagValue)) { throw new Exception("PrimarySortTag Not found: " + InDeserializationContext.PrimarySortInfo.FieldName); } #endregion if (InDeserializationContext.EnterCondition != null && enterConditionPassed == false) { #region enter condition processing if (FilterPassed(internalItem, InDeserializationContext.EnterCondition)) { if (InDeserializationContext.ExitCondition != null && !FilterPassed(internalItem, InDeserializationContext.ExitCondition)) { // no need to search beyond this point break; } enterConditionPassed = true; ApplyFilterAndAddItem(internalItem); } #endregion } else if (InDeserializationContext.ExitCondition != null) { #region exit condition processing if (FilterPassed(internalItem, InDeserializationContext.ExitCondition)) { // since item passed exit filter, we keep it. ApplyFilterAndAddItem(internalItem); } else { // no need to search beyond this point break; } #endregion } else if (InDeserializationContext.EnterCondition != null && enterConditionPassed && InDeserializationContext.ExitCondition == null) { #region enter condition processing when no exit condition exists ApplyFilterAndAddItem(internalItem); #endregion } #endregion } #endregion } else { #region No Enter/Exit Condition DeserializeTags(internalItem, InDeserializationContext, OutDeserializationContext, reader); ApplyFilterAndAddItem(internalItem); #endregion } #endregion } //Set ReadItemCount on OutDeserializationContext outDeserializationContext.ReadItemCount = i; #endregion } }