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); }
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); }
public ConsistencySLAEngine(ServiceLevelAgreement sla, ReplicaConfiguration config, SessionState sessionState = null, ServerMonitor monitor = null, ChosenUtility chosenUtility = null) { this.Sla = sla; this.Config = config; if (sessionState != null) { this.Session = sessionState; } else { this.Session = new SessionState(); } if (monitor != null) { this.Monitor = monitor; } else { this.Monitor = new ServerMonitor(config); } this.chosenUtility = chosenUtility; this.selector = new ServerSelector(Session, Config, Monitor); }
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); } }
/// <summary> /// Constructs a new server selector instance. /// </summary> /// <param name="session">holds the session state</param> /// <param name="config">holds the current replica configuration</param> public ServerSelector(SessionState session, ReplicaConfiguration config, ServerMonitor monitor) { this.session = session; this.config = config; this.monitor = monitor; }