Result result = recordTable.get(get);
if (!result.isEmpty()) {
// If the record existed it should have been deleted
byte[] recordDeleted = result.getValue(RecordCf.DATA.bytes, RecordColumn.DELETED.bytes);
if (recordDeleted != null && !Bytes.toBoolean(recordDeleted)) {
throw new RecordExistsException(recordId);
}
oldOccBytes = result.getValue(RecordCf.DATA.bytes, RecordColumn.OCC.bytes);
newOcc = Bytes.toLong(nextOcc(oldOccBytes));
byte[] oldVersion = result.getValue(RecordCf.DATA.bytes, RecordColumn.VERSION.bytes);
if (oldVersion != null) {
version = Bytes.toLong(oldVersion) + 1;
// Make sure any old data gets cleared and old blobs are deleted
// This is to cover the failure scenario where a record was deleted, but a failure
// occurred before executing the clearData
// If this was already done, this is a no-op
// Note: since the removal of the row locking, this part could run concurrent with other
// threads trying to re-create a record or with a delete still being in progress. This
// should be no problem since the clearData will only remove the versions at the old
// timestamps, and leave the non-versioned fields untouched.
clearData(recordId, null, Bytes.toLong(oldVersion));
}
}
RecordEvent recordEvent = new RecordEvent();
recordEvent.setType(Type.CREATE);
recordEvent.setTableName(getTableName());
if (record.hasAttributes()) {
recordEvent.getAttributes().putAll(record.getAttributes());
}
Record newRecord = record.cloneRecord();
newRecord.setId(recordId);
for (RecordUpdateHook hook : updateHooks) {
hook.beforeCreate(newRecord, this, fieldTypes, recordEvent);
}
Set<BlobReference> referencedBlobs = new HashSet<BlobReference>();
Set<BlobReference> unReferencedBlobs = new HashSet<BlobReference>();
Put put = buildPut(newRecord, version, fieldTypes, recordEvent, referencedBlobs, unReferencedBlobs, newOcc);
// Make sure the record type changed flag stays false for a newly
// created record
recordEvent.setRecordTypeChanged(false);
Long newVersion = newRecord.getVersion();
if (newVersion != null) {
recordEvent.setVersionCreated(newVersion);
}
// Reserve blobs so no other records can use them
reserveBlobs(null, referencedBlobs);
put.add(RecordCf.DATA.bytes, RecordColumn.PAYLOAD.bytes, recordEvent.toJsonBytes());
boolean success = recordTable.checkAndPut(put.getRow(), RecordCf.DATA.bytes, RecordColumn.OCC.bytes,
oldOccBytes, put);
if (!success) {
throw new RecordExistsException(recordId);
}
// Remove the used blobs from the blobIncubator
blobManager.handleBlobReferences(recordId, referencedBlobs, unReferencedBlobs);