@Override public void awaitClosedTransactionId( long txId, long timeoutMillis ) throws TimeoutException, InterruptedException { assertNotClosed(); checkInitialized( lastCommittingTxField.get() ); lastClosedTx.await( txId, timeoutMillis ); }
@Override public long[] getLastClosedTransaction() { return closedTransactionId.get(); }
@Override public long getLastClosedTransactionId() { return closedTransactionId.getHighestGapFreeNumber(); }
@Test public void highestEverSeenTest() { final OutOfOrderSequence sequence = new ArrayQueueOutOfOrderSequence( 0, 5, EMPTY_META ); assertEquals( 0L, sequence.highestEverSeen() ); sequence.offer( 1L, EMPTY_META ); assertEquals( 1L, sequence.highestEverSeen() ); sequence.offer( 42L, EMPTY_META ); assertEquals( 42L, sequence.highestEverSeen() ); }
@Override public void transactionClosed( long transactionId, long logVersion, long byteOffset ) { if ( lastClosedTx.offer( transactionId, new long[]{logVersion, byteOffset} ) ) { long pageId = pageIdForRecord( Position.LAST_CLOSED_TRANSACTION_LOG_VERSION.id ); assert pageId == pageIdForRecord( Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET.id ); synchronized ( transactionClosedLock ) { try ( PageCursor cursor = pagedFile.io( pageId, PF_SHARED_WRITE_LOCK ) ) { if ( cursor.next() ) { long[] lastClosedTransactionData = lastClosedTx.get(); setRecord( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_VERSION, lastClosedTransactionData[1] ); setRecord( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET, lastClosedTransactionData[2] ); } } catch ( IOException e ) { throw new UnderlyingStorageException( e ); } } } }
@Override public void setLastCommittedAndClosedTransactionId( long transactionId, long checksum, long commitTimestamp, long byteOffset, long logVersion ) { committingTransactionId.set( transactionId ); committedTransactionId.set( new TransactionId( transactionId, checksum, commitTimestamp ) ); closedTransactionId.set( transactionId, new long[]{logVersion, byteOffset} ); }
@Override public void transactionClosed( long transactionId, long logVersion, long byteOffset ) { closedTransactionId.offer( transactionId, new long[]{logVersion, byteOffset} ); }
@Override public void transactionClosed( long transactionId, long logVersion, long byteOffset ) { if ( lastClosedTx.offer( transactionId, new long[]{logVersion, byteOffset} ) ) { long pageId = pageIdForRecord( Position.LAST_CLOSED_TRANSACTION_LOG_VERSION.id ); assert pageId == pageIdForRecord( Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET.id ); synchronized ( transactionClosedLock ) { try ( PageCursor cursor = pagedFile.io( pageId, PF_SHARED_WRITE_LOCK ) ) { if ( cursor.next() ) { long[] lastClosedTransactionData = lastClosedTx.get(); setRecord( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_VERSION, lastClosedTransactionData[1] ); setRecord( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET, lastClosedTransactionData[2] ); } } catch ( IOException e ) { throw new UnderlyingStorageException( e ); } } } }
@Override public void setLastCommittedAndClosedTransactionId( long transactionId, long checksum, long commitTimestamp, long byteOffset, long logVersion ) { assertNotClosed(); setRecord( Position.LAST_TRANSACTION_ID, transactionId ); setRecord( Position.LAST_TRANSACTION_CHECKSUM, checksum ); setRecord( Position.LAST_CLOSED_TRANSACTION_LOG_VERSION, logVersion ); setRecord( Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET, byteOffset ); setRecord( Position.LAST_TRANSACTION_COMMIT_TIMESTAMP, commitTimestamp ); checkInitialized( lastCommittingTxField.get() ); lastCommittingTxField.set( transactionId ); lastClosedTx.set( transactionId, new long[]{logVersion, byteOffset} ); highestCommittedTransaction.set( transactionId, checksum, commitTimestamp ); } /**
@Test public void shouldExposeGapFreeSequenceSingleThreaded() { // GIVEN OutOfOrderSequence sequence = new ArrayQueueOutOfOrderSequence( 0L, 10, new long[1] ); // WHEN/THEN offer( sequence, 1, new long[]{1} ); assertGet( sequence, 1, new long[]{1} ); offer( sequence, 2, new long[]{2} ); assertGet( sequence, 2, new long[]{2} ); assertFalse( sequence.seen( 4, new long[]{3} ) ); sequence.offer( 4, new long[]{3} ); assertGet( sequence, 2, new long[]{2} ); offer( sequence, 3, new long[]{4} ); assertGet( sequence, 4, new long[]{3} ); offer( sequence, 5, new long[]{5} ); assertGet( sequence, 5, new long[]{5} ); // AND WHEN/THEN offer( sequence, 10, new long[]{6} ); offer( sequence, 11, new long[]{7} ); offer( sequence, 8, new long[]{8} ); offer( sequence, 9, new long[]{9} ); offer( sequence, 7, new long[]{10} ); assertGet( sequence, 5, new long[]{5} ); offer( sequence, 6, new long[]{11} ); assertGet( sequence, 11L, new long[]{7} ); }
long lastClosedTransactionLogVersion = getRecordValue( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_VERSION ); long lastClosedTransactionLogByteOffset = getRecordValue( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET ); lastClosedTx.set( lastCommittedTxId, new long[]{lastClosedTransactionLogVersion, lastClosedTransactionLogByteOffset} ); highestCommittedTransaction.set( lastCommittedTxId,
@Test public void shouldBeAbleToReturnImmediatelyWhenNumberAvailable() throws Exception { // given final OutOfOrderSequence sequence = new ArrayQueueOutOfOrderSequence( 4, 5, EMPTY_META ); // when sequence.await( 4, 0 ); // then: should return without exceptions }
@Override public long[] getLastClosedTransaction() { assertNotClosed(); checkInitialized( lastCommittingTxField.get() ); return lastClosedTx.get(); }
@Override public long getLastClosedTransactionId() { assertNotClosed(); checkInitialized( lastCommittingTxField.get() ); return lastClosedTx.getHighestGapFreeNumber(); }
@Override public void setLastCommittedAndClosedTransactionId( long transactionId, long checksum, long commitTimestamp, long byteOffset, long logVersion ) { assertNotClosed(); setRecord( Position.LAST_TRANSACTION_ID, transactionId ); setRecord( Position.LAST_TRANSACTION_CHECKSUM, checksum ); setRecord( Position.LAST_CLOSED_TRANSACTION_LOG_VERSION, logVersion ); setRecord( Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET, byteOffset ); setRecord( Position.LAST_TRANSACTION_COMMIT_TIMESTAMP, commitTimestamp ); checkInitialized( lastCommittingTxField.get() ); lastCommittingTxField.set( transactionId ); lastClosedTx.set( transactionId, new long[]{logVersion, byteOffset} ); highestCommittedTransaction.set( transactionId, checksum, commitTimestamp ); } /**
@Test public void shouldBeAbleToTimeoutWaitingForNumber() throws Exception { // given long timeout = 10; final OutOfOrderSequence sequence = new ArrayQueueOutOfOrderSequence( 3, 5, EMPTY_META ); long startTime = System.currentTimeMillis(); try { // when sequence.await( 4, timeout ); fail(); } catch ( TimeoutException e ) { // expected } long endTime = System.currentTimeMillis(); assertThat( endTime - startTime, greaterThanOrEqualTo( timeout ) ); }
private void assertGet( OutOfOrderSequence sequence, long number, long[] meta ) { long[] data = sequence.get(); long[] expected = new long[meta.length + 1]; expected[0] = number; System.arraycopy( meta, 0, expected, 1, meta.length ); assertArrayEquals( expected, data ); }
@Override public long getLastClosedTransactionId() { assertNotClosed(); checkInitialized( lastCommittingTxField.get() ); return lastClosedTx.getHighestGapFreeNumber(); }
long lastClosedTransactionLogVersion = getRecordValue( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_VERSION ); long lastClosedTransactionLogByteOffset = getRecordValue( cursor, Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET ); lastClosedTx.set( lastCommittedTxId, new long[]{lastClosedTransactionLogVersion, lastClosedTransactionLogByteOffset} ); highestCommittedTransaction.set( lastCommittedTxId,