blob: a6e7947b23f10e1769a95a297b6b002e534818e7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.db.monitoring;
import static org.apache.cassandra.utils.MonotonicClock.approxTime;
public abstract class MonitorableImpl implements Monitorable
{
private MonitoringState state;
private boolean isSlow;
private long approxCreationTimeNanos = -1;
private long timeoutNanos;
private long slowTimeoutNanos;
private boolean isCrossNode;
protected MonitorableImpl()
{
this.state = MonitoringState.IN_PROGRESS;
this.isSlow = false;
}
/**
* This setter is ugly but the construction chain to ReadCommand
* is too complex, it would require passing new parameters to all serializers
* or specializing the serializers to accept these message properties.
*/
public void setMonitoringTime(long approxCreationTimeNanos, boolean isCrossNode, long timeoutNanos, long slowTimeoutNanos)
{
assert approxCreationTimeNanos >= 0;
this.approxCreationTimeNanos = approxCreationTimeNanos;
this.isCrossNode = isCrossNode;
this.timeoutNanos = timeoutNanos;
this.slowTimeoutNanos = slowTimeoutNanos;
}
public long creationTimeNanos()
{
return approxCreationTimeNanos;
}
public long timeoutNanos()
{
return timeoutNanos;
}
public boolean isCrossNode()
{
return isCrossNode;
}
public long slowTimeoutNanos()
{
return slowTimeoutNanos;
}
public boolean isInProgress()
{
check();
return state == MonitoringState.IN_PROGRESS;
}
public boolean isAborted()
{
check();
return state == MonitoringState.ABORTED;
}
public boolean isCompleted()
{
check();
return state == MonitoringState.COMPLETED;
}
public boolean isSlow()
{
check();
return isSlow;
}
public boolean abort()
{
if (state == MonitoringState.IN_PROGRESS)
{
if (approxCreationTimeNanos >= 0)
MonitoringTask.addFailedOperation(this, approxTime.now());
state = MonitoringState.ABORTED;
return true;
}
return state == MonitoringState.ABORTED;
}
public boolean complete()
{
if (state == MonitoringState.IN_PROGRESS)
{
if (isSlow && slowTimeoutNanos > 0 && approxCreationTimeNanos >= 0)
MonitoringTask.addSlowOperation(this, approxTime.now());
state = MonitoringState.COMPLETED;
return true;
}
return state == MonitoringState.COMPLETED;
}
private void check()
{
if (approxCreationTimeNanos < 0 || state != MonitoringState.IN_PROGRESS)
return;
long minElapsedNanos = (approxTime.now() - approxCreationTimeNanos) - approxTime.error();
if (minElapsedNanos >= slowTimeoutNanos && !isSlow)
isSlow = true;
if (minElapsedNanos >= timeoutNanos)
abort();
}
}