using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace System.Fire.Container { public class ContainerStack { private struct StackPositions { public byte ContainerGroup; public byte Container; public ushort ChunkId; public StackPositions(byte Group, byte Container, ushort ChunkId) { this.ContainerGroup = Group; this.Container = Container; this.ChunkId = ChunkId; } } private List _stack = new List(); private int _position; private List _stackPosition = new List(); private bool _done = false; private long _size; private long _writtenBytes; private string _fileName; private long startTime; private long endTime; private long expectedSize; private long lastRecivedTime; private double lastBytesPerTick; public ContainerStack() { this.startTime = DateTime.Now.Ticks; this.lastRecivedTime = DateTime.Now.Ticks; } public ContainerStack(string FileName) { this._fileName = FileName; this.startTime = DateTime.Now.Ticks; this.lastRecivedTime = DateTime.Now.Ticks; } public ContainerStack(long expectedSize) { this.startTime = DateTime.Now.Ticks; this.expectedSize = expectedSize; this.lastRecivedTime = DateTime.Now.Ticks; } public ContainerStack(string FileName, long expectedSize) { this._fileName = FileName; this.expectedSize = expectedSize; this.startTime = DateTime.Now.Ticks; this.lastRecivedTime = DateTime.Now.Ticks; } public void AddStackPosition(Container c, ushort chunkId) { this._stackPosition.Add(new StackPositions(c.GroupId, c.ContainerId, chunkId)); } public void AddStackPosition(byte GroupId, byte ContainerId, ushort chunkId) { this._stackPosition.Add(new StackPositions(GroupId, ContainerId, chunkId)); } public void add(byte[] bytes) { this._stack.AddRange(bytes); this._size += bytes.Length; this._writtenBytes += bytes.Length; long tmp = DateTime.Now.Ticks - this.lastRecivedTime; if (tmp == 0) tmp = 1; this.lastBytesPerTick = bytes.Length / tmp; this.lastRecivedTime = DateTime.Now.Ticks; } public void add(byte b) { this._stack.Add(b); this._size++; this._writtenBytes++; this.lastBytesPerTick = 1 / (DateTime.Now.Ticks - this.lastRecivedTime); this.lastRecivedTime = DateTime.Now.Ticks; } public byte[] read(int length) { int c = this._position; this._position += length; int stackLen = Math.Min(length, this._stack.Count); byte[] b = this._stack.GetRange(0, stackLen).ToArray(); this._stack.RemoveRange(0, stackLen); this._size -= length; return b; } public long Size { get { return this._size; } } public long WrittenBytes { get { return this._writtenBytes; } } public string FileName { get { return this._fileName; } set { this._fileName = value; } } /// /// Returns the upload duration in miliseconds /// public double UploadDuration { get { if (this.endTime == 0) return (DateTime.Now.Ticks - this.startTime) / (TimeSpan.TicksPerMillisecond / 1000); else return (this.endTime - this.startTime) / (TimeSpan.TicksPerMillisecond / 1000); } } /// /// Returns the remaining expected upload time in seconds /// public double ExpectedTimeRemaining { get { if (this.endTime != 0 && this.expectedSize>0) { if(this.lastBytesPerTick>0) { // Long version //double bytesPerTick = ((this._writtenBytes / (DateTime.Now.Ticks - this.startTime)) + this.lastBytesPerTick) / 2; //long remaining = this.expectedSize - this._writtenBytes; //return bytesPerTick * remaining * TimeSpan.TicksPerSecond; // Short version return (((this._writtenBytes / (DateTime.Now.Ticks - this.startTime)) + this.lastBytesPerTick) / 2) * (this.expectedSize - this._writtenBytes) * TimeSpan.TicksPerSecond; } else { // Long version //double bytesPerTick = (this._writtenBytes / (DateTime.Now.Ticks - this.startTime)); //long remaining = this.expectedSize - this._writtenBytes; //return bytesPerTick * remaining * TimeSpan.TicksPerSecond; // Short version return (this._writtenBytes / (DateTime.Now.Ticks - this.startTime)) * (this.expectedSize - this._writtenBytes) * TimeSpan.TicksPerSecond; } } else return 0; } } public byte[] getStackPositions() { byte[] b = new byte[this._stackPosition.Count * 4]; for(int i = 0, c = this._stackPosition.Count; i> 8); b[(i * 4) + 3] = (byte)(this._stackPosition[i].ChunkId % 256); } return b; } public float PercentLoaded { get { if (this.expectedSize == 0 && this.endTime == 0) return 0.0f; if (this.endTime > 0) return 1.0f; return this._writtenBytes / this.expectedSize; } } public float PercentWritten { get { if (this.expectedSize == 0) return 0.0f; return (this._writtenBytes - this._size) / this.expectedSize; } } public bool IsDone { get { return this._done; } set { this.endTime = DateTime.Now.Ticks; this._done = value; } } } }