You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ignite.apache.org by GitBox <gi...@apache.org> on 2021/12/24 10:57:17 UTC

[GitHub] [ignite-3] rpuch commented on a change in pull request #521: IGNITE-16155 Implement (un)marshalling of built-ins

rpuch commented on a change in pull request #521:
URL: https://github.com/apache/ignite-3/pull/521#discussion_r774976932



##########
File path: modules/network/src/main/java/org/apache/ignite/internal/network/serialization/marshal/BuiltInContainerMarshallers.java
##########
@@ -0,0 +1,198 @@
+/*
+ * 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.ignite.internal.network.serialization.marshal;
+
+import static java.util.Collections.singletonList;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.IntFunction;
+import org.apache.ignite.internal.network.serialization.ClassDescriptor;
+
+/**
+ * Utility to (un)marshal built-in collections and maps.
+ */
+class BuiltInContainerMarshallers {
+    /**
+     * Map of all classes which are built-in collections AND may have different sizes AND are mutable. This makes
+     * them eligible for a generic unmarshal algorithm: read length, create an empty collection, then read N elements
+     * and add each of them into the collection.
+     */
+    private final Map<Class<?>, IntFunction<? extends Collection<?>>> mutableBuiltInCollectionFactories = Map.of(
+            ArrayList.class, ArrayList::new,
+            LinkedList.class, len -> new LinkedList<>(),
+            HashSet.class, HashSet::new,
+            LinkedHashSet.class, LinkedHashSet::new
+    );
+
+    /**
+     * Map of all classes which are built-in maps AND may have different sizes AND are mutable. This makes
+     * them eligible for a generic unmarshal algorithm: read length, create an empty map, then read N entries
+     * and put each of them into the map.
+     */
+    private final Map<Class<?>, IntFunction<? extends Map<?, ?>>> mutableBuiltInMapFactories = Map.of(
+            HashMap.class, HashMap::new,
+            LinkedHashMap.class, LinkedHashMap::new
+    );
+
+    private final TrackingMarshaller trackingMarshaller;
+
+    BuiltInContainerMarshallers(TrackingMarshaller trackingMarshaller) {
+        this.trackingMarshaller = trackingMarshaller;
+    }
+
+    List<ClassDescriptor> writeGenericRefArray(Object[] array, ClassDescriptor arrayDescriptor, DataOutput output)
+            throws IOException, MarshalException {
+        output.writeUTF(array.getClass().getComponentType().getName());
+        return writeCollection(Arrays.asList(array), arrayDescriptor, output);
+    }
+
+    <T> T[] readGenericRefArray(DataInput input, ValueReader<T> elementReader)
+            throws IOException, UnmarshalException {
+        return BuiltInMarshalling.readGenericRefArray(input, elementReader);
+    }
+
+    List<ClassDescriptor> writeBuiltInCollection(Collection<?> object, ClassDescriptor descriptor, DataOutput output)
+            throws IOException, MarshalException {
+        if (supportsAsMutableBuiltInCollection(descriptor)) {
+            return writeCollection(object, descriptor, output);
+        } else if (descriptor.isSingletonList()) {
+            return writeSingletonList(object, descriptor, output);
+        } else {
+            throw new IllegalStateException("Marshalling of " + descriptor.clazz() + " is not supported, but it's marked as a built-in");
+        }
+    }
+
+    /**
+     * Returns {@code true} if the given descriptor is supported as a built-in mutable collection. Such types
+     * are eligible for a generic unmarshal algorithm: read length, create an empty collection, then read N elements
+     * and add each of them into the collection.
+     *
+     * @param descriptor the descriptor to check
+     * @return {@code true} if the given descriptor is supported as a built-in mutable collection
+     */
+    private boolean supportsAsMutableBuiltInCollection(ClassDescriptor descriptor) {
+        return mutableBuiltInCollectionFactories.containsKey(descriptor.clazz());
+    }
+
+    private List<ClassDescriptor> writeCollection(Collection<?> collection, ClassDescriptor collectionDescriptor, DataOutput output)
+            throws IOException, MarshalException {
+        Set<ClassDescriptor> usedDescriptors = new HashSet<>();
+        usedDescriptors.add(collectionDescriptor);
+
+        BuiltInMarshalling.writeCollection(collection, output, writerAddingUsedDescriptor(usedDescriptors));
+
+        return List.copyOf(usedDescriptors);
+    }
+
+    private <T> ValueWriter<T> writerAddingUsedDescriptor(Set<ClassDescriptor> usedDescriptors) {
+        return (elem, out) -> {
+            List<ClassDescriptor> elementDescriptors = trackingMarshaller.marshal(elem, out);
+            usedDescriptors.addAll(elementDescriptors);
+        };
+    }
+
+    private List<ClassDescriptor> writeSingletonList(Collection<?> collection, ClassDescriptor listDescriptor, DataOutput output)
+            throws MarshalException, IOException {
+        assert collection.size() == 1;
+
+        Object element = collection.iterator().next();
+
+        Set<ClassDescriptor> usedDescriptors = new HashSet<>();
+        usedDescriptors.add(listDescriptor);
+
+        List<ClassDescriptor> descriptorsFromElement = trackingMarshaller.marshal(element, output);
+        usedDescriptors.addAll(descriptorsFromElement);
+
+        return List.copyOf(usedDescriptors);
+    }
+
+    <T, C extends Collection<T>> C readBuiltInCollection(
+            ClassDescriptor collectionDescriptor,
+            ValueReader<T> elementReader,
+            DataInput input
+    ) throws UnmarshalException, IOException {
+        if (collectionDescriptor.isSingletonList()) {
+            @SuppressWarnings("unchecked")
+            C castResult = (C) singletonList(elementReader.read(input));

Review comment:
       'cast' here is past participle, like 'something that was cast to a correct type'




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@ignite.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org