* badversion is caused by the result of previous correctly setData
* @return Stat instance
*/
public Stat setData(String path, byte[] data, int version)
throws KeeperException, InterruptedException {
RetryCounter retryCounter = retryCounterFactory.create();
byte[] newData = appendMetaData(data);
while (true) {
try {
return zk.setData(path, newData, version);
} catch (KeeperException e) {
switch (e.code()) {
case CONNECTIONLOSS:
case OPERATIONTIMEOUT:
retryOrThrow(retryCounter, e, "setData");
break;
case BADVERSION:
// try to verify whether the previous setData success or not
try{
Stat stat = new Stat();
byte[] revData = zk.getData(path, false, stat);
int idLength = Bytes.toInt(revData, ID_LENGTH_SIZE);
int dataLength = revData.length-ID_LENGTH_SIZE-idLength;
int dataOffset = ID_LENGTH_SIZE+idLength;
if(Bytes.compareTo(revData, ID_LENGTH_SIZE, id.length,
revData, dataOffset, dataLength) == 0) {
// the bad version is caused by previous successful setData
return stat;
}
} catch(KeeperException keeperException){
// the ZK is not reliable at this moment. just throwing exception
throw keeperException;
}
// throw other exceptions and verified bad version exceptions
default:
throw e;
}
}
retryCounter.sleepUntilNextRetry();
retryCounter.useRetry();
}
}