/* * 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.activemq.artemis.tests.unit.core.journal.impl; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.UUID; import org.apache.activemq.artemis.api.core.ActiveMQBuffer; import org.apache.activemq.artemis.api.core.ActiveMQBuffers; import org.apache.activemq.artemis.core.io.SequentialFile; import org.apache.activemq.artemis.core.io.SequentialFileFactory; import org.apache.activemq.artemis.jlibaio.LibaioContext; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public abstract class SequentialFileFactoryTestBase extends ActiveMQTestBase { @Override @Before public void setUp() throws Exception { super.setUp(); factory = createFactory(getTestDir()); factory.start(); } @Override @After public void tearDown() throws Exception { factory.stop(); factory = null; ActiveMQTestBase.forceGC(); Assert.assertEquals(0, LibaioContext.getTotalMaxIO()); super.tearDown(); } protected abstract SequentialFileFactory createFactory(String folder); protected SequentialFileFactory factory; @Test public void listFilesOnNonExistentFolder() throws Exception { SequentialFileFactory fileFactory = createFactory("./target/dontexist"); List<String> list = fileFactory.listFiles("tmp"); Assert.assertNotNull(list); Assert.assertEquals(0, list.size()); } @Test public void testCreateAndListFiles() throws Exception { List<String> expectedFiles = new ArrayList<>(); final int numFiles = 10; for (int i = 0; i < numFiles; i++) { String fileName = UUID.randomUUID().toString() + ".amq"; expectedFiles.add(fileName); SequentialFile sf = factory.createSequentialFile(fileName); sf.open(); Assert.assertEquals(fileName, sf.getFileName()); sf.close(); } // Create a couple with a different extension - they shouldn't be picked // up SequentialFile sf1 = factory.createSequentialFile("different.file"); sf1.open(); SequentialFile sf2 = factory.createSequentialFile("different.cheese"); sf2.open(); List<String> fileNames = factory.listFiles("amq"); Assert.assertEquals(expectedFiles.size(), fileNames.size()); for (String fileName : expectedFiles) { Assert.assertTrue(fileNames.contains(fileName)); } fileNames = factory.listFiles("file"); Assert.assertEquals(1, fileNames.size()); Assert.assertTrue(fileNames.contains("different.file")); fileNames = factory.listFiles("cheese"); Assert.assertEquals(1, fileNames.size()); Assert.assertTrue(fileNames.contains("different.cheese")); sf1.close(); sf2.close(); } @Test public void testFill() throws Exception { SequentialFile sf = factory.createSequentialFile("fill.amq"); sf.open(); try { checkFill(factory, sf, 2048); checkFill(factory, sf, 512); checkFill(factory, sf, 512 * 4); } finally { sf.close(); } } @Test public void testDelete() throws Exception { SequentialFile sf = factory.createSequentialFile("delete-me.amq"); sf.open(); SequentialFile sf2 = factory.createSequentialFile("delete-me2.amq"); sf2.open(); List<String> fileNames = factory.listFiles("amq"); Assert.assertEquals(2, fileNames.size()); Assert.assertTrue(fileNames.contains("delete-me.amq")); Assert.assertTrue(fileNames.contains("delete-me2.amq")); sf.delete(); fileNames = factory.listFiles("amq"); Assert.assertEquals(1, fileNames.size()); Assert.assertTrue(fileNames.contains("delete-me2.amq")); sf2.close(); } @Test public void testRename() throws Exception { SequentialFile sf = factory.createSequentialFile("test1.amq"); sf.open(); List<String> fileNames = factory.listFiles("amq"); Assert.assertEquals(1, fileNames.size()); Assert.assertTrue(fileNames.contains("test1.amq")); sf.renameTo("test1.cmp"); fileNames = factory.listFiles("cmp"); Assert.assertEquals(1, fileNames.size()); Assert.assertTrue(fileNames.contains("test1.cmp")); sf.delete(); fileNames = factory.listFiles("amq"); Assert.assertEquals(0, fileNames.size()); fileNames = factory.listFiles("cmp"); Assert.assertEquals(0, fileNames.size()); } @Test public void testWriteandRead() throws Exception { SequentialFile sf = factory.createSequentialFile("write.amq"); sf.open(); String s1 = "aardvark"; byte[] bytes1 = s1.getBytes(StandardCharsets.UTF_8); ActiveMQBuffer bb1 = wrapBuffer(bytes1); String s2 = "hippopotamus"; byte[] bytes2 = s2.getBytes(StandardCharsets.UTF_8); ActiveMQBuffer bb2 = wrapBuffer(bytes2); String s3 = "echidna"; byte[] bytes3 = s3.getBytes(StandardCharsets.UTF_8); ActiveMQBuffer bb3 = wrapBuffer(bytes3); long initialPos = sf.position(); sf.write(bb1, true); long bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes1.length, factory.getAlignment()), bytesWritten); initialPos = sf.position(); sf.write(bb2, true); bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes2.length, factory.getAlignment()), bytesWritten); initialPos = sf.position(); sf.write(bb3, true); bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes3.length, factory.getAlignment()), bytesWritten); sf.position(0); ByteBuffer rb1 = factory.newBuffer(bytes1.length); ByteBuffer rb2 = factory.newBuffer(bytes2.length); ByteBuffer rb3 = factory.newBuffer(bytes3.length); int bytesRead = sf.read(rb1); Assert.assertEquals(calculateRecordSize(bytes1.length, factory.getAlignment()), bytesRead); for (int i = 0; i < bytes1.length; i++) { Assert.assertEquals(bytes1[i], rb1.get(i)); } bytesRead = sf.read(rb2); Assert.assertEquals(calculateRecordSize(bytes2.length, factory.getAlignment()), bytesRead); for (int i = 0; i < bytes2.length; i++) { Assert.assertEquals(bytes2[i], rb2.get(i)); } bytesRead = sf.read(rb3); Assert.assertEquals(calculateRecordSize(bytes3.length, factory.getAlignment()), bytesRead); for (int i = 0; i < bytes3.length; i++) { Assert.assertEquals(bytes3[i], rb3.get(i)); } sf.close(); } @Test public void testPosition() throws Exception { SequentialFile sf = factory.createSequentialFile("position.amq"); sf.open(); try { sf.fill(3 * 512); String s1 = "orange"; byte[] bytes1 = s1.getBytes(StandardCharsets.UTF_8); byte[] bytes2 = s1.getBytes(StandardCharsets.UTF_8); String s3 = "lemon"; byte[] bytes3 = s3.getBytes(StandardCharsets.UTF_8); long initialPos = sf.position(); sf.write(wrapBuffer(bytes1), true); long bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes1.length, factory.getAlignment()), bytesWritten); initialPos = sf.position(); sf.write(wrapBuffer(bytes2), true); bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes2.length, factory.getAlignment()), bytesWritten); initialPos = sf.position(); sf.write(wrapBuffer(bytes3), true); bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes3.length, factory.getAlignment()), bytesWritten); byte[] rbytes1 = new byte[bytes1.length]; byte[] rbytes2 = new byte[bytes2.length]; byte[] rbytes3 = new byte[bytes3.length]; ByteBuffer rb1 = factory.newBuffer(rbytes1.length); ByteBuffer rb2 = factory.newBuffer(rbytes2.length); ByteBuffer rb3 = factory.newBuffer(rbytes3.length); sf.position(calculateRecordSize(bytes1.length, factory.getAlignment()) + calculateRecordSize(bytes2.length, factory.getAlignment())); int bytesRead = sf.read(rb3); Assert.assertEquals(rb3.limit(), bytesRead); rb3.rewind(); rb3.get(rbytes3); ActiveMQTestBase.assertEqualsByteArrays(bytes3, rbytes3); sf.position(rb1.limit()); bytesRead = sf.read(rb2); Assert.assertEquals(rb2.limit(), bytesRead); rb2.get(rbytes2); ActiveMQTestBase.assertEqualsByteArrays(bytes2, rbytes2); sf.position(0); bytesRead = sf.read(rb1); Assert.assertEquals(rb1.limit(), bytesRead); rb1.get(rbytes1); ActiveMQTestBase.assertEqualsByteArrays(bytes1, rbytes1); } finally { try { sf.close(); } catch (Exception ignored) { } } } @Test public void testOpenClose() throws Exception { SequentialFile sf = factory.createSequentialFile("openclose.amq"); sf.open(); sf.fill(512); String s1 = "cheesecake"; byte[] bytes1 = s1.getBytes(StandardCharsets.UTF_8); long initialPos = sf.position(); sf.write(wrapBuffer(bytes1), true); long bytesWritten = sf.position() - initialPos; Assert.assertEquals(calculateRecordSize(bytes1.length, factory.getAlignment()), bytesWritten); sf.close(); try { sf.write(wrapBuffer(bytes1), true); Assert.fail("Should throw exception"); } catch (Exception e) { } sf.open(); sf.write(wrapBuffer(bytes1), true); sf.close(); } // Private --------------------------------- private ActiveMQBuffer wrapBuffer(final byte[] bytes) { return ActiveMQBuffers.wrappedBuffer(bytes); } protected void checkFill(final SequentialFileFactory factory, final SequentialFile file, final int size) throws Exception { file.fill(size); file.close(); file.open(); file.position(0); ByteBuffer bb = factory.newBuffer(size); int bytesRead = file.read(bb); Assert.assertEquals(calculateRecordSize(size, factory.getAlignment()), bytesRead); for (int i = 0; i < size; i++) { // log.debug(" i is " + i); Assert.assertEquals(0, bb.get(i)); } } }