/*
* 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.cassandra.io.compress;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.apache.cassandra.db.composites.SimpleDenseCellNameType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
import org.apache.cassandra.io.util.FileMark;
public class CompressedSequentialWriterTest
{
private ICompressor compressor;
private void runTests(String testName) throws IOException, ConfigurationException
{
// Test small < 1 chunk data set
testWrite(File.createTempFile(testName + "_small", "1"), 25);
// Test to confirm pipeline w/chunk-aligned data writes works
testWrite(File.createTempFile(testName + "_chunkAligned", "1"), CompressionParameters.DEFAULT_CHUNK_LENGTH);
// Test to confirm pipeline on non-chunk boundaries works
testWrite(File.createTempFile(testName + "_large", "1"), CompressionParameters.DEFAULT_CHUNK_LENGTH * 3 + 100);
}
@Test
public void testLZ4Writer() throws IOException, ConfigurationException
{
compressor = LZ4Compressor.instance;
runTests("LZ4");
}
@Test
public void testDeflateWriter() throws IOException, ConfigurationException
{
compressor = DeflateCompressor.instance;
runTests("Deflate");
}
@Test
public void testSnappyWriter() throws IOException, ConfigurationException
{
compressor = SnappyCompressor.instance;
runTests("Snappy");
}
private void testWrite(File f, int bytesToTest) throws IOException, ConfigurationException
{
try
{
final String filename = f.getAbsolutePath();
MetadataCollector sstableMetadataCollector = new MetadataCollector(new SimpleDenseCellNameType(BytesType.instance)).replayPosition(null);
CompressedSequentialWriter writer = new CompressedSequentialWriter(f, filename + ".metadata", new CompressionParameters(compressor), sstableMetadataCollector);
byte[] dataPre = new byte[bytesToTest];
byte[] rawPost = new byte[bytesToTest];
Random r = new Random();
// Test both write with byte[] and ByteBuffer
r.nextBytes(dataPre);
r.nextBytes(rawPost);
writer.write(dataPre);
FileMark mark = writer.mark();
// Write enough garbage to transition chunk
for (int i = 0; i < CompressionParameters.DEFAULT_CHUNK_LENGTH; i++)
{
writer.write((byte)i);
}
writer.resetAndTruncate(mark);
writer.write(rawPost);
writer.close();
assert f.exists();
CompressedRandomAccessReader reader = CompressedRandomAccessReader.open(filename, new CompressionMetadata(filename + ".metadata", f.length(), true));
assertEquals(dataPre.length + rawPost.length, reader.length());
byte[] result = new byte[(int)reader.length()];
reader.readFully(result);
assert(reader.isEOF());
reader.close();
byte[] fullInput = new byte[bytesToTest * 2];
System.arraycopy(dataPre, 0, fullInput, 0, dataPre.length);
System.arraycopy(rawPost, 0, fullInput, bytesToTest, rawPost.length);
assert Arrays.equals(result, fullInput);
}
finally
{
// cleanup
if (f.exists())
f.delete();
File metadata = new File(f + ".metadata");
if (metadata.exists())
metadata.delete();
}
}
}