/// <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 } }
/// <summary> /// Converts an InternalItem to an IndexItem. /// </summary> /// <param name="internalItem">The internal item.</param> /// <param name="inDeserializationContext">The in deserialization context.</param> /// <returns></returns> internal static IndexItem ConvertToIndexItem(InternalItem internalItem, InDeserializationContext inDeserializationContext) { return(new IndexItem(internalItem.ItemId, ConvertToTagDictionary(internalItem.TagList, inDeserializationContext))); }