@Override public void updateRecord( RECORD record ) long id = record.getId(); IdValidator.assertValidId( getIdType(), id, recordFormat.getMaxId() ); recordFormat.write( record, cursor, recordSize ); if ( !record.inUse() ) if ( (!record.inUse() || !record.requiresSecondaryUnit()) && record.hasSecondaryUnitId() ) freeId( record.getSecondaryUnitId() );
private void prepareForReading( PageCursor cursor, RECORD record ) { // Mark this record as unused. This to simplify implementations of readRecord. // readRecord can behave differently depending on RecordLoad argument and so it may be that // contents of a record may be loaded even if that record is unused, where the contents // can still be initialized data. Know that for many record stores, deleting a record means // just setting one byte or bit in that record. record.setInUse( false ); cursor.setOffsetToMark(); }
@Override public void clear() { super.clear(); key = null; count = 0; }
private void track( RecordStore<?> store, AbstractBaseRecord record ) { long id = max( record.getId(), record.requiresSecondaryUnit() ? record.getSecondaryUnitId() : -1 ); HighId highId = highIds.get( store ); if ( highId == null ) { highIds.put( store, new HighId( id ) ); } else { highId.track( id ); } }
@Override protected void process( T[] batch, BatchSender sender ) { for ( T item : batch ) { if ( item != null && item.inUse() ) { if ( !processor.process( item ) ) { // No change for this record item.setInUse( false ); } } } // This step can be used in different stage settings, possible as the last step, // where nothing should be emitted if ( !endOfLine ) { sender.send( batch ); } }
throws IOException if ( record.inUse() ) assert (headerByte & 0x7) == 0 : "Format-specific header bits (" + headerByte + ") collides with format-generic header bits"; headerByte = set( headerByte, IN_USE_BIT, record.inUse() ); headerByte = set( headerByte, HEADER_BIT_RECORD_UNIT, record.requiresSecondaryUnit() ); if ( record.requiresSecondaryUnit() ) headerByte = set( headerByte, HEADER_BIT_FIXED_REFERENCE, !record.isUseFixedReferences() ); if ( record.requiresSecondaryUnit() ) long secondaryUnitId = record.getSecondaryUnitId(); long pageId = pageIdForRecord( secondaryUnitId, primaryCursor.getCurrentPageSize(), recordSize ); int offset = offsetForId( secondaryUnitId, primaryCursor.getCurrentPageSize(), recordSize ); record.clear(); return;
@Override public final void prepare( RECORD record, int recordSize, IdSequence idSequence ) { if ( record.inUse() ) { record.setUseFixedReferences( canUseFixedReferences( record, recordSize )); if ( !record.isUseFixedReferences() ) { int requiredLength = HEADER_BYTE + requiredDataLength( record ); boolean requiresSecondaryUnit = requiredLength > recordSize; record.setRequiresSecondaryUnit( requiresSecondaryUnit ); if ( record.requiresSecondaryUnit() && !record.hasSecondaryUnitId() ) { // Allocate a new id at this point, but this is not the time to free this ID the the case where // this record doesn't need this secondary unit anymore... that needs to be done when applying to store. record.setSecondaryUnitId( idSequence.nextId() ); } } } }
read.setId( written.getId() ); int offset = Math.toIntExact( written.getId() * recordSize ); do if ( written.inUse() ) assertEquals( written.inUse(), read.inUse() ); assertEquals( written.getId(), read.getId() ); assertEquals( written.getSecondaryUnitId(), read.getSecondaryUnitId() ); key.assertRecordsEquals( written, read ); assertEquals( written.inUse(), read.inUse() );
@Override long recordId() { return record.getId(); }
@Override protected void process( RECORD[] batch, BatchSender sender ) { LongFunction<IdSequence> idSequence = prepareIdSequence.apply( store ); int recordsUpdatedInThisBatch = 0; for ( RECORD record : batch ) { if ( record != null && record.inUse() && !IdValidator.isReservedId( record.getId() ) ) { store.prepareForCommit( record, idSequence.apply( record.getId() ) ); store.updateRecord( record ); recordsUpdatedInThisBatch++; } } recordsUpdated.add( recordsUpdatedInThisBatch ); }
boolean inUse = isInUse( headerByte ); boolean doubleRecordUnit = has( headerByte, HEADER_BIT_RECORD_UNIT ); record.setUseFixedReferences( false ); if ( doubleRecordUnit ) record.clear(); record.clear(); primaryCursor.setCursorException( illegalSecondaryReferenceMessage( pageId ) ); return; primaryCursor, primarySize, secondaryCursor, secondarySize ); doReadInternal( record, composite, recordSize, headerByte, inUse ); record.setSecondaryUnitId( secondaryId ); record.setUseFixedReferences( isUseFixedReferences( headerByte ) ); doReadInternal( record, primaryCursor, recordSize, headerByte, inUse );
protected void markAsUnused( PageCursor cursor, RECORD record, int recordSize ) throws IOException { markAsUnused( cursor ); if ( record.hasSecondaryUnitId() ) { long secondaryUnitId = record.getSecondaryUnitId(); long pageIdForSecondaryRecord = pageIdForRecord( secondaryUnitId, cursor.getCurrentPageSize(), recordSize ); int offsetForSecondaryId = offsetForId( secondaryUnitId, cursor.getCurrentPageSize(), recordSize ); if ( !cursor.next( pageIdForSecondaryRecord ) ) { throw new UnderlyingStorageException( "Couldn't move to secondary page " + pageIdForSecondaryRecord ); } cursor.setOffset( offsetForSecondaryId ); markAsUnused( cursor ); } }
@Override public void prepareForCommit( RECORD record, IdSequence idSequence ) { if ( record.inUse() ) { recordFormat.prepare( record, recordSize, idSequence ); } }
@Override public final void prepare( RECORD record, int recordSize, IdSequence idSequence ) { if ( record.inUse() ) { int requiredLength = HEADER_BYTE + requiredDataLength( record ); boolean requiresSecondaryUnit = requiredLength > recordSize; record.setRequiresSecondaryUnit( requiresSecondaryUnit ); if ( record.requiresSecondaryUnit() && !record.hasSecondaryUnitId() ) { // Allocate a new id at this point, but this is not the time to free this ID the the case where // this record doesn't need this secondary unit anymore... that needs to be done when applying to store. record.setSecondaryUnitId( idSequence.nextId() ); } } }
@Override public void nextRecordByCursor( RECORD record, RecordLoad mode, PageCursor cursor ) throws UnderlyingStorageException { if ( cursor.getCurrentPageId() < -1 ) { throw new IllegalArgumentException( "Pages are assumed to be positive or -1 if not initialized" ); } try { int offset = cursor.getOffset(); long id = record.getId() + 1; record.setId( id ); long pageId = cursor.getCurrentPageId(); if ( offset >= pagedFile.pageSize() || pageId < 0 ) { if ( !cursor.next() ) { verifyAfterNotRead( record, mode ); return; } cursor.setOffset( 0 ); } readRecordFromPage( id, record, mode, cursor ); } catch ( IOException e ) { throw new UnderlyingStorageException( e ); } }
private <RECORD extends AbstractBaseRecord> void createRecordIn( RecordStore<RECORD> store ) { RECORD record = store.newRecord(); record.setId( store.nextId() ); record.setInUse( true ); if ( record instanceof PropertyRecord ) { // Special hack for property store, since it's not enough to simply set a record as in use there PropertyBlock block = new PropertyBlock(); ((PropertyStore)store).encodeValue( block, 0, Values.of( 10 ) ); ((PropertyRecord) record).addPropertyBlock( block ); } store.updateRecord( record ); }
private <T extends AbstractBaseRecord> void verifySecondaryUnit( T record, T commandRecord ) { assertEquals( "Secondary unit requirements should be the same", record.requiresSecondaryUnit(), commandRecord.requiresSecondaryUnit() ); assertEquals( "Secondary unit ids should be the same", record.getSecondaryUnitId(), commandRecord.getSecondaryUnitId() ); } }
public static <R extends AbstractBaseRecord> long loadRecords(long[] submitted, R record, RecordStore<R> recordStore, TerminationGuard guard) { if (Util.transactionIsTerminated(guard)) return 0; for (long recordId : submitted) { record.setId(recordId); record.clear(); try { recordStore.getRecord(recordId, record, RecordLoad.NORMAL); } catch (Exception ignore) { // ignore } } return submitted.length; }
private void throwOutOfBoundsException( long recordId ) { RECORD record = newRecord(); record.setId( recordId ); long pageId = pageIdForRecord( recordId ); int offset = offsetForId( recordId ); throw new UnderlyingStorageException( buildOutOfBoundsExceptionMessage( record, pageId, offset, recordSize, pagedFile.pageSize(), storageFile.getAbsolutePath() ) ); }