org.apache.flink.runtime.state.StateSnapshotTransformer Maven / Gradle / Ivy
/*
* 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.runtime.state;
import org.apache.flink.runtime.state.StateSnapshotTransformer.CollectionStateSnapshotTransformer.TransformStrategy;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import static org.apache.flink.runtime.state.StateSnapshotTransformer.CollectionStateSnapshotTransformer.TransformStrategy.STOP_ON_FIRST_INCLUDED;
/**
* Transformer of state values which are included or skipped in the snapshot.
*
* This transformer can be applied to state values
* to decide which entries should be included into the snapshot.
* The included entries can be optionally modified before.
*
*
Unless specified differently, the transformer should be applied per entry
* for collection types of state, like list or map.
*
* @param type of state
*/
@FunctionalInterface
public interface StateSnapshotTransformer {
/**
* Transform or filter out state values which are included or skipped in the snapshot.
*
* @param value non-serialized form of value
* @return value to snapshot or null which means the entry is not included
*/
@Nullable
T filterOrTransform(@Nullable T value);
/** Collection state specific transformer which says how to transform entries of the collection. */
interface CollectionStateSnapshotTransformer extends StateSnapshotTransformer {
enum TransformStrategy {
/** Transform all entries. */
TRANSFORM_ALL,
/**
* Skip first null entries.
*
* While traversing collection entries, as optimisation, stops transforming
* if encounters first non-null included entry and returns it plus the rest untouched.
*/
STOP_ON_FIRST_INCLUDED
}
default TransformStrategy getFilterStrategy() {
return TransformStrategy.TRANSFORM_ALL;
}
}
/**
* General implementation of list state transformer.
*
*
This transformer wraps a transformer per-entry
* and transforms the whole list state.
* If the wrapped per entry transformer is {@link CollectionStateSnapshotTransformer},
* it respects its {@link TransformStrategy}.
*/
class ListStateSnapshotTransformer implements StateSnapshotTransformer> {
private final StateSnapshotTransformer entryValueTransformer;
private final TransformStrategy transformStrategy;
public ListStateSnapshotTransformer(StateSnapshotTransformer entryValueTransformer) {
this.entryValueTransformer = entryValueTransformer;
this.transformStrategy = entryValueTransformer instanceof CollectionStateSnapshotTransformer ?
((CollectionStateSnapshotTransformer) entryValueTransformer).getFilterStrategy() :
TransformStrategy.TRANSFORM_ALL;
}
@Override
@Nullable
public List filterOrTransform(@Nullable List list) {
if (list == null) {
return null;
}
List transformedList = new ArrayList<>();
boolean anyChange = false;
for (int i = 0; i < list.size(); i++) {
T entry = list.get(i);
T transformedEntry = entryValueTransformer.filterOrTransform(entry);
if (transformedEntry != null) {
if (transformStrategy == STOP_ON_FIRST_INCLUDED) {
transformedList = list.subList(i, list.size());
anyChange = i > 0;
break;
} else {
transformedList.add(transformedEntry);
}
}
anyChange |= transformedEntry == null || !Objects.equals(entry, transformedEntry);
}
transformedList = anyChange ? transformedList : list;
return transformedList.isEmpty() ? null : transformedList;
}
}
/**
* General implementation of map state transformer.
*
* This transformer wraps a transformer per-entry
* and transforms the whole map state.
*/
class MapStateSnapshotTransformer implements StateSnapshotTransformer