/**
* 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.store.kahadb;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.apache.activemq.store.AbstractMessageStoreSizeTest;
import org.apache.activemq.store.MessageStore;
import org.apache.activemq.store.PersistenceAdapter;
import org.apache.activemq.store.kahadb.disk.util.LocationMarshaller;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.junit.Test;
/**
* This test is for AMQ-5748 to verify that {@link MessageStore} implements correctly
* compute the size of the messages in the store.
*
* For KahaDB specifically, the size was not being stored in in the index ({@link LocationMarshaller}). LocationMarshaller
* has been updated to include an option to include the size in the serialized value. This way the message
* size will be persisted in the index and be available between broker restarts without needing to rebuild the index.
* Note that the KahaDB version has been incremented from 5 to 6 because the index will need to be rebuild when a version
* 5 index is detected since it will be detected as corrupt.
*
*/
public abstract class AbstractKahaDBMessageStoreSizeTest extends AbstractMessageStoreSizeTest {
MessageStore messageStore;
PersistenceAdapter store;
@Override
public void initStore() throws Exception {
createStore(true, dataDirectory);
}
abstract protected void createStore(boolean deleteAllMessages, String directory) throws Exception;
abstract protected String getVersion5Dir();
@Override
public void destroyStore() throws Exception {
if (store != null) {
store.stop();
}
}
/**
* This method tests that the message sizes exist for all messages that exist after messages are recovered
* off of disk.
*
* @throws Exception
*/
@Test
public void testMessageSizeStoreRecovery() throws Exception {
writeMessages();
store.stop();
createStore(false, dataDirectory);
writeMessages();
long messageSize = messageStore.getMessageSize();
assertEquals(40, messageStore.getMessageCount());
assertTrue(messageSize > 40 * testMessageSize);
}
/**
* This method tests that a version 5 store with an old index still works but returns 0 for messgage sizes.
*
* @throws Exception
*/
@Test
public void testMessageSizeStoreRecoveryVersion5() throws Exception {
store.stop();
//Copy over an existing version 5 store with messages
File dataDir = new File(dataDirectory);
if (dataDir.exists())
FileUtils.deleteDirectory(new File(dataDirectory));
FileUtils.copyDirectory(new File(getVersion5Dir()),
dataDir);
//reload store
createStore(false, dataDirectory);
//make sure size is 0
long messageSize = messageStore.getMessageSize();
assertTrue(messageStore.getMessageCount() == 20);
assertTrue(messageSize == 0);
}
/**
* This method tests that a version 5 store with existing messages will correctly be recovered and converted
* to version 6. After index deletion, the index will be rebuilt and will include message sizes.
*
* @throws Exception
*/
@Test
public void testMessageSizeStoreRecoveryVersion5RebuildIndex() throws Exception {
store.stop();
//Copy over an existing version 5 store with messages
File dataDir = new File(dataDirectory);
if (dataDir.exists())
FileUtils.deleteDirectory(new File(dataDirectory));
FileUtils.copyDirectory(new File(getVersion5Dir()),
dataDir);
for (File index : FileUtils.listFiles(new File(dataDirectory), new WildcardFileFilter("*.data"), TrueFileFilter.INSTANCE)) {
FileUtils.deleteQuietly(index);
}
//append more messages...at this point the index should be rebuilt
createStore(false, dataDirectory);
writeMessages();
//after writing new messages to the existing store, make sure the index is rebuilt and size is correct
long messageSize = messageStore.getMessageSize();
assertTrue(messageStore.getMessageCount() == 40);
assertTrue(messageSize > 40 * testMessageSize);
}
@Override
protected MessageStore getMessageStore() {
return messageStore;
}
}