/// <summary>
        /// Returns a standardized string identifier for a <see cref="DataSourceState"/>.
        /// </summary>
        /// <remarks>
        /// These Java-style uppercase identifiers (<c>INITIALIZING</c>, <c>VALID</c>, etc.) may be used in
        /// logging for consistency across SDKs.
        /// </remarks>
        /// <param name="state">a state value</param>
        /// <returns>a string identifier</returns>
        public static string Identifier(this DataSourceState state)
        {
            switch (state)
            {
            case DataSourceState.Initializing:
                return("INITIALIZING");

            case DataSourceState.Valid:
                return("VALID");

            case DataSourceState.Interrupted:
                return("INTERRUPTED");

            case DataSourceState.NetworkUnavailable:
                return("NETWORK_UNAVAILABLE");

            case DataSourceState.SetOffline:
                return("SET_OFFLINE");

            case DataSourceState.Shutdown:
                return("SHUTDOWN");

            default:
                return(state.ToString());
            }
        }
        public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
        {
            DataSourceStatus?statusToBroadcast = null;

            lock (_stateLock)
            {
                var oldStatus = _currentStatus;

                if (newState == DataSourceState.Interrupted && oldStatus.State == DataSourceState.Initializing)
                {
                    newState = DataSourceState.Initializing; // see comment on IDataSourceUpdates.UpdateStatus
                }

                if (newState != oldStatus.State || newError.HasValue)
                {
                    _currentStatus = new DataSourceStatus
                    {
                        State      = newState,
                        StateSince = newState == oldStatus.State ? oldStatus.StateSince : DateTime.Now,
                        LastError  = newError.HasValue ? newError : oldStatus.LastError
                    };
                    statusToBroadcast = _currentStatus;
                    _stateChangedSignal.NotifyAll();
                }
            }

            _outageTracker?.TrackDataSourceState(newState, newError);

            if (statusToBroadcast.HasValue)
            {
                _taskExecutor.ScheduleEvent(this, statusToBroadcast.Value, StatusChanged);
            }
        }
        internal async Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout)
        {
            var newStatus = await _status.WaitForAsync(
                status => status.State == desiredState || status.State == DataSourceState.Off,
                timeout
                );

            return(newStatus.HasValue && newStatus.Value.State == desiredState);
        }
        public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
        {
            var updated = _status.Update(new StateAndError {
                State = newState, Error = newError
            },
                                         out var newStatus);

            if (updated)
            {
                _taskExecutor.ScheduleEvent(newStatus, StatusChanged);
            }
        }
示例#5
0
 /// <summary>
 /// Simulates a change in the data source status.
 /// </summary>
 /// <remarks>
 /// Use this if you want to test the behavior of application code that uses
 /// <see cref="LdClient.DataSourceStatusProvider"/> to track whether the data source is having
 /// problems (for example, a network failure interrupting the streaming connection). It does
 /// not actually stop the <see cref="TestData"/> data source from working, so even if you have
 /// simulated an outage, calling <see cref="Update(FlagBuilder)"/> will still send updates.
 /// </remarks>
 /// <param name="newState">one of the constants defined by <see cref="DataSourceState"/></param>
 /// <param name="newError">an optional <see cref="DataSourceStatus.ErrorInfo"/> instance</param>
 /// <returns>the same <see cref="TestData"/> instance</returns>
 public TestData UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
 {
     DataSourceImpl[] instances;
     lock (_lock)
     {
         instances = _instances.ToArray();
     }
     foreach (var instance in instances)
     {
         instance.DoUpdateStatus(newState, newError);
     }
     return(this);
 }
示例#6
0
 public void Resume()
 {
     State = DataSourceState.Resuming;
     try
     {
         OnResume();
         State = DataSourceState.Running;
     }
     catch (Exception ex)
     {
         State      = DataSourceState.Error;
         _exception = new Exception("OnResume() got a fatal error.", ex);
     }
 }
示例#7
0
 public void Pause()
 {
     State = DataSourceState.Pausing;
     try
     {
         OnPause();
         State = DataSourceState.Paused;
     }
     catch (Exception ex)
     {
         State      = DataSourceState.Error;
         _exception = new Exception("OnPause() got a fatal error.", ex);
     }
 }
示例#8
0
 public void Stop()
 {
     State = DataSourceState.Stopping;
     try
     {
         OnStop();
         State = DataSourceState.Stopped;
     }
     catch (Exception ex)
     {
         State      = DataSourceState.Error;
         _exception = new Exception("OnStop() got a fatal error.", ex);
     }
 }
示例#9
0
 public void Initialize()
 {
     State = DataSourceState.Initializing;
     try
     {
         OnInitialize();
         State = DataSourceState.Initialized;
     }
     catch (Exception ex)
     {
         State      = DataSourceState.Error;
         _exception = new Exception("OnInitialize() got a fatal error.", ex);
     }
 }
        internal async Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout)
        {
            var  deadline   = DateTime.Now.Add(timeout);
            bool hasTimeout = timeout.CompareTo(TimeSpan.Zero) > 0;

            while (true)
            {
                MultiNotifierToken stateAwaiter;
                TimeSpan           timeToWait;
                lock (_stateLock)
                {
                    if (_currentStatus.State == desiredState)
                    {
                        return(true);
                    }
                    if (_currentStatus.State == DataSourceState.Off)
                    {
                        return(false);
                    }

                    // Here we're using a slightly roundabout mechanism to keep track of however many tasks might
                    // be simultaneously waiting on WaitForAsync, because .NET doesn't have an async concurrency
                    // primitive equivalent to Java's wait/notifyAll(). What we're creating here is a cancellation
                    // token that will be cancelled (by UpdateStatus) the next time the status is changed in any
                    // way.
                    if (hasTimeout)
                    {
                        timeToWait = deadline.Subtract(DateTime.Now);
                        if (timeToWait.CompareTo(TimeSpan.Zero) <= 0)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        timeToWait = TimeSpan.FromMilliseconds(-1); // special value makes Task.Delay wait indefinitely
                    }
                    stateAwaiter = _stateChangedSignal.Token;
                }
                await stateAwaiter.WaitAsync(timeToWait);
            }
        }
示例#11
0
        /// <summary>
        /// Returns a standardized string identifier for a <see cref="DataSourceState"/>.
        /// </summary>
        /// <remarks>
        /// These Java-style uppercase identifiers (<c>INITIALIZING</c>, <c>VALID</c>, etc.) may be used in
        /// logging for consistency across SDKs.
        /// </remarks>
        /// <param name="state">a state value</param>
        /// <returns>a string identifier</returns>
        public static string Identifier(this DataSourceState state)
        {
            switch (state)
            {
            case DataSourceState.Initializing:
                return("INITIALIZING");

            case DataSourceState.Valid:
                return("VALID");

            case DataSourceState.Interrupted:
                return("INTERRUPTED");

            case DataSourceState.Off:
                return("OFF");

            default:
                return(state.ToString());
            }
        }
示例#12
0
 private void SetState(Guid id, DataSourceState state)
 {
     //lock (dataStateInfoTable)
     //{
     if (dataStateInfoTable.ContainsKey(id))
     {
         dataStateInfoTable[id].State = state;
         if (state == DataSourceState.InTransfer)
         {
             dataStateInfoTable[id].StateDescription = IntransferStateDescription;
         }
         if (state == DataSourceState.Paused)
         {
             dataStateInfoTable[id].StateDescription = PausedStateDescription;
         }
     }
     else
     {
         //dataStateTable.Add(id, state);
     }
     //}
 }
示例#13
0
 internal void TrackDataSourceState(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
 {
     lock (_trackerLock)
     {
         if (newState == DataSourceState.Interrupted || newError.HasValue ||
             (newState == DataSourceState.Initializing && _inOutage))
         {
             // We are in a potentially recoverable outage. If that wasn't the case already, and if
             // we've been configured with a timeout for logging the outage at a higher level, schedule
             // that timeout.
             if (_inOutage)
             {
                 // We were already in one - just record this latest error for logging later.
                 RecordError(newError);
             }
             else
             {
                 // We weren't already in one, so set the timeout and start recording errors.
                 _inOutage = true;
                 _errorCounts.Clear();
                 RecordError(newError);
                 _outageEndedSignal = new TaskCompletionSource <bool>();
                 Task.Run(() => WaitForTimeout(_outageEndedSignal.Task));
             }
         }
         else
         {
             if (_outageEndedSignal != null)
             {
                 _outageEndedSignal.SetResult(true);
                 _outageEndedSignal = null;
             }
             _inOutage = false;
         }
     }
 }
示例#14
0
 public void Pause()
 {
     State = DataSourceState.Pausing;
     try
     {
         OnPause();
         State = DataSourceState.Paused;
     }
     catch (Exception ex)
     {
         State = DataSourceState.Error;
         _exception = new Exception("OnPause() got a fatal error.", ex);
     }
 }
示例#15
0
 public void Initialize()
 {
     State = DataSourceState.Initializing;
     try
     {
         OnInitialize();
         State = DataSourceState.Initialized;
     }
     catch (Exception ex)
     {
         State = DataSourceState.Error;
         _exception = new Exception("OnInitialize() got a fatal error.", ex);
     }
 }
示例#16
0
 public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) =>
 Actions.Enqueue(new ReceivedStatusUpdate {
     State = newState, Error = newError
 });
示例#17
0
 public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
 {
     State = newState;
 }
示例#18
0
 internal void DoUpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError)
 {
     _log.Debug("updating status to {0}{1}", newState,
                newError.HasValue ? (" (" + newError.Value + ")") : "");
     _updateSink.UpdateStatus(newState, newError);
 }
示例#19
0
 public bool WaitFor(DataSourceState desiredState, TimeSpan timeout) =>
 AsyncUtils.WaitSafely(() => _dataSourceUpdates.WaitForAsync(desiredState, timeout));
示例#20
0
 public void Resume()
 {
     State = DataSourceState.Resuming;
     try
     {
         OnResume();
         State = DataSourceState.Running;
     }
     catch (Exception ex)
     {
         State = DataSourceState.Error;
         _exception = new Exception("OnResume() got a fatal error.", ex);
     }
 }
示例#21
0
 public void UpdateStatus(DataSourceState newState, DataSourceStatus.ErrorInfo?newError) =>
 StatusUpdates.Enqueue(new StatusParams {
     State = newState, Error = newError
 });
示例#22
0
 public void Stop()
 {
     State = DataSourceState.Stopping;
     try
     {
         OnStop();
         State = DataSourceState.Stopped;
     }
     catch (Exception ex)
     {
         State = DataSourceState.Error;
         _exception = new Exception("OnStop() got a fatal error.", ex);
     }
 }
示例#23
0
 public Task <bool> WaitForAsync(DataSourceState desiredState, TimeSpan timeout) =>
 _dataSourceUpdates.WaitForAsync(desiredState, timeout);