private void StartReplicating() { Dictionary <string, SynchronizeContainer> syncing = new Dictionary <string, SynchronizeContainer>(); Dictionary <string, DateTimeOffset> lastSynced = new Dictionary <string, DateTimeOffset>(); int alreadySleep = 0; while (true) { if (configuration.IsInFastMode() && configuration.SecondaryServers.Count > 0) { alreadySleep = 0; syncing.Clear(); // compute shortest sync period int sleepTime = ConstPool.DEFAULT_SYNC_INTERVAL; foreach (string server in configuration.SecondaryServers) { if (configuration.GetSyncPeriod(server) < sleepTime) { sleepTime = configuration.GetSyncPeriod(server); } } Thread.Sleep(sleepTime - alreadySleep); foreach (string server in configuration.SecondaryServers) { //server should not exist in primary servers. This case happens during first phase of MakeSoloPrimaryServer action //where a secondary server also exist in primary server set. if (configuration.GetSyncPeriod(server) == sleepTime && !configuration.PrimaryServers.Contains(server)) { Console.WriteLine("Starting to sync " + configuration.Name + " with " + server); DateTimeOffset?tmpOffset = null; if (lastSynced.ContainsKey(server)) { tmpOffset = lastSynced[server]; } lastSynced[server] = DateTimeOffset.Now; SynchronizeContainer synchronizer = new SynchronizeContainer(ClientRegistry.GetMainPrimaryContainer(name), ClientRegistry.GetCloudBlobContainer(server, name), tmpOffset); synchronizer.BeginSyncContainers(); syncing[server] = synchronizer; } } foreach (string syncedServer in syncing.Keys) { syncing[syncedServer].EndSyncContainers(); } Console.WriteLine("Finished synchronization. "); alreadySleep = sleepTime; } else { lock (configuration) Monitor.Wait(configuration, ConstPool.CONFIGURATION_ACTION_DURATION); } } }
/// <summary> /// Read the configuration blob from Azure storage and update the local configuration. /// </summary> internal bool DownloadConfiguration() { try { using (MemoryStream stream = new MemoryStream()) { configurationBlob.DownloadToStream(stream); stream.Seek(0, 0); BinaryFormatter formatter = new BinaryFormatter(); ReplicaConfiguration cloudConfig = (ReplicaConfiguration)formatter.Deserialize(stream); if (!configurationBlob.Metadata.ContainsKey(ConstPool.EPOCH_NUMBER)) { Console.WriteLine("No Epoch in configuration metadata!"); // this should not happen return(false); // stay with current configuration for now } int currentEpoch = Convert.ToInt32(configurationBlob.Metadata[ConstPool.EPOCH_NUMBER]); if (currentEpoch > config.Epoch) { config.PrimaryServers = cloudConfig.PrimaryServers; config.PrimaryServers.Sort(); config.SecondaryServers = cloudConfig.SecondaryServers ?? new List <string>(); config.WriteOnlyPrimaryServers = cloudConfig.WriteOnlyPrimaryServers ?? new List <string>(); foreach (string server in config.SecondaryServers) { config.SetSyncPeriod(server, cloudConfig.GetSyncPeriod(server)); } config.Epoch = currentEpoch; if (configurationBlob.Metadata[ConstPool.EPOCH_MODIFIED_TIME] != null) { config.EpochModifiedTime = DateTimeOffset.Parse(configurationBlob.Metadata[ConstPool.EPOCH_MODIFIED_TIME]); } else { config.EpochModifiedTime = DateTimeOffset.MinValue; } } } } catch (StorageException se) { Console.WriteLine(se.ToString()); Console.WriteLine(se.StackTrace); throw se; } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.WriteLine(ex.StackTrace); throw ex; } return(true); }
// Returns the likelihood that a given server is sufficiently up-to-date to meet the given consistency // For many consistencies, this is hard to predict, and better predicitve models are possible. public float ProbabilityOfServerConsistency(ReplicaConfiguration config, string server, Consistency consistency, int bound) { float prob = 0; switch (consistency) { case Consistency.Strong: if (config.PrimaryServers.Contains(server) && !config.WriteOnlyPrimaryServers.Contains(server)) { prob = 1.0F; } break; case Consistency.ReadMyWrites: case Consistency.Session: // could possibly compute probability based on past performance and read/write ratio // for now, arbitrarily return 0.5 prob = 0.5F; break; case Consistency.MonotonicReads: // almost always will read from the closest server prob = 1.0F; break; case Consistency.Causal: // could possibly compute probability based on past performance and read/write ratio // for now, arbitrarily return 0.25 prob = 0.25F; break; case Consistency.Bounded: case Consistency.BoundedMonotonicReads: // depends on the sync frequency if (bound >= config.GetSyncPeriod(server)) { prob = 1.0F; } else { prob = bound / config.GetSyncPeriod(server); } break; case Consistency.BoundedReadMyWrites: case Consistency.BoundedSession: // depends on the sync frequency if (bound >= config.GetSyncPeriod(server)) { prob = 0.5F; } else { prob = bound / config.GetSyncPeriod(server); } break; case Consistency.Eventual: if (config.PrimaryServers.Contains(server) || config.SecondaryServers.Contains(server)) { prob = 1.0F; } break; default: prob = 0; break; } return(prob); }