RetryManagerpublic class RetryManager extends Object Retry manager allows a simple way to declare a series of
retry timeouts. After creating a RetryManager the configure
method is used to define the sequence. A simple linear series
may be initialized using configure with three integer parameters
The other configure method allows a series to be declared using
a string.
The format of the configuration string is a series of parameters
separated by a comma. There are two name value pair parameters plus a series
of delay times. The units of of these delay times is unspecified.
The name value pairs which may be specified are:
- max_retries=
- default_randomizationTime=
max_retries is the number of times that incrementRetryCount
maybe called before isRetryNeeded will return false. if value
is infinite then isRetryNeeded will always return true.
default_randomizationTime will be used as the randomizationTime
for delay times which have no supplied randomizationTime. If
default_randomizationTime is not defined it defaults to 0.
The other parameters define The series of delay times and each
may have an optional randomization value separated from the
delay time by a colon.
Examples:
- 3 retries with no randomization value which means its 0:
- 10 retries with a 500 default randomization value for each and
the 4..10 retries all using 3000 as the delay:
"max_retries=10, default_randomization=500, 1000, 2000, 3000"
- 4 retries with a 100 as the default randomization value for the first 2 values and
the other two having specified values of 500:
"default_randomization=100, 1000, 2000, 4000:500, 5000:500"
- Infinite number of retries with the first one at 1000, the second at 2000 all
others will be at 3000.
"max_retries=infinite,1000,2000,3000
{@hide} |
Fields Summary |
---|
public static final String | LOG_TAG | public static final boolean | DBG | public static final boolean | VDBG | private ArrayList | mRetryArrayThe array of retry records | private boolean | mRetryForeverWhen true isRetryNeeded() will always return true | private int | mMaxRetryCountThe maximum number of retries to attempt before
isRetryNeeded returns false | private int | mCurMaxRetryCount | private int | mRetryCountThe current number of retries | private Random | mRngRandom number generator | private String | mConfig |
Constructors Summary |
---|
public RetryManager()Constructor
if (VDBG) log("constructor");
|
Methods Summary |
---|
public boolean | configure(int maxRetryCount, int retryTime, int randomizationTime)Configure for a simple linear sequence of times plus
a random value.
Pair<Boolean, Integer> value;
if (VDBG) log("configure: " + maxRetryCount + ", " + retryTime + "," + randomizationTime);
if (!validateNonNegativeInt("maxRetryCount", maxRetryCount)) {
return false;
}
if (!validateNonNegativeInt("retryTime", retryTime)) {
return false;
}
if (!validateNonNegativeInt("randomizationTime", randomizationTime)) {
return false;
}
mMaxRetryCount = maxRetryCount;
mCurMaxRetryCount = mMaxRetryCount;
resetRetryCount();
mRetryArray.clear();
mRetryArray.add(new RetryRec(retryTime, randomizationTime));
return true;
| public boolean | configure(java.lang.String configStr)Configure for using string which allow arbitrary
sequences of times. See class comments for the
string format.
// Strip quotes if present.
if ((configStr.startsWith("\"") && configStr.endsWith("\""))) {
configStr = configStr.substring(1, configStr.length()-1);
}
if (VDBG) log("configure: '" + configStr + "'");
mConfig = configStr;
if (!TextUtils.isEmpty(configStr)) {
int defaultRandomization = 0;
if (VDBG) log("configure: not empty");
mMaxRetryCount = 0;
resetRetryCount();
mRetryArray.clear();
String strArray[] = configStr.split(",");
for (int i = 0; i < strArray.length; i++) {
if (VDBG) log("configure: strArray[" + i + "]='" + strArray[i] + "'");
Pair<Boolean, Integer> value;
String splitStr[] = strArray[i].split("=", 2);
splitStr[0] = splitStr[0].trim();
if (VDBG) log("configure: splitStr[0]='" + splitStr[0] + "'");
if (splitStr.length > 1) {
splitStr[1] = splitStr[1].trim();
if (VDBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
if (TextUtils.equals(splitStr[0], "default_randomization")) {
value = parseNonNegativeInt(splitStr[0], splitStr[1]);
if (!value.first) return false;
defaultRandomization = value.second;
} else if (TextUtils.equals(splitStr[0], "max_retries")) {
if (TextUtils.equals("infinite",splitStr[1])) {
mRetryForever = true;
} else {
value = parseNonNegativeInt(splitStr[0], splitStr[1]);
if (!value.first) return false;
mMaxRetryCount = value.second;
}
} else {
Rlog.e(LOG_TAG, "Unrecognized configuration name value pair: "
+ strArray[i]);
return false;
}
} else {
/**
* Assume a retry time with an optional randomization value
* following a ":"
*/
splitStr = strArray[i].split(":", 2);
splitStr[0] = splitStr[0].trim();
RetryRec rr = new RetryRec(0, 0);
value = parseNonNegativeInt("delayTime", splitStr[0]);
if (!value.first) return false;
rr.mDelayTime = value.second;
// Check if optional randomization value present
if (splitStr.length > 1) {
splitStr[1] = splitStr[1].trim();
if (VDBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
value = parseNonNegativeInt("randomizationTime", splitStr[1]);
if (!value.first) return false;
rr.mRandomizationTime = value.second;
} else {
rr.mRandomizationTime = defaultRandomization;
}
mRetryArray.add(rr);
}
}
if (mRetryArray.size() > mMaxRetryCount) {
mMaxRetryCount = mRetryArray.size();
if (VDBG) log("configure: setting mMaxRetryCount=" + mMaxRetryCount);
}
mCurMaxRetryCount = mMaxRetryCount;
if (VDBG) log("configure: true");
return true;
} else {
if (VDBG) log("configure: false it's empty");
return false;
}
| public int | getRetryCount()
if (DBG) log("getRetryCount: " + mRetryCount);
return mRetryCount;
| public int | getRetryTimer()Return the timer that should be used to trigger the data reconnection
int index;
if (mRetryCount < mRetryArray.size()) {
index = mRetryCount;
} else {
index = mRetryArray.size() - 1;
}
int retVal;
if ((index >= 0) && (index < mRetryArray.size())) {
retVal = mRetryArray.get(index).mDelayTime + nextRandomizationTime(index);
} else {
retVal = 0;
}
if (DBG) log("getRetryTimer: " + retVal);
return retVal;
| public void | increaseRetryCount()Increase the retry counter, does not change retry forever.
mRetryCount++;
if (mRetryCount > mCurMaxRetryCount) {
mRetryCount = mCurMaxRetryCount;
}
if (DBG) log("increaseRetryCount: " + mRetryCount);
| public boolean | isRetryForever()
if (DBG) log("isRetryForever: " + mRetryForever);
return mRetryForever;
| public boolean | isRetryNeeded()Report whether data reconnection should be retried
boolean retVal = mRetryForever || (mRetryCount < mCurMaxRetryCount);
if (DBG) log("isRetryNeeded: " + retVal);
return retVal;
| private void | log(java.lang.String s)
Rlog.d(LOG_TAG, "[RM] " + s);
| private int | nextRandomizationTime(int index)Return next random number for the index
int randomTime = mRetryArray.get(index).mRandomizationTime;
if (randomTime == 0) {
return 0;
} else {
return mRng.nextInt(randomTime);
}
| private android.util.Pair | parseNonNegativeInt(java.lang.String name, java.lang.String stringValue)Parse an integer validating the value is not negative.
int value;
Pair<Boolean, Integer> retVal;
try {
value = Integer.parseInt(stringValue);
retVal = new Pair<Boolean, Integer>(validateNonNegativeInt(name, value), value);
} catch (NumberFormatException e) {
Rlog.e(LOG_TAG, name + " bad value: " + stringValue, e);
retVal = new Pair<Boolean, Integer>(false, 0);
}
if (VDBG) log("parseNonNetativeInt: " + name + ", " + stringValue + ", "
+ retVal.first + ", " + retVal.second);
return retVal;
| public void | resetRetryCount()Clear the data-retry counter
mRetryCount = 0;
if (DBG) log("resetRetryCount: " + mRetryCount);
| public void | restoreCurMaxRetryCount()Restore CurMaxRetryCount
mCurMaxRetryCount = mMaxRetryCount;
// Make sure mRetryCount is within range
setRetryCount(mRetryCount);
| public void | retryForeverUsingLastTimeout()Retry forever using last timeout time.
mRetryCount = mCurMaxRetryCount;
mRetryForever = true;
if (DBG) log("retryForeverUsingLastTimeout: " + mRetryForever + ", " + mRetryCount);
| public void | setCurMaxRetryCount(int count)Set current maximum retry count to the specified value
mCurMaxRetryCount = count;
// Make sure it's not negative
if (mCurMaxRetryCount < 0) {
mCurMaxRetryCount = 0;
}
// Make sure mRetryCount is within range
setRetryCount(mRetryCount);
if (DBG) log("setCurMaxRetryCount: " + mCurMaxRetryCount);
| public void | setRetryCount(int count)Set retry count to the specified value
mRetryCount = count;
if (mRetryCount > mCurMaxRetryCount) {
mRetryCount = mCurMaxRetryCount;
}
if (mRetryCount < 0) {
mRetryCount = 0;
}
if (DBG) log("setRetryCount: " + mRetryCount);
| public void | setRetryForever(boolean retryForever)Set retry forever to the specified value
mRetryForever = retryForever;
if (DBG) log("setRetryForever: " + mRetryForever);
| public java.lang.String | toString()
String ret = "RetryManager: { forever=" + mRetryForever + " maxRetry=" + mMaxRetryCount
+ " curMaxRetry=" + mCurMaxRetryCount + " retry=" + mRetryCount
+ " config={" + mConfig + "} retryArray={";
for (RetryRec r : mRetryArray) {
ret += r.mDelayTime + ":" + r.mRandomizationTime + " ";
}
ret += "}}";
return ret;
| private boolean | validateNonNegativeInt(java.lang.String name, int value)Validate an integer is >= 0 and logs an error if not
boolean retVal;
if (value < 0) {
Rlog.e(LOG_TAG, name + " bad value: is < 0");
retVal = false;
} else {
retVal = true;
}
if (VDBG) log("validateNonNegative: " + name + ", " + value + ", " + retVal);
return retVal;
|
|