/// WriteTo writes data to w until the buffer is drained or an error occurs. /// The return value n is the number of bytes written; it always fits into an /// int, but it is int64 to match the io.WriterTo interface. Any error /// encountered during the write is also returned. public long WriteTo(Stream w) { var n = 0L; _lastRead = ReadOp.opInvalid; if (_off < _buf.Length) { var nBytes = this.Len(); var arr = _buf.Slice(_off).ToArray(); w.Write(arr, 0, arr.Length); var m = arr.Length; if (m > nBytes) { throw new Exception("bytes.Buffer.WriteTo: invalid Write count"); } _off += m; n = (long)m; // all bytes should have been written, by definition of // Write method in io.Writer if (m != nBytes) { return(n); } } // Buffer is now empty; reset. Reset(); return(n); }
public void SetupOperations(Boolean monitorOps) { if (monitorOps) { ReadOperationHandler = (b, o, c) => { if (m_Core.State.PC != Position && m_Core.State.BranchPC != Position) { Machine.Current.DeviceCPU.ResourceMonitor.CPUMemRead(Position); } return(base.Read(b, o, c)); }; WriteOperationHandler = (b, o, c) => { Machine.Current.DeviceCPU.ResourceMonitor.CPUMemWrite(Position); base.Write(b, o, c); }; } else { ReadOperationHandler = (b, o, c) => { return(base.Read(b, o, c)); }; WriteOperationHandler = (b, o, c) => { base.Write(b, o, c); }; } }
/// ReadFrom reads data from r until EOF and appends it to the buffer, growing /// the buffer as needed. The return value n is the number of bytes read. Any /// error except io.EOF encountered during the read is also returned. If the /// buffer becomes too large, ReadFrom will panic with ErrTooLarge. public long ReadFrom(Stream r) //func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { { var n = 0L; _lastRead = ReadOp.opInvalid; // If buffer is empty, reset to recover space. if (_off >= _buf.Length) { Reset(); } for (;;) { var free = _buf.Capacity - _buf.Length; if (free < MinRead) { // not enough space at end var newBuf = _buf; if (_off + free < MinRead) { // not enough space using beginning of buffer; // double buffer capacity newBuf = MakeSlice(2 * _buf.Capacity + MinRead); } newBuf.CopyFrom(_buf.Slice(_off)); _buf = newBuf.Slice(upper: _buf.Length - _off); _off = 0; } var bytes = new byte[_buf.Capacity - _buf.Length]; var m = r.Read(bytes, 0, bytes.Length); if (m > 0) { var slice = bytes.Slice(upper: m); _buf = _buf.AppendAll(slice); n += (long)m; } else { break; } // m, e := r.Read(b.buf[len(b.buf):cap(b.buf)]) // b.buf = b.buf[0 : len(b.buf)+m] // n += int64(m) // if e == io.EOF { // break // } // if e != nil { // return n, e // } } return(n); //return n, nil // err is EOF, so return nil explicitly }
/// WriteByte appends the byte c to the buffer, growing the buffer as needed. /// The returned error is always nil, but is included to match bufio.Writer's /// WriteByte. If the buffer becomes too large, WriteByte will panic with /// ErrTooLarge. public override void WriteByte(byte c) { _lastRead = ReadOp.opInvalid; var(m, ok) = TryGrowByReslice(1); if (!ok) { m = GrowInternal(1); } _buf[m] = c; }
/// WriteString appends the contents of s to the buffer, growing the buffer as /// needed. The return value n is the length of s; err is always nil. If the /// buffer becomes too large, WriteString will panic with ErrTooLarge. public int WriteString(string s) { _lastRead = ReadOp.opInvalid; var(m, ok) = TryGrowByReslice(s.Length); if (!ok) { m = GrowInternal(s.Length); } return(_buf.Slice(m).CopyFrom(Encoding.UTF8.GetBytes(s).Slice())); }
public void Read(ReadOp op) { if (configuration.IsInFastMode()) { FastRead(op); } else { SlowRead(op); } }
/// Write appends the contents of p to the buffer, growing the buffer as /// needed. The return value n is the length of p; err is always nil. If the /// buffer becomes too large, Write will panic with ErrTooLarge. public int Write(slice <byte> p) { _lastRead = ReadOp.opInvalid; var(m, ok) = TryGrowByReslice(p.Length); if (!ok) { m = GrowInternal(p.Length); } return(_buf.Slice(m).CopyFrom(p)); }
/// UnreadRune unreads the last rune returned by ReadRune. /// If the most recent read or write operation on the buffer was /// not a successful ReadRune, UnreadRune returns an error. (In this regard /// it is stricter than UnreadByte, which will unread the last byte /// from any read operation.) public void UnreadRune() { if (_lastRead <= ReadOp.opInvalid) { throw new Exception("bytes.Buffer: UnreadRune: previous operation was not a successful ReadRune"); } if (_off >= (int)_lastRead) { _off -= (int)_lastRead; } _lastRead = ReadOp.opInvalid; }
/// UnreadByte unreads the last byte returned by the most recent successful /// read operation that read at least one byte. If a write has happened since /// the last read, if the last read returned an error, or if the read read zero /// bytes, UnreadByte returns an error. public void UnreadByte() { if (_lastRead == ReadOp.opInvalid) { throw new Exception("bytes.Buffer: UnreadByte: previous operation was not a successful read"); } _lastRead = ReadOp.opInvalid; if (_off > 0) { _off--; } }
/// <summary> /// Perform standard read and update server and session state. /// </summary> /// <param name="op">The read operation</param> /// <param name="blob">The blob being read</param> /// <param name="ss">The chosen server</param> private void FastRead(ReadOp op) { ServerState ss = slaEngine.FindServerToRead(blobName); blobForRead = ClientRegistry.GetCloudBlob(ss.Name, containerName, blobName); watch.Start(); op(blobForRead); watch.Stop(); slaEngine.RecordObjectRead(blobForRead.Name, Timestamp(blobForRead), ss, watch.ElapsedMilliseconds); }
private TResult ReadLoop <TResult>(byte register, ReadOp <TResult> op) where TResult : new() { TResult result = new(); for (int i = 0; i < MaxRetries; i++) { if (op(register, out result)) { return(result); } } return(result); }
/// Truncate discards all but the first n unread bytes from the buffer /// but continues to use the same allocated storage. /// It panics if n is negative or greater than the length of the buffer. public void Truncate(int n) { if (n == 0) { Reset(); return; } _lastRead = ReadOp.opInvalid; if (n < 0 || n > Len()) { throw new Exception("bytes.Buffer: truncation out of range"); } _buf = _buf.Slice(0, _off + n); }
/// readSlice is like ReadBytes but returns a reference to internal buffer data. private (slice <byte> line, bool eof) ReadSlice(byte delim) { var line = slice <byte> .Empty; var eof = false; var i = _buf.Slice(_off).IndexOf(delim); var end = _off + i + 1; if (i < 0) { end = _buf.Length; eof = true; } line = _buf.Slice(_off, end); _off = end; _lastRead = ReadOp.opRead; return(line, eof); }
/// Next returns a slice containing the next n bytes from the buffer, /// advancing the buffer as if the bytes had been returned by Read. /// If there are fewer than n bytes in the buffer, Next returns the entire buffer. /// The slice is only valid until the next call to a read or write method. public slice <byte> Next(int n) { _lastRead = ReadOp.opInvalid; var m = Len(); if (n > m) { n = m; } var data = _buf.Slice(_off, _off + n); _off += n; if (n > 0) { _lastRead = ReadOp.opRead; } return(data); }
/// WriteRune appends the UTF-8 encoding of Unicode code point r to the // buffer, returning its length and an error, which is always nil but is /// included to match bufio.Writer's WriteRune. The buffer is grown as needed; /// if it becomes too large, WriteRune will panic with ErrTooLarge. public int WriteRune(char r) { var n = 0; if (r < RuneSelf) { WriteByte((byte)r); return(1); } _lastRead = ReadOp.opInvalid; var(m, ok) = TryGrowByReslice(UTFMax); if (!ok) { m = GrowInternal(UTFMax); } n = _buf.Slice(m, m + UTFMax).EncodeRune(r); _buf = _buf.Slice(upper: m + n); return(n); }
// ReadRune reads and returns the next UTF-8-encoded // Unicode code point from the buffer. // If no bytes are available, the error returned is io.EOF. // If the bytes are an erroneous UTF-8 encoding, it // consumes one byte and returns U+FFFD, 1. public (char r, int size, bool eof) ReadRune() { _lastRead = ReadOp.opInvalid; if (_off >= _buf.Length) { // Buffer is empty, reset to recover space. Reset(); return(char.MinValue, 0, eof : true); } var c = _buf[_off]; if (c < RuneSelf) { _off++; _lastRead = ReadOp.opReadRune1; return((char)c, 1, false); } var(r, n) = _buf.Slice(_off).DecodeRune(); _off += n; _lastRead = (ReadOp)n; return(r, n, false); }
/// ReadByte reads and returns the next byte from the buffer. /// If no byte is available, it returns error io.EOF. /// /// NOTE: we added some additional logic here to support returning /// 0 when the buffer is currently empty but not signaling an EOF. public (byte val, bool eof) ReadByteOrEof(bool eofIfEmpty = true) { _lastRead = ReadOp.opInvalid; if (_off >= _buf.Length) { if (eofIfEmpty) { // Buffer is empty, reset to recover space. Reset(); return(0, eof : true); } else { return(0, eof : false); } } var c = _buf[_off]; _off++; _lastRead = ReadOp.opRead; return(c, false); }
/// Read reads the next len(p) bytes from the buffer or until the buffer /// is drained. The return value n is the number of bytes read. If the /// buffer has no data to return, err is io.EOF (unless len(p) is zero); /// otherwise it is nil. public (int val, bool eof) Read(slice <byte> p) { var n = 0; _lastRead = ReadOp.opInvalid; if (_off >= _buf.Length) { // Buffer is empty, reset to recover space. Reset(); if (p.Length == 0) { return(n, false); } return(0, eof : true); } n = p.CopyFrom(_buf.Slice(_off)); _off += n; if (n > 0) { _lastRead = ReadOp.opRead; } return(n, false); }
public void SetupOperations(Boolean monitorOps) { if (monitorOps) { ReadOperationHandler = (b, o, c) => { if (m_Core.State.PC != Position && m_Core.State.BranchPC != Position) Machine.Current.DeviceCPU.ResourceMonitor.CPUMemRead(Position); return base.Read(b, o, c); }; WriteOperationHandler = (b, o, c) => { Machine.Current.DeviceCPU.ResourceMonitor.CPUMemWrite(Position); base.Write(b, o, c); }; } else { ReadOperationHandler = (b, o, c) => { return base.Read(b, o, c); }; WriteOperationHandler = (b, o, c) => { base.Write(b, o, c); }; } }
/// <summary> /// Optimization #6: /// Constant substitution /// /// TODO: This method has some inconsistencies when setting the offset with the new memory operations. /// For some memory operations, I'm using "new {Op}(ptr + {op}.Offset)" /// and for others I'm just using "new {Op}({op}.Offset)". /// I'm pretty sure this inconsistency is causing some problems. /// </summary> /// <param name="operations"></param> private bool SubstituteConstants(ref DILOperationSet operations) { if (WereConstantsSubstituted) { return(false); } var ptr = 0; var arr = operations.ToArray(); var didAnysubstitutions = false; for (int i = 0; i < arr.Length; i++) { var operation = arr[i]; if (operation is AdditionMemoryOp) { var add = (AdditionMemoryOp)operation; if (add.Constant == null) { arr[i] = new AdditionMemoryOp(ptr + add.Offset, add.Scalar, new ConstantValue(ptr + add.Offset)); didAnysubstitutions = true; } } else if (operation is MultiplicationMemoryOp) { var mul = (MultiplicationMemoryOp)operation; if (mul.Constant == null) { arr[i] = new MultiplicationMemoryOp(ptr + mul.Offset, mul.Scalar, new ConstantValue(ptr + mul.Offset), new ConstantValue(ptr)); } } else if (operation is AssignOp) { var ass = arr[i] as AssignOp; if (ass.Constant == null) { arr[i] = new AssignOp(ptr + ass.Offset, ass.Value, new ConstantValue(ptr + ass.Offset)); didAnysubstitutions = true; } } else if (operation is PtrOp) { arr[i] = null; // if we're using constants, then we don't need pointer movements var ptrOp = (PtrOp)operation; ptr += ptrOp.Delta; //didAnysubstitutions = true; } else if (operation is WriteOp) { var write = ((WriteOp)arr[i]); if (write.Constant == null) { arr[i] = new WriteOp(write.Offset, write.Repeated, new ConstantValue(ptr)); didAnysubstitutions = true; } } else if (operation is ReadOp) { var read = ((ReadOp)arr[i]); if (read.Constant == null) { arr[i] = new ReadOp(read.Offset, read.Repeated, new ConstantValue(ptr)); didAnysubstitutions = true; } } } var list = arr.ToList(); list.RemoveAll(l => l == null); operations = new DILOperationSet(list); operations.WereConstantsSubstituted = true; return(didAnysubstitutions); }
/// <summary> /// Perform read optimistically and then verify configuration. /// </summary> /// <param name="op">The read operation</param> /// <param name="blob">The blob being read</param> /// <param name="ss">The chosen server</param> /// <returns>whether the read succeeded; if not, then it should be tried again.</returns> private void SlowRead(ReadOp op) { // TODO: Deal with the case that we try to read from a replica that is no longer a replica and the read fails // In this case, the read should be retried after refreshing the configuration. ServerState ss = null; try { bool isDone = false; do // until we enter fast mode or succeed at reading in slow mode with the correct configuration { ss = slaEngine.FindServerToRead(blobName); blobForRead = ClientRegistry.GetCloudBlob(ss.Name, containerName, blobName); // TODO: this should really check if the reader wants strong consistency // It could be that eventual consistency is fine but the SLA Engine just happened to choose a primary server // In this case, we can do a fast mode read since we don't care if the chosen server is no longer a primary if (configuration.IsInFastMode() || !configuration.PrimaryServers.Contains(ss.Name)) { // it is fine to read from the selected secondary replica // or from a primary replica if we have now entered fast mode FastRead(op); isDone = true; } else { // read from the selected replica that we believe to be a primary replica watch.Start(); op(blobForRead); watch.Stop(); // then see if the configuration has changed and the selected replica is no longer primary configuration.SyncWithCloud(ClientRegistry.GetConfigurationAccount()); // TODO: check the epoch number on the configuration to make sure that we have not missed a configuration. // i.e. we need to make sure that the server from which we read did not become a secondary during our read, // and then back to primary when we checked. // TODO: maybe we should check that the read delivered a non-zero utility. // It is possible that the configuration was so stale that a much better server could have been chosen. if (configuration.PrimaryServers.Contains(ss.Name)) { //We have contacted the primary replica, hence we are good to go. slaEngine.RecordObjectRead(blobForRead.Name, Timestamp(blobForRead), ss, watch.ElapsedMilliseconds); isDone = true; } isDone = false; // not done } } while (!isDone); } // TODO: decide if we need to catch any exceptions here or just let then propagate through catch (StorageException se) { if (StorageExceptionCode.NotFound(se)) { //blob is not found. //this is fine because the replica might have removed. //it simply returns, so client need to re-execute if this happens. //We can also re-execute the read here, but for debugging purposes, it's simpler for the client to re-execute. //Of course in real system, we need to re-execute at this level. return; } // storage exceptions are passed through to the caller throw; } catch (Exception ex) { if (ex.Message.Contains("Object reference not set to an instance of an object")) { return; } throw ex; } }
/// Reset resets the buffer to be empty, /// but it retains the underlying storage for use by future writes. /// Reset is the same as Truncate(0). public void Reset() { _buf = _buf.Slice(upper: 0); _off = 0; _lastRead = ReadOp.opInvalid; }