public LocationConstraint(string containerName, ReplicaConfiguration currentConfig, string serverName, LocationConstraintType type) : base(containerName, currentConfig) { this.Type = type; this.ConstrainedContainer = ClientRegistry.GetCloudBlobContainer(serverName, containerName); this.ServerName = serverName; }
internal ConfigurationAction(string containerName, string serverName, float?utility, string SLAId = null, ConfigurationActionSource source = ConfigurationActionSource.NonConstraint, int numberOfReads = 0, int numberOfWrites = 0) { this.Configuration = ClientRegistry.GetConfiguration(containerName, false); this.ModifyingContainer = ClientRegistry.GetCloudBlobContainer(serverName, containerName); this.GainedUtility = utility ?? 0; OriginatingSLAs = new HashSet <string>(); Clients = new HashSet <string>(); if (SLAId != null) { OriginatingSLAs.Add(SLAId); } this.Source = source; this.numberOfReads = numberOfReads; this.numberOfWrites = numberOfWrites; this.ServerName = serverName; if (numberOfBlobs == 0) { CloudBlobContainer primaryContainer = ClientRegistry.GetCloudBlobContainer(Configuration.PrimaryServers.First(), containerName); numberOfBlobs = primaryContainer.ListBlobs().Count(); } Cost = ComputeCost(); }
public override void Execute() { CloudBlobContainer primaryContainer = ClientRegistry.GetCloudBlobContainer(Configuration.PrimaryServers.First(), ModifyingContainer.Name); SynchronizeContainer synchronizer = new SynchronizeContainer(primaryContainer, ModifyingContainer); synchronizer.BeginSyncContainers(); Configuration.EndCurrentEpoch(); Configuration.PrimaryServers.Add(ServerName); //we add the new primary also to the list of write_only primaries. //Servers in this list are not registered in session state, hence a get operation cannot be issued for them. //This makes put operations to go to all primaries (including the new one), but get_primary only goes to old primaries (those that does not exist in not register list). Configuration.WriteOnlyPrimaryServers.Add(ServerName); Configuration.StartNewEpoch(); //We wait until sync is finihsed synchronizer.EndSyncContainers(); // TODO: check that the new primary server did indeed get all of the writes. Configuration.EndCurrentEpoch(); //We clear the not register primary list, so the new primary can also be registered and used for get_primary operations. Configuration.WriteOnlyPrimaryServers.Clear(); //Finally, we update the lookup service by writing the new configuration to the cloud, so every other client can read it. Configuration.StartNewEpoch(); }
public override void Execute() { if (!Configuration.PrimaryServers.Contains(ServerName)) { AppendToLogger("Start Asynchronous Synchronization."); CloudBlobContainer primaryContainer = ClientRegistry.GetCloudBlobContainer(Configuration.PrimaryServers.First(), ModifyingContainer.Name); SynchronizeContainer synchronizer = new SynchronizeContainer(primaryContainer, ModifyingContainer); // let's try avoiding asynchronous sync to see if that makes things run faster // synchronizer.BeginSyncContainers(); AppendToLogger("Ending Epoch " + Configuration.Epoch); Configuration.EndCurrentEpoch(); Configuration.PrimaryServers.Add(ServerName); //add the new primary also to the list of write_only primaries. //Servers in this list are not registered in session state, hence a get operation cannot be issued for them. //This makes put operations to go to all primaries (including the new one), but get_primary only goes to old primaries (those that does not exist in not register list). Configuration.WriteOnlyPrimaryServers.Add(ServerName); AppendToLogger("Starting the new Epoch"); Configuration.StartNewEpoch(); //wait until sync is finihsed AppendToLogger("Wait to finish Synchronization"); // synchronizer.EndSyncContainers(); synchronizer.SyncContainers(); } AppendToLogger("Synchronization finished. Ending current epoch again."); Configuration.EndCurrentEpoch(); //clear the not registered primary list, so the new primary can also be registered and used for get_primary operations. Configuration.WriteOnlyPrimaryServers.Clear(); //all primaries will become secondaries, hence they are added to secondary list, and their sync period is set. Configuration.PrimaryServers.ForEach(s => { if (!s.Equals(ServerName)) { Configuration.SecondaryServers.Add(s); } Configuration.SetSyncPeriod(s, ConstPool.DEFAULT_SYNC_INTERVAL); }); Configuration.PrimaryServers.Clear(); //new primary is added to primary list. Configuration.PrimaryServers.Add(ServerName); //if the new primary has been a secondary, it is removed from the secondary list. if (Configuration.SecondaryServers.Contains(ServerName)) { Configuration.SecondaryServers.Remove(ServerName); } //Finally, update the lookup service by writing the new configuration to the cloud, so every other client can read it. AppendToLogger("Starting the new Epoch with One Primary"); Configuration.StartNewEpoch(); }
/// <summary> /// Pings all servers to obtain their round-trips times and their high timestamps. /// </summary> public void PingTimestampsNow() { Stopwatch watch = new Stopwatch(); foreach (string server in configuration.SecondaryServers) { // if the server is not reached yet, we perform a dummy operation for it. if (!replicas[server].IsContacted()) { try { //we perform a dummy operation to get the rtt latency! DateTimeOffset?serverTime = null; long rtt; if (server.EndsWith("-secondary") && configuration.PrimaryServers.Contains(server.Replace("-secondary", ""))) { // get the server's last sync time from Azure // this call only works on Azure secondaries CloudBlobClient blobClient = ClientRegistry.GetCloudBlobClient(server); watch.Restart(); ServiceStats stats = blobClient.GetServiceStats(); rtt = watch.ElapsedMilliseconds; replicas[server].AddRtt(rtt); if (stats.GeoReplication.LastSyncTime.HasValue) { serverTime = stats.GeoReplication.LastSyncTime.Value; } } else { // get the server's last sync time from the container's metadata CloudBlobContainer blobContainer = ClientRegistry.GetCloudBlobContainer(server, configuration.Name); watch.Restart(); blobContainer.FetchAttributes(); rtt = watch.ElapsedMilliseconds; if (blobContainer.Metadata.ContainsKey("lastsync")) { //if no lastmodified time is provided in the constructor, we still try to be fast. //So, we check to see if by any chance the container previously has synchronized. serverTime = DateTimeOffset.Parse(blobContainer.Metadata["lastsync"]); } } if (serverTime.HasValue && serverTime > replicas[server].HighTime) { replicas[server].HighTime = serverTime.Value; } } catch (StorageException) { // do nothing } } } }
public override void Execute() { AppendToLogger("Start Synchronization"); CloudBlobContainer primaryContainer = ClientRegistry.GetCloudBlobContainer(Configuration.PrimaryServers.First(), ModifyingContainer.Name); SynchronizeContainer synchronizer = new SynchronizeContainer(primaryContainer, ModifyingContainer); synchronizer.SyncContainers(); AppendToLogger("Synchronization finished."); //Update the configuration Configuration.SecondaryServers.Add(ServerName); AppendToLogger("Starting the new Epoch"); Configuration.StartNewEpoch(); }
private static void SyncSecondaryServers() { string primarySite = config.PrimaryServers.First(); foreach (string secondarySite in config.SecondaryServers) { if (!config.ReadOnlySecondaryServers.Contains(secondarySite)) { SynchronizeContainer synchronizer = new SynchronizeContainer(ClientRegistry.GetCloudBlobContainer(primarySite, containerName), ClientRegistry.GetCloudBlobContainer(secondarySite, containerName)); synchronizer.SyncContainers(); Log("Synchronization completed to " + SiteName(secondarySite) + "."); } else { Log("Could not sync to " + SiteName(secondarySite) + " since secondary is read-only."); } } }