/// <summary> /// Reads the current value of <see cref="Cursor"/>. /// </summary> /// <param name="itemValue">A <see cref="ResourcePoolItem{MemoryStream}"/> that provides /// streams used for deserializing the value.</param> /// <param name="valueBuffer">Outputs the <see cref="DataBuffer"/> value read.</param> /// <returns>The <see cref="Int32"/> length of the cursor read.</returns> public int ReadCursor(ResourcePoolItem <MemoryStream> itemValue, out DataBuffer valueBuffer) { var valueStream = itemValue.Item; valueBuffer = SerializingObjectStorage.GetReadBuffer(valueStream); var results = Cursor.Get(valueBuffer, true); if (results < 0) { return(results); } var bfExcessValue = SerializingObjectStorage.GetExcessBuffer(valueStream, valueBuffer, results); if (!bfExcessValue.IsEmpty) { var len = valueBuffer.Length; valueBuffer = bfExcessValue; if (!Storage.Storage.SupportsIncompleteReads) { bfExcessValue = bfExcessValue.RestrictOffset(len); results = Cursor.Get(len, bfExcessValue, false); if (results >= 0) { results += len; } } else { results = Cursor.Get(0, bfExcessValue, false); } } return(results); }
/// <summary> /// <para>Initializes a new instance of the <see cref="ObjectListForSingles{T, THeader}"/> class /// for an existing list.</para> /// </summary> /// <param name="storage"> /// <para>The <see cref="SerializingObjectStorage"/> containing the list.</para> /// </param> /// <param name="keySpace"> /// <para>The <see cref="DataBuffer"/> keyspace the list is stored in.</para> /// </param> /// <param name="key"> /// <para>The single <see cref="StorageKey"/> all the binary entries are /// stored under.</para> /// </param> /// <param name="buffer"> /// <para><see cref="DataBuffer"/> that holds the entire list. If /// <see cref="DataBuffer.IsEmpty"/> is true, then the list is read /// from <paramref name="storage"/>.</para> /// </param> /// <param name="creator"> /// <para>The <see cref="Func{T}"/> that produces new <typeparamref name="T"/> /// instances for deserialization.</para> /// </param> /// <param name="headerCreator"> /// <para>The <see cref="Func{THeader}"/> that produces new <typeparamref name="THeader"/> /// instances for deserialization.</para> /// </param> public ObjectListForSingles(SerializingObjectStorage storage, DataBuffer keySpace, StorageKey key, DataBuffer buffer, Func <T> creator, Func <THeader> headerCreator) : this(storage, keySpace, key, creator) { ArraySegment <byte> seg; if (buffer.IsEmpty) { _stream = _pooled.Item; buffer = SerializingObjectStorage.GetReadBuffer(_stream); var entryLen = storage.Storage.Get(keySpace, key, buffer); if (entryLen < 0) { throw new ApplicationException(string.Format( "No list found for key space '{0}', key '{1}'", keySpace, key)); } var bfExcess = SerializingObjectStorage.GetExcessBuffer(_stream, buffer, entryLen); if (bfExcess.IsEmpty) { buffer = buffer.Restrict(entryLen); } else { if (storage.Storage.SupportsIncompleteReads) { storage.Storage.Get(keySpace, key, buffer.Length, bfExcess.RestrictOffset(buffer.Length)); } else { storage.Storage.Get(keySpace, key, 0, bfExcess); } buffer = bfExcess; } seg = buffer.ByteArraySegmentValue; } else { _pooled.Dispose(); _pooled = null; seg = buffer.ByteArraySegmentValue; _stream = new MemoryStream(seg.Array, seg.Offset, seg.Count); } var ticks = BitConverter.ToInt64(seg.Array, seg.Offset); // expires listed first, since SetExpires can change it by itself // and this way it doesn't have to worry about future changes // to header Expires = new DateTime(ticks); _stream.Position = sizeof(long); _header = headerCreator(); Serializer.Deserialize(_stream, _header); _headerLength = _stream.Position; }