Java tutorial
/** * 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 com.datatorrent.lib.io.fs; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.zip.GZIPInputStream; import javax.annotation.Nonnull; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.validation.ConstraintViolationException; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.google.common.io.LimitInputStream; import com.datatorrent.api.Attribute; import com.datatorrent.api.Context; import com.datatorrent.api.DAG; import com.datatorrent.api.LocalMode; import com.datatorrent.api.StreamingApplication; import com.datatorrent.api.annotation.Stateless; import com.datatorrent.lib.helper.OperatorContextTestHelper; import com.datatorrent.lib.testbench.RandomWordGenerator; import com.datatorrent.lib.util.TestUtils; import com.datatorrent.lib.util.TestUtils.TestInfo; import com.datatorrent.netlet.util.DTThrowable; public class AbstractFileOutputOperatorTest { private static final Logger LOG = LoggerFactory.getLogger(AbstractFileOutputOperatorTest.class); private static final String SINGLE_FILE = "single.txt"; private static final String EVEN_FILE = "even.txt"; private static final String ODD_FILE = "odd.txt"; @Rule public FSTestWatcher testMeta = new FSTestWatcher(); public static class FSTestWatcher extends TestInfo { public boolean writeToTmp = false; public OperatorContextTestHelper.TestIdOperatorContext testOperatorContext; @Override protected void starting(Description description) { super.starting(description); TestUtils.deleteTargetTestClassFolder(description); try { FileUtils.forceMkdir(new File(getDir())); Attribute.AttributeMap.DefaultAttributeMap attributeMap = new Attribute.AttributeMap.DefaultAttributeMap(); attributeMap.put(Context.DAGContext.CHECKPOINT_WINDOW_COUNT, 60); attributeMap.put(Context.OperatorContext.SPIN_MILLIS, 500); testOperatorContext = new OperatorContextTestHelper.TestIdOperatorContext(0, attributeMap); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void finished(Description description) { super.finished(description); TestUtils.deleteTargetTestClassFolder(description); } } /** * Simple writer which writes to two files. */ private static class EvenOddHDFSExactlyOnceWriter extends AbstractFileOutputOperator<Integer> { @Override protected FileSystem getFSInstance() throws IOException { return FileSystem.getLocal(new Configuration()).getRaw(); } @Override protected String getFileName(Integer tuple) { if (tuple % 2 == 0) { return EVEN_FILE; } else { return ODD_FILE; } } @Override protected byte[] getBytesForTuple(Integer tuple) { return (tuple.toString() + "\n").getBytes(); } } /** * Simple writer which writes to one file. */ private static class SingleHDFSExactlyOnceWriter extends AbstractFileOutputOperator<Integer> { @Override protected FileSystem getFSInstance() throws IOException { return FileSystem.getLocal(new Configuration()).getRaw(); } @Override protected String getFileName(Integer tuple) { return SINGLE_FILE; } @Override protected byte[] getBytesForTuple(Integer tuple) { return (tuple.toString() + "\n").getBytes(); } } /** * Simple writer which writes byte array tuples to one file. */ private static class SingleHDFSByteExactlyOnceWriter extends AbstractFileOutputOperator<byte[]> { SingleHDFSByteExactlyOnceWriter() { } @Override protected FileSystem getFSInstance() throws IOException { return FileSystem.getLocal(new Configuration()).getRaw(); } @Override protected String getFileName(byte[] tuple) { return SINGLE_FILE; } @Override protected byte[] getBytesForTuple(byte[] tuple) { return tuple; } } /** * This is a test app to make sure that the operator validation works properly. */ private static class ValidationTestApp implements StreamingApplication { private final File testDir; private final Long maxLength; private final AbstractFileOutputOperator<byte[]> fsWriter; ValidationTestApp(File testDir, Long maxLength, AbstractFileOutputOperator<byte[]> fsWriter) { this.testDir = testDir; this.maxLength = maxLength; this.fsWriter = fsWriter; } @Override public void populateDAG(DAG dag, Configuration conf) { RandomWordGenerator randomWordGenerator = new RandomWordGenerator(); randomWordGenerator.setTuplesPerWindow(2); dag.addOperator("random", randomWordGenerator); if (maxLength != null) { fsWriter.setMaxLength(maxLength); } fsWriter.setFilePath(testDir.getPath()); dag.addOperator("fswriter", fsWriter); dag.addStream("fswriterstream", randomWordGenerator.output, fsWriter.input); } } private void populateFile(String fileName, String contents) throws IOException { File testFile = new File(testMeta.getDir() + "/" + fileName); testFile.createNewFile(); FileWriter fileWriter = new FileWriter(testFile); fileWriter.write(contents); fileWriter.close(); } /** * This method checkpoints the given writer. * @param writer The writer to checkpoint. * @return new writer. */ public static AbstractFileOutputOperator checkpoint(AbstractFileOutputOperator writer, long windowId) { if (windowId >= Stateless.WINDOW_ID) { writer.beforeCheckpoint(windowId); } Kryo kryo = new Kryo(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); Output loutput = new Output(bos); kryo.writeObject(loutput, writer); loutput.close(); Input lInput = new Input(bos.toByteArray()); @SuppressWarnings("unchecked") AbstractFileOutputOperator checkPointedWriter = kryo.readObject(lInput, writer.getClass()); lInput.close(); return checkPointedWriter; } /** * Restores the checkpointed writer. * @param checkPointWriter The checkpointed writer. * @param writer The writer to restore state into. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static void restoreCheckPoint(AbstractFileOutputOperator checkPointWriter, AbstractFileOutputOperator writer) { writer.counts = checkPointWriter.counts; writer.endOffsets = checkPointWriter.endOffsets; writer.openPart = checkPointWriter.openPart; writer.filePath = checkPointWriter.filePath; writer.maxOpenFiles = checkPointWriter.maxOpenFiles; writer.replication = checkPointWriter.replication; writer.totalBytesWritten = checkPointWriter.totalBytesWritten; writer.maxLength = checkPointWriter.maxLength; writer.rollingFile = checkPointWriter.rollingFile; writer.getFileNameToTmpName().putAll(checkPointWriter.getFileNameToTmpName()); writer.getFinalizedFiles().putAll(checkPointWriter.getFinalizedFiles()); } public static void checkOutput(int fileCount, String baseFilePath, String expectedOutput) { if (fileCount >= 0) { baseFilePath += "." + fileCount; } File file = new File(baseFilePath); String fileContents = null; try { fileContents = FileUtils.readFileToString(file); } catch (IOException ex) { DTThrowable.rethrow(ex); } Assert.assertEquals("Single file " + fileCount + " output contents", expectedOutput, fileContents); } @Test public void testSingleFileCompletedWrite() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleFileCompletedWriteHelper(writer); String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "2\n" + "3\n"; checkOutput(-1, singleFileName, correctContents); } @Test public void testSingleFileCompletedWriteTmp() { testMeta.writeToTmp = true; testSingleFileCompletedWrite(); } @Test public void testSingleFileCompletedWriteOverwriteInitial() throws IOException { populateFile(SINGLE_FILE, "0\n" + "1\n" + "2\n"); SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleFileCompletedWriteHelper(writer); String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "2\n" + "3\n"; checkOutput(-1, singleFileName, correctContents); } @Test public void testSingleFileCompletedWriteOverwriteInitialTmp() throws IOException { testMeta.writeToTmp = true; testSingleFileCompletedWriteOverwriteInitial(); } private void testSingleFileCompletedWriteHelper(SingleHDFSExactlyOnceWriter writer) { writer.setFilePath(testMeta.getDir()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.endWindow(); writer.beginWindow(1); writer.input.put(2); writer.input.put(3); writer.endWindow(); writer.requestFinalize(SINGLE_FILE); writer.committed(1); writer.teardown(); } @Test public void testSingleFileFailedWrite() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleFileFailedWriteHelper(writer); String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "4\n" + "5\n" + "6\n" + "7\n"; checkOutput(-1, singleFileName, correctContents); } @Test public void testSingleFileFailedWriteTmp() { testMeta.writeToTmp = true; testSingleFileFailedWrite(); } @Test public void testSingleFileFailedWriteOverwriteInitial() throws IOException { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); populateFile(SINGLE_FILE, "0\n" + "1\n" + "2\n"); testSingleFileFailedWriteHelper(writer); String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "4\n" + "5\n" + "6\n" + "7\n"; checkOutput(-1, singleFileName, correctContents); } @Test public void testSingleFileFailedWriteOverwriteInitiaTmp() throws IOException { testMeta.writeToTmp = true; testSingleFileFailedWriteOverwriteInitial(); } private void testSingleFileFailedWriteHelper(SingleHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.requestFinalize(SINGLE_FILE); writer.input.put(1); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.put(2); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.put(4); writer.requestFinalize(SINGLE_FILE); writer.input.put(5); writer.endWindow(); writer.beginWindow(2); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.committed(2); writer.teardown(); } @Test public void testMultiFileCompletedWrite() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiFileCompletedWriteHelper(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n" + "6\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n" + "7\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileCompletedWriteTmp() { testMeta.writeToTmp = true; testMultiFileCompletedWrite(); } //@Ignore @Test public void testMultiFileCompletedWriteCache1() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiFileCompletedWriteHelper(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n" + "6\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n" + "7\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileCompletedWriteCache1Tmp() { testMeta.writeToTmp = true; testMultiFileCompletedWriteCache1(); } //@Ignore @Test public void testMultiFileCompletedWriteOverwriteInitial() throws IOException { populateFile(EVEN_FILE, "0\n" + "2\n"); populateFile(ODD_FILE, "1\n" + "3\n"); EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiFileCompletedWriteHelper(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n" + "6\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n" + "7\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileCompletedWriteOverwriteInitialTmp() throws IOException { testMeta.writeToTmp = true; testMultiFileCompletedWriteOverwriteInitial(); } @Test public void testMultiFileCompletedWriteOverwriteCache1Initial() throws IOException { populateFile(EVEN_FILE, "0\n" + "2\n"); populateFile(ODD_FILE, "1\n" + "3\n"); EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiFileCompletedWriteHelperCache1(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n" + "6\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n" + "7\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileCompletedWriteOverwriteCache1InitialTmp() throws IOException { testMeta.writeToTmp = true; testMultiFileCompletedWriteOverwriteCache1Initial(); } private void testMultiFileCompletedWriteHelperCache1(EvenOddHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.endWindow(); writer.beginWindow(1); writer.input.put(4); writer.input.put(5); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.requestFinalize(EVEN_FILE); writer.requestFinalize(ODD_FILE); writer.beforeCheckpoint(1); writer.committed(1); } private void testMultiFileCompletedWriteHelper(EvenOddHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.endWindow(); writer.beginWindow(1); writer.input.put(4); writer.input.put(5); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.requestFinalize(ODD_FILE); writer.requestFinalize(EVEN_FILE); writer.beforeCheckpoint(1); writer.committed(1); } @Test public void testMultiFileFailedWrite() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiFileFailedWriteHelper(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "6\n" + "8\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "7\n" + "9\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileFailedWriteTmp() { testMeta.writeToTmp = true; testMultiFileFailedWrite(); } @Test public void testMultiFileFailedWriteCache1() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiFileFailedWriteHelper(writer); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "6\n" + "8\n"; checkOutput(-1, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "7\n" + "9\n"; checkOutput(-1, oddFileName, correctContents); } @Test public void testMultiFileFailedWriteCache1Tmp() { testMeta.writeToTmp = true; testMultiFileFailedWriteCache1(); } private void testMultiFileFailedWriteHelper(EvenOddHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.requestFinalize(EVEN_FILE); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.put(4); writer.input.put(5); writer.requestFinalize(ODD_FILE); writer.endWindow(); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(2); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.endWindow(); writer.beforeCheckpoint(2); writer.committed(2); } @Test public void testSingleRollingFileCompletedWrite() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleRollingFileCompletedWriteHelper(writer); //Rolling file 0 String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFileName, correctContents); //Rolling file 1 correctContents = "3\n" + "4\n" + "5\n"; checkOutput(1, singleFileName, correctContents); } @Test public void testSingleRollingFileCompletedWriteTmp() { testMeta.writeToTmp = true; testSingleRollingFileCompletedWrite(); } @Test public void testSingleRollingFileCompletedWriteOverwriteInitial() throws IOException { populateFile(SINGLE_FILE + ".0", "0\n" + "1\n" + "2\n"); populateFile(SINGLE_FILE + ".1", "0\n" + "1\n" + "2\n"); populateFile(SINGLE_FILE + ".2", "0\n" + "1\n" + "2\n"); SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleRollingFileCompletedWriteHelper(writer); //Rolling file 0 String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFileName, correctContents); //Rolling file 1 correctContents = "3\n" + "4\n" + "5\n"; checkOutput(1, singleFileName, correctContents); } @Test public void testSingleRollingFileCompletedWriteOverwriteInitialTmp() throws IOException { testMeta.writeToTmp = true; testSingleRollingFileCompletedWriteOverwriteInitial(); } private void testSingleRollingFileCompletedWriteHelper(SingleHDFSExactlyOnceWriter writer) { writer.setFilePath(testMeta.getDir()); writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); writer.beginWindow(1); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.input.put(6); writer.endWindow(); writer.committed(1); writer.teardown(); } @Test public void testSingleRollingFileEmptyWindowsWrite() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleRollingFileEmptyWindowsWriteHelper(writer); //Rolling file 0 String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; int numberOfFiles = new File(testMeta.getDir()).listFiles().length; Assert.assertEquals("More than one File in Directory", 1, numberOfFiles); String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFileName, correctContents); } private void testSingleRollingFileEmptyWindowsWriteHelper(SingleHDFSExactlyOnceWriter writer) { writer.setFilePath(testMeta.getDir()); writer.setMaxLength(4); writer.setRotationWindows(1); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); writer.beginWindow(1); writer.endWindow(); writer.beginWindow(2); writer.endWindow(); writer.beforeCheckpoint(2); writer.checkpointed(2); writer.committed(2); writer.teardown(); } @Test public void testSingleRollingFileFailedWrite() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); testSingleRollingFileFailedWriteHelper(writer); //Rolling file 0 String singleFileName = testMeta.getDir() + File.separator + SINGLE_FILE; String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFileName, correctContents); //Rolling file 1 correctContents = "3\n" + "4\n" + "5\n"; checkOutput(1, singleFileName, correctContents); //Rolling file 2 correctContents = "6\n" + "7\n" + "8\n"; checkOutput(2, singleFileName, correctContents); } @Test public void testSingleRollingFileFailedWriteTmp() { testMeta.writeToTmp = true; testSingleRollingFileFailedWrite(); } private void testSingleRollingFileFailedWriteHelper(SingleHDFSExactlyOnceWriter writer) { writer.setMaxLength(4); writer.setFilePath(testMeta.getDir()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.put(3); writer.input.put(4); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(2); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.endWindow(); writer.committed(2); writer.teardown(); } @Test public void testSingleRollingFileFailedWrite1() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); writer.setFilePath(testMeta.getDir()); writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); writer.beginWindow(1); writer.input.put(3); writer.input.put(4); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); AbstractFileOutputOperator checkPointWriter1 = checkpoint(writer, Stateless.WINDOW_ID); LOG.debug("Checkpoint endOffsets={}", checkPointWriter.endOffsets); writer.beginWindow(2); writer.input.put(5); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); LOG.debug("Checkpoint endOffsets={}", checkPointWriter.endOffsets); writer.setup(testMeta.testOperatorContext); writer.beginWindow(2); writer.input.put(5); writer.endWindow(); writer.beginWindow(3); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.endWindow(); writer.teardown(); restoreCheckPoint(checkPointWriter1, writer); writer.setup(testMeta.testOperatorContext); writer.committed(2); String singleFilePath = testMeta.getDir() + File.separator + SINGLE_FILE; //Rolling file 0 String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFilePath, correctContents); //Rolling file 1 correctContents = "3\n" + "4\n"; checkOutput(1, singleFilePath, correctContents); } @Test public void testSingleRollingFileFailedWrite1Tmp() { testMeta.writeToTmp = true; testSingleRollingFileFailedWrite1(); } //@Ignore @Test public void testMultiRollingFileCompletedWrite() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiRollingFileCompletedWriteHelper(writer); } @Test public void testMultiRollingFileCompletedWriteTmp() { testMeta.writeToTmp = true; testMultiRollingFileCompletedWrite(); } @Test public void testMultiRollingFileCompletedWriteCache1() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiRollingFileCompletedWriteHelper(writer); } @Test public void testMultiRollingFileCompletedWriteCache1Tmp() { testMeta.writeToTmp = true; testMultiRollingFileCompletedWriteCache1(); } @Test public void testMultiRollingFileCompletedWriteOverwrite() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiRollingFileCompletedWriteHelper(writer); } @Test public void testMultiRollingFileCompletedWriteOverwriteTmp() { testMeta.writeToTmp = true; testMultiRollingFileCompletedWriteOverwrite(); } @Test public void testMultiRollingFileCompletedWriteOverwriteCache1() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiRollingFileCompletedWriteHelperCache1(writer); } @Test public void testMultiRollingFileCompletedWriteOverwriteCache1Tmp() { testMeta.writeToTmp = true; testMultiRollingFileCompletedWriteOverwriteCache1(); } private void testMultiRollingFileCompletedWriteHelperCache1(EvenOddHDFSExactlyOnceWriter writer) { writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(1); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.committed(1); //Even file String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n"; checkOutput(0, evenFileName, correctContents); correctContents = "6\n" + "8\n" + "6\n"; checkOutput(1, evenFileName, correctContents); //Odd file String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n"; checkOutput(0, oddFileName, correctContents); correctContents = "7\n" + "9\n" + "7\n"; checkOutput(1, oddFileName, correctContents); } private void testMultiRollingFileCompletedWriteHelper(EvenOddHDFSExactlyOnceWriter writer) { writer.setMaxLength(4); File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(1); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.committed(1); //Even file String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n"; checkOutput(0, evenFileName, correctContents); correctContents = "6\n" + "8\n" + "6\n"; checkOutput(1, evenFileName, correctContents); //Odd file String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n"; checkOutput(0, oddFileName, correctContents); correctContents = "7\n" + "9\n" + "7\n"; checkOutput(1, oddFileName, correctContents); } @Test public void testMultiRollingFileFailedWrite() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiRollingFileFailedWriteHelperHelper(writer); } @Test public void testMultiRollingFileFailedWriteTmp() { testMeta.writeToTmp = true; testMultiRollingFileFailedWrite(); } @Test public void testMultiRollingFileFailedWriteCache1() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); testMultiRollingFileFailedWriteHelperHelper(writer); } @Test public void testMultiRollingFileFailedWriteCache1Tmp() { testMeta.writeToTmp = true; testMultiRollingFileFailedWriteCache1(); } private void testMultiRollingFileFailedWriteHelperHelper(EvenOddHDFSExactlyOnceWriter writer) { testMultiRollingFileFailedWriteHelper(writer); //Even file String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n"; checkOutput(0, evenFileName, correctContents); correctContents = "6\n" + "8\n" + "6\n"; checkOutput(1, evenFileName, correctContents); //Odd file String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n"; checkOutput(0, oddFileName, correctContents); correctContents = "7\n" + "9\n" + "7\n"; checkOutput(1, oddFileName, correctContents); } private void testMultiRollingFileFailedWriteHelper(EvenOddHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.put(2); writer.input.put(3); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.put(2); writer.input.put(3); writer.endWindow(); writer.beginWindow(2); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(3); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.committed(3); } @Test public void testMultiRollingFileFailedWriteOverwrite() throws IOException { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); testMultiRollingFileFailedWriteOverwriteHelper(writer); } @Test public void testMultiRollingFileFailedWriteOverwriteTmp() throws IOException { testMeta.writeToTmp = true; testMultiRollingFileFailedWriteOverwrite(); } @Test public void testMultiRollingFileFailedWriteOverwriteCache1() throws IOException { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxOpenFiles(1); String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; populateFile(EVEN_FILE + ".0", "0\n" + "2\n" + "4\n"); populateFile(ODD_FILE + ".0", "1\n" + "3\n" + "5\n"); testMultiRollingFileFailedWriteOverwriteHelperCache1(writer); //Even file String correctContents = "0\n" + "4\n" + "6\n"; checkOutput(0, evenFileName, correctContents); correctContents = "8\n" + "6\n" + "10\n"; checkOutput(1, evenFileName, correctContents); //Odd file correctContents = "1\n" + "5\n" + "7\n"; checkOutput(0, oddFileName, correctContents); correctContents = "9\n" + "7\n" + "11\n"; checkOutput(1, oddFileName, correctContents); } @Test public void testMultiRollingFileFailedWriteOverwriteCache1Tmp() throws IOException { testMeta.writeToTmp = true; testMultiRollingFileFailedWriteOverwriteCache1(); } private void testMultiRollingFileFailedWriteOverwriteHelperCache1(EvenOddHDFSExactlyOnceWriter writer) { File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.put(2); writer.input.put(3); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(2); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.input.put(6); writer.input.put(7); writer.input.put(10); writer.input.put(11); writer.endWindow(); writer.committed(2); } private void testMultiRollingFileFailedWriteOverwriteHelper(EvenOddHDFSExactlyOnceWriter writer) throws IOException { String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; populateFile(EVEN_FILE + ".0", "0\n" + "2\n" + "4\n"); populateFile(ODD_FILE + ".0", "1\n" + "3\n" + "5\n"); File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setMaxLength(4); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.process(0); writer.input.process(1); writer.endWindow(); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.beginWindow(1); writer.input.process(2); writer.input.process(3); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.process(4); writer.input.process(5); writer.endWindow(); writer.beginWindow(2); writer.input.process(6); writer.input.process(7); writer.input.process(8); writer.input.process(9); writer.input.process(6); writer.input.process(7); writer.input.process(10); writer.input.process(11); writer.endWindow(); writer.committed(2); //Even file String correctContents = "0\n" + "4\n" + "6\n"; checkOutput(0, evenFileName, correctContents); correctContents = "8\n" + "6\n" + "10\n"; checkOutput(1, evenFileName, correctContents); //Odd file correctContents = "1\n" + "5\n" + "7\n"; checkOutput(0, oddFileName, correctContents); correctContents = "9\n" + "7\n" + "11\n"; checkOutput(1, oddFileName, correctContents); } @Test public void singleFileMultiRollingFailure() { SingleHDFSExactlyOnceWriter writer = new SingleHDFSExactlyOnceWriter(); File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setMaxLength(4); singleFileMultiRollingFailureHelper(writer); String singleFilePath = testMeta.getDir() + File.separator + SINGLE_FILE; //Rolling file 0 String correctContents = "0\n" + "1\n" + "2\n"; checkOutput(0, singleFilePath, correctContents); //Rolling file 1 correctContents = "3\n" + "4\n" + "0\n"; checkOutput(1, singleFilePath, correctContents); //Rolling file 2 correctContents = "1\n" + "2\n" + "3\n"; checkOutput(2, singleFilePath, correctContents); //Rolling file 3 correctContents = "4\n" + "5\n" + "6\n"; checkOutput(3, singleFilePath, correctContents); } @Test public void singleFileMultiRollingFailureTmp() { testMeta.writeToTmp = true; singleFileMultiRollingFailure(); } private void singleFileMultiRollingFailureHelper(SingleHDFSExactlyOnceWriter writer) { writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); writer.beginWindow(1); writer.input.put(3); writer.input.put(4); AbstractFileOutputOperator checkPointWriter = checkpoint(writer, Stateless.WINDOW_ID); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(2); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.endWindow(); writer.teardown(); restoreCheckPoint(checkPointWriter, writer); writer.setup(testMeta.testOperatorContext); writer.beginWindow(1); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.endWindow(); writer.beginWindow(2); writer.input.put(3); writer.input.put(4); writer.input.put(5); writer.input.put(6); writer.endWindow(); writer.committed(2); } @Test public void validateNothingWrongTest() { ValidationTestApp validationTestApp = new ValidationTestApp(new File(testMeta.getDir()), null, new SingleHDFSByteExactlyOnceWriter()); LocalMode.runApp(validationTestApp, 1); } @Test public void validateNegativeMaxLengthTest() { ValidationTestApp validationTestApp = new ValidationTestApp(new File(testMeta.getDir()), -1L, new SingleHDFSByteExactlyOnceWriter()); boolean error = false; try { LocalMode.runApp(validationTestApp, 1); } catch (RuntimeException e) { if (e.getCause() instanceof ConstraintViolationException) { error = true; } } Assert.assertEquals("Max length validation not thrown with -1 max length", true, error); } @Test public void testPeriodicRotation() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); File dir = new File(testMeta.getDir()); writer.setFilePath(testMeta.getDir()); writer.setRotationWindows(30); writer.setAlwaysWriteToTmp(testMeta.writeToTmp); writer.setup(testMeta.testOperatorContext); // Check that rotation doesn't happen prematurely for (int i = 0; i < 30; ++i) { writer.beginWindow(i); for (int j = 0; j < i; ++j) { writer.input.put(2 * j + 1); } writer.endWindow(); } writer.committed(29); Set<String> fileNames = new TreeSet<String>(); fileNames.add(ODD_FILE + ".0"); Collection<File> files = FileUtils.listFiles(dir, null, false); Assert.assertEquals("Number of part files", 1, files.size()); Assert.assertEquals("Part file names", fileNames, getFileNames(files)); // Check that rotation is happening consistently and for all files for (int i = 30; i < 120; ++i) { writer.beginWindow(i); for (int j = 0; j < i; ++j) { writer.input.put(j); } writer.endWindow(); } writer.committed(119); files = FileUtils.listFiles(dir, null, false); Assert.assertEquals("Number of part files", 7, files.size()); for (int i = 0; i < 3; ++i) { fileNames.add(EVEN_FILE + "." + i); } for (int i = 1; i < 4; ++i) { fileNames.add(ODD_FILE + "." + i); } Assert.assertEquals("Part file names", fileNames, getFileNames(files)); // Check that rotation doesn't happen for files that don't have data during the rotation period for (int i = 120; i < 180; ++i) { writer.beginWindow(i); for (int j = 0; j < i; ++j) { writer.input.put(j * 2); } writer.endWindow(); } writer.committed(179); files = FileUtils.listFiles(dir, null, false); Assert.assertEquals("Number of part files", 9, files.size()); for (int i = 3; i < 5; ++i) { fileNames.add(EVEN_FILE + "." + i); } Assert.assertEquals("Part file names", fileNames, getFileNames(files)); writer.teardown(); } @Test public void testPeriodicRotationTmp() { testMeta.writeToTmp = true; testPeriodicRotation(); } @Test public void testPeriodicRotationWithEviction() throws InterruptedException { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); File dir = new File(testMeta.getDir()); writer.setFilePath(testMeta.getDir()); writer.setRotationWindows(30); writer.setAlwaysWriteToTmp(true); writer.setExpireStreamAfterAccessMillis(1L); writer.setup(testMeta.testOperatorContext); // Check that rotation for even.txt.0 happens for (int i = 0; i < 30; ++i) { writer.beginWindow(i); if (i == 0) { writer.input.put(i); } Thread.sleep(100L); writer.endWindow(); } writer.committed(29); Set<String> fileNames = new TreeSet<>(); fileNames.add(EVEN_FILE + ".0"); Collection<File> files = FileUtils.listFiles(dir, null, false); Assert.assertEquals("Number of part files", 1, files.size()); Assert.assertEquals("Part file names", fileNames, getFileNames(files)); // Check that rotation doesn't happen for files that don't have data during the rotation period for (int i = 30; i < 120; ++i) { writer.beginWindow(i); writer.endWindow(); } writer.committed(119); files = FileUtils.listFiles(dir, null, false); Assert.assertEquals("Number of part files", 1, files.size()); Assert.assertEquals("Part file names", fileNames, getFileNames(files)); } @Test public void testCompression() throws IOException { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setFilterStreamProvider(new FilterStreamCodec.GZipFilterStreamProvider()); File evenFile = new File(testMeta.getDir(), EVEN_FILE); File oddFile = new File(testMeta.getDir(), ODD_FILE); // To get around the multi member gzip issue with openjdk // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4691425 List<Long> evenOffsets = new ArrayList<Long>(); List<Long> oddOffsets = new ArrayList<Long>(); writer.setFilePath(testMeta.getDir()); writer.setAlwaysWriteToTmp(false); writer.setup(testMeta.testOperatorContext); for (int i = 0; i < 10; ++i) { writer.beginWindow(i); for (int j = 0; j < 1000; ++j) { writer.input.put(i); } writer.endWindow(); if ((i % 2) == 1) { writer.beforeCheckpoint(i); evenOffsets.add(evenFile.length()); oddOffsets.add(oddFile.length()); } } writer.teardown(); checkCompressedFile(evenFile, evenOffsets, 0, 5, 1000, null, null); checkCompressedFile(oddFile, oddOffsets, 1, 5, 1000, null, null); } @Test public void testRecoveryOfOpenFiles() { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); writer.setMaxLength(4); File meta = new File(testMeta.getDir()); writer.setFilePath(meta.getAbsolutePath()); writer.setAlwaysWriteToTmp(true); writer.setup(testMeta.testOperatorContext); writer.beginWindow(0); writer.input.put(0); writer.input.put(1); writer.input.put(2); writer.input.put(3); writer.endWindow(); writer.beforeCheckpoint(0); //failure and restored writer.setup(testMeta.testOperatorContext); writer.input.put(4); writer.input.put(5); writer.endWindow(); writer.beginWindow(1); writer.input.put(6); writer.input.put(7); writer.input.put(8); writer.input.put(9); writer.input.put(6); writer.input.put(7); writer.endWindow(); writer.committed(1); //Part 0 checks String evenFileName = testMeta.getDir() + File.separator + EVEN_FILE; String correctContents = "0\n" + "2\n" + "4\n"; checkOutput(0, evenFileName, correctContents); String oddFileName = testMeta.getDir() + File.separator + ODD_FILE; correctContents = "1\n" + "3\n" + "5\n"; checkOutput(0, oddFileName, correctContents); //Part 1 checks correctContents = "6\n" + "8\n" + "6\n"; checkOutput(1, evenFileName, correctContents); correctContents = "7\n" + "9\n" + "7\n"; checkOutput(1, oddFileName, correctContents); } private void checkCompressedFile(File file, List<Long> offsets, int startVal, int totalWindows, int totalRecords, SecretKey secretKey, byte[] iv) throws IOException { FileInputStream fis; InputStream gss = null; GZIPInputStream gis = null; BufferedReader br = null; Cipher cipher = null; if (secretKey != null) { try { cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivps = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivps); } catch (Exception e) { throw new RuntimeException(e); } } int numWindows = 0; try { fis = new FileInputStream(file); //fis.skip(startOffset); gss = fis; if (secretKey != null) { try { /* Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); IvParameterSpec ivps = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivps); */ gss = new CipherInputStream(fis, cipher); } catch (Exception e) { throw new RuntimeException(e); } } long startOffset = 0; for (long offset : offsets) { // Skip initial case in case file is not yet created if (offset == 0) { continue; } long limit = offset - startOffset; LimitInputStream lis = new LimitInputStream(gss, limit); //gis = new GZIPInputStream(fis); gis = new GZIPInputStream(lis); br = new BufferedReader(new InputStreamReader(gis)); //br = new BufferedReader(new InputStreamReader(gss)); String eline = "" + (startVal + numWindows * 2); int count = 0; String line; while ((line = br.readLine()) != null) { Assert.assertEquals("File line", eline, line); ++count; if ((count % totalRecords) == 0) { ++numWindows; eline = "" + (startVal + numWindows * 2); } } startOffset = offset; } } catch (Exception e) { e.printStackTrace(); } finally { if (br != null) { br.close(); } else { if (gis != null) { gis.close(); } else if (gss != null) { gss.close(); } } } Assert.assertEquals("Total", totalWindows, numWindows); } @Test public void testChainFilters() throws NoSuchAlgorithmException, IOException { EvenOddHDFSExactlyOnceWriter writer = new EvenOddHDFSExactlyOnceWriter(); KeyGenerator keygen = KeyGenerator.getInstance("AES"); keygen.init(128); final SecretKey secretKey = keygen.generateKey(); byte[] iv = "TestParam16bytes".getBytes(); final IvParameterSpec ivps = new IvParameterSpec(iv); FilterStreamProvider.FilterChainStreamProvider<FilterOutputStream, OutputStream> chainStreamProvider = new FilterStreamProvider.FilterChainStreamProvider<FilterOutputStream, OutputStream>(); chainStreamProvider.addStreamProvider(new FilterStreamCodec.GZipFilterStreamProvider()); // The filter is to keep track of the offsets to handle multi member gzip issue with openjdk // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4691425 final CounterFilterStreamContext evenCounterContext = new CounterFilterStreamContext(); final CounterFilterStreamContext oddCounterContext = new CounterFilterStreamContext(); chainStreamProvider.addStreamProvider( new FilterStreamProvider.SimpleFilterReusableStreamProvider<CounterFilterOutputStream, OutputStream>() { @Override protected FilterStreamContext<CounterFilterOutputStream> createFilterStreamContext( OutputStream outputStream) throws IOException { if (evenCounterContext.isDoInit()) { evenCounterContext.init(outputStream); return evenCounterContext; } else { oddCounterContext.init(outputStream); return oddCounterContext; } } }); chainStreamProvider.addStreamProvider( new FilterStreamProvider.SimpleFilterReusableStreamProvider<CipherOutputStream, OutputStream>() { @Override protected FilterStreamContext<CipherOutputStream> createFilterStreamContext( OutputStream outputStream) throws IOException { try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivps); return new FilterStreamCodec.CipherFilterStreamContext(outputStream, cipher); } catch (Exception e) { throw new IOException(e); } } }); writer.setFilterStreamProvider(chainStreamProvider); File evenFile = new File(testMeta.getDir(), EVEN_FILE); File oddFile = new File(testMeta.getDir(), ODD_FILE); List<Long> evenOffsets = new ArrayList<Long>(); List<Long> oddOffsets = new ArrayList<Long>(); writer.setFilePath(testMeta.getDir()); writer.setAlwaysWriteToTmp(false); writer.setup(testMeta.testOperatorContext); for (int i = 0; i < 10; ++i) { writer.beginWindow(i); for (int j = 0; j < 1000; ++j) { writer.input.put(i); } writer.endWindow(); if ((i % 2) == 1) { writer.beforeCheckpoint(i); evenOffsets.add(evenCounterContext.getCounter()); oddOffsets.add(oddCounterContext.getCounter()); } } writer.teardown(); /* evenOffsets.add(evenFile.length()); oddOffsets.add(oddFile.length()); */ checkCompressedFile(evenFile, evenOffsets, 0, 5, 1000, secretKey, iv); checkCompressedFile(oddFile, oddOffsets, 1, 5, 1000, secretKey, iv); } private Set<String> getFileNames(Collection<File> files) { Set<String> filesNames = new TreeSet<String>(); for (File file : files) { filesNames.add(file.getName()); } return filesNames; } private static class CounterFilterStreamContext implements FilterStreamContext<CounterFilterOutputStream> { private CounterFilterOutputStream counterStream; public void init(OutputStream outputStream) { counterStream = new CounterFilterOutputStream(outputStream); } public boolean isDoInit() { return (counterStream == null); } @Override public CounterFilterOutputStream getFilterStream() { return counterStream; } @Override public void finalizeContext() throws IOException { } public long getCounter() { if (isDoInit()) { return 0; } else { return counterStream.getCounter(); } } } private static class CounterFilterOutputStream extends FilterOutputStream { long counter; int refCount; public CounterFilterOutputStream(OutputStream out) { super(out); } @Override public void write(int b) throws IOException { ++refCount; super.write(b); --refCount; if (refCount == 0) { counter += 1; } } @Override public void write(@Nonnull byte[] b) throws IOException { ++refCount; super.write(b); --refCount; if (refCount == 0) { counter += b.length; } } @Override public void write(@Nonnull byte[] b, int off, int len) throws IOException { ++refCount; super.write(b, off, len); --refCount; if (refCount == 0) { counter += len; } } public long getCounter() { return counter; } } }