This is an automated email from the ASF dual-hosted git repository.
lgbo-ustc pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gluten.git
The following commit(s) were added to refs/heads/main by this push:
new 9202345c23 [GLUTEN-10246][FLINK] Support processing time
window(tumble) for nextmark q12 (#10898)
9202345c23 is described below
commit 9202345c23fec9e62f516bde51a07b09f4d58ef6
Author: kevinyhzou <[email protected]>
AuthorDate: Wed Jun 10 09:39:04 2026 +0800
[GLUTEN-10246][FLINK] Support processing time window(tumble) for nextmark
q12 (#10898)
* support proctime window
* remove useless changes
* remove useless changes
* support kafka data source
* fix reviews
* optimize code
* fix memory leak
* merge master
* xxx
* support proc time window
* remove useless code
* fix ut
* restore q5,q7,q8 tests
* Fix tz download failure
* fix ci
* update velox4j version
---
.github/workflows/flink.yml | 12 ++-
gluten-flink/docs/Flink.md | 2 +-
.../stream/StreamExecGlobalWindowAggregate.java | 85 ++++++----------
.../stream/StreamExecLocalWindowAggregate.java | 5 +-
.../exec/stream/StreamExecWindowAggregate.java | 42 +++++---
.../org/apache/gluten/rexnode/WindowUtils.java | 31 +++++-
.../gluten/client/OffloadedJobGraphGenerator.java | 10 +-
.../operators/GlutenOneInputOperatorFactory.java | 6 ++
.../streaming/api/operators/GlutenOperator.java | 45 +++++++++
.../runtime/tasks/GlutenOutputCollector.java | 3 -
.../table/runtime/config/VeloxQueryConfig.java | 3 +
.../runtime/operators/GlutenMailboxHolder.java} | 30 +++---
.../operators/GlutenMailboxOperatorHelper.java | 108 +++++++++++++++++++++
.../runtime/operators/GlutenOneInputOperator.java | 78 +++++++++------
...onResource.java => GlutenSessionResources.java} | 41 ++++++++
.../runtime/operators/GlutenSourceFunction.java | 3 +-
.../runtime/operators/GlutenTwoInputOperator.java | 41 ++++++--
.../table/runtime/operators/WindowAggOperator.java | 4 +-
.../typeutils/GlutenStatefulRecordSerializer.java | 56 ++++-------
19 files changed, 431 insertions(+), 174 deletions(-)
diff --git a/.github/workflows/flink.yml b/.github/workflows/flink.yml
index b53a8f62c5..cf607f5f30 100644
--- a/.github/workflows/flink.yml
+++ b/.github/workflows/flink.yml
@@ -59,10 +59,18 @@ jobs:
run: |
source /opt/rh/gcc-toolset-11/enable
sudo dnf install -y patchelf
- sudo yum install
https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/Packages/tzdata-2025a-1.el9.noarch.rpm
-y
+ sudo yum install
https://mirror.stream.centos.org/9-stream/BaseOS/x86_64/os/Packages/tzdata-2026a-1.el9.noarch.rpm
-y
sudo .github/workflows/util/install-flink-deps.sh
+ # Remove system fmt v11 from the CI image to avoid header conflicts
with
+ # velox bundled fmt 10.x during folly/velox native compilation.
+ sudo rm -rf /usr/local/include/fmt
+ sudo rm -rf /usr/local/lib/cmake/fmt
+ sudo rm -f /usr/local/lib/libfmt* /usr/local/lib64/libfmt*
+ export VELOX_DEPENDENCY_SOURCE=BUNDLED
+ export fmt_SOURCE=BUNDLED
+ export folly_SOURCE=BUNDLED
git clone -b gluten-0530 https://github.com/bigo-sg/velox4j.git
- cd velox4j && git reset --hard
889bafcf2fa04e8c31a30edbdf40fe203ef58484
+ cd velox4j && git reset --hard
115edf79d265a61c30d45dfcc6ce932ad92378ca
git apply $GITHUB_WORKSPACE/gluten-flink/patches/fix-velox4j.patch
$GITHUB_WORKSPACE/build/mvn clean install -DskipTests -Dgpg.skip
-Dspotless.skip=true
cd ..
diff --git a/gluten-flink/docs/Flink.md b/gluten-flink/docs/Flink.md
index 1c800fb42d..ba8f4ec1dc 100644
--- a/gluten-flink/docs/Flink.md
+++ b/gluten-flink/docs/Flink.md
@@ -48,7 +48,7 @@ As some features have not been committed to upstream, you
have to use the follow
## fetch velox4j code
git clone -b gluten-0530 https://github.com/bigo-sg/velox4j.git
cd velox4j
-git reset --hard 889bafcf2fa04e8c31a30edbdf40fe203ef58484
+git reset --hard 115edf79d265a61c30d45dfcc6ce932ad92378ca
mvn clean install -DskipTests -Dgpg.skip -Dspotless.skip=true
```
**Get gluten**
diff --git
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecGlobalWindowAggregate.java
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecGlobalWindowAggregate.java
index 9cbc017232..e5dca4ee8d 100644
---
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecGlobalWindowAggregate.java
+++
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecGlobalWindowAggregate.java
@@ -19,7 +19,6 @@ package org.apache.flink.table.planner.plan.nodes.exec.stream;
import org.apache.gluten.rexnode.AggregateCallConverter;
import org.apache.gluten.rexnode.Utils;
import org.apache.gluten.rexnode.WindowUtils;
-import org.apache.gluten.table.runtime.operators.GlutenOneInputOperator;
import org.apache.gluten.util.LogicalTypeConverter;
import org.apache.gluten.util.PlanNodeIdGenerator;
@@ -37,14 +36,13 @@ import
io.github.zhztheplayer.velox4j.plan.StreamWindowPartitionFunctionSpec;
import org.apache.flink.FlinkVersion;
import org.apache.flink.api.dag.Transformation;
+import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple5;
import org.apache.flink.configuration.ReadableConfig;
import org.apache.flink.streaming.api.operators.OneInputStreamOperator;
import org.apache.flink.streaming.api.operators.SimpleOperatorFactory;
import org.apache.flink.streaming.api.transformations.OneInputTransformation;
import org.apache.flink.table.data.RowData;
-import org.apache.flink.table.planner.codegen.CodeGeneratorContext;
-import org.apache.flink.table.planner.codegen.agg.AggsHandlerCodeGenerator;
import org.apache.flink.table.planner.delegation.PlannerBase;
import org.apache.flink.table.planner.plan.logical.WindowingStrategy;
import org.apache.flink.table.planner.plan.nodes.exec.ExecEdge;
@@ -55,24 +53,21 @@ import
org.apache.flink.table.planner.plan.nodes.exec.ExecNodeMetadata;
import org.apache.flink.table.planner.plan.nodes.exec.InputProperty;
import org.apache.flink.table.planner.plan.nodes.exec.utils.ExecNodeUtil;
import org.apache.flink.table.planner.plan.utils.AggregateInfoList;
+import org.apache.flink.table.planner.plan.utils.AggregateUtil;
import org.apache.flink.table.planner.plan.utils.KeySelectorUtil;
import org.apache.flink.table.planner.utils.JavaScalaConversionUtil;
import org.apache.flink.table.planner.utils.TableConfigUtils;
-import
org.apache.flink.table.runtime.generated.GeneratedNamespaceAggsHandleFunction;
import org.apache.flink.table.runtime.groupwindow.NamedWindowProperty;
-import org.apache.flink.table.runtime.groupwindow.WindowProperty;
import org.apache.flink.table.runtime.keyselector.RowDataKeySelector;
-import
org.apache.flink.table.runtime.operators.window.tvf.slicing.SliceAssigner;
import org.apache.flink.table.runtime.typeutils.InternalTypeInfo;
import org.apache.flink.table.runtime.util.TimeWindowUtil;
-import org.apache.flink.table.types.DataType;
+import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.RowType;
import
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
import
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.calcite.rel.core.AggregateCall;
-import org.apache.calcite.tools.RelBuilder;
import org.apache.commons.math3.util.ArithmeticUtils;
import javax.annotation.Nullable;
@@ -184,6 +179,14 @@ public class StreamExecGlobalWindowAggregate extends
StreamExecWindowAggregateBa
final ZoneId shiftTimeZone =
TimeWindowUtil.getShiftTimeZone(
windowing.getTimeAttributeType(),
TableConfigUtils.getLocalTimeZone(config));
+ final AggregateInfoList globalAggInfoList =
+ AggregateUtil.deriveStreamWindowAggregateInfoList(
+ planner.getTypeFactory(),
+ localAggInputRowType, // should use original input here
+ JavaScalaConversionUtil.toScala(Arrays.asList(aggCalls)),
+ needRetraction,
+ windowing.getWindow(),
+ true);
// --- Begin Gluten-specific code changes ---
// TODO: velox window not equal to flink window.
@@ -205,11 +208,15 @@ public class StreamExecGlobalWindowAggregate extends
StreamExecWindowAggregateBa
// TODO: support more window types.
Tuple5<Long, Long, Long, Integer, Integer> windowSpecParams =
WindowUtils.extractWindowParameters(windowing);
+ Tuple2<Integer, Integer> windowStartAndEndIndexes =
+ WindowUtils.getWindowStartAndEndIndexes(namedWindowProperties,
(RowType) getOutputType());
long size = windowSpecParams.f0;
long slide = windowSpecParams.f1;
long offset = windowSpecParams.f2;
int rowtimeIndex = windowSpecParams.f3;
int windowType = windowSpecParams.f4;
+ int windowStartIndex = windowStartAndEndIndexes.f0;
+ int windowEndIndex = windowStartAndEndIndexes.f1;
PartitionFunctionSpec sliceAssignerSpec =
new StreamWindowPartitionFunctionSpec(
inputType, rowtimeIndex, size, slide, offset, windowType);
@@ -252,24 +259,30 @@ public class StreamExecGlobalWindowAggregate extends
StreamExecWindowAggregateBa
offset,
windowType,
outputType,
- rowtimeIndex);
- final OneInputStreamOperator windowOperator =
- new GlutenOneInputOperator(
+ true,
+ rowtimeIndex,
+ windowStartIndex,
+ windowEndIndex);
+ final LogicalType[] accTypes =
convertToLogicalTypes(globalAggInfoList.getAccTypes());
+ final RowDataKeySelector selector =
+ KeySelectorUtil.getRowDataSelector(
+ planner.getFlinkContext().getClassLoader(),
+ grouping,
+ InternalTypeInfo.of(inputRowType));
+ final OneInputStreamOperator<RowData, RowData> windowOperator =
+ new
org.apache.gluten.table.runtime.operators.WindowAggOperator<RowData, RowData,
Long>(
new StatefulPlanNode(windowAgg.getId(), windowAgg),
PlanNodeIdGenerator.newId(),
inputType,
Map.of(windowAgg.getId(), outputType),
RowData.class,
RowData.class,
- "StreamExecGlobalWindowAggregate");
+ "StreamExecWindowAggregate",
+ selector.getProducedType(),
+ globalAggInfoList.getAggNames(),
+ accTypes);
// --- End Gluten-specific code changes ---
- final RowDataKeySelector selector =
- KeySelectorUtil.getRowDataSelector(
- planner.getFlinkContext().getClassLoader(),
- grouping,
- InternalTypeInfo.of(inputRowType));
-
final OneInputTransformation<RowData, RowData> transform =
ExecNodeUtil.createOneInputTransformation(
inputTransform,
@@ -285,40 +298,4 @@ public class StreamExecGlobalWindowAggregate extends
StreamExecWindowAggregateBa
transform.setStateKeyType(selector.getProducedType());
return transform;
}
-
- private GeneratedNamespaceAggsHandleFunction<Long> createAggsHandler(
- String name,
- SliceAssigner sliceAssigner,
- AggregateInfoList aggInfoList,
- int mergedAccOffset,
- boolean mergedAccIsOnHeap,
- DataType[] mergedAccExternalTypes,
- ExecNodeConfig config,
- ClassLoader classLoader,
- RelBuilder relBuilder,
- ZoneId shifTimeZone) {
- final AggsHandlerCodeGenerator generator =
- new AggsHandlerCodeGenerator(
- new CodeGeneratorContext(config, classLoader),
- relBuilder,
-
JavaScalaConversionUtil.toScala(localAggInputRowType.getChildren()),
- true) // copyInputField
- .needAccumulate()
- .needMerge(mergedAccOffset, mergedAccIsOnHeap,
mergedAccExternalTypes);
-
- final List<WindowProperty> windowProperties =
- Arrays.asList(
- Arrays.stream(namedWindowProperties)
- .map(NamedWindowProperty::getProperty)
- .toArray(WindowProperty[]::new));
-
- return generator.generateNamespaceAggsHandler(
- name,
- aggInfoList,
- JavaScalaConversionUtil.toScala(windowProperties),
- sliceAssigner,
- // we use window end timestamp to indicate a slicing window, see
SliceAssigner
- Long.class,
- shifTimeZone);
- }
}
diff --git
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecLocalWindowAggregate.java
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecLocalWindowAggregate.java
index fd0cc04a30..d67d61709e 100644
---
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecLocalWindowAggregate.java
+++
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecLocalWindowAggregate.java
@@ -220,7 +220,10 @@ public class StreamExecLocalWindowAggregate extends
StreamExecWindowAggregateBas
offset,
windowType,
outputType,
- rowtimeIndex);
+ false,
+ rowtimeIndex,
+ -1,
+ -1);
final OneInputStreamOperator localAggOperator =
new GlutenOneInputOperator(
new StatefulPlanNode(windowAgg.getId(), windowAgg),
diff --git
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecWindowAggregate.java
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecWindowAggregate.java
index 93e0703986..28b78687f6 100644
---
a/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecWindowAggregate.java
+++
b/gluten-flink/planner/src/main/java/org/apache/flink/table/planner/plan/nodes/exec/stream/StreamExecWindowAggregate.java
@@ -36,6 +36,7 @@ import
io.github.zhztheplayer.velox4j.plan.StreamWindowPartitionFunctionSpec;
import org.apache.flink.FlinkVersion;
import org.apache.flink.api.dag.Transformation;
+import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple5;
import org.apache.flink.configuration.ReadableConfig;
import org.apache.flink.streaming.api.operators.OneInputStreamOperator;
@@ -208,11 +209,16 @@ public class StreamExecWindowAggregate extends
StreamExecWindowAggregateBase {
// TODO: support more window types.
Tuple5<Long, Long, Long, Integer, Integer> windowSpecParams =
WindowUtils.extractWindowParameters(windowing);
+ Tuple2<Integer, Integer> windowStartAndEndIndexes =
+ WindowUtils.getWindowStartAndEndIndexes(namedWindowProperties,
(RowType) getOutputType());
long size = windowSpecParams.f0;
long slide = windowSpecParams.f1;
long offset = windowSpecParams.f2;
int rowtimeIndex = windowSpecParams.f3;
int windowType = windowSpecParams.f4;
+ boolean isRowTime = windowing.isRowtime();
+ int windowStartIndex = windowStartAndEndIndexes.f0;
+ int windowEndIndex = windowStartAndEndIndexes.f1;
PartitionFunctionSpec sliceAssignerSpec =
new StreamWindowPartitionFunctionSpec(
inputType, rowtimeIndex, size, slide, offset, windowType);
@@ -221,25 +227,29 @@ public class StreamExecWindowAggregate extends
StreamExecWindowAggregateBase {
PlanNodeIdGenerator.newId(),
AggregateStep.SINGLE,
groupingKeys,
- groupingKeys,
+ isRowTime ? groupingKeys : List.of(),
aggNames,
aggregates,
false,
List.of(new EmptyNode(inputType)),
null,
List.of());
+ // processing time window can not apply to local-global aggregate
optimization, so here we need
+ // to set local aggregtate as null when it is not event time window.
PlanNode localAgg =
- new AggregationNode(
- PlanNodeIdGenerator.newId(),
- AggregateStep.SINGLE,
- groupingKeys,
- groupingKeys,
- aggNames,
- aggregates,
- false,
- List.of(new EmptyNode(inputType)),
- null,
- List.of());
+ isRowTime
+ ? new AggregationNode(
+ PlanNodeIdGenerator.newId(),
+ AggregateStep.SINGLE,
+ groupingKeys,
+ groupingKeys,
+ aggNames,
+ aggregates,
+ false,
+ List.of(new EmptyNode(inputType)),
+ null,
+ List.of())
+ : null;
PlanNode windowAgg =
new StreamWindowAggregationNode(
PlanNodeIdGenerator.newId(),
@@ -255,7 +265,10 @@ public class StreamExecWindowAggregate extends
StreamExecWindowAggregateBase {
offset,
windowType,
outputType,
- rowtimeIndex);
+ windowing.isRowtime(),
+ rowtimeIndex,
+ windowStartIndex,
+ windowEndIndex);
final RowDataKeySelector selector =
KeySelectorUtil.getRowDataSelector(
planner.getFlinkContext().getClassLoader(),
@@ -266,6 +279,9 @@ public class StreamExecWindowAggregate extends
StreamExecWindowAggregateBase {
.map(x -> x.getLogicalType())
.collect(Collectors.toList())
.toArray(new LogicalType[] {});
+ // For TVF windows (Tumbling, Hopping, Cumulative, Session), the window
namespace
+ // is identified by the window end timestamp (Long). If count-based
windows are
+ // supported in the future, a different serializer may be needed.
final OneInputStreamOperator<RowData, RowData> windowOperator =
new
org.apache.gluten.table.runtime.operators.WindowAggOperator<RowData, RowData,
Long>(
new StatefulPlanNode(windowAgg.getId(), windowAgg),
diff --git
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/WindowUtils.java
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/WindowUtils.java
index 6f7a64f6f4..021969f2a2 100644
---
a/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/WindowUtils.java
+++
b/gluten-flink/planner/src/main/java/org/apache/gluten/rexnode/WindowUtils.java
@@ -16,16 +16,24 @@
*/
package org.apache.gluten.rexnode;
+import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple5;
+import org.apache.flink.table.planner.plan.logical.CumulativeWindowSpec;
import org.apache.flink.table.planner.plan.logical.HoppingWindowSpec;
+import org.apache.flink.table.planner.plan.logical.SessionWindowSpec;
import
org.apache.flink.table.planner.plan.logical.SliceAttachedWindowingStrategy;
import
org.apache.flink.table.planner.plan.logical.TimeAttributeWindowingStrategy;
import org.apache.flink.table.planner.plan.logical.TumblingWindowSpec;
import
org.apache.flink.table.planner.plan.logical.WindowAttachedWindowingStrategy;
import org.apache.flink.table.planner.plan.logical.WindowSpec;
import org.apache.flink.table.planner.plan.logical.WindowingStrategy;
+import org.apache.flink.table.runtime.groupwindow.NamedWindowProperty;
+import org.apache.flink.table.runtime.groupwindow.WindowEnd;
+import org.apache.flink.table.runtime.groupwindow.WindowStart;
+import org.apache.flink.table.types.logical.RowType;
import java.time.Duration;
+import java.util.List;
/** Utility to store some useful functions. */
public class WindowUtils {
@@ -53,24 +61,27 @@ public class WindowUtils {
if (windowOffset != null) {
offset = windowOffset.toMillis();
}
+ windowType = 0;
} else if (windowSpec instanceof TumblingWindowSpec) {
size = ((TumblingWindowSpec) windowSpec).getSize().toMillis();
Duration windowOffset = ((TumblingWindowSpec) windowSpec).getOffset();
if (windowOffset != null) {
offset = windowOffset.toMillis();
}
+ windowType = 1;
+ } else if (windowSpec instanceof CumulativeWindowSpec) {
+ windowType = 2;
+ } else if (windowSpec instanceof SessionWindowSpec) {
+ windowType = 3;
} else {
throw new RuntimeException("Not support window spec " + windowSpec);
}
-
if (windowing instanceof TimeAttributeWindowingStrategy) {
if (windowing.isRowtime()) {
rowtimeIndex = ((TimeAttributeWindowingStrategy)
windowing).getTimeAttributeIndex();
}
- windowType = 0;
} else if (windowing instanceof WindowAttachedWindowingStrategy) {
rowtimeIndex = ((WindowAttachedWindowingStrategy)
windowing).getWindowEnd();
- windowType = 1;
} else if (windowing instanceof SliceAttachedWindowingStrategy) {
rowtimeIndex = ((SliceAttachedWindowingStrategy)
windowing).getSliceEnd();
} else {
@@ -79,4 +90,18 @@ public class WindowUtils {
return new Tuple5<Long, Long, Long, Integer, Integer>(
size, slide, offset, rowtimeIndex, windowType);
}
+
+ public static Tuple2<Integer, Integer> getWindowStartAndEndIndexes(
+ NamedWindowProperty[] props, RowType outputType) {
+ int windowStartIndex = -1, windowEndIndex = -1;
+ List<String> outputNames = outputType.getFieldNames();
+ for (NamedWindowProperty prop : props) {
+ if (prop.getProperty() instanceof WindowStart) {
+ windowStartIndex = outputNames.indexOf(prop.getName());
+ } else if (prop.getProperty() instanceof WindowEnd) {
+ windowEndIndex = outputNames.indexOf(prop.getName());
+ }
+ }
+ return new Tuple2<Integer, Integer>(windowStartIndex, windowEndIndex);
+ }
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/client/OffloadedJobGraphGenerator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/client/OffloadedJobGraphGenerator.java
index 42784fce28..27dc0b1933 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/client/OffloadedJobGraphGenerator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/client/OffloadedJobGraphGenerator.java
@@ -240,7 +240,7 @@ public class OffloadedJobGraphGenerator {
Class<?> inClass = supportsVectorInput ? StatefulRecord.class :
RowData.class;
Class<?> outClass = supportsVectorOutput ? StatefulRecord.class :
RowData.class;
GlutenOneInputOperator<?, ?> newOneInputOp =
- sourceOperator.cloneWithInputOutputClasses(inClass, outClass);
+ sourceOperator.cloneWithInputOutputClasses(planNode, inClass,
outClass);
offloadedOpConfig.setStreamOperator(newOneInputOp);
if (supportsVectorOutput) {
setOffloadedOutputSerializer(offloadedOpConfig, sourceOperator);
@@ -292,19 +292,19 @@ public class OffloadedJobGraphGenerator {
private void setOffloadedOutputSerializer(StreamConfig opConfig,
GlutenOperator operator) {
RowType rowType =
operator.getOutputTypes().entrySet().iterator().next().getValue();
- opConfig.setTypeSerializerOut(new GlutenStatefulRecordSerializer(rowType,
operator.getId()));
+ opConfig.setTypeSerializerOut(new GlutenStatefulRecordSerializer(rowType,
operator));
}
private void setOffloadedInputSerializer(StreamConfig opConfig,
GlutenOperator operator) {
opConfig.setupNetworkInputs(
- new GlutenStatefulRecordSerializer(operator.getInputType(),
operator.getId()));
+ new GlutenStatefulRecordSerializer(operator.getInputType(), operator));
}
private void setOffloadedInputSerializersForTwoInputOperator(
StreamConfig opConfig, GlutenTwoInputOperator<?, ?> operator) {
opConfig.setupNetworkInputs(
- new GlutenStatefulRecordSerializer(operator.getLeftInputType(),
operator.getId()),
- new GlutenStatefulRecordSerializer(operator.getRightInputType(),
operator.getId()));
+ new GlutenStatefulRecordSerializer(operator.getLeftInputType(),
operator),
+ new GlutenStatefulRecordSerializer(operator.getRightInputType(),
operator));
}
private void setOffloadedStatePartitioner(
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOneInputOperatorFactory.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOneInputOperatorFactory.java
index 831dfde66f..41522731a3 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOneInputOperatorFactory.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOneInputOperatorFactory.java
@@ -16,6 +16,8 @@
*/
package org.apache.gluten.streaming.api.operators;
+import org.apache.gluten.table.runtime.operators.GlutenMailboxOperatorHelper;
+
import io.github.zhztheplayer.velox4j.serde.Serde;
import org.apache.flink.streaming.api.operators.AbstractStreamOperator;
@@ -59,6 +61,10 @@ public class GlutenOneInputOperatorFactory<IN, OUT> extends
AbstractStreamOperat
.setup(
parameters.getContainingTask(), parameters.getStreamConfig(),
parameters.getOutput());
}
+ if (operator instanceof GlutenOperator) {
+ GlutenMailboxOperatorHelper.bindAtTaskStartup(
+ ((GlutenOperator) operator).mailboxHolder(), parameters);
+ }
return (T) operator;
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
index 9720551967..bb6bc3bf54 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
@@ -16,9 +16,15 @@
*/
package org.apache.gluten.streaming.api.operators;
+import org.apache.gluten.table.runtime.operators.GlutenMailboxHolder;
+import org.apache.gluten.table.runtime.operators.GlutenSessionResources;
+
import io.github.zhztheplayer.velox4j.plan.StatefulPlanNode;
import io.github.zhztheplayer.velox4j.type.RowType;
+import org.apache.flink.api.common.operators.MailboxExecutor;
+import org.apache.flink.streaming.runtime.tasks.StreamTask;
+
import java.util.Map;
/** Interface for all gluten operators. */
@@ -34,4 +40,43 @@ public interface GlutenOperator {
public default String getDescription() {
return "";
}
+
+ /** Mailbox drain helper holder; must be a non-transient field on the
concrete operator. */
+ default GlutenMailboxHolder mailboxHolder() {
+ return new GlutenMailboxHolder();
+ }
+
+ default void processElementInternal() {}
+
+ default void bindMailboxExecutor(MailboxExecutor mailboxExecutor) {
+ mailboxHolder().get().bindMailboxExecutor(mailboxExecutor);
+ }
+
+ default void ensureMailboxInitialized(StreamTask<?, ?> containingTask) {
+ mailboxHolder().get().ensureMailboxInitialized(containingTask);
+ }
+
+ default void drainOutput(Runnable drainAction) {
+ mailboxHolder().get().runDrain(drainAction);
+ }
+
+ default void scheduleDrainOnMailbox(Runnable drainAction) {
+ mailboxHolder().get().scheduleDrain(drainAction);
+ }
+
+ /**
+ * Called from native Velox code to drain operator output. Drain is always
scheduled on the Flink
+ * task mailbox thread.
+ */
+ static void processElementByJni(String operatorId) {
+ GlutenOperator operator =
+
GlutenSessionResources.getInstance().getOperator(operatorId).orElse(null);
+ if (operator == null) {
+ throw new IllegalArgumentException("Operator not found: " + operatorId);
+ }
+ operator.scheduleProcessElementOnMailbox();
+ }
+
+ /** Schedules native output drain on the mailbox thread. Implemented by
concrete operators. */
+ default void scheduleProcessElementOnMailbox() {}
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/runtime/tasks/GlutenOutputCollector.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/runtime/tasks/GlutenOutputCollector.java
index 60dc8b62c6..8da53faa93 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/runtime/tasks/GlutenOutputCollector.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/runtime/tasks/GlutenOutputCollector.java
@@ -29,10 +29,8 @@ import
org.apache.flink.streaming.runtime.tasks.OutputWithChainingCheck;
import org.apache.flink.streaming.runtime.tasks.WatermarkGaugeExposingOutput;
import org.apache.flink.streaming.runtime.watermarkstatus.WatermarkStatus;
import org.apache.flink.util.OutputTag;
-import org.apache.flink.util.XORShiftRandom;
import java.util.Map;
-import java.util.Random;
/**
* Collector for gluten, it may contain several outputs, dispatch the record
according to node id.
@@ -40,7 +38,6 @@ import java.util.Random;
public class GlutenOutputCollector<T> implements
WatermarkGaugeExposingOutput<StreamRecord<T>> {
protected final Map<String, OutputWithChainingCheck<StreamRecord<T>>>
outputs;
- private final Random random = new XORShiftRandom();
private final WatermarkGauge watermarkGauge = new WatermarkGauge();
protected final Counter numRecordsOutForTask;
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/config/VeloxQueryConfig.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/config/VeloxQueryConfig.java
index 788ecb4a68..a1026cfe49 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/config/VeloxQueryConfig.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/config/VeloxQueryConfig.java
@@ -31,6 +31,8 @@ public class VeloxQueryConfig {
private static final String keyVeloxAdjustTimestampToSessionTimeZone =
"adjust_timestamp_to_session_timezone";
private static final String keyVeloxSessionTimezone = "session_timezone";
+ private static final String kStreamingAggregationMinOutputBatchRows =
+ "streaming_aggregation_min_output_batch_rows";
public static Config getConfig(RuntimeContext context) {
if (!(context instanceof StreamingRuntimeContext)) {
@@ -47,6 +49,7 @@ public class VeloxQueryConfig {
} else {
configMap.put(keyVeloxSessionTimezone, localTimeZone);
}
+ configMap.put(kStreamingAggregationMinOutputBatchRows, String.valueOf(1));
return Config.create(configMap);
}
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxHolder.java
similarity index 57%
copy from
gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
copy to
gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxHolder.java
index 9720551967..9415fcfe36 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/streaming/api/operators/GlutenOperator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxHolder.java
@@ -14,24 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.gluten.streaming.api.operators;
+package org.apache.gluten.table.runtime.operators;
-import io.github.zhztheplayer.velox4j.plan.StatefulPlanNode;
-import io.github.zhztheplayer.velox4j.type.RowType;
+import java.io.Serializable;
-import java.util.Map;
-
-/** Interface for all gluten operators. */
-public interface GlutenOperator {
- public StatefulPlanNode getPlanNode();
-
- public RowType getInputType();
+/**
+ * Serializable holder for {@link GlutenMailboxOperatorHelper}.
+ *
+ * <p>The holder survives Flink operator deserialization; the helper is lazily
recreated because it
+ * is {@code transient}.
+ */
+public final class GlutenMailboxHolder implements Serializable {
- public Map<String, RowType> getOutputTypes();
+ private static final long serialVersionUID = 1L;
- public String getId();
+ private transient GlutenMailboxOperatorHelper helper;
- public default String getDescription() {
- return "";
+ public GlutenMailboxOperatorHelper get() {
+ if (helper == null) {
+ helper = new GlutenMailboxOperatorHelper();
+ }
+ return helper;
}
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxOperatorHelper.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxOperatorHelper.java
new file mode 100644
index 0000000000..ecec25ede6
--- /dev/null
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenMailboxOperatorHelper.java
@@ -0,0 +1,108 @@
+/*
+ * 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.gluten.table.runtime.operators;
+
+import org.apache.flink.api.common.operators.MailboxExecutor;
+import org.apache.flink.streaming.api.operators.StreamOperatorParameters;
+import org.apache.flink.streaming.runtime.tasks.StreamTask;
+
+/**
+ * Schedules Velox output drain onto the Flink task mailbox thread.
+ *
+ * <p>JNI callbacks from Velox must not call {@code SerialTask.advance()} or
emit records directly.
+ * When a callback arrives while a drain is already in progress on the mailbox
thread, a follow-up
+ * drain is requested via {@code pendingMailboxDrain} instead of nesting
another drain.
+ */
+public final class GlutenMailboxOperatorHelper {
+
+ private transient MailboxExecutor mailboxExecutor;
+ private transient boolean draining;
+ private transient boolean pendingMailboxDrain;
+ private transient boolean mailboxDrainScheduled;
+
+ public void bindMailboxExecutor(MailboxExecutor mailboxExecutor) {
+ this.mailboxExecutor = mailboxExecutor;
+ }
+
+ public void ensureMailboxInitialized(StreamTask<?, ?> containingTask) {
+ if (mailboxExecutor == null) {
+ mailboxExecutor =
containingTask.getMailboxExecutorFactory().createExecutor(0);
+ }
+ }
+
+ public boolean isMailboxBound() {
+ return mailboxExecutor != null;
+ }
+
+ public void runDrain(Runnable drainAction) {
+ draining = true;
+ try {
+ boolean repeat;
+ do {
+ pendingMailboxDrain = false;
+ drainAction.run();
+ repeat = pendingMailboxDrain;
+ } while (repeat);
+ } finally {
+ draining = false;
+ }
+ }
+
+ public void scheduleDrain(Runnable drainAction) {
+ if (mailboxExecutor == null) {
+ runDrain(drainAction);
+ return;
+ }
+ if (draining) {
+ pendingMailboxDrain = true;
+ return;
+ }
+ synchronized (this) {
+ if (mailboxDrainScheduled) {
+ return;
+ }
+ mailboxDrainScheduled = true;
+ }
+ try {
+ mailboxExecutor.submit(
+ () -> {
+ try {
+ runDrain(drainAction);
+ } finally {
+ synchronized (GlutenMailboxOperatorHelper.this) {
+ mailboxDrainScheduled = false;
+ }
+ }
+ },
+ "gluten-drain-output");
+ } catch (RuntimeException e) {
+ synchronized (this) {
+ mailboxDrainScheduled = false;
+ }
+ throw e;
+ }
+ }
+
+ /** Binds mailbox from {@link StreamOperatorParameters} during operator
factory startup on TM. */
+ public static void bindAtTaskStartup(
+ GlutenMailboxHolder mailboxHolder, StreamOperatorParameters<?>
parameters) {
+ mailboxHolder
+ .get()
+ .bindMailboxExecutor(
+
parameters.getContainingTask().getMailboxExecutorFactory().createExecutor(0));
+ }
+}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenOneInputOperator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenOneInputOperator.java
index a2733c2438..09b059f3bc 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenOneInputOperator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenOneInputOperator.java
@@ -36,6 +36,7 @@ import io.github.zhztheplayer.velox4j.stateful.StatefulRecord;
import io.github.zhztheplayer.velox4j.stateful.StatefulWatermark;
import io.github.zhztheplayer.velox4j.type.RowType;
+import org.apache.flink.contrib.streaming.state.RocksDBKeyedStateBackend;
import org.apache.flink.runtime.state.StateInitializationContext;
import org.apache.flink.runtime.state.StateSnapshotContext;
import org.apache.flink.streaming.api.operators.OneInputStreamOperator;
@@ -43,9 +44,6 @@ import org.apache.flink.streaming.api.watermark.Watermark;
import org.apache.flink.streaming.runtime.streamrecord.StreamRecord;
import org.apache.flink.table.runtime.operators.TableStreamOperator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.util.List;
import java.util.Map;
@@ -53,8 +51,6 @@ import java.util.Map;
public class GlutenOneInputOperator<IN, OUT> extends TableStreamOperator<OUT>
implements OneInputStreamOperator<IN, OUT>, GlutenOperator {
- private static final Logger LOG =
LoggerFactory.getLogger(GlutenOneInputOperator.class);
-
private final StatefulPlanNode glutenPlan;
private final String id;
private final RowType inputType;
@@ -70,6 +66,7 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
private final Class<OUT> outClass;
private transient VectorInputBridge<IN> inputBridge;
private transient VectorOutputBridge<OUT> outputBridge;
+ private final GlutenMailboxHolder mailboxHolder = new GlutenMailboxHolder();
public GlutenOneInputOperator(
StatefulPlanNode plan,
@@ -121,6 +118,8 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
outputBridge = VectorOutputBridge.Factory.create(outClass);
}
sessionResource = new GlutenSessionResource();
+ GlutenSessionResources.getInstance().addSessionResource(id,
sessionResource);
+
GlutenSessionResources.getInstance().addOperator(this.getClass().getSimpleName(),
this);
inputQueue =
sessionResource.getSession().externalStreamOps().newBlockingQueue();
// add a mock input as velox not allow the source is empty.
if (inputType == null) {
@@ -152,6 +151,9 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
@Override
public void open() throws Exception {
super.open();
+ if (!mailboxHolder().get().isMailboxBound()) {
+ ensureMailboxInitialized(getContainingTask());
+ }
initSession();
}
@@ -163,28 +165,48 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
StatefulRecord statefulRecord =
inputBridge.convertToStatefulRecord(
element, sessionResource.getAllocator(),
sessionResource.getSession(), inputType);
- inputQueue.put(statefulRecord.getRowVector());
-
- // Only the rowvectors generated by this operator should be closed here.
- if (getId().equals(statefulRecord.getNodeId())) {
- statefulRecord.close();
+ try {
+ inputQueue.put(statefulRecord.getRowVector());
+ } finally {
+ // Only the rowvectors generated by this operator should be closed here.
+ if (getId().equals(statefulRecord.getNodeId())) {
+ statefulRecord.close();
+ }
}
processElementInternal();
}
- private void processElementInternal() {
+ @Override
+ public GlutenMailboxHolder mailboxHolder() {
+ return mailboxHolder;
+ }
+
+ @Override
+ public void scheduleProcessElementOnMailbox() {
+ scheduleDrainOnMailbox(this::drainTaskOutput);
+ }
+
+ @Override
+ public void processElementInternal() {
+ drainOutput(this::drainTaskOutput);
+ }
+
+ private void drainTaskOutput() {
while (true) {
UpIterator.State state = task.advance();
if (state == UpIterator.State.AVAILABLE) {
final StatefulElement statefulElement = task.statefulGet();
- if (statefulElement.isWatermark()) {
- StatefulWatermark watermark = statefulElement.asWatermark();
- output.emitWatermark(new Watermark(watermark.getTimestamp()));
- } else {
- outputBridge.collect(
- output, statefulElement.asRecord(),
sessionResource.getAllocator(), outputType);
+ try {
+ if (statefulElement.isWatermark()) {
+ StatefulWatermark watermark = statefulElement.asWatermark();
+ output.emitWatermark(new Watermark(watermark.getTimestamp()));
+ } else {
+ outputBridge.collect(
+ output, statefulElement.asRecord(),
sessionResource.getAllocator(), outputType);
+ }
+ } finally {
+ statefulElement.close();
}
- statefulElement.close();
} else {
break;
}
@@ -192,15 +214,9 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
}
public <NIN, NOUT> GlutenOneInputOperator<NIN, NOUT>
cloneWithInputOutputClasses(
- Class<NIN> newInClass, Class<NOUT> newOutClass) {
+ StatefulPlanNode plan, Class<NIN> newInClass, Class<NOUT> newOutClass) {
return new GlutenOneInputOperator<>(
- this.glutenPlan,
- this.id,
- this.inputType,
- this.outputTypes,
- newInClass,
- newOutClass,
- this.description);
+ plan, this.id, this.inputType, this.outputTypes, newInClass,
newOutClass, this.description);
}
@Override
@@ -222,13 +238,13 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
@Override
public void close() throws Exception {
+ if (task != null) {
+ task.close();
+ }
if (inputQueue != null) {
inputQueue.noMoreInput();
inputQueue.close();
}
- if (task != null) {
- task.close();
- }
if (sessionResource != null) {
sessionResource.close();
}
@@ -272,7 +288,9 @@ public class GlutenOneInputOperator<IN, OUT> extends
TableStreamOperator<OUT>
if (task == null) {
initSession();
}
- task.initializeState(0, null);
+ if (!(getKeyedStateBackend() instanceof RocksDBKeyedStateBackend)) {
+ task.initializeState(0, null);
+ }
super.initializeState(context);
}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResource.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResources.java
similarity index 67%
rename from
gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResource.java
rename to
gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResources.java
index ea38229e95..fac0784a24 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResource.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSessionResources.java
@@ -16,6 +16,8 @@
*/
package org.apache.gluten.table.runtime.operators;
+import org.apache.gluten.streaming.api.operators.GlutenOperator;
+
import io.github.zhztheplayer.velox4j.Velox4j;
import io.github.zhztheplayer.velox4j.memory.AllocationListener;
import io.github.zhztheplayer.velox4j.memory.MemoryManager;
@@ -26,6 +28,10 @@ import org.apache.flink.runtime.state.KeyedStateBackend;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
// Manage the session and resource for Velox.
class GlutenSessionResource {
private Session session;
@@ -74,3 +80,38 @@ class GlutenSessionResource {
this.keyedStateBackend = keyedStateBackend;
}
}
+
+public class GlutenSessionResources {
+ private static final GlutenSessionResources instance = new
GlutenSessionResources();
+ private Map<String, GlutenSessionResource> sessionResources = new
HashMap<>();
+ private Map<String, GlutenOperator> operators = new HashMap<>();
+
+ private GlutenSessionResources() {}
+
+ public static GlutenSessionResources getInstance() {
+ return instance;
+ }
+
+ public GlutenSessionResource getSessionResource(String id) {
+ return sessionResources.get(id);
+ }
+
+ public void addSessionResource(String id, GlutenSessionResource
sessionResource) {
+ sessionResources.put(id, sessionResource);
+ }
+
+ public Session getSession(String id) {
+ return sessionResources.get(id).getSession();
+ }
+
+ public void addOperator(String id, GlutenOperator operator) {
+ operators.put(id, operator);
+ }
+
+ public Optional<GlutenOperator> getOperator(String id) {
+ if (operators.containsKey(id)) {
+ return Optional.of(operators.get(id));
+ }
+ return Optional.empty();
+ }
+}
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSourceFunction.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSourceFunction.java
index ea0ddcbc7c..53f36fcf67 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSourceFunction.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenSourceFunction.java
@@ -109,10 +109,8 @@ public class GlutenSourceFunction<OUT> extends
RichParallelSourceFunction<OUT>
processAvailableElement(sourceContext);
break;
case BLOCKED:
- LOG.debug("Get empty row");
break;
default:
- LOG.info("Velox task finished");
return;
}
taskMetrics.updateMetrics(task, id);
@@ -233,6 +231,7 @@ public class GlutenSourceFunction<OUT> extends
RichParallelSourceFunction<OUT>
return;
}
sessionResource = new GlutenSessionResource();
+ GlutenSessionResources.getInstance().addSessionResource(id,
sessionResource);
Session session = sessionResource.getSession();
query =
new Query(
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenTwoInputOperator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenTwoInputOperator.java
index 2352d74943..3f73ad4bbd 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenTwoInputOperator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/GlutenTwoInputOperator.java
@@ -72,6 +72,7 @@ public class GlutenTwoInputOperator<IN, OUT> extends
AbstractStreamOperator<OUT>
private VectorInputBridge<IN> inputBridge;
private VectorOutputBridge<OUT> outputBridge;
private String description;
+ private final GlutenMailboxHolder mailboxHolder = new GlutenMailboxHolder();
public GlutenTwoInputOperator(
StatefulPlanNode plan,
@@ -117,6 +118,9 @@ public class GlutenTwoInputOperator<IN, OUT> extends
AbstractStreamOperator<OUT>
@Override
public void open() throws Exception {
super.open();
+ if (!mailboxHolder().get().isMailboxBound()) {
+ ensureMailboxInitialized(getContainingTask());
+ }
initSession();
}
@@ -125,6 +129,16 @@ public class GlutenTwoInputOperator<IN, OUT> extends
AbstractStreamOperator<OUT>
return glutenPlan.getId();
}
+ @Override
+ public GlutenMailboxHolder mailboxHolder() {
+ return mailboxHolder;
+ }
+
+ @Override
+ public void scheduleProcessElementOnMailbox() {
+ scheduleDrainOnMailbox(this::drainTaskOutput);
+ }
+
@Override
public void processElement1(StreamRecord<IN> element) {
StatefulRecord statefulRecord =
@@ -152,19 +166,27 @@ public class GlutenTwoInputOperator<IN, OUT> extends
AbstractStreamOperator<OUT>
processElementInternal();
}
- private void processElementInternal() {
+ @Override
+ public void processElementInternal() {
+ drainOutput(this::drainTaskOutput);
+ }
+
+ private void drainTaskOutput() {
while (true) {
UpIterator.State state = task.advance();
if (state == UpIterator.State.AVAILABLE) {
final StatefulElement element = task.statefulGet();
- if (element.isWatermark()) {
- StatefulWatermark watermark = element.asWatermark();
- output.emitWatermark(new Watermark(watermark.getTimestamp()));
- } else {
- outputBridge.collect(
- output, element.asRecord(), sessionResource.getAllocator(),
outputType);
+ try {
+ if (element.isWatermark()) {
+ StatefulWatermark watermark = element.asWatermark();
+ output.emitWatermark(new Watermark(watermark.getTimestamp()));
+ } else {
+ outputBridge.collect(
+ output, element.asRecord(), sessionResource.getAllocator(),
outputType);
+ }
+ } finally {
+ element.close();
}
- element.close();
} else {
break;
}
@@ -263,7 +285,8 @@ public class GlutenTwoInputOperator<IN, OUT> extends
AbstractStreamOperator<OUT>
}
sessionResource = new GlutenSessionResource();
-
+ GlutenSessionResources.getInstance().addSessionResource(getId(),
sessionResource);
+ GlutenSessionResources.getInstance().addOperator(getId(), this);
leftInputQueue =
sessionResource.getSession().externalStreamOps().newBlockingQueue();
rightInputQueue =
sessionResource.getSession().externalStreamOps().newBlockingQueue();
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/WindowAggOperator.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/WindowAggOperator.java
index 50d91f2c73..f15d4c8c39 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/WindowAggOperator.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/operators/WindowAggOperator.java
@@ -129,12 +129,14 @@ public class WindowAggOperator<IN, OUT, W> extends
GlutenOneInputOperator<IN, OU
new
org.apache.flink.table.types.logical.RowType(accFields))),
Map.of(windowStateName, new BigIntType()));
task.initializeState(0, parameters);
+ } else {
+ task.initializeState(0, null);
}
}
@Override
public <NIN, NOUT> WindowAggOperator<NIN, NOUT, W>
cloneWithInputOutputClasses(
- Class<NIN> newInClass, Class<NOUT> newOutClass) {
+ StatefulPlanNode plan, Class<NIN> newInClass, Class<NOUT> newOutClass) {
return new WindowAggOperator<>(
getPlanNode(),
getId(),
diff --git
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/typeutils/GlutenStatefulRecordSerializer.java
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/typeutils/GlutenStatefulRecordSerializer.java
index 1040e776c1..66fdd7bc51 100644
---
a/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/typeutils/GlutenStatefulRecordSerializer.java
+++
b/gluten-flink/runtime/src/main/java/org/apache/gluten/table/runtime/typeutils/GlutenStatefulRecordSerializer.java
@@ -16,11 +16,10 @@
*/
package org.apache.gluten.table.runtime.typeutils;
-import io.github.zhztheplayer.velox4j.Velox4j;
+import org.apache.gluten.streaming.api.operators.GlutenOperator;
+import org.apache.gluten.table.runtime.operators.GlutenSessionResources;
+
import io.github.zhztheplayer.velox4j.data.RowVector;
-import io.github.zhztheplayer.velox4j.memory.AllocationListener;
-import io.github.zhztheplayer.velox4j.memory.MemoryManager;
-import io.github.zhztheplayer.velox4j.session.Session;
import io.github.zhztheplayer.velox4j.stateful.StatefulRecord;
import io.github.zhztheplayer.velox4j.type.RowType;
@@ -31,31 +30,23 @@ import
org.apache.flink.api.common.typeutils.TypeSerializerSnapshot;
import org.apache.flink.core.memory.DataInputView;
import org.apache.flink.core.memory.DataOutputView;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Closeable;
import java.io.IOException;
/** Serializer for {@link RowVector}. */
@Internal
-public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecord>
- implements Closeable {
- private static final Logger LOG =
LoggerFactory.getLogger(GlutenStatefulRecordSerializer.class);
+public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecord> {
private static final long serialVersionUID = 1L;
private final RowType rowType;
- private transient MemoryManager memoryManager;
- private transient Session session;
- private final String nodeId;
+ private final GlutenOperator operator;
- public GlutenStatefulRecordSerializer(RowType rowType, String nodeId) {
- this.nodeId = nodeId;
+ public GlutenStatefulRecordSerializer(RowType rowType, GlutenOperator
operator) {
this.rowType = rowType;
+ this.operator = operator;
}
@Override
public TypeSerializer<StatefulRecord> duplicate() {
- return new GlutenStatefulRecordSerializer(rowType, nodeId);
+ return new GlutenStatefulRecordSerializer(rowType, operator);
}
@Override
@@ -72,15 +63,16 @@ public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecor
@Override
public StatefulRecord deserialize(DataInputView source) throws IOException {
- if (memoryManager == null) {
- memoryManager = MemoryManager.create(AllocationListener.NOOP);
- session = Velox4j.newSession(memoryManager);
- }
int len = source.readInt();
byte[] str = new byte[len];
source.readFully(str);
- RowVector rowVector = session.baseVectorOps().deserializeOne(new
String(str)).asRowVector();
- StatefulRecord record = new StatefulRecord(nodeId, 0, 0, false, -1);
+ RowVector rowVector =
+ GlutenSessionResources.getInstance()
+ .getSession(operator.getId())
+ .baseVectorOps()
+ .deserializeOne(new String(str))
+ .asRowVector();
+ StatefulRecord record = new StatefulRecord(operator.getId(),
rowVector.id(), 0, false, -1);
record.setRowVector(rowVector);
return record;
}
@@ -138,15 +130,7 @@ public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecor
@Override
public TypeSerializerSnapshot<StatefulRecord> snapshotConfiguration() {
- return new RowVectorSerializerSnapshot(rowType, nodeId);
- }
-
- @Override
- public void close() {
- if (memoryManager != null) {
- memoryManager.close();
- session.close();
- }
+ return new RowVectorSerializerSnapshot(rowType, operator);
}
/** {@link TypeSerializerSnapshot} for Gluten RowVector.. */
@@ -155,16 +139,16 @@ public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecor
private static final int CURRENT_VERSION = 1;
private RowType rowType;
- private String nodeId;
+ private GlutenOperator operator;
@SuppressWarnings("unused")
public RowVectorSerializerSnapshot() {
// this constructor is used when restoring from a checkpoint/savepoint.
}
- RowVectorSerializerSnapshot(RowType rowType, String nodeId) {
- this.nodeId = nodeId;
+ RowVectorSerializerSnapshot(RowType rowType, GlutenOperator operator) {
this.rowType = rowType;
+ this.operator = operator;
}
@Override
@@ -181,7 +165,7 @@ public class GlutenStatefulRecordSerializer extends
TypeSerializer<StatefulRecor
@Override
public GlutenStatefulRecordSerializer restoreSerializer() {
- return new GlutenStatefulRecordSerializer(rowType, nodeId);
+ return new GlutenStatefulRecordSerializer(rowType, operator);
}
@Override
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]