/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.flink.runtime.io.disk; import static org.junit.Assert.*; import java.io.EOFException; import java.util.ArrayList; import java.util.List; import org.apache.flink.core.memory.MemorySegment; import org.apache.flink.core.memory.MemoryType; import org.apache.flink.runtime.io.disk.iomanager.BlockChannelWriter; import org.apache.flink.runtime.io.disk.iomanager.FileIOChannel; import org.apache.flink.runtime.io.disk.iomanager.IOManager; import org.apache.flink.runtime.io.disk.iomanager.IOManagerAsync; import org.apache.flink.runtime.memory.MemoryManager; import org.apache.flink.runtime.operators.testutils.DummyInvokable; import org.junit.Test; public class SeekableFileChannelInputViewTest { @Test public void testSeek() { final IOManager ioManager = new IOManagerAsync(); final int PAGE_SIZE = 16 * 1024; final int NUM_RECORDS = 120000; // integers across 7.x pages (7 pages = 114.688 bytes, 8 pages = 131.072 bytes) try { MemoryManager memMan = new MemoryManager(4 * PAGE_SIZE, 1, PAGE_SIZE, MemoryType.HEAP, true); List<MemorySegment> memory = new ArrayList<MemorySegment>(); memMan.allocatePages(new DummyInvokable(), memory, 4); FileIOChannel.ID channel = ioManager.createChannel(); BlockChannelWriter<MemorySegment> writer = ioManager.createBlockChannelWriter(channel); FileChannelOutputView out = new FileChannelOutputView(writer, memMan, memory, memMan.getPageSize()); // write some integers across 7.5 pages (7 pages = 114.688 bytes, 8 pages = 131.072 bytes) for (int i = 0; i < NUM_RECORDS; i += 4) { out.writeInt(i); } // close for the first time, make sure all memory returns out.close(); assertTrue(memMan.verifyEmpty()); memMan.allocatePages(new DummyInvokable(), memory, 4); SeekableFileChannelInputView in = new SeekableFileChannelInputView(ioManager, channel, memMan, memory, out.getBytesInLatestSegment()); // read first, complete for (int i = 0; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to the middle of the 3rd page int i = 2 * PAGE_SIZE + PAGE_SIZE / 4; in.seek(i); for (; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to the end i = 120000 - 4; in.seek(i); for (; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to the beginning i = 0; in.seek(i); for (; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to after a page i = PAGE_SIZE; in.seek(i); for (; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to after a page i = 3 * PAGE_SIZE; in.seek(i); for (; i < NUM_RECORDS; i += 4) { assertEquals(i, in.readInt()); } try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek to the end i = NUM_RECORDS; in.seek(i); try { in.readInt(); fail("should throw EOF exception"); } catch (EOFException ignored) {} // seek out of bounds try { in.seek(-10); fail("should throw an exception"); } catch (IllegalArgumentException ignored) {} try { in.seek(NUM_RECORDS + 1); fail("should throw an exception"); } catch (IllegalArgumentException ignored) {} } catch (Exception e) { e.printStackTrace(); fail(e.getMessage()); } finally { ioManager.shutdown(); } } }