/// <summary> /// Selects the servers to use for strong consistency reads. /// This always returns the primary, though, in some cases, it may be possible to /// determine whether a secondary replica is sufficiently up-to-date. /// </summary> /// <param name="objectName">The object being read</param> /// <returns>The selected servers.</returns> public HashSet <ServerState> SelectServersForStrongConsistency(string objectName) { HashSet <ServerState> set = new HashSet <ServerState>(); foreach (string server in config.PrimaryServers) { if (!config.WriteOnlyPrimaryServers.Contains(server)) { set.Add(monitor.GetServerState(server)); } } return(set); }
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 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); } } }