Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,28 @@ public SELF withBloomFilterEnabled(String columnPath, boolean enabled) {
return self();
}

/**
* Sets the minimum number of rows to write before a page size check is done.
*
* @param min writes at least `min` rows before invoking a page size check
* @return this builder for method chaining
*/
public SELF withMinRowCountForPageSizeCheck(int min) {
encodingPropsBuilder.withMinRowCountForPageSizeCheck(min);
return self();
}

/**
* Sets the maximum number of rows to write before a page size check is done.
*
* @param max makes a page size check after `max` rows have been written
* @return this builder for method chaining
*/
public SELF withMaxRowCountForPageSizeCheck(int max) {
encodingPropsBuilder.withMaxRowCountForPageSizeCheck(max);
return self();
}

/**
* Set a property that will be available to the read path. For writers that use a Hadoop
* configuration, this is the recommended way to add configuration values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,22 @@
import static org.apache.parquet.schema.MessageTypeParser.parseMessageType;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

import net.openhft.hashing.LongHashFunction;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.parquet.column.values.bloomfilter.BloomFilter;
import org.apache.parquet.example.data.GroupFactory;
import org.apache.parquet.hadoop.example.ExampleParquetWriter;
import org.apache.parquet.hadoop.util.HadoopInputFile;
import org.apache.parquet.hadoop.util.HadoopOutputFile;
import org.apache.parquet.hadoop.util.HadoopStreams;
import org.apache.parquet.schema.GroupType;
import org.apache.parquet.schema.InvalidSchemaException;
import org.apache.parquet.schema.Types;
Expand Down Expand Up @@ -77,32 +80,35 @@ public class TestParquetWriter {
/**
* A test OutputFile implementation to validate the scenario of an OutputFile is implemented by an API client.
*/
private static class TestOutputFile implements OutputFile {
private class TestOutputFile implements OutputFile {

private final OutputFile outputFile;
private final File file;
private final FileSystem.Statistics stats;

TestOutputFile(Path path, Configuration conf) throws IOException {
outputFile = HadoopOutputFile.fromPath(path, conf);
TestOutputFile() throws IOException {
this.file = temp.newFile();
this.stats = new FileSystem.Statistics("TestParquetWriter");
}

@Override
public PositionOutputStream create(long blockSizeHint) throws IOException {
return outputFile.create(blockSizeHint);
return createOrOverwrite(blockSizeHint);
}

@Override
public PositionOutputStream createOrOverwrite(long blockSizeHint) throws IOException {
return outputFile.createOrOverwrite(blockSizeHint);
FileOutputStream fos = new FileOutputStream(file);
return HadoopStreams.wrap(new FSDataOutputStream(fos, this.stats));
}

@Override
public boolean supportsBlockSize() {
return outputFile.supportsBlockSize();
return false;
}

@Override
public long defaultBlockSize() {
return outputFile.defaultBlockSize();
return 0;
}
}

Expand Down Expand Up @@ -132,7 +138,7 @@ public void test() throws Exception {
for (int modulo : asList(10, 1000)) {
for (WriterVersion version : WriterVersion.values()) {
Path file = new Path(root, version.name() + "_" + modulo);
ParquetWriter<Group> writer = ExampleParquetWriter.builder(new TestOutputFile(file, conf))
ParquetWriter<Group> writer = ExampleParquetWriter.builder(file)
.withCompressionCodec(UNCOMPRESSED)
.withRowGroupSize(1024)
.withPageSize(1024)
Expand Down Expand Up @@ -279,4 +285,133 @@ public void testParquetFileWithBloomFilter() throws IOException {
LongHashFunction.xx(0).hashBytes(Binary.fromString(name).toByteBuffer())));
}
}

@Test
public void testParquetFileNotFlushedWhenRowCountLimitsAreNotExceeded() throws IOException {
MessageType schema = Types
.buildMessage()
.required(BINARY)
.as(stringType())
.named("str")
.named("msg");

TestOutputFile file = new TestOutputFile();
ParquetWriter<Group> writer = getParquetWriterBuilder(schema, file)
.withMinRowCountForPageSizeCheck(4)
.withMaxRowCountForPageSizeCheck(4)
.build();

writeRecords(writer, schema);
assertHasNotFlushed(file);
}

@Test
public void testParquetFileIsFlushedWhenMinRowCountIsExceeded() throws IOException {
MessageType schema = Types
.buildMessage()
.required(BINARY)
.as(stringType())
.named("str")
.named("msg");

TestOutputFile file = new TestOutputFile();
ParquetWriter<Group> writer = getParquetWriterBuilder(schema, file)
.withMinRowCountForPageSizeCheck(3)
.withMaxRowCountForPageSizeCheck(4)
.build();

writeRecords(writer, schema);

assertHasFlushed(file, 3, 1);
}

@Test
public void testParquetFileIsNotFlushedIfMinRowCountIsNotExceeded() throws IOException {
MessageType schema = Types
.buildMessage()
.required(BINARY)
.as(stringType())
.named("str")
.named("msg");

TestOutputFile file = new TestOutputFile();
ParquetWriter<Group> writer = getParquetWriterBuilder(schema, file)
.withMinRowCountForPageSizeCheck(4)
.withMaxRowCountForPageSizeCheck(2)
.build();

writeRecords(writer, schema);

assertHasNotFlushed(file);
}

@Test
public void testParquetFileIsFlushedAfterEachRecord() throws IOException {
Comment thread
Miksu82 marked this conversation as resolved.
Outdated
MessageType schema = Types
.buildMessage()
.required(BINARY)
.as(stringType())
.named("str")
.named("msg");

TestOutputFile file = new TestOutputFile();
ParquetWriter<Group> writer = getParquetWriterBuilder(schema, file)
.withMinRowCountForPageSizeCheck(1)
.withMaxRowCountForPageSizeCheck(4)
.build();

writeRecords(writer, schema);

assertHasFlushed(file, 3, 3);
}

@Test
public void testParquetFileNotFlushingAllRows() throws IOException {
MessageType schema = Types
.buildMessage()
.required(BINARY)
.as(stringType())
.named("str")
.named("msg");

TestOutputFile file = new TestOutputFile();
ParquetWriter<Group> writer = getParquetWriterBuilder(schema, file)
.withMinRowCountForPageSizeCheck(2)
.withMaxRowCountForPageSizeCheck(3)
.build();

writeRecords(writer, schema);

assertHasFlushed(file, 2, 1);
}

private ExampleParquetWriter.Builder getParquetWriterBuilder(MessageType schema,
TestOutputFile file) throws IOException {
Configuration conf = new Configuration();
GroupWriteSupport.setSchema(schema, conf);
return ExampleParquetWriter.builder(file)
.withConf(conf)
// Set row group size to 1, to make sure we flush every time
// minRowCountForPageSizeCheck or maxRowCountForPageSizeCheck is exceeded
.withRowGroupSize(1);
}

private void writeRecords(ParquetWriter<Group> writer, MessageType schema) throws IOException {
SimpleGroupFactory factory = new SimpleGroupFactory(schema);
writer.write(factory.newGroup().append("str", "foo"));
writer.write(factory.newGroup().append("str", "bar"));
writer.write(factory.newGroup().append("str", "baz"));
}

private void assertHasNotFlushed(TestOutputFile file) {
int emptyFileLength = ParquetFileWriter.MAGIC.length;
assertEquals(emptyFileLength, file.stats.getBytesWritten());
}

private void assertHasFlushed(TestOutputFile file, int numWrites, int numFlushes) {
Comment thread
Miksu82 marked this conversation as resolved.
Outdated
int emptyFileLength = ParquetFileWriter.MAGIC.length;
// Each write in "writerRecords" writes 7B, and every flush writers 23B
assertEquals(emptyFileLength + 7L * numWrites + 23L * numFlushes,
file.stats.getBytesWritten());
}
}