/// <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;
                }
            }
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #5
0
        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
        }
Beispiel #6
0
        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);
        }
Beispiel #10
0
        /// <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
            }
        }