private void SlowWrite(WriteOp op, AccessCondition accessCondition, List <SessionState> sessions = null, ServerMonitor monitor = null) { // A reconfiguration is in progress, but may not have happened yet. // We could try to complete this write before the reconfiguration, but that would require locking // to prevent the configuration service from changing the configuration during this write. // Instead, we take the simple approach of waiting for the reconfiguration to complete. bool isDone = false; do // while unable to lease the configuration { if (configuration.IsInFastMode(renew: true)) { if (configuration.PrimaryServers.Count == 1) { FastWrite(op, sessions, monitor); } else { MultiWrite(op, accessCondition, sessions, monitor); } isDone = true; } else { Thread.Sleep(ConstPool.CONFIGURATION_ACTION_DURATION); } }while (!isDone); }
private void FastWrite(WriteOp op, List <SessionState> sessions = null, ServerMonitor monitor = null) { // there should only be one primary server since we are in fast mode string server = configuration.PrimaryServers.First(); ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false); watch.Start(); op(blob); watch.Stop(); // update server and session state ServerState ss = (monitor == null) ? slaEngine.Monitor.GetServerState(server) : monitor.GetServerState(server); ss.AddRtt(watch.ElapsedMilliseconds); if (sessions == null) { slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss); } else { foreach (SessionState session in sessions) { session.RecordObjectWritten(blobName, Timestamp(blob), ss); } } }
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); }; } }
private void WriteLoop <TValue>(byte register, TValue value, WriteOp <TValue> op) { for (int i = 0; i < MaxRetries; i++) { if (op(register, value)) { return; } } }
/// <summary> /// Perform a local write operation, e.g. set a property, on all blobs holding a replica. /// This does not bother to check the lease on the configuration. /// It should not be used for arbitrary writes that need to be performed atomically. /// </summary> /// <param name="op">the write operation being done</param> public void SetProperty(WriteOp op) { foreach (string server in configuration.PrimaryServers) { ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName); op(blob); } foreach (string server in configuration.SecondaryServers) { ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName); op(blob); } }
public void Write(WriteOp op, AccessCondition accessCondition, List <SessionState> sessions = null, ServerMonitor monitor = null) { // TODO: ensure that there is enough time left on the lease to complete the write // Can set a timeout using BlobRequestOptions and/or renew a least that is about to expire if (configuration.IsInFastMode()) { if (configuration.PrimaryServers.Count == 1) { FastWrite(op, sessions, monitor); } else { MultiWrite(op, accessCondition, sessions, monitor); } } else { SlowWrite(op, accessCondition, sessions, monitor); } }
private void MultiWriteUsingBlobLease(WriteOp op) { // TODO: recover from failed clients that may leave a write partially completed // TODO: remove use of leases and replace with ETags // throw new Exception("Write to multiple primaries not yet implemented."); try { bool done = false; while (!done) { // grab lease on blob to guard against concurrent writers using (PrimaryCloudBlobLease lease = new PrimaryCloudBlobLease(blobName, configuration, true)) { if (lease.HasLease) { // TODO: fix code for writing to multiple primaries (and remove it from here) foreach (string server in configuration.PrimaryServers) { watch.Start(); ICloudBlob blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false); op(blob); watch.Stop(); ServerState ss = slaEngine.Monitor.GetServerState(server); ss.AddRtt(watch.ElapsedMilliseconds); slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss); } done = true; } } } } catch (StorageException se) { throw se; } catch (Exception ex) { throw ex; } }
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); }
private void DoFlush(IoSession session, WriteOp op) { if (op != null && !op.IsExpired) { try { long cnt = flushCounter.AtomicIncrementAndGet(); long now = new DateTime().CurrentTimeMillis(); if (now - lastLogTime.ReadFullFence() > 60000) { lastLogTime.WriteFullFence(now); string log = String.Format("opQueueSize: {0}, session: {1}, couner: {2}", opQueue.Count, session.RemoteEndPoint.ToString(), cnt); client.Log.Info(log); } var writeFuture = session.Write(op.Command); writeFuture.Complete += (s, e) => { if (e.Future.Done) { flushing.AtomicExchange(false); flushingOp.AtomicExchange(null); } else { if (!IsClosed) { Thread.Sleep(client.Config.EndpointSessionWriteRetryDealyInMills); DoFlush(e.Future.Session, op); } } }; } catch (Exception ex) { client.Log.Error(ex); flushing.AtomicExchange(false); flushingOp.AtomicExchange(null); } } else { flushing.AtomicExchange(false); flushingOp.AtomicExchange(null); } }
private void MultiWrite(WriteOp op, AccessCondition access, List <SessionState> sessions = null, ServerMonitor monitor = null) { // This protocol uses three phases and ETags // It assumes that the client is in fast mode and remains so throughout the protocol // i.e. it assumes that the set of primaries does not change. // TODO: recover from failed clients that may leave a write partially completed ICloudBlob blob; Dictionary <string, string> eTags; // Phase 1. Mark intention to write with write-in-progress flags eTags = SetWiPFlags(); if (eTags == null) { // flags were not successfully set, so abort the protocol return; } // Phase 2. Perform write at all primaries bool didAtLeastOne = false; foreach (string server in configuration.PrimaryServers) { blob = ClientRegistry.GetCloudBlob(server, configuration.Name, blobName, false); access.IfMatchETag = eTags[server]; watch.Start(); try { op(blob); } catch (StorageException) { // If writing fails at some primary, then abort the protocol // It could be that a concurrent writer is in progress // Note that some writes may have already been performed // If so, then we leave the WiP flags set so the recovery process will kick in // or so a concurrent writer can complete its protocol and overwrite our writes // If not, then we can clear the WiP flags if (!didAtLeastOne) { ClearWiPFlags(eTags); } return; } watch.Stop(); eTags[server] = blob.Properties.ETag; didAtLeastOne = true; // update session and server state ServerState ss = (monitor == null) ? slaEngine.Monitor.GetServerState(server) : monitor.GetServerState(server); ss.AddRtt(watch.ElapsedMilliseconds); if (sessions == null) { slaEngine.Session.RecordObjectWritten(blobName, Timestamp(blob), ss); } else { foreach (SessionState session in sessions) { session.RecordObjectWritten(blobName, Timestamp(blob), ss); } } } // Phase 3. Clear write-in-progress flags to indicate that write has completed ClearWiPFlags(eTags); }