/// <summary> /// Make this index writable again by injecting a new memory map. /// </summary> public void MakeWritable(MemoryMap map) { if (!this.IsReadonly) { throw new InvalidOperationException("Index is already writable, check IsReadonly."); } var accessor = _accessors[0]; _map = map; _createAccessor = MemoryMap.GetCreateAccessorFuncFor <T>(); _accessorSize = accessor.Capacity; // the only way to handle this now. _nextPositionInBytes = _accessorSize; if (_accessorSize == 0) { // this was empty, start over. _accessors.Clear(); _accessorSize = 1024; } if (!accessor.ElementSizeFixed) { // use the size in bytes. _accessorSizeElements = _accessorSize; } else { // use the size in elements. _accessorSizeElements = accessor.CapacityElements; } if (_accessors.Count == 0) { // was empty, create at least one. _accessors.Add(_createAccessor(_map, _accessorSizeElements)); } }
/// <summary> /// Creates a memory mapped array. /// </summary> public Array(MemoryMap map, long length, long accessorSize, int bufferSize, int cacheSize) { if (accessorSize < 0) { throw new ArgumentOutOfRangeException("accessorSize"); } if (length < 0) { throw new ArgumentOutOfRangeException("length"); } _map = map; _accessors = new List <MappedAccessor <T> >(); _accessorSize = accessorSize; _createAccessor = MemoryMap.GetCreateAccessorFuncFor <T>(); // create first accessor. var accessor = _createAccessor(_map, _accessorSize); _accessors.Add(accessor); _length = length; _bufferSize = bufferSize; _cachedBuffer = null; _cachedBuffers = new LRUCache <long, CachedBuffer>(cacheSize); _cachedBuffers.OnRemove += new LRUCache <long, CachedBuffer> .OnRemoveDelegate(buffer_OnRemove); var blockCount = (int)System.Math.Max(System.Math.Ceiling((double)length / _accessorSize), 1); for (int i = 1; i < blockCount; i++) { _accessors.Add(_createAccessor(_map, _accessorSize)); } }
/// <summary> /// Copies an array from the given stream. /// </summary> public virtual void CopyFrom(Stream stream) { using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { this.CopyFrom(accessor, stream); } }
/// <summary> /// Creates a mapped array with the given size. /// </summary> public static ArrayBase <T> CreateFor(MemoryMap map, long size, ArrayProfile profile) { var func = MemoryMap.GetCreateAccessorFuncFor <T>(); using (var accessor = func(map, 0)) { if (accessor.ElementSizeFixed) { // fixed element size. return(new Array <T>(map, size, profile)); } } return(new VariableArray <T>(map, size)); }
/// <summary> /// Copies an array to the given stream. /// </summary> public virtual void CopyFrom(Stream stream) { var position = stream.Position; var i = 0; using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { var element = default(T); while (i < this.Length) { accessor.ReadFrom(stream, stream.Position, ref element); this[i] = element; i++; } } }
/// <summary> /// Copies an array to the given stream. /// </summary> public virtual long CopyTo(Stream stream) { var position = stream.Position; var i = 0; using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { var element = default(T); while (i < this.Length) { element = this[i]; accessor.WriteTo(stream, stream.Position, ref element); i++; } } return(stream.Position - position); }
/// <summary> /// Copies a sorted list of elements to a stream. /// </summary> public static long CopyTo <T>(this IList <T> list, Stream stream) { var position = stream.Position; var i = 0; using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { var element = default(T); while (i < list.Count) { element = list[i]; accessor.WriteTo(stream, stream.Position, ref element); i++; } } return(stream.Position - position); }
/// <summary> /// Copies the data from the stream to this index. /// </summary> public static Index <T> CreateFrom(Stream stream, long size, bool useAsMap = false) { if (useAsMap) { // use the existing stream as map. var map = new MemoryMapStream(new CappedStream(stream, stream.Position, size)); var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(map, size); return(new Index <T>(accessor)); } else { // copy to memory stream and release the given stream. var data = new byte[size]; var position = stream.Position; stream.Read(data, 0, (int)size); var map = new MemoryMapStream(new CappedStream(new MemoryStream(data), 0, size)); var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(map, size); return(new Index <T>(accessor)); } }
/// <summary> /// Creates a new index. /// </summary> public Index(MemoryMap map, int accessorSize) { _map = map; _createAccessor = MemoryMap.GetCreateAccessorFuncFor <T>(); _accessorSize = accessorSize; _accessors = new System.Collections.Generic.List <MappedAccessor <T> >(); _accessors.Add(_createAccessor(_map, _accessorSize)); _accessorSize = _accessors[0].Capacity; // make sure to get the size in bytes, not elements for fixed-size structures. if (!_accessors[0].ElementSizeFixed) { // use the size in bytes. _accessorSizeElements = _accessorSize; } else { // use the size in elements. _accessorSizeElements = _accessors[0].CapacityElements; } _accessorBytesLost = new System.Collections.Generic.List <long>(); _accessorBytesLost.Add(0); }
/// <summary> /// Deserializes an array. /// </summary> protected static ArrayBase <T> DeserializeArray <T>(Stream stream, ArrayProfile profile, long length, int elementSize) { ArrayBase <T> data; if (profile == null) { // just create arrays and read the data. data = new MemoryArray <T>(length); data.CopyFrom(stream); } else { // create accessors over the exact part of the stream that represents items/edges. var position = stream.Position; var byteCount = length * elementSize; var map = new MemoryMapStream(new CappedStream(stream, position, byteCount)); var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(map, length); data = new Array <T>(accessor, profile); stream.Seek(position + byteCount, SeekOrigin.Begin); } return(data); }
/// <summary> /// Copies an array to the given stream. /// </summary> public virtual long CopyTo(Stream stream, bool writeLengthIfNeeded) { var position = stream.Position; long i = 0; using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { if (writeLengthIfNeeded && !accessor.ElementSizeFixed) { // also write the element count here, it cannot be reconstructed from length of data. stream.Write(BitConverter.GetBytes(this.Length), 0, 8); } while (i < this.Length) { var element = this[i]; accessor.WriteTo(stream, stream.Position, ref element); i++; } } return(stream.Position - position); }
/// <summary> /// Creates a new memory array reading the size and copying from stream. /// </summary> /// <param name="stream">The stream.</param> /// <returns>A memory array.</returns> public static MemoryArray <T> CopyFromWithSize(Stream stream) { using (var accessor = MemoryMap.GetCreateAccessorFuncFor <T>()(new MemoryMapStream(), 0)) { var buffer = new byte[8]; stream.Read(buffer, 0, 8); var size = BitConverter.ToInt64(buffer, 0); long length; if (!accessor.ElementSizeFixed) { // if the element size is not fixed, it should have been written here if copy to with size was used. stream.Read(buffer, 0, 8); length = BitConverter.ToInt64(buffer, 0); } else { // the length of the array can be calculate from the size of the data. length = size / accessor.ElementSize; } var memoryArray = new MemoryArray <T>(length); memoryArray.CopyFrom(accessor, stream); return(memoryArray); } }