/// <summary> /// Schedules the next delayed execution /// </summary> private void ScheduleNext() { if (Statement == null || !(Statement.IsIdempotent ?? _session.Cluster.Configuration.QueryOptions.GetDefaultIdempotence())) { //its not idempotent, we should not schedule an speculative execution return; } if (_executionPlan == null) { _executionPlan = Policies.SpeculativeExecutionPolicy.NewPlan(_session.Keyspace, Statement); } var delay = _executionPlan.NextExecution(_host); if (delay <= 0) { return; } //There is one live timer at a time. _nextExecutionTimeout = _session.Cluster.Configuration.Timer.NewTimeout(_ => { if (HasCompleted()) { return; } Logger.Info("Starting new speculative execution after {0}, last used host {1}", delay, _host.Address); StartNewExecution(); }, null, delay); }
public void ConsiderResizingPool(int inFlight) { if (inFlight < _maxInflightThreshold) { // The requests in-flight are normal return; } if (_expectedConnectionLength >= _maxConnectionLength) { // We can not add more connections return; } if (_connections.Count < _expectedConnectionLength) { // The pool is still trying to acquire the correct size return; } var canResize = Interlocked.Exchange(ref _poolResizing, 1) == 0; if (!canResize) { // There is already another thread resizing the pool return; } if (IsClosing) { return; } _expectedConnectionLength++; Logger.Info("Increasing pool #{0} size to {1}, as in-flight requests are above threshold ({2})", GetHashCode(), _expectedConnectionLength, _maxInflightThreshold); StartCreatingConnection(null); _resizingEndTimeout = _timer.NewTimeout(_ => Interlocked.Exchange(ref _poolResizing, 0), null, BetweenResizeDelay); }
/// <summary> /// Schedules the next delayed execution /// </summary> private void ScheduleNext(Host currentHost) { if (Statement == null || Statement.IsIdempotent == false) { //its not idempotent, we should not schedule an speculative execution return; } if (_executionPlan == null) { _executionPlan = Policies.SpeculativeExecutionPolicy.NewPlan(_session.Keyspace, Statement); } var delay = _executionPlan.NextExecution(currentHost); if (delay <= 0) { return; } //There is one live timer at a time. _nextExecutionTimeout = _session.Cluster.Configuration.Timer.NewTimeout(_ => { // Start the speculative execution outside the IO thread Task.Run(() => { if (HasCompleted()) { return; } RequestHandler.Logger.Info("Starting new speculative execution after {0}, last used host {1}", delay, currentHost.Address); StartNewExecution(); }); }, null, delay); }
/// <summary> /// Cancels the previous and set the next reconnection timeout, as an atomic operation. /// </summary> private void SetReconnectionTimeout(HashedWheelTimer.ITimeout nextTimeout) { var timeout = Interlocked.Exchange(ref _timeout, nextTimeout); if (timeout != null) { timeout.Cancel(); } }
private void OnHostUp(Host host) { var timeout = _timeout; if (timeout != null) { timeout.Cancel(); } _timeout = null; //The host is back up, we can start creating the pool (if applies) MaybeCreateCorePool(); }
private void CancelNewConnectionTimeout(HashedWheelTimer.ITimeout newTimeout = null) { var previousTimeout = Interlocked.Exchange(ref _newConnectionTimeout, newTimeout); if (previousTimeout != null) { // Clear previous reconnection attempt timeout previousTimeout.Cancel(); } if (newTimeout != null && IsClosing) { // It could have been the case the it was set after it was set as closed. Interlocked.Exchange(ref _newConnectionTimeout, null); } }
private void SetNewConnectionTimeout(IReconnectionSchedule schedule) { if (schedule != null && _reconnectionSchedule != schedule) { // There's another reconnection schedule, leave it return; } HashedWheelTimer.ITimeout timeout = null; if (schedule != null) { // Schedule the creation var delay = schedule.NextDelayMs(); Logger.Info("Scheduling reconnection from #{0} to {1} in {2}ms", GetHashCode(), _host.Address, delay); timeout = _timer.NewTimeout(_ => Task.Run(() => StartCreatingConnection(schedule)), null, delay); } CancelNewConnectionTimeout(timeout); if (schedule == null) { // Start creating immediately after de-scheduling the timer Logger.Info("Starting reconnection from pool #{0} to {1}", GetHashCode(), _host.Address); StartCreatingConnection(null); } }
private void OnHostDown(Host h, long delay) { if (Interlocked.CompareExchange(ref _hostDownFlag, 1, 0) != 0) { //A reconnection attempt is being scheduled concurrently return; } var currentTimeout = _timeout; //De-schedule the current reconnection attempt if (currentTimeout != null) { currentTimeout.Cancel(); } //Schedule next reconnection attempt (without using the timer thread) _timeout = _timer.NewTimeout(() => Task.Factory.StartNew(AttemptReconnection), delay); //Dispose all current connections foreach (var c in _connections) { //Connection class allows multiple calls to Dispose c.Dispose(); } Interlocked.Exchange(ref _hostDownFlag, 0); }
/// <summary> /// Sets the read timeout associated with the request /// </summary> public void SetTimeout(HashedWheelTimer.ITimeout value) { _timeout = value; }