Search in sources :

Example 1 with StreamCodecWrapperForPersistance

use of com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance in project apex-core by apache.

the class StreamPersistanceTests method testDynamicPartitioning.

@Test
public void testDynamicPartitioning() throws ClassNotFoundException, IOException {
    AscendingNumbersOperator ascend = dag.addOperator("ascend", new AscendingNumbersOperator());
    final TestReceiverOperator console = dag.addOperator("console", new TestReceiverOperator());
    dag.setOperatorAttribute(console, Context.OperatorContext.PARTITIONER, new StatelessPartitioner<TestReceiverOperator>(2));
    dag.setOperatorAttribute(console, Context.OperatorContext.STATS_LISTENERS, Lists.newArrayList((StatsListener) new PartitioningTest.PartitionLoadWatch()));
    final PartitionedTestPersistanceOperator console1 = new PartitionedTestPersistanceOperator();
    StreamMeta s = dag.addStream("Stream1", ascend.outputPort, console.inport);
    dag.setInputPortAttribute(console.inport, PortContext.STREAM_CODEC, new TestPartitionCodec());
    s.persistUsing("persister", console1, console1.inport);
    dag.setAttribute(LogicalPlan.CONTAINERS_MAX_COUNT, Integer.MAX_VALUE);
    StramTestSupport.MemoryStorageAgent msa = new StramTestSupport.MemoryStorageAgent();
    dag.setAttribute(Context.OperatorContext.STORAGE_AGENT, msa);
    StreamingContainerManager dnm = new StreamingContainerManager(dag);
    PhysicalPlan plan = dnm.getPhysicalPlan();
    List<PTContainer> containers = plan.getContainers();
    Assert.assertEquals("number containers", 4, containers.size());
    for (int i = 0; i < containers.size(); ++i) {
        StreamingContainerManagerTest.assignContainer(dnm, "container" + (i + 1));
    }
    LogicalPlan.OperatorMeta passThruMeta = dag.getMeta(console);
    List<PTOperator> ptos = plan.getOperators(passThruMeta);
    PTOperator persistOperatorContainer = null;
    for (PTContainer container : plan.getContainers()) {
        for (PTOperator operator : container.getOperators()) {
            operator.setState(PTOperator.State.ACTIVE);
            if (operator.getName().equals("persister")) {
                persistOperatorContainer = operator;
            }
        }
    }
    // Check that persist operator is part of dependents redeployed
    Set<PTOperator> operators = plan.getDependents(ptos);
    logger.debug("Operators to be re-deployed = {}", operators);
    // Validate that persist operator is part of dependents
    assertTrue("persist operator should be part of the operators to be redeployed", operators.contains(persistOperatorContainer));
    LogicalPlan.StreamMeta s1 = (LogicalPlan.StreamMeta) s;
    StreamCodec codec = s1.getPersistOperatorInputPort().getStreamCodec();
    assertEquals("Codec should be instance of StreamCodecWrapper", codec instanceof StreamCodecWrapperForPersistance, true);
    StreamCodecWrapperForPersistance wrapperCodec = (StreamCodecWrapperForPersistance) codec;
    Entry<InputPortMeta, Collection<PartitionKeys>> keys = (Entry<InputPortMeta, Collection<PartitionKeys>>) wrapperCodec.inputPortToPartitionMap.entrySet().iterator().next();
    logger.debug(keys.toString());
    assertEquals("Size of partitions should be 2", 2, keys.getValue().size());
    for (PTOperator ptOperator : ptos) {
        PartitioningTest.PartitionLoadWatch.put(ptOperator, -1);
        plan.onStatusUpdate(ptOperator);
    }
    dnm.processEvents();
    assertEquals("Input port map", wrapperCodec.inputPortToPartitionMap.size(), 1);
    keys = (Entry<InputPortMeta, Collection<PartitionKeys>>) wrapperCodec.inputPortToPartitionMap.entrySet().iterator().next();
    assertEquals("Size of partitions should be 1 after repartition", 1, keys.getValue().size());
    logger.debug(keys.toString());
}
Also used : DefaultKryoStreamCodec(com.datatorrent.stram.plan.logical.DefaultKryoStreamCodec) StreamCodec(com.datatorrent.api.StreamCodec) StreamCodecWrapperForPersistance(com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance) StreamMeta(com.datatorrent.api.DAG.StreamMeta) Entry(java.util.Map.Entry) PartitioningTest(com.datatorrent.stram.PartitioningTest) StramTestSupport(com.datatorrent.stram.support.StramTestSupport) PTContainer(com.datatorrent.stram.plan.physical.PTContainer) PartitionKeys(com.datatorrent.api.Partitioner.PartitionKeys) StreamingContainerManager(com.datatorrent.stram.StreamingContainerManager) PhysicalPlan(com.datatorrent.stram.plan.physical.PhysicalPlan) PTOperator(com.datatorrent.stram.plan.physical.PTOperator) InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) StatsListener(com.datatorrent.api.StatsListener) Collection(java.util.Collection) LogicalPlan(com.datatorrent.stram.plan.logical.LogicalPlan) Test(org.junit.Test) PartitioningTest(com.datatorrent.stram.PartitioningTest) StreamingContainerManagerTest(com.datatorrent.stram.StreamingContainerManagerTest)

Example 2 with StreamCodecWrapperForPersistance

use of com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance in project apex-core by apache.

the class StreamingContainer method deployInputStreams.

@SuppressWarnings("unchecked")
private void deployInputStreams(List<OperatorDeployInfo> operatorList, HashMap<String, ComponentContextPair<Stream, StreamContext>> newStreams) throws UnknownHostException {
    /*
     * collect any input operators along with their smallest window id,
     * those are subsequently used to setup the window generator
     */
    ArrayList<OperatorDeployInfo> inputNodes = new ArrayList<>();
    long smallestCheckpointedWindowId = Long.MAX_VALUE;
    // a simple map which maps the oio node to it's the node which owns the thread.
    Map<Integer, Integer> oioNodes = new ConcurrentHashMap<>();
    /*
     * Hook up all the downstream ports. There are 2 places where we deal with more than 1
     * downstream ports. The first one follows immediately for WindowGenerator. The second
     * case is when source for the input port of some node in this container is in another
     * container. So we need to create the stream. We need to track this stream along with
     * other streams,and many such streams may exist, we hash them against buffer server
     * info as we did for outputs but throw in the sinkid in the mix as well.
     */
    for (OperatorDeployInfo ndi : operatorList) {
        if (ndi.inputs == null || ndi.inputs.isEmpty()) {
            /*
         * This has to be InputNode, so let's hook the WindowGenerator to it.
         * A node which does not take any input cannot exist in the DAG since it would be completely
         * unaware of the windows. So for that reason, AbstractInputNode allows Component.INPUT port.
         */
            inputNodes.add(ndi);
            /*
         * When we activate the window Generator, we plan to activate it only from required windowId.
         */
            ndi.checkpoint = getFinishedCheckpoint(ndi);
            if (ndi.checkpoint.windowId < smallestCheckpointedWindowId) {
                smallestCheckpointedWindowId = ndi.checkpoint.windowId;
            }
        } else {
            Node<?> node = nodes.get(ndi.id);
            for (OperatorDeployInfo.InputDeployInfo nidi : ndi.inputs) {
                if (nidi.streamCodecs.size() != 1) {
                    throw new IllegalStateException("Only one input codec configuration should be present");
                }
                Map.Entry<Integer, StreamCodec<?>> entry = nidi.streamCodecs.entrySet().iterator().next();
                Integer streamCodecIdentifier = entry.getKey();
                StreamCodec<?> streamCodec = entry.getValue();
                String sourceIdentifier = Integer.toString(nidi.sourceNodeId).concat(Component.CONCAT_SEPARATOR).concat(nidi.sourcePortName);
                String sinkIdentifier = Integer.toString(ndi.id).concat(Component.CONCAT_SEPARATOR).concat(nidi.portName);
                int queueCapacity = getValue(PortContext.QUEUE_CAPACITY, nidi, ndi);
                Checkpoint checkpoint = getFinishedCheckpoint(ndi);
                ComponentContextPair<Stream, StreamContext> pair = streams.get(sourceIdentifier);
                if (pair == null) {
                    pair = newStreams.get(sourceIdentifier);
                }
                if (pair == null) {
                    /*
             * We connect to the buffer server for the input on this port.
             * We have already placed all the output streams for all the operators in this container.
             * Yet, there is no stream which can source this port so it has to come from the buffer
             * server, so let's make a connection to it.
             */
                    assert (nidi.locality != Locality.CONTAINER_LOCAL && nidi.locality != Locality.THREAD_LOCAL);
                    StreamContext context = new StreamContext(nidi.declaredStreamId);
                    context.setBufferServerAddress(InetSocketAddress.createUnresolved(nidi.bufferServerHost, nidi.bufferServerPort));
                    InetAddress inetAddress = context.getBufferServerAddress().getAddress();
                    if (inetAddress != null && NetUtils.isLocalAddress(inetAddress)) {
                        context.setBufferServerAddress(new InetSocketAddress(InetAddress.getByName(null), nidi.bufferServerPort));
                    }
                    context.put(StreamContext.BUFFER_SERVER_TOKEN, nidi.bufferServerToken);
                    String connIdentifier = sourceIdentifier + Component.CONCAT_SEPARATOR + streamCodecIdentifier;
                    context.setPortId(nidi.portName);
                    context.put(StreamContext.CODEC, streamCodec);
                    context.put(StreamContext.EVENT_LOOP, eventloop);
                    context.setPartitions(nidi.partitionMask, nidi.partitionKeys);
                    // context.setSourceId(sourceIdentifier);
                    context.setSourceId(connIdentifier);
                    context.setSinkId(sinkIdentifier);
                    context.setFinishedWindowId(checkpoint.windowId);
                    BufferServerSubscriber subscriber = fastPublisherSubscriber ? new FastSubscriber("tcp://".concat(nidi.bufferServerHost).concat(":").concat(String.valueOf(nidi.bufferServerPort)).concat("/").concat(connIdentifier), queueCapacity) : new BufferServerSubscriber("tcp://".concat(nidi.bufferServerHost).concat(":").concat(String.valueOf(nidi.bufferServerPort)).concat("/").concat(connIdentifier), queueCapacity);
                    if (streamCodec instanceof StreamCodecWrapperForPersistance) {
                        subscriber.acquireReservoirForPersistStream(sinkIdentifier, queueCapacity, streamCodec);
                    }
                    SweepableReservoir reservoir = subscriber.acquireReservoir(sinkIdentifier, queueCapacity);
                    if (checkpoint.windowId >= 0) {
                        node.connectInputPort(nidi.portName, new WindowIdActivatedReservoir(sinkIdentifier, reservoir, checkpoint.windowId));
                    }
                    node.connectInputPort(nidi.portName, reservoir);
                    newStreams.put(sinkIdentifier, new ComponentContextPair<Stream, StreamContext>(subscriber, context));
                    logger.debug("put input stream {} against key {}", subscriber, sinkIdentifier);
                } else {
                    assert (nidi.locality == Locality.CONTAINER_LOCAL || nidi.locality == Locality.THREAD_LOCAL);
                    /* we are still dealing with the MuxStream originating at the output of the source port */
                    StreamContext inlineContext = new StreamContext(nidi.declaredStreamId);
                    inlineContext.setSourceId(sourceIdentifier);
                    inlineContext.setSinkId(sinkIdentifier);
                    Stream stream;
                    SweepableReservoir reservoir;
                    switch(nidi.locality) {
                        case CONTAINER_LOCAL:
                            int outputQueueCapacity = getOutputQueueCapacity(operatorList, nidi.sourceNodeId, nidi.sourcePortName);
                            if (outputQueueCapacity > queueCapacity) {
                                queueCapacity = outputQueueCapacity;
                            }
                            stream = new InlineStream(queueCapacity);
                            reservoir = ((InlineStream) stream).getReservoir();
                            if (checkpoint.windowId >= 0) {
                                node.connectInputPort(nidi.portName, new WindowIdActivatedReservoir(sinkIdentifier, reservoir, checkpoint.windowId));
                            }
                            break;
                        case THREAD_LOCAL:
                            stream = new OiOStream();
                            reservoir = ((OiOStream) stream).getReservoir();
                            ((OiOStream.OiOReservoir) reservoir).setControlSink(((OiONode) node).getControlSink(reservoir));
                            oioNodes.put(ndi.id, nidi.sourceNodeId);
                            break;
                        default:
                            throw new IllegalStateException("Locality can be either ContainerLocal or ThreadLocal");
                    }
                    node.connectInputPort(nidi.portName, reservoir);
                    newStreams.put(sinkIdentifier, new ComponentContextPair<>(stream, inlineContext));
                    if (!(pair.component instanceof Stream.MultiSinkCapableStream)) {
                        String originalSinkId = pair.context.getSinkId();
                        /* we come here only if we are trying to augment the dag */
                        StreamContext muxContext = new StreamContext(nidi.declaredStreamId);
                        muxContext.setSourceId(sourceIdentifier);
                        muxContext.setFinishedWindowId(checkpoint.windowId);
                        muxContext.setSinkId(originalSinkId);
                        MuxStream muxStream = new MuxStream();
                        muxStream.setSink(originalSinkId, pair.component);
                        streams.put(originalSinkId, pair);
                        Node<?> sourceNode = nodes.get(nidi.sourceNodeId);
                        sourceNode.connectOutputPort(nidi.sourcePortName, muxStream);
                        newStreams.put(sourceIdentifier, pair = new ComponentContextPair<Stream, StreamContext>(muxStream, muxContext));
                    }
                    /* here everything should be multisink capable */
                    if (streamCodec instanceof StreamCodecWrapperForPersistance) {
                        PartitionAwareSinkForPersistence pas;
                        if (nidi.partitionKeys == null) {
                            pas = new PartitionAwareSinkForPersistence((StreamCodecWrapperForPersistance<Object>) streamCodec, nidi.partitionMask, stream);
                        } else {
                            pas = new PartitionAwareSinkForPersistence((StreamCodecWrapperForPersistance<Object>) streamCodec, nidi.partitionKeys, nidi.partitionMask, stream);
                        }
                        ((Stream.MultiSinkCapableStream) pair.component).setSink(sinkIdentifier, pas);
                    } else if (nidi.partitionKeys == null || nidi.partitionKeys.isEmpty()) {
                        ((Stream.MultiSinkCapableStream) pair.component).setSink(sinkIdentifier, stream);
                    } else {
                        /*
               * generally speaking we do not have partitions on the inline streams so the control should not
               * come here but if it comes, then we are ready to handle it using the partition aware streams.
               */
                        PartitionAwareSink<Object> pas = new PartitionAwareSink<>(streamCodec == null ? nonSerializingStreamCodec : (StreamCodec<Object>) streamCodec, nidi.partitionKeys, nidi.partitionMask, stream);
                        ((Stream.MultiSinkCapableStream) pair.component).setSink(sinkIdentifier, pas);
                    }
                    String streamSinkId = pair.context.getSinkId();
                    if (streamSinkId == null) {
                        pair.context.setSinkId(sinkIdentifier);
                    } else {
                        pair.context.setSinkId(streamSinkId.concat(", ").concat(sinkIdentifier));
                    }
                }
            }
        }
    }
    setupOiOGroups(oioNodes);
    if (!inputNodes.isEmpty()) {
        WindowGenerator windowGenerator = setupWindowGenerator(smallestCheckpointedWindowId);
        for (OperatorDeployInfo ndi : inputNodes) {
            generators.put(ndi.id, windowGenerator);
            Node<?> node = nodes.get(ndi.id);
            SweepableReservoir reservoir = windowGenerator.acquireReservoir(String.valueOf(ndi.id), 1024);
            if (ndi.checkpoint.windowId >= 0) {
                node.connectInputPort(Node.INPUT, new WindowIdActivatedReservoir(Integer.toString(ndi.id), reservoir, ndi.checkpoint.windowId));
            }
            node.connectInputPort(Node.INPUT, reservoir);
        }
    }
}
Also used : InetSocketAddress(java.net.InetSocketAddress) ArrayList(java.util.ArrayList) StreamCodec(com.datatorrent.api.StreamCodec) BufferServerSubscriber(com.datatorrent.stram.stream.BufferServerSubscriber) PartitionAwareSinkForPersistence(com.datatorrent.stram.stream.PartitionAwareSinkForPersistence) StreamCodecWrapperForPersistance(com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance) ComponentContextPair(com.datatorrent.stram.ComponentContextPair) FastSubscriber(com.datatorrent.stram.stream.FastSubscriber) InlineStream(com.datatorrent.stram.stream.InlineStream) OiOStream(com.datatorrent.stram.stream.OiOStream) InlineStream(com.datatorrent.stram.stream.InlineStream) MuxStream(com.datatorrent.stram.stream.MuxStream) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) PartitionAwareSink(com.datatorrent.stram.stream.PartitionAwareSink) OperatorDeployInfo(com.datatorrent.stram.api.OperatorDeployInfo) Checkpoint(com.datatorrent.stram.api.Checkpoint) Checkpoint(com.datatorrent.stram.api.Checkpoint) MuxStream(com.datatorrent.stram.stream.MuxStream) OiOStream(com.datatorrent.stram.stream.OiOStream) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) InetAddress(java.net.InetAddress)

Example 3 with StreamCodecWrapperForPersistance

use of com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance in project apex-core by apache.

the class PhysicalPlan method updatePartitionsInfoForPersistOperator.

private void updatePartitionsInfoForPersistOperator(LogicalPlan dag) {
    // StreamCodec for persist operator
    try {
        for (OperatorMeta n : dag.getAllOperators()) {
            for (StreamMeta s : n.getOutputStreams().values()) {
                if (s.getPersistOperator() != null) {
                    InputPortMeta persistInputPort = s.getPersistOperatorInputPort();
                    StreamCodecWrapperForPersistance<?> persistCodec = (StreamCodecWrapperForPersistance<?>) persistInputPort.getStreamCodec();
                    if (persistCodec == null) {
                        continue;
                    }
                    // Logging is enabled for the stream
                    for (InputPortMeta portMeta : s.getSinksToPersist()) {
                        updatePersistOperatorWithSinkPartitions(persistInputPort, s.getPersistOperator(), persistCodec, portMeta);
                    }
                }
                // Check partitioning for persist operators per sink too
                for (Map.Entry<InputPortMeta, InputPortMeta> entry : s.sinkSpecificPersistInputPortMap.entrySet()) {
                    InputPortMeta persistInputPort = entry.getValue();
                    StreamCodec<?> streamCodec = persistInputPort.getStreamCodec();
                    if (streamCodec != null && streamCodec instanceof StreamCodecWrapperForPersistance) {
                        updatePersistOperatorWithSinkPartitions(persistInputPort, s.sinkSpecificPersistOperatorMap.get(entry.getKey()), (StreamCodecWrapperForPersistance<?>) streamCodec, entry.getKey());
                    }
                }
            }
        }
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}
Also used : StreamMeta(com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta) OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) Map(java.util.Map) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) LinkedHashMap(java.util.LinkedHashMap) IOException(java.io.IOException) StreamCodecWrapperForPersistance(com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance)

Example 4 with StreamCodecWrapperForPersistance

use of com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance in project apex-core by apache.

the class PhysicalPlan method updatePersistOperatorStreamCodec.

private void updatePersistOperatorStreamCodec(LogicalPlan dag) {
    HashMap<StreamMeta, StreamCodec<?>> streamMetaToCodecMap = new HashMap<>();
    try {
        for (OperatorMeta n : dag.getAllOperators()) {
            for (StreamMeta s : n.getOutputStreams().values()) {
                if (s.getPersistOperator() != null) {
                    Map<InputPortMeta, StreamCodec<?>> inputStreamCodecs = new HashMap<>();
                    // Logging is enabled for the stream
                    for (InputPortMeta portMeta : s.getSinksToPersist()) {
                        StreamCodec<?> inputStreamCodec = portMeta.getStreamCodec();
                        if (inputStreamCodec != null) {
                            boolean alreadyAdded = false;
                            for (StreamCodec<?> codec : inputStreamCodecs.values()) {
                                if (inputStreamCodec.equals(codec)) {
                                    alreadyAdded = true;
                                    break;
                                }
                            }
                            if (!alreadyAdded) {
                                inputStreamCodecs.put(portMeta, inputStreamCodec);
                            }
                        }
                    }
                    if (inputStreamCodecs.isEmpty()) {
                    // Stream codec not specified
                    // So everything out of Source should be captured without any
                    // StreamCodec
                    // Do nothing
                    } else {
                        // Create Wrapper codec for Stream persistence using all unique
                        // stream codecs
                        // Logger should write merged or union of all input stream codecs
                        StreamCodec<?> specifiedCodecForLogger = s.getPersistOperatorInputPort().getStreamCodec();
                        @SuppressWarnings({ "unchecked", "rawtypes" }) StreamCodecWrapperForPersistance<Object> codec = new StreamCodecWrapperForPersistance(inputStreamCodecs, specifiedCodecForLogger);
                        streamMetaToCodecMap.put(s, codec);
                    }
                }
            }
        }
        for (java.util.Map.Entry<StreamMeta, StreamCodec<?>> entry : streamMetaToCodecMap.entrySet()) {
            dag.setInputPortAttribute(entry.getKey().getPersistOperatorInputPort().getPort(), PortContext.STREAM_CODEC, entry.getValue());
        }
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}
Also used : OperatorMeta(com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta) InputPortMeta(com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) StreamCodec(com.datatorrent.api.StreamCodec) IOException(java.io.IOException) StreamCodecWrapperForPersistance(com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance) StreamMeta(com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta) Map(java.util.Map) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

StreamCodecWrapperForPersistance (com.datatorrent.stram.plan.logical.StreamCodecWrapperForPersistance)4 StreamCodec (com.datatorrent.api.StreamCodec)3 InputPortMeta (com.datatorrent.stram.plan.logical.LogicalPlan.InputPortMeta)3 HashMap (java.util.HashMap)3 LinkedHashMap (java.util.LinkedHashMap)3 Map (java.util.Map)3 OperatorMeta (com.datatorrent.stram.plan.logical.LogicalPlan.OperatorMeta)2 StreamMeta (com.datatorrent.stram.plan.logical.LogicalPlan.StreamMeta)2 IOException (java.io.IOException)2 ConcurrentMap (java.util.concurrent.ConcurrentMap)2 StreamMeta (com.datatorrent.api.DAG.StreamMeta)1 PartitionKeys (com.datatorrent.api.Partitioner.PartitionKeys)1 StatsListener (com.datatorrent.api.StatsListener)1 ComponentContextPair (com.datatorrent.stram.ComponentContextPair)1 PartitioningTest (com.datatorrent.stram.PartitioningTest)1 StreamingContainerManager (com.datatorrent.stram.StreamingContainerManager)1 StreamingContainerManagerTest (com.datatorrent.stram.StreamingContainerManagerTest)1 Checkpoint (com.datatorrent.stram.api.Checkpoint)1 OperatorDeployInfo (com.datatorrent.stram.api.OperatorDeployInfo)1 DefaultKryoStreamCodec (com.datatorrent.stram.plan.logical.DefaultKryoStreamCodec)1