if (record.getId() == null) {
// While we could generate an ID ourselves in this case, this would defeat partly the purpose of
// createOrUpdate, which is that clients would be able to retry the operation (in case of IO exceptions)
// without having to worry that more than one record might be created.
throw new RecordException("Record ID is mandatory when using create-or-update.");
}
byte[] rowId = record.getId().toBytes();
Get get = new Get(rowId);
get.addColumn(RecordCf.DATA.bytes, RecordColumn.DELETED.bytes);
int attempts;
for (attempts = 0; attempts < 3; attempts++) {
Result result;
try {
result = recordTable.get(get);
} catch (IOException e) {
throw new RecordException("Error reading record row for record id " + record.getId(), e);
}
byte[] deleted = recdec.getLatest(result, RecordCf.DATA.bytes, RecordColumn.DELETED.bytes);
if ((deleted == null) || (Bytes.toBoolean(deleted))) {
// do the create
try {
return create(record);
} catch (RecordExistsException e) {
// someone created the record since we checked, we will try again
}
} else {
// do the update
try {
record = update(record, false, useLatestRecordType);
return record;
} catch (RecordNotFoundException e) {
// some deleted the record since we checked, we will try again
}
}
}
throw new RecordException("Create-or-update failed after " + attempts +
" attempts, toggling between create and update mode.");
}