throw new JodbIOException("Object length estimate error");
}
//long targetObjectBodyLength = objectBodyLength;
if(!tHandle.isNewObject()){
DataContainersCache dataContainersCache = TransactionUtils.getObjectDataContainerCache();
ObjectDataContainer existingObjectHeaderData = dataContainersCache.pullObjectDataContainer();// tContainer.getTempObjectDataContainer();
//ioTicket.getRandomAccessBuffer().seek(tHandle.getHandle().getObjectEntryOffset());
//JODBIOUtils.readObjectHeader(ioTicket, existingObjectHeaderData, false);
existingObjectHeaderData.readHeader(ioTicket.getRandomAccessBuffer(),tHandle.getHandle().getObjectEntryOffset(), false);
tHandle.setTransactionOffset(existingObjectHeaderData.getOffset());//JODBIOUtils.addAbsoluteOffsetIdentifierBit(existingObjectHeaderData.getOffset()));//if object already existed than alvays point to initial object position
long redirectorOffset = existingObjectHeaderData.isRedirection()?existingObjectHeaderData.getOffset():-1;
if(objectBodyLength > existingObjectHeaderData.getBodyLength() || fieldsWithRelativeAddr.size() > 0 ){
if( existingObjectHeaderData.isRedirection() ){
//redirection entry space is too small, let see what is under redirection offset
//ioTicket.getRandomAccessBuffer().seek(existingObjectHeaderData.getRedirectionOffset());
long existingObjectRedirectionOffset = existingObjectHeaderData.getRedirectionOffset();
existingObjectHeaderData.reset();
existingObjectHeaderData.readHeader(ioTicket.getRandomAccessBuffer(), existingObjectRedirectionOffset, true);
//JODBIOUtils.readObjectHeader(ioTicket, existingObjectHeaderData, true);
}
}
if(objectBodyLength <= existingObjectHeaderData.getBodyLength() && fieldsWithRelativeAddr.size() == 0){
boolean isRedirection = existingObjectHeaderData.isRedirection();
long redirectionOffset = existingObjectHeaderData.getRedirectionOffset();
//long targetObjectBodyLength = existingObjectHeaderData.getBodyLength();//length for new object's header
//object id(length bits) may change as we fit to maybe bigger space
objId = JODBIOBase.ENTRY_OBJECT_ID | existingObjectHeaderData.getLengthModifierFromID();// composeEntryID( JODBIOBase.ENTRY_OBJECT_ID, targetObjectBodyLength);
if(existingObjectHeaderData.isRedirectedObject()){
objIdWithRedirectionBit = JODBIOBase.addRedirectedObjectModifier(objId);//this is redirected entry
}else{
objIdWithRedirectionBit = objId;
}
if( isRedirection ){//if we fit into redirection record than delete record under redirection offset
deleteObject(ioTicket, session, redirectionOffset, tContainer);//delete/backup record under redirection offset
}
//object can fit to old spot, write it to replacements file insteard of transaction file
IRandomAccessDataBuffer replacementsFile = tContainer.getTransactionReplacementsDataFile();
replacementsFile.resetToEnd();
replacementsFile.writeByte(TRANSACTION_REPLACEMENT_ENTRY_TYPE_STATIC);
replacementsFile.writeLong(existingObjectHeaderData.getOffset());
long replacementLengthEntryOffset = replacementsFile.getCursorOffset();
replacementsFile.writeLong(0);//reserve space for replacement length entry. //TODO skip faster?
long newObjectIDOffset = replacementsFile.getCursorOffset();
replacementsFile.writeShort(objIdWithRedirectionBit);//write new ID to replacements file
writeEntryLenForID(objId,objectBodyLength,replacementsFile);//write length of replacements file, could be bigger than actual object's data occupies
long newObjectBodyOffset = replacementsFile.getCursorOffset();
//return to write actual length of replacement entry
replacementsFile.seek(replacementLengthEntryOffset);
replacementsFile.writeLong(newObjectBodyOffset-newObjectIDOffset+objectBodyLength);
replacementsFile.seek(newObjectBodyOffset);//back to the header end
transactionFile.transferTo(objectBodyOffset, objectBodyLength, replacementsFile.getChannel());
transactionFile.seek(objectIDOffset);//return position in transaction file to the start of object(like it wasn't here)
transactionFile.setLength(objectIDOffset);//truncate "new data" file
objectIDOffset = newObjectIDOffset;//this now offset in replacements file
objectBodyOffset = newObjectBodyOffset;
objectBodyLength = existingObjectHeaderData.getBodyLength();//length for new object
transactionFile = replacementsFile;
replacementsFile.resetToEnd();//replacements file to the end
objectEndOffset = replacementsFile.getCursorOffset();
}else{
if(redirectorOffset!=-1){
//this is record under redirection offset
deleteObject(ioTicket, session, existingObjectHeaderData.getOffset(), tContainer);
}
IRandomAccessDataBuffer replacementsFile = tContainer.getTransactionReplacementsDataFile();
long offset = tHandle.getHandle().getObjectEntryOffset();//offset of record that will be replaced with redirector
//backupObject(ioTicket, offset, tContainer);
//write redirector entry with relative offset
replacementsFile.writeByte(TRANSACTION_REPLACEMENT_ENTRY_TYPE_REDIRECTOR);
replacementsFile.writeLong(offset);
replacementsFile.writeLong(objectIDOffset);//relative offset in new data transaction file
}
dataContainersCache.pushObjectDataContainer(existingObjectHeaderData);
}
for (int i = 0; i < fieldsWithRelativeAddr.size(); i++) {
ObjectFieldRecord next = fieldsWithRelativeAddr.elementAt(i);
next._offset = assembleTransactionDataForObject(context, next._value , tContainer);