package com.linkedin.databus.core; /* * * Copyright 2013 LinkedIn Corp. All rights reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ import java.nio.ByteOrder; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.easymock.EasyMock; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.linkedin.databus.core.DbusEventBuffer.AllocationPolicy; import com.linkedin.databus.core.util.BufferPositionParser; import com.linkedin.databus2.core.AssertLevel; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.fail; public class TestScnIndex { public static final Logger LOG = Logger.getLogger(TestScnIndex.class); static AssertLevel DEFAULT_ASSERT_LEVEL = AssertLevel.ALL; @BeforeMethod public void setUp() throws Exception { Logger.getRootLogger().setLevel(Level.OFF); //Logger.getRootLogger().setLevel(Level.INFO); //Logger.getRootLogger().setLevel(Level.DEBUG); } @AfterMethod public void tearDown() throws Exception { } static { BasicConfigurator.configure(); Logger.getRootLogger().setLevel(Level.ERROR); } /* @Test public void testScnIndexUtilities() { ScnIndex index = new ScnIndex(10240000, 20000000000L, 500 * ByteSizeConstants.ONE_MEGABYTE_IN_BYTES); assertTrue("blockNumber = "+index.getBlockNumber(17327387028L), index.getBlockNumber(17327387028L) > 0); } */ @Test public void testScnIndexOnEventWithLargeBatch() { /** * Index is broken up into 3 entries for offsets * 0-1000, 1001-2000, 2001-3000 */ BufferPositionParser parser = new BufferPositionParser(3000,3); ScnIndex index = new ScnIndex(3 * ScnIndex.SIZE_OF_SCN_OFFSET_RECORD, 3000, 10000, parser, AllocationPolicy.DIRECT_MEMORY, false, null, DEFAULT_ASSERT_LEVEL, true /* enabled */, ByteOrder.BIG_ENDIAN); DbusEvent eopEvent = EasyMock.createNiceMock(DbusEvent.class); EasyMock.expect(eopEvent.isEndOfPeriodMarker()).andReturn(true).anyTimes(); EasyMock.expect(eopEvent.isControlMessage()).andReturn(true).anyTimes(); EasyMock.replay(eopEvent); index.onEvent(eopEvent, 0, 76); //200 index.onEvent(createMockDataEvent(200L), 500, 0); // 1st block index.onEvent(eopEvent, 510,0); // 1st block //200 index.onEvent(createMockDataEvent(250L), 1500,0); // 2nd block index.onEvent(eopEvent, 1510,0); // 2nd block //300 index.onEvent(createMockDataEvent(300L), 2100,0); // 3rd block index.onEvent(eopEvent, 2210,0); // 3rd block // Index should look like: 200->500, 250->1500, 300->2100 LOG.info("index=" + index); index.printVerboseString(LOG, Level.DEBUG); checkSuccess(index, 200, 500,200); checkSuccess(index, 200, 500,200); checkSuccess(index, 300, 2100,300); assertEquals("Head Check", 0, index.getHead()); assertEquals("Tail Check", 0, index.getTail()); //400 index.moveHead(2100); long ofs1_450 = index.getPositionParser().setGenId(450, 1); index.onEvent(createMockDataEvent(400L), ofs1_450,0); // Back to 1st block, this should erase the existence of 200 long ofs1_460 = index.getPositionParser().setGenId(460, 1); index.onEvent(eopEvent, ofs1_460,0); // Back to 1st block // Index should look like: 400->[1:450], 250->1500, 300->2100 checkSuccess(index, 300, 2100, 300); checkSuccess(index, 500, ofs1_450, 400); checkFailure(index, 200); assertEquals("Head Check", 32, index.getHead()); assertEquals("Tail Check", 16, index.getTail()); //500 long ofs1_1100 = index.getPositionParser().setGenId(1100, 1); index.onEvent(createMockDataEvent(500L), ofs1_1100,0); long ofs1_1110 = index.getPositionParser().setGenId(1110, 1); index.onEvent(eopEvent, ofs1_1110, 0); // 3rd block // Index should look like: 400->[1:450], 500->[1:1100], 300->2100 checkFailure(index, 200); checkSuccess(index, 400, ofs1_450, 400); checkSuccess(index, 500, ofs1_1100, 500 ); checkSuccess(index, 300, 2100, 300); long ofs1_1010 = index.getPositionParser().setGenId(1010, 1); assertEquals(2100, index.getLargerOffset(ofs1_1010)); assertEquals("Head Check", 32, index.getHead()); assertEquals("Tail Check", 32, index.getTail()); //600 long ofs1_1800 = index.getPositionParser().setGenId(1800, 1); index.onEvent(createMockDataEvent(600L), ofs1_1800, 0); long ofs1_1805 = index.getPositionParser().setGenId(1805, 1); index.onEvent(eopEvent, ofs1_1805, 0); // 3rd block // Index should look like: 400->[1:450], 500->[1:1100], 600->[1:1800], 300->2100 checkSuccess(index, 600, ofs1_1100, 500); checkSuccess(index, 400, ofs1_450, 400); checkSuccess(index, 500, ofs1_1100, 500); checkSuccess(index, 300, 2100, 300); assertEquals("Head Check", 32, index.getHead()); assertEquals("Tail Check", 32, index.getTail()); //700 long ofs0_100 = index.getPositionParser().setGenId(100, 0); index.moveHead(ofs0_100); long ofs1_2010 = index.getPositionParser().setGenId(2010, 1); index.onEvent(createMockDataEvent(700L), ofs1_2010, 0); long ofs2_5 = index.getPositionParser().setGenId(5, 2); index.onEvent(createMockDataEvent(700L), ofs2_5, 0); long ofs2_10 = index.getPositionParser().setGenId(10, 0); index.onEvent(eopEvent, ofs2_10, 0); // 3rd block // Index should look like: 400->[1:450], 500->[1:1100], 600->[1:1800], 700->[1:2010] LOG.info("index=" + index); checkSuccess(index, 700, ofs1_2010, 700); assertEquals(400, index.getMinScn()); assertEquals("Head Check", 0, index.getHead()); assertEquals("Tail Check", 0, index.getTail()); // let's pretend that the next event will end at 451 long ofs1_451 = index.getPositionParser().setGenId(451, 1); long potentialHead = index.getLargerOffset(ofs1_451); LOG.info("Potential Head is:" + potentialHead); index.moveHead(potentialHead); assertEquals(ofs1_1100, potentialHead); long ofs1_2900 = index.getPositionParser().setGenId(2900, 1); index.moveHead(ofs1_2900); // let's pretend that the next event will end at 2500 long ofs2_2500 = index.getPositionParser().setGenId(2500, 2); potentialHead = index.getLargerOffset(ofs2_2500); LOG.info("potentialHead=" + potentialHead); assertEquals(-1, potentialHead); long ofs2_1100 = index.getPositionParser().setGenId(1100, 2); index.onEvent(createMockDataEvent(800L), ofs2_1100, 0); LOG.info("index=" + index); long ofs2_1500 = index.getPositionParser().setGenId(1500, 2); index.onEvent(eopEvent, ofs2_1500, 0); // Index should look like: 700->2010, 800->1100, 700->2010 checkSuccess(index, 800, ofs2_1100, 800); checkSuccess(index, 700, ofs1_2900, 700); checkFailure(index, 500); assertEquals(700, index.getMinScn()); LOG.info("index=" + index); assertEquals("Head Check", 32, index.getHead()); assertEquals("Tail Check", 32, index.getTail()); } private DbusEvent createMockDataEvent(long windowScn) { DbusEvent event = EasyMock.createNiceMock(DbusEvent.class); EasyMock.expect(event.sequence()).andReturn(windowScn).anyTimes(); EasyMock.expect(event.isEndOfPeriodMarker()).andReturn(false).anyTimes(); EasyMock.expect(event.isControlMessage()).andReturn(false).anyTimes(); EasyMock.replay(event); return event; } private void checkSuccess(ScnIndex index, long scn, long offset, long expSCN) { try { ScnIndex.ScnIndexEntry entry = index.getClosestOffset(scn); long readOffset = entry.getOffset(); LOG.info("Offset Check:" + scn + " : " + readOffset); LOG.info("SCN Check:" + scn + " : " + entry.getScn()); assertEquals(offset, readOffset); assertEquals(expSCN, entry.getScn()); } catch (OffsetNotFoundException e) { LOG.error(scn + " : OffsetNotFound"); fail("Exception should not have been thrown"); } } private void checkFailure(ScnIndex index, long scn) { try { ScnIndex.ScnIndexEntry entry = index.getClosestOffset(scn); long readOffset = entry.getOffset(); LOG.info(scn + " : " + readOffset); fail("Exception should have been thrown"); } catch (OffsetNotFoundException e) { LOG.info(scn + " : OffsetNotFound"); } } }