Пример #1
0
		public void Update(DateTime utcNow, IReadOnlyList<LocationState> locations, bool simulateFailure)
		{
			this.LastUpdateRequest = utcNow;
			if (this.PeerGroup.CanPoll(utcNow, this.LastUpdated))
			{
				this.LastUpdated = utcNow;

				// Increment this each time so we can uniquely identify which Update call last
				// updated an item and so we'll round-robin through each location in the list.
				this.UpdateCounter++;

				bool wasConnected = this.IsConnected;

				bool? isPeerGroupConnected = null;
				int numLocations = locations.Count;
				for (int i = 0; i < numLocations; i++)
				{
					int locationIndex = (int)unchecked((this.UpdateCounter + i) % numLocations);
					LocationState locationState = locations[locationIndex];
					bool? wasLocationUpdated = locationState.Update(utcNow, this.UpdateCounter, simulateFailure);

					// A null result means we've polled it too recently.
					if (wasLocationUpdated != null)
					{
						// If we get a connected result, then we can quit early.
						isPeerGroupConnected = locationState.IsConnected;
						if (isPeerGroupConnected ?? false)
						{
							break;
						}
					}
				}

				if (isPeerGroupConnected != null)
				{
					this.IsConnected = isPeerGroupConnected.Value;
				}

				if (this.IsConnected != wasConnected)
				{
					this.IsConnectedChanged = utcNow;
				}

				bool wasFailed = this.IsFailed;
				if (this.IsConnected)
				{
					this.IsFailed = false;
				}
				else if (!this.IsFailed && (this.IsConnectedChanged == null || utcNow >= (this.IsConnectedChanged.Value + this.PeerGroup.Fail)))
				{
					this.IsFailed = true;
				}

				if (this.IsFailed != wasFailed)
				{
					this.IsFailedChanged = utcNow;
				}
			}
		}
Пример #2
0
        private void UpdateLocations(NotifyCollectionChangedEventArgs e)
        {
            bool FindLocationState(Location location, out LocationState state)
            {
                state = this.Locations.FirstOrDefault(l => l.Location == location);
                return(state != null);
            }

            LocationState GetLocationState(Location location, bool allowAdd = true)
            {
                if (!FindLocationState(location, out LocationState result))
                {
                    this.GetPeerGroupState(location.PeerGroup);

                    result = new LocationState(location);
                    if (allowAdd)
                    {
                        this.Locations.Add(result);
                    }
                }

                return(result);
            }

            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
                foreach (Location location in e.NewItems)
                {
                    GetLocationState(location);
                }

                break;

            case NotifyCollectionChangedAction.Remove:
                foreach (Location location in e.OldItems)
                {
                    if (FindLocationState(location, out LocationState state))
                    {
                        this.Locations.Remove(state);
                    }
                }

                break;

            case NotifyCollectionChangedAction.Replace:
                foreach (var pair in e.OldItems.Cast <Location>().Zip(e.NewItems.Cast <Location>(), (o, n) => Tuple.Create(o, n)))
                {
                    if (FindLocationState(pair.Item1, out LocationState oldState))
                    {
                        LocationState newState = GetLocationState(pair.Item2, allowAdd: false);
                        int           index    = this.Locations.IndexOf(oldState);
                        this.Locations[index] = newState;
                    }
                }

                break;

            case NotifyCollectionChangedAction.Move:
                // We don't care about the profile's Location positions.
                break;

            default:                     // NotifyCollectionChangedAction.Reset
                foreach (Location location in this.profile.Locations)
                {
                    GetLocationState(location);
                }

                foreach (LocationState state in this.Locations.ToList())
                {
                    if (!this.profile.Locations.Contains(state.Location))
                    {
                        this.Locations.Remove(state);
                    }
                }

                break;
            }

            lock (this.mapLock)
            {
                this.peerGroupToLocationsMap = this.Locations
                                               .GroupBy(l => this.GetPeerGroupState(l.Location.PeerGroup))
                                               .ToDictionary(group => group.Key, group => group.OrderBy(l => l.Location.Name).ToList());
            }
        }
Пример #3
0
        public void Update(DateTime utcNow, IReadOnlyList <LocationState> locations, ConnectionState?simulateConnection)
        {
            this.LastUpdateRequest = utcNow;
            if (this.PeerGroup.CanPoll(utcNow, this.LastUpdated))
            {
                this.LastUpdated = utcNow;

                // Increment this each time so we can uniquely identify which Update call last
                // updated an item and so we'll round-robin through each location in the list.
                this.UpdateCounter++;

                ConnectionState priorConnection = this.Connection;

                ConnectionState?peerGroupConnection = null;
                int             numLocations        = locations.Count;
                for (int i = 0; i < numLocations; i++)
                {
                    int           locationIndex      = (int)unchecked ((this.UpdateCounter + i) % numLocations);
                    LocationState locationState      = locations[locationIndex];
                    bool?         wasLocationUpdated = locationState.Update(utcNow, this.UpdateCounter, simulateConnection);

                    // A null result means we've polled it too recently.
                    if (wasLocationUpdated != null)
                    {
                        // If we get a Connected result, then we can quit early.
                        // If we only get Disconnected or Unavailable, then we have to check them all.
                        peerGroupConnection = locationState.Connection;
                        if (peerGroupConnection == ConnectionState.Connected)
                        {
                            break;
                        }
                    }
                }

                // This should only be null when we've polled all the locations too recently, so Connection shouldn't change.
                if (peerGroupConnection != null)
                {
                    this.Connection = peerGroupConnection.Value;
                }

                if (this.Connection != priorConnection)
                {
                    this.ConnectionChanged = utcNow;
                }

                bool wasFailed = this.IsFailed;
                if (this.Connection == ConnectionState.Connected || this.Connection == ConnectionState.Unavailable)
                {
                    this.IsFailed = false;
                }
                else if (!this.IsFailed && (this.ConnectionChanged == null || utcNow >= (this.ConnectionChanged.Value + this.PeerGroup.Fail)))
                {
                    this.IsFailed = true;
                }

                if (this.IsFailed != wasFailed)
                {
                    this.IsFailedChanged = utcNow;
                }
            }
        }