This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-table-store.git
The following commit(s) were added to refs/heads/master by this push:
new 835632c6 [FLINK-29345] Create reusing reader/writer config in orc
format
835632c6 is described below
commit 835632c6e4758ad7d11ccbdb3a8ebb8dfa6aa709
Author: shammon <[email protected]>
AuthorDate: Wed Sep 21 11:37:28 2022 +0800
[FLINK-29345] Create reusing reader/writer config in orc format
This closes #296
---
.../store/format/orc/OrcBulkWriterFactory.java | 116 +++++++++++++++++++++
.../table/store/format/orc/OrcFileFormat.java | 35 ++++---
.../store/format/orc/OrcBulkWriterFactoryTest.java | 83 +++++++++++++++
.../table/store/format/orc/OrcFileFormatTest.java | 9 +-
4 files changed, 225 insertions(+), 18 deletions(-)
diff --git
a/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactory.java
b/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactory.java
new file mode 100644
index 00000000..b6670392
--- /dev/null
+++
b/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactory.java
@@ -0,0 +1,116 @@
+/*
+ * 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.flink.table.store.format.orc;
+
+import org.apache.flink.annotation.VisibleForTesting;
+import org.apache.flink.api.common.serialization.BulkWriter;
+import org.apache.flink.core.fs.FSDataOutputStream;
+import org.apache.flink.orc.vector.Vectorizer;
+import org.apache.flink.orc.writer.PhysicalWriterImpl;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
+import org.apache.orc.OrcFile;
+import org.apache.orc.Writer;
+import org.apache.orc.impl.WriterImpl;
+
+import java.io.IOException;
+import java.util.UUID;
+
+import static org.apache.flink.util.Preconditions.checkNotNull;
+
+/**
+ * Orc {@link BulkWriter.Factory}. The main code is copied from Flink {@code
OrcBulkWriterFactory}.
+ */
+public class OrcBulkWriterFactory<T> implements BulkWriter.Factory<T> {
+
+ private final Vectorizer<T> vectorizer;
+ private final OrcFile.WriterOptions writerOptions;
+
+ /**
+ * Creates a new OrcBulkWriterFactory using the provided Vectorizer, ORC
WriterOptions.
+ *
+ * @param vectorizer The vectorizer implementation to convert input record
to a
+ * VectorizerRowBatch.
+ * @param writerOptions ORC WriterOptions.
+ */
+ public OrcBulkWriterFactory(Vectorizer<T> vectorizer,
OrcFile.WriterOptions writerOptions) {
+ this.vectorizer = checkNotNull(vectorizer);
+ this.writerOptions = checkNotNull(writerOptions);
+ }
+
+ @Override
+ public BulkWriter<T> create(FSDataOutputStream out) throws IOException {
+ OrcFile.WriterOptions opts = getWriterOptions();
+ opts.physicalWriter(new PhysicalWriterImpl(out, opts));
+
+ // The path of the Writer is not used to indicate the destination file
+ // in this case since we have used a dedicated physical writer to write
+ // to the give output stream directly. However, the path would be used
as
+ // the key of writer in the ORC memory manager, thus we need to make
it unique.
+ Path unusedPath = new Path(UUID.randomUUID().toString());
+ return new OrcBulkWriter<>(vectorizer, new WriterImpl(null,
unusedPath, opts));
+ }
+
+ @VisibleForTesting
+ protected OrcFile.WriterOptions getWriterOptions() {
+ return writerOptions;
+ }
+
+ /** Orc {@link BulkWriter}. The main code is copied from Flink {@code
OrcBulkWriter}. */
+ private static class OrcBulkWriter<T> implements BulkWriter<T> {
+
+ private final Writer writer;
+ private final Vectorizer<T> vectorizer;
+ private final VectorizedRowBatch rowBatch;
+
+ OrcBulkWriter(Vectorizer<T> vectorizer, Writer writer) {
+ this.vectorizer = checkNotNull(vectorizer);
+ this.writer = checkNotNull(writer);
+ this.rowBatch = vectorizer.getSchema().createRowBatch();
+
+ // Configure the vectorizer with the writer so that users can add
+ // metadata on the fly through the Vectorizer#vectorize(...)
method.
+ this.vectorizer.setWriter(this.writer);
+ }
+
+ @Override
+ public void addElement(T element) throws IOException {
+ vectorizer.vectorize(element, rowBatch);
+ if (rowBatch.size == rowBatch.getMaxSize()) {
+ writer.addRowBatch(rowBatch);
+ rowBatch.reset();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (rowBatch.size != 0) {
+ writer.addRowBatch(rowBatch);
+ rowBatch.reset();
+ }
+ }
+
+ @Override
+ public void finish() throws IOException {
+ flush();
+ writer.close();
+ }
+ }
+}
diff --git
a/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcFileFormat.java
b/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcFileFormat.java
index 8b028210..9910409e 100644
---
a/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcFileFormat.java
+++
b/flink-table-store-format/src/main/java/org/apache/flink/table/store/format/orc/OrcFileFormat.java
@@ -27,7 +27,8 @@ import org.apache.flink.connector.file.src.reader.BulkFormat;
import org.apache.flink.orc.OrcFilters;
import org.apache.flink.orc.OrcSplitReaderUtil;
import org.apache.flink.orc.vector.RowDataVectorizer;
-import org.apache.flink.orc.writer.OrcBulkWriterFactory;
+import org.apache.flink.orc.vector.Vectorizer;
+import org.apache.flink.orc.writer.ThreadLocalClassLoaderConfiguration;
import org.apache.flink.table.data.RowData;
import org.apache.flink.table.store.file.predicate.Predicate;
import org.apache.flink.table.store.format.FileFormat;
@@ -36,6 +37,7 @@ import org.apache.flink.table.store.utils.Projection;
import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.RowType;
+import org.apache.orc.OrcFile;
import org.apache.orc.TypeDescription;
import javax.annotation.Nullable;
@@ -50,16 +52,24 @@ import static
org.apache.flink.table.store.format.orc.OrcFileFormatFactory.IDENT
/** Orc {@link FileFormat}. The main code is copied from Flink {@code
OrcFileFormatFactory}. */
public class OrcFileFormat extends FileFormat {
- private final Configuration formatOptions;
+ private final Properties orcProperties;
+ private final org.apache.hadoop.conf.Configuration readerConf;
+ private final org.apache.hadoop.conf.Configuration writerConf;
public OrcFileFormat(Configuration formatOptions) {
super(org.apache.flink.orc.OrcFileFormatFactory.IDENTIFIER);
- this.formatOptions = formatOptions;
+ this.orcProperties = getOrcProperties(formatOptions);
+ this.readerConf = new org.apache.hadoop.conf.Configuration();
+ this.orcProperties.forEach((k, v) -> readerConf.set(k.toString(),
v.toString()));
+
+ org.apache.hadoop.conf.Configuration conf = new
org.apache.hadoop.conf.Configuration();
+ this.writerConf = new ThreadLocalClassLoaderConfiguration();
+ conf.forEach(entry -> writerConf.set(entry.getKey(),
entry.getValue()));
}
@VisibleForTesting
- Configuration formatOptions() {
- return formatOptions;
+ Properties orcProperties() {
+ return orcProperties;
}
@Override
@@ -81,12 +91,8 @@ public class OrcFileFormat extends FileFormat {
}
}
- Properties properties = getOrcProperties(formatOptions);
- org.apache.hadoop.conf.Configuration conf = new
org.apache.hadoop.conf.Configuration();
- properties.forEach((k, v) -> conf.set(k.toString(), v.toString()));
-
return OrcInputFormatFactory.create(
- conf, type, Projection.of(projection).toTopLevelIndexes(),
orcPredicates);
+ readerConf, type,
Projection.of(projection).toTopLevelIndexes(), orcPredicates);
}
@Override
@@ -94,11 +100,12 @@ public class OrcFileFormat extends FileFormat {
LogicalType[] orcTypes = type.getChildren().toArray(new
LogicalType[0]);
TypeDescription typeDescription =
OrcSplitReaderUtil.logicalTypeToOrcType(type);
+ Vectorizer<RowData> vectorizer =
+ new RowDataVectorizer(typeDescription.toString(), orcTypes);
+ OrcFile.WriterOptions writerOptions =
OrcFile.writerOptions(orcProperties, writerConf);
+ writerOptions.setSchema(vectorizer.getSchema());
- return new OrcBulkWriterFactory<>(
- new RowDataVectorizer(typeDescription.toString(), orcTypes),
- getOrcProperties(formatOptions),
- new org.apache.hadoop.conf.Configuration());
+ return new OrcBulkWriterFactory<>(vectorizer, writerOptions);
}
private static Properties getOrcProperties(ReadableConfig options) {
diff --git
a/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactoryTest.java
b/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactoryTest.java
new file mode 100644
index 00000000..374bc1c6
--- /dev/null
+++
b/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcBulkWriterFactoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.flink.table.store.format.orc;
+
+import org.apache.flink.configuration.Configuration;
+import org.apache.flink.core.fs.local.LocalDataOutputStream;
+import org.apache.flink.table.data.RowData;
+import org.apache.flink.table.types.logical.IntType;
+import org.apache.flink.table.types.logical.RowType;
+import org.apache.flink.table.types.logical.VarCharType;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.orc.MemoryManager;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+/** Test for {@link OrcBulkWriterFactory}. */
+public class OrcBulkWriterFactoryTest {
+ @TempDir File tempDir;
+
+ @Test
+ public void testNotOverrideInMemoryManager() throws IOException {
+ OrcFileFormat orcFileFormat = new OrcFileFormat(new Configuration());
+ OrcBulkWriterFactory<RowData> factory =
+ (OrcBulkWriterFactory<RowData>)
+ orcFileFormat.createWriterFactory(
+ RowType.of(new VarCharType(), new IntType()));
+
+ TestMemoryManager memoryManager = new TestMemoryManager();
+ factory.getWriterOptions().memory(memoryManager);
+
+ factory.create(new LocalDataOutputStream(new File(tempDir,
UUID.randomUUID().toString())));
+ factory.create(new LocalDataOutputStream(new File(tempDir,
UUID.randomUUID().toString())));
+
+ List<Path> addedWriterPath = memoryManager.getAddedWriterPath();
+ assertEquals(2, addedWriterPath.size());
+ assertNotEquals(addedWriterPath.get(1), addedWriterPath.get(0));
+ }
+
+ private static class TestMemoryManager implements MemoryManager {
+ private final List<Path> addedWriterPath = new ArrayList<>();
+
+ @Override
+ public void addWriter(Path path, long requestedAllocation, Callback
callback) {
+ addedWriterPath.add(path);
+ }
+
+ public List<Path> getAddedWriterPath() {
+ return addedWriterPath;
+ }
+
+ @Override
+ public void removeWriter(Path path) {}
+
+ @Override
+ public void addedRow(int rows) {}
+ }
+}
diff --git
a/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcFileFormatTest.java
b/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcFileFormatTest.java
index b99d337f..ba1dbacb 100644
---
a/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcFileFormatTest.java
+++
b/flink-table-store-format/src/test/java/org/apache/flink/table/store/format/orc/OrcFileFormatTest.java
@@ -22,6 +22,7 @@ import org.apache.flink.configuration.Configuration;
import org.junit.jupiter.api.Test;
+import static
org.apache.flink.table.store.format.orc.OrcFileFormatFactory.IDENTIFIER;
import static org.assertj.core.api.Assertions.assertThat;
/** Test for {@link OrcFileFormatFactory}. */
@@ -32,8 +33,8 @@ public class OrcFileFormatTest {
Configuration options = new Configuration();
options.setString("haha", "1");
OrcFileFormat orc = new OrcFileFormatFactory().create(options);
- assertThat(orc.formatOptions().getString("haha", "")).isEqualTo("1");
- assertThat(orc.formatOptions().getString("compress",
"")).isEqualTo("lz4");
+ assertThat(orc.orcProperties().getProperty(IDENTIFIER + ".haha",
"")).isEqualTo("1");
+ assertThat(orc.orcProperties().getProperty(IDENTIFIER + ".compress",
"")).isEqualTo("lz4");
}
@Test
@@ -42,7 +43,7 @@ public class OrcFileFormatTest {
options.setString("haha", "1");
options.setString("compress", "zlib");
OrcFileFormat orc = new OrcFileFormatFactory().create(options);
- assertThat(orc.formatOptions().getString("haha", "")).isEqualTo("1");
- assertThat(orc.formatOptions().getString("compress",
"")).isEqualTo("zlib");
+ assertThat(orc.orcProperties().getProperty(IDENTIFIER + ".haha",
"")).isEqualTo("1");
+ assertThat(orc.orcProperties().getProperty(IDENTIFIER + ".compress",
"")).isEqualTo("zlib");
}
}