From e5f78b07275e3dbc50902f4a231069c7eb8cefc0 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Mon, 29 Apr 2024 20:52:59 +0800 Subject: [PATCH 1/8] feat(java): support user context for serialize global data --- .../src/main/java/org/apache/fury/Fury.java | 24 ++--- .../java/org/apache/fury/config/Config.java | 12 +++ .../org/apache/fury/config/FuryBuilder.java | 7 ++ .../apache/fury/resolver/ClassResolver.java | 44 +++++++- .../fury/resolver/SerializationContext.java | 14 +++ .../fury/resolver/UserContextResolver.java | 37 +++++++ .../apache/fury/resolver/UserContextTest.java | 100 ++++++++++++++++++ 7 files changed, 223 insertions(+), 15 deletions(-) create mode 100644 java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java create mode 100644 java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java diff --git a/java/fury-core/src/main/java/org/apache/fury/Fury.java b/java/fury-core/src/main/java/org/apache/fury/Fury.java index 8115ed5aca..5e7f6b0462 100644 --- a/java/fury-core/src/main/java/org/apache/fury/Fury.java +++ b/java/fury-core/src/main/java/org/apache/fury/Fury.java @@ -305,8 +305,8 @@ public void resetBuffer() { private void write(MemoryBuffer buffer, Object obj) { int startOffset = buffer.writerIndex(); - boolean shareMetaContext = config.shareMetaContext(); - if (shareMetaContext) { + boolean shareGlobalContext = config.shareGlobalContext(); + if (shareGlobalContext) { buffer.writeInt32(-1); // preserve 4-byte for nativeObjects start offsets. } // reduce caller stack @@ -315,9 +315,9 @@ private void write(MemoryBuffer buffer, Object obj) { classResolver.writeClass(buffer, classInfo); writeData(buffer, classInfo, obj); } - if (shareMetaContext) { + if (shareGlobalContext) { buffer.putInt32(startOffset, buffer.writerIndex()); - classResolver.writeClassDefs(buffer); + classResolver.writeGlobalContext(buffer); } } @@ -754,8 +754,8 @@ public Object deserialize(MemoryBuffer buffer, Iterable outOfBandB if (isTargetXLang) { obj = xdeserializeInternal(buffer); } else { - if (config.shareMetaContext()) { - classResolver.readClassDefs(buffer); + if (config.shareGlobalContext()) { + classResolver.readGlobalContext(buffer); } obj = readRef(buffer); } @@ -1025,7 +1025,7 @@ public void serializeJavaObject(MemoryBuffer buffer, Object obj) { if (depth != 0) { throwDepthSerializationException(); } - if (config.shareMetaContext()) { + if (config.shareGlobalContext()) { int startOffset = buffer.writerIndex(); buffer.writeInt32(-1); // preserve 4-byte for nativeObjects start offsets. if (!refResolver.writeRefOrNull(buffer, obj)) { @@ -1033,7 +1033,7 @@ public void serializeJavaObject(MemoryBuffer buffer, Object obj) { writeData(buffer, classInfo, obj); } buffer.putInt32(startOffset, buffer.writerIndex()); - classResolver.writeClassDefs(buffer); + classResolver.writeGlobalContext(buffer); } else { if (!refResolver.writeRefOrNull(buffer, obj)) { ClassInfo classInfo = classResolver.getOrUpdateClassInfo(obj.getClass()); @@ -1070,8 +1070,8 @@ public T deserializeJavaObject(MemoryBuffer buffer, Class cls) { if (depth != 0) { throwDepthDeserializationException(); } - if (config.shareMetaContext()) { - classResolver.readClassDefs(buffer); + if (config.shareGlobalContext()) { + classResolver.readGlobalContext(buffer); } T obj; int nextReadRefId = refResolver.tryPreserveRefId(buffer); @@ -1184,8 +1184,8 @@ public Object deserializeJavaObjectAndClass(MemoryBuffer buffer) { if (depth != 0) { throwDepthDeserializationException(); } - if (config.shareMetaContext()) { - classResolver.readClassDefs(buffer); + if (config.shareGlobalContext()) { + classResolver.readGlobalContext(buffer); } return readRef(buffer); } catch (Throwable t) { diff --git a/java/fury-core/src/main/java/org/apache/fury/config/Config.java b/java/fury-core/src/main/java/org/apache/fury/config/Config.java index 2e7deb60d9..26140baa40 100644 --- a/java/fury-core/src/main/java/org/apache/fury/config/Config.java +++ b/java/fury-core/src/main/java/org/apache/fury/config/Config.java @@ -49,7 +49,9 @@ public class Config implements Serializable { private final boolean requireClassRegistration; private final boolean suppressClassRegistrationWarnings; private final boolean registerGuavaTypes; + private final boolean shareGlobalContext; private final boolean shareMetaContext; + private final boolean shareUserContext; private final boolean asyncCompilationEnabled; private final boolean deserializeUnexistedClass; private final boolean scalaOptimizationEnabled; @@ -75,6 +77,8 @@ public Config(FuryBuilder builder) { checkJdkClassSerializable = builder.checkJdkClassSerializable; defaultJDKStreamSerializerType = builder.defaultJDKStreamSerializerType; shareMetaContext = builder.shareMetaContext; + shareUserContext = builder.shareUserContext; + shareGlobalContext = shareMetaContext || shareUserContext; deserializeUnexistedClass = builder.deserializeUnexistedClass; if (deserializeUnexistedClass) { // Only in meta share mode or compatibleMode, fury knows how to deserialize @@ -182,6 +186,14 @@ public boolean shareMetaContext() { return shareMetaContext; } + public boolean shareUserContext() { + return shareUserContext; + } + + public boolean shareGlobalContext() { + return shareGlobalContext; + } + /** * Whether deserialize/skip data of un-existed class. If not enabled, an exception will be thrown * if class not exist. diff --git a/java/fury-core/src/main/java/org/apache/fury/config/FuryBuilder.java b/java/fury-core/src/main/java/org/apache/fury/config/FuryBuilder.java index 9df183a960..9a6154fc19 100644 --- a/java/fury-core/src/main/java/org/apache/fury/config/FuryBuilder.java +++ b/java/fury-core/src/main/java/org/apache/fury/config/FuryBuilder.java @@ -69,6 +69,7 @@ public final class FuryBuilder { Class defaultJDKStreamSerializerType = ObjectStreamSerializer.class; boolean requireClassRegistration = true; boolean shareMetaContext = false; + boolean shareUserContext = false; boolean codeGenEnabled = true; Boolean deserializeUnexistedClass; boolean asyncCompilationEnabled = false; @@ -238,6 +239,12 @@ public FuryBuilder withMetaContextShare(boolean shareMetaContext) { return this; } + /** Whether to enable user context share feature. */ + public FuryBuilder withUserContextShare(boolean shareUserContext) { + this.shareUserContext = shareUserContext; + return this; + } + /** * Whether deserialize/skip data of un-existed class. * diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index 30ec3b9b05..eee0b7d162 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -1408,6 +1408,25 @@ public void writeClassDefs(MemoryBuffer buffer) { metaContext.writingClassDefs.clear(); } + /** write user context by register order. */ + public void writeUserContext(MemoryBuffer buffer) { + final Map userContextResolvers = + fury.getSerializationContext().getUserContextResolvers(); + for (UserContextResolver userContextResolver : userContextResolvers.values()) { + userContextResolver.write(buffer); + } + } + + /** after all data, write share meta context and user context. */ + public void writeGlobalContext(MemoryBuffer buffer) { + if (fury.getConfig().shareMetaContext()) { + writeClassDefs(buffer); + } + if (fury.getConfig().shareUserContext()) { + writeUserContext(buffer); + } + } + /** * Ensure all class definition are read and populated, even there are deserialization exception * such as ClassNotFound. So next time a class def written previously identified by an id can be @@ -1415,9 +1434,6 @@ public void writeClassDefs(MemoryBuffer buffer) { */ public void readClassDefs(MemoryBuffer buffer) { MetaContext metaContext = fury.getSerializationContext().getMetaContext(); - int classDefOffset = buffer.readInt32(); - int readerIndex = buffer.readerIndex(); - buffer.readerIndex(classDefOffset); int numClassDefs = buffer.readVarUint32Small14(); for (int i = 0; i < numClassDefs; i++) { long id = buffer.readInt64(); @@ -1437,6 +1453,28 @@ public void readClassDefs(MemoryBuffer buffer) { // can be created still. metaContext.readClassInfos.add(null); } + } + + /** read user context by register order. */ + public void readUserContext(MemoryBuffer buffer) { + final Map userContextResolvers = + fury.getSerializationContext().getUserContextResolvers(); + for (UserContextResolver userContextResolver : userContextResolvers.values()) { + userContextResolver.read(buffer); + } + } + + /** read share meta context and user context before read data. */ + public void readGlobalContext(MemoryBuffer buffer) { + int globalContextOffSet = buffer.readInt32(); + int readerIndex = buffer.readerIndex(); + buffer.readerIndex(globalContextOffSet); + if (fury.getConfig().shareMetaContext()) { + readClassDefs(buffer); + } + if (fury.getConfig().shareUserContext()) { + readUserContext(buffer); + } buffer.readerIndex(readerIndex); } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index ed5aead62a..69a3c9970c 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -20,6 +20,8 @@ package org.apache.fury.resolver; import java.util.IdentityHashMap; +import java.util.LinkedHashMap; +import java.util.Map; import org.apache.fury.config.FuryBuilder; /** @@ -30,6 +32,7 @@ public final class SerializationContext { private final IdentityHashMap objects = new IdentityHashMap<>(); private MetaContext metaContext; + private final Map userContextResolvers = new LinkedHashMap<>(); /** Return the previous value associated with key, or null. */ public Object add(Object key, Object value) { @@ -58,10 +61,21 @@ public void setMetaContext(MetaContext metaContext) { this.metaContext = metaContext; } + public Map getUserContextResolvers() { + return userContextResolvers; + } + + public void registerUserContextResolver(String name, UserContextResolver userContextResolver) { + userContextResolvers.put(name, userContextResolver); + } + public void reset() { if (objects.size() > 0) { objects.clear(); } metaContext = null; + if (!userContextResolvers.isEmpty()) { + userContextResolvers.clear(); + } } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java new file mode 100644 index 0000000000..9ec91dec3e --- /dev/null +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java @@ -0,0 +1,37 @@ +/* + * 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.fury.resolver; + +import org.apache.fury.Fury; +import org.apache.fury.memory.MemoryBuffer; + +/** write/read user custom global data after metaContext data. */ +public abstract class UserContextResolver { + + protected final Fury fury; + + public UserContextResolver(Fury fury) { + this.fury = fury; + } + + abstract void write(MemoryBuffer buffer); + + abstract void read(MemoryBuffer buffer); +} diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java new file mode 100644 index 0000000000..00d5e5fe0a --- /dev/null +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -0,0 +1,100 @@ +/* + * 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.fury.resolver; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.apache.fury.Fury; +import org.apache.fury.FuryTestBase; +import org.apache.fury.config.Language; +import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.test.bean.Foo; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class UserContextTest extends FuryTestBase { + + public static class StringUserContextResolver extends UserContextResolver { + + public String data; + + public StringUserContextResolver(Fury fury) { + super(fury); + } + + @Override + void write(MemoryBuffer buffer) { + fury.writeJavaStringRef(buffer, data); + } + + @Override + void read(MemoryBuffer buffer) { + data = fury.readJavaStringRef(buffer); + } + } + + private Fury buildFury() { + return Fury.builder() + .withLanguage(Language.JAVA) + .withUserContextShare(true) + .requireClassRegistration(false) + .build(); + } + + @Test + public void checkShareUserContext() { + Fury writrfury = buildFury(); + final List resolvers = getResolver(writrfury, 4, false); + final int size = resolvers.size(); + for (int i = 0; i < size; i++) { + writrfury + .getSerializationContext() + .registerUserContextResolver(String.valueOf(i), resolvers.get(i)); + } + final Foo o = Foo.create(); + final byte[] bytes = writrfury.serialize(o); + Fury readFury = buildFury(); + final List readResolvers = getResolver(readFury, 4, true); + for (int i = 0; i < size; i++) { + readFury + .getSerializationContext() + .registerUserContextResolver(String.valueOf(i), readResolvers.get(i)); + } + Assert.assertEquals(readFury.deserialize(bytes), o); + for (int i = 0; i < size; i++) { + Assert.assertEquals(resolvers.get(i).data, readResolvers.get(i).data); + } + } + + private List getResolver(Fury fury, int num, boolean empty) { + return IntStream.range(0, num) + .mapToObj( + idx -> { + final StringUserContextResolver userContextResolver = + new StringUserContextResolver(fury); + if (!empty) { + userContextResolver.data = "data" + idx; + } + return userContextResolver; + }) + .collect(Collectors.toList()); + } +} From f81760b0ced751f5d5fe1499bb810533ed205b5f Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Tue, 30 Apr 2024 11:48:31 +0800 Subject: [PATCH 2/8] clear user data after serialize/deserialize --- .../fury/resolver/SerializationContext.java | 4 +- .../fury/resolver/UserContextResolver.java | 3 + .../apache/fury/resolver/UserContextTest.java | 82 +++++++++++++++---- 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index 69a3c9970c..aec52ff09a 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -74,8 +74,8 @@ public void reset() { objects.clear(); } metaContext = null; - if (!userContextResolvers.isEmpty()) { - userContextResolvers.clear(); + for (UserContextResolver userContextResolver : userContextResolvers.values()) { + userContextResolver.reset(); } } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java index 9ec91dec3e..af2e69d1a7 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java @@ -34,4 +34,7 @@ public UserContextResolver(Fury fury) { abstract void write(MemoryBuffer buffer); abstract void read(MemoryBuffer buffer); + + /** write/read end should clear user data. */ + abstract void reset(); } diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index 00d5e5fe0a..0cb98a4ce1 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -19,19 +19,25 @@ package org.apache.fury.resolver; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.apache.fury.Fury; import org.apache.fury.FuryTestBase; import org.apache.fury.config.Language; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.serializer.ObjectSerializer; +import org.apache.fury.serializer.Serializer; import org.apache.fury.test.bean.Foo; import org.testng.Assert; import org.testng.annotations.Test; public class UserContextTest extends FuryTestBase { + private static final int NUM = 10; + public static class StringUserContextResolver extends UserContextResolver { public String data; @@ -49,6 +55,45 @@ void write(MemoryBuffer buffer) { void read(MemoryBuffer buffer) { data = fury.readJavaStringRef(buffer); } + + @Override + void reset() { + data = null; + } + } + + public static class FooSerializer extends Serializer { + + private final ObjectSerializer serializer; + + public FooSerializer(Fury fury, Class type) { + super(fury, type); + serializer = new ObjectSerializer<>(fury, Foo.class); + } + + @Override + public void write(MemoryBuffer buffer, Foo value) { + final Map userContextResolvers = + fury.getSerializationContext().getUserContextResolvers(); + for (int i = 0; i < NUM; i++) { + final StringUserContextResolver userContextResolver = + (StringUserContextResolver) userContextResolvers.get(String.valueOf(i)); + userContextResolver.data = getData(i); + } + serializer.write(buffer, value); + } + + @Override + public Foo read(MemoryBuffer buffer) { + final Map userContextResolvers = + fury.getSerializationContext().getUserContextResolvers(); + for (int i = 0; i < NUM; i++) { + final StringUserContextResolver userContextResolver = + (StringUserContextResolver) userContextResolvers.get(String.valueOf(i)); + Assert.assertEquals(userContextResolver.data, getData(i)); + } + return serializer.read(buffer); + } } private Fury buildFury() { @@ -61,26 +106,23 @@ private Fury buildFury() { @Test public void checkShareUserContext() { - Fury writrfury = buildFury(); - final List resolvers = getResolver(writrfury, 4, false); - final int size = resolvers.size(); - for (int i = 0; i < size; i++) { - writrfury - .getSerializationContext() - .registerUserContextResolver(String.valueOf(i), resolvers.get(i)); + Fury fury = buildFury(); + fury.registerSerializer(Foo.class, FooSerializer.class); + List resolvers = new ArrayList<>(NUM); + for (int i = 0; i < NUM; i++) { + final StringUserContextResolver userContextResolver = new StringUserContextResolver(fury); + fury.getSerializationContext() + .registerUserContextResolver(String.valueOf(i), userContextResolver); + resolvers.add(userContextResolver); } final Foo o = Foo.create(); - final byte[] bytes = writrfury.serialize(o); - Fury readFury = buildFury(); - final List readResolvers = getResolver(readFury, 4, true); - for (int i = 0; i < size; i++) { - readFury - .getSerializationContext() - .registerUserContextResolver(String.valueOf(i), readResolvers.get(i)); + final byte[] bytes = fury.serialize(o); + for (int i = 0; i < NUM; i++) { + Assert.assertNull(resolvers.get(i).data); } - Assert.assertEquals(readFury.deserialize(bytes), o); - for (int i = 0; i < size; i++) { - Assert.assertEquals(resolvers.get(i).data, readResolvers.get(i).data); + Assert.assertEquals(fury.deserialize(bytes), o); + for (int i = 0; i < NUM; i++) { + Assert.assertNull(resolvers.get(i).data); } } @@ -91,10 +133,14 @@ private List getResolver(Fury fury, int num, boolean final StringUserContextResolver userContextResolver = new StringUserContextResolver(fury); if (!empty) { - userContextResolver.data = "data" + idx; + userContextResolver.data = getData(idx); } return userContextResolver; }) .collect(Collectors.toList()); } + + private static String getData(int idx) { + return "data" + idx; + } } From 84538c64b447eac01e3ab716ebbadf04c9113b37 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Tue, 30 Apr 2024 14:29:59 +0800 Subject: [PATCH 3/8] fix method access type and config --- .../src/main/java/org/apache/fury/config/Config.java | 4 ++++ .../java/org/apache/fury/resolver/UserContextResolver.java | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/config/Config.java b/java/fury-core/src/main/java/org/apache/fury/config/Config.java index 26140baa40..7b0224299a 100644 --- a/java/fury-core/src/main/java/org/apache/fury/config/Config.java +++ b/java/fury-core/src/main/java/org/apache/fury/config/Config.java @@ -248,6 +248,8 @@ public boolean equals(Object o) { && suppressClassRegistrationWarnings == config.suppressClassRegistrationWarnings && registerGuavaTypes == config.registerGuavaTypes && shareMetaContext == config.shareMetaContext + && shareUserContext == config.shareUserContext + && shareGlobalContext == config.shareGlobalContext && asyncCompilationEnabled == config.asyncCompilationEnabled && deserializeUnexistedClass == config.deserializeUnexistedClass && scalaOptimizationEnabled == config.scalaOptimizationEnabled @@ -278,6 +280,8 @@ public int hashCode() { suppressClassRegistrationWarnings, registerGuavaTypes, shareMetaContext, + shareUserContext, + shareGlobalContext, asyncCompilationEnabled, deserializeUnexistedClass, scalaOptimizationEnabled); diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java index af2e69d1a7..53d7e7c855 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java @@ -31,10 +31,10 @@ public UserContextResolver(Fury fury) { this.fury = fury; } - abstract void write(MemoryBuffer buffer); + public abstract void write(MemoryBuffer buffer); - abstract void read(MemoryBuffer buffer); + public abstract void read(MemoryBuffer buffer); /** write/read end should clear user data. */ - abstract void reset(); + public abstract void reset(); } From 883845f1575d162061d28ec3e2dd2a05de93f7b0 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Tue, 30 Apr 2024 14:41:02 +0800 Subject: [PATCH 4/8] fix method access type and config --- .../test/java/org/apache/fury/resolver/UserContextTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index 0cb98a4ce1..8e38574fce 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -47,17 +47,17 @@ public StringUserContextResolver(Fury fury) { } @Override - void write(MemoryBuffer buffer) { + public void write(MemoryBuffer buffer) { fury.writeJavaStringRef(buffer, data); } @Override - void read(MemoryBuffer buffer) { + public void read(MemoryBuffer buffer) { data = fury.readJavaStringRef(buffer); } @Override - void reset() { + public void reset() { data = null; } } From d3acd244963b2ff634a351e52f078bb8fbf450e8 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Tue, 30 Apr 2024 17:49:04 +0800 Subject: [PATCH 5/8] extract public user context method to BaseFury --- .../java/org/apache/fury/AbstractThreadSafeFury.java | 7 +++++++ .../src/main/java/org/apache/fury/BaseFury.java | 9 +++++++++ java/fury-core/src/main/java/org/apache/fury/Fury.java | 7 +++++++ .../org/apache/fury/resolver/SerializationContext.java | 2 ++ .../java/org/apache/fury/resolver/UserContextTest.java | 3 +-- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java index 752a4dc22c..6d8238efa5 100644 --- a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java @@ -21,6 +21,7 @@ import java.util.function.Consumer; import java.util.function.Function; +import org.apache.fury.resolver.UserContextResolver; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -65,5 +66,11 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { processCallback(fury -> fury.setSerializerFactory(serializerFactory)); } + @Override + public void registerUserContext( + String name, Function userContextResolverCtr) { + processCallback(fury -> fury.registerUserContext(name, userContextResolverCtr)); + } + protected abstract void processCallback(Consumer callback); } diff --git a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java index 1ee1aec82a..21df87513a 100644 --- a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java @@ -24,6 +24,7 @@ import org.apache.fury.io.FuryInputStream; import org.apache.fury.io.FuryReadableChannel; import org.apache.fury.memory.MemoryBuffer; +import org.apache.fury.resolver.UserContextResolver; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -82,6 +83,14 @@ public interface BaseFury { void setSerializerFactory(SerializerFactory serializerFactory); + /** + * Register user context. + * + * @param name user context name to register + * @param userContextResolverCtr constructor for usr context + */ + void registerUserContext(String name, Function userContextResolverCtr); + /** Return serialized obj as a byte array. */ byte[] serialize(Object obj); diff --git a/java/fury-core/src/main/java/org/apache/fury/Fury.java b/java/fury-core/src/main/java/org/apache/fury/Fury.java index 5e7f6b0462..d880297699 100644 --- a/java/fury-core/src/main/java/org/apache/fury/Fury.java +++ b/java/fury-core/src/main/java/org/apache/fury/Fury.java @@ -49,6 +49,7 @@ import org.apache.fury.resolver.NoRefResolver; import org.apache.fury.resolver.RefResolver; import org.apache.fury.resolver.SerializationContext; +import org.apache.fury.resolver.UserContextResolver; import org.apache.fury.serializer.ArraySerializers; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.BufferObject; @@ -186,6 +187,12 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { classResolver.setSerializerFactory(serializerFactory); } + @Override + public void registerUserContext( + String name, Function userContextResolverCtr) { + serializationContext.registerUserContextResolver(name, userContextResolverCtr.apply(this)); + } + public SerializerFactory getSerializerFactory() { return classResolver.getSerializerFactory(); } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index aec52ff09a..fe012592c8 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.Map; import org.apache.fury.config.FuryBuilder; +import org.apache.fury.util.Preconditions; /** * A context is used to add some context-related information, so that the serializers can set up @@ -66,6 +67,7 @@ public Map getUserContextResolvers() { } public void registerUserContextResolver(String name, UserContextResolver userContextResolver) { + Preconditions.checkState(!userContextResolvers.containsKey(name)); userContextResolvers.put(name, userContextResolver); } diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index 8e38574fce..101189219b 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -111,8 +111,7 @@ public void checkShareUserContext() { List resolvers = new ArrayList<>(NUM); for (int i = 0; i < NUM; i++) { final StringUserContextResolver userContextResolver = new StringUserContextResolver(fury); - fury.getSerializationContext() - .registerUserContextResolver(String.valueOf(i), userContextResolver); + fury.registerUserContext(String.valueOf(i), StringUserContextResolver::new); resolvers.add(userContextResolver); } final Foo o = Foo.create(); From bcc81b5746596e3918e016d1e269d4a16908f7be Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Tue, 7 May 2024 12:55:51 +0800 Subject: [PATCH 6/8] rename UserContextResolver to UserContext --- .../apache/fury/AbstractThreadSafeFury.java | 5 ++-- .../main/java/org/apache/fury/BaseFury.java | 4 +-- .../src/main/java/org/apache/fury/Fury.java | 5 ++-- .../apache/fury/resolver/ClassResolver.java | 12 ++++----- .../fury/resolver/SerializationContext.java | 12 ++++----- ...rContextResolver.java => UserContext.java} | 4 +-- .../apache/fury/resolver/UserContextTest.java | 27 +++++++++---------- 7 files changed, 33 insertions(+), 36 deletions(-) rename java/fury-core/src/main/java/org/apache/fury/resolver/{UserContextResolver.java => UserContext.java} (93%) diff --git a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java index 6d8238efa5..945656c926 100644 --- a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java @@ -21,7 +21,7 @@ import java.util.function.Consumer; import java.util.function.Function; -import org.apache.fury.resolver.UserContextResolver; +import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -67,8 +67,7 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { } @Override - public void registerUserContext( - String name, Function userContextResolverCtr) { + public void registerUserContext(String name, Function userContextResolverCtr) { processCallback(fury -> fury.registerUserContext(name, userContextResolverCtr)); } diff --git a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java index 21df87513a..56b097856f 100644 --- a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java @@ -24,7 +24,7 @@ import org.apache.fury.io.FuryInputStream; import org.apache.fury.io.FuryReadableChannel; import org.apache.fury.memory.MemoryBuffer; -import org.apache.fury.resolver.UserContextResolver; +import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -89,7 +89,7 @@ public interface BaseFury { * @param name user context name to register * @param userContextResolverCtr constructor for usr context */ - void registerUserContext(String name, Function userContextResolverCtr); + void registerUserContext(String name, Function userContextResolverCtr); /** Return serialized obj as a byte array. */ byte[] serialize(Object obj); diff --git a/java/fury-core/src/main/java/org/apache/fury/Fury.java b/java/fury-core/src/main/java/org/apache/fury/Fury.java index d880297699..a91140dade 100644 --- a/java/fury-core/src/main/java/org/apache/fury/Fury.java +++ b/java/fury-core/src/main/java/org/apache/fury/Fury.java @@ -49,7 +49,7 @@ import org.apache.fury.resolver.NoRefResolver; import org.apache.fury.resolver.RefResolver; import org.apache.fury.resolver.SerializationContext; -import org.apache.fury.resolver.UserContextResolver; +import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.ArraySerializers; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.BufferObject; @@ -188,8 +188,7 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { } @Override - public void registerUserContext( - String name, Function userContextResolverCtr) { + public void registerUserContext(String name, Function userContextResolverCtr) { serializationContext.registerUserContextResolver(name, userContextResolverCtr.apply(this)); } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index eee0b7d162..178e47dea3 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -1410,10 +1410,10 @@ public void writeClassDefs(MemoryBuffer buffer) { /** write user context by register order. */ public void writeUserContext(MemoryBuffer buffer) { - final Map userContextResolvers = + final Map userContextResolvers = fury.getSerializationContext().getUserContextResolvers(); - for (UserContextResolver userContextResolver : userContextResolvers.values()) { - userContextResolver.write(buffer); + for (UserContext userContext : userContextResolvers.values()) { + userContext.write(buffer); } } @@ -1457,10 +1457,10 @@ public void readClassDefs(MemoryBuffer buffer) { /** read user context by register order. */ public void readUserContext(MemoryBuffer buffer) { - final Map userContextResolvers = + final Map userContextResolvers = fury.getSerializationContext().getUserContextResolvers(); - for (UserContextResolver userContextResolver : userContextResolvers.values()) { - userContextResolver.read(buffer); + for (UserContext userContext : userContextResolvers.values()) { + userContext.read(buffer); } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index fe012592c8..8a006c1d05 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -33,7 +33,7 @@ public final class SerializationContext { private final IdentityHashMap objects = new IdentityHashMap<>(); private MetaContext metaContext; - private final Map userContextResolvers = new LinkedHashMap<>(); + private final Map userContextResolvers = new LinkedHashMap<>(); /** Return the previous value associated with key, or null. */ public Object add(Object key, Object value) { @@ -62,13 +62,13 @@ public void setMetaContext(MetaContext metaContext) { this.metaContext = metaContext; } - public Map getUserContextResolvers() { + public Map getUserContextResolvers() { return userContextResolvers; } - public void registerUserContextResolver(String name, UserContextResolver userContextResolver) { + public void registerUserContextResolver(String name, UserContext userContext) { Preconditions.checkState(!userContextResolvers.containsKey(name)); - userContextResolvers.put(name, userContextResolver); + userContextResolvers.put(name, userContext); } public void reset() { @@ -76,8 +76,8 @@ public void reset() { objects.clear(); } metaContext = null; - for (UserContextResolver userContextResolver : userContextResolvers.values()) { - userContextResolver.reset(); + for (UserContext userContext : userContextResolvers.values()) { + userContext.reset(); } } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java similarity index 93% rename from java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java rename to java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java index 53d7e7c855..989e78a2fe 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContextResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java @@ -23,11 +23,11 @@ import org.apache.fury.memory.MemoryBuffer; /** write/read user custom global data after metaContext data. */ -public abstract class UserContextResolver { +public abstract class UserContext { protected final Fury fury; - public UserContextResolver(Fury fury) { + public UserContext(Fury fury) { this.fury = fury; } diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index 101189219b..ef20f333b4 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -38,11 +38,11 @@ public class UserContextTest extends FuryTestBase { private static final int NUM = 10; - public static class StringUserContextResolver extends UserContextResolver { + public static class StringUserContext extends UserContext { public String data; - public StringUserContextResolver(Fury fury) { + public StringUserContext(Fury fury) { super(fury); } @@ -73,11 +73,11 @@ public FooSerializer(Fury fury, Class type) { @Override public void write(MemoryBuffer buffer, Foo value) { - final Map userContextResolvers = + final Map userContextResolvers = fury.getSerializationContext().getUserContextResolvers(); for (int i = 0; i < NUM; i++) { - final StringUserContextResolver userContextResolver = - (StringUserContextResolver) userContextResolvers.get(String.valueOf(i)); + final StringUserContext userContextResolver = + (StringUserContext) userContextResolvers.get(String.valueOf(i)); userContextResolver.data = getData(i); } serializer.write(buffer, value); @@ -85,11 +85,11 @@ public void write(MemoryBuffer buffer, Foo value) { @Override public Foo read(MemoryBuffer buffer) { - final Map userContextResolvers = + final Map userContextResolvers = fury.getSerializationContext().getUserContextResolvers(); for (int i = 0; i < NUM; i++) { - final StringUserContextResolver userContextResolver = - (StringUserContextResolver) userContextResolvers.get(String.valueOf(i)); + final StringUserContext userContextResolver = + (StringUserContext) userContextResolvers.get(String.valueOf(i)); Assert.assertEquals(userContextResolver.data, getData(i)); } return serializer.read(buffer); @@ -108,10 +108,10 @@ private Fury buildFury() { public void checkShareUserContext() { Fury fury = buildFury(); fury.registerSerializer(Foo.class, FooSerializer.class); - List resolvers = new ArrayList<>(NUM); + List resolvers = new ArrayList<>(NUM); for (int i = 0; i < NUM; i++) { - final StringUserContextResolver userContextResolver = new StringUserContextResolver(fury); - fury.registerUserContext(String.valueOf(i), StringUserContextResolver::new); + final StringUserContext userContextResolver = new StringUserContext(fury); + fury.registerUserContext(String.valueOf(i), StringUserContext::new); resolvers.add(userContextResolver); } final Foo o = Foo.create(); @@ -125,12 +125,11 @@ public void checkShareUserContext() { } } - private List getResolver(Fury fury, int num, boolean empty) { + private List getResolver(Fury fury, int num, boolean empty) { return IntStream.range(0, num) .mapToObj( idx -> { - final StringUserContextResolver userContextResolver = - new StringUserContextResolver(fury); + final StringUserContext userContextResolver = new StringUserContext(fury); if (!empty) { userContextResolver.data = getData(idx); } From 06375c0091c9588a80f946315f336a503f0308b7 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Wed, 8 May 2024 14:18:46 +0800 Subject: [PATCH 7/8] rename UserContextResolver to UserContext --- .../apache/fury/resolver/ClassResolver.java | 10 ++++---- .../fury/resolver/SerializationContext.java | 12 +++++----- .../apache/fury/resolver/UserContextTest.java | 24 +++++++++---------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index 178e47dea3..9b98ef9733 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -1410,9 +1410,8 @@ public void writeClassDefs(MemoryBuffer buffer) { /** write user context by register order. */ public void writeUserContext(MemoryBuffer buffer) { - final Map userContextResolvers = - fury.getSerializationContext().getUserContextResolvers(); - for (UserContext userContext : userContextResolvers.values()) { + final Map userContexts = fury.getSerializationContext().getUserContexts(); + for (UserContext userContext : userContexts.values()) { userContext.write(buffer); } } @@ -1457,9 +1456,8 @@ public void readClassDefs(MemoryBuffer buffer) { /** read user context by register order. */ public void readUserContext(MemoryBuffer buffer) { - final Map userContextResolvers = - fury.getSerializationContext().getUserContextResolvers(); - for (UserContext userContext : userContextResolvers.values()) { + final Map userContexts = fury.getSerializationContext().getUserContexts(); + for (UserContext userContext : userContexts.values()) { userContext.read(buffer); } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index 8a006c1d05..c49a8e586c 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -33,7 +33,7 @@ public final class SerializationContext { private final IdentityHashMap objects = new IdentityHashMap<>(); private MetaContext metaContext; - private final Map userContextResolvers = new LinkedHashMap<>(); + private final Map userContexts = new LinkedHashMap<>(); /** Return the previous value associated with key, or null. */ public Object add(Object key, Object value) { @@ -62,13 +62,13 @@ public void setMetaContext(MetaContext metaContext) { this.metaContext = metaContext; } - public Map getUserContextResolvers() { - return userContextResolvers; + public Map getUserContexts() { + return userContexts; } public void registerUserContextResolver(String name, UserContext userContext) { - Preconditions.checkState(!userContextResolvers.containsKey(name)); - userContextResolvers.put(name, userContext); + Preconditions.checkState(!userContexts.containsKey(name)); + userContexts.put(name, userContext); } public void reset() { @@ -76,7 +76,7 @@ public void reset() { objects.clear(); } metaContext = null; - for (UserContext userContext : userContextResolvers.values()) { + for (UserContext userContext : userContexts.values()) { userContext.reset(); } } diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index ef20f333b4..0b293e09e8 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -73,24 +73,24 @@ public FooSerializer(Fury fury, Class type) { @Override public void write(MemoryBuffer buffer, Foo value) { - final Map userContextResolvers = - fury.getSerializationContext().getUserContextResolvers(); + final Map userContexts = + fury.getSerializationContext().getUserContexts(); for (int i = 0; i < NUM; i++) { - final StringUserContext userContextResolver = - (StringUserContext) userContextResolvers.get(String.valueOf(i)); - userContextResolver.data = getData(i); + final StringUserContext userContext = + (StringUserContext) userContexts.get(String.valueOf(i)); + userContext.data = getData(i); } serializer.write(buffer, value); } @Override public Foo read(MemoryBuffer buffer) { - final Map userContextResolvers = - fury.getSerializationContext().getUserContextResolvers(); + final Map userContexts = + fury.getSerializationContext().getUserContexts(); for (int i = 0; i < NUM; i++) { - final StringUserContext userContextResolver = - (StringUserContext) userContextResolvers.get(String.valueOf(i)); - Assert.assertEquals(userContextResolver.data, getData(i)); + final StringUserContext userContext = + (StringUserContext) userContexts.get(String.valueOf(i)); + Assert.assertEquals(userContext.data, getData(i)); } return serializer.read(buffer); } @@ -110,9 +110,9 @@ public void checkShareUserContext() { fury.registerSerializer(Foo.class, FooSerializer.class); List resolvers = new ArrayList<>(NUM); for (int i = 0; i < NUM; i++) { - final StringUserContext userContextResolver = new StringUserContext(fury); + final StringUserContext userContext = new StringUserContext(fury); fury.registerUserContext(String.valueOf(i), StringUserContext::new); - resolvers.add(userContextResolver); + resolvers.add(userContext); } final Foo o = Foo.create(); final byte[] bytes = fury.serialize(o); From c497e6dcb38c87920d9f5b8747db74e93b700c52 Mon Sep 17 00:00:00 2001 From: MrChang0 Date: Fri, 24 May 2024 15:48:24 +0800 Subject: [PATCH 8/8] change user context code --- docs/guide/java_serialization_guide.md | 1 + .../apache/fury/AbstractThreadSafeFury.java | 6 - .../main/java/org/apache/fury/BaseFury.java | 9 -- .../src/main/java/org/apache/fury/Fury.java | 30 ++--- .../java/org/apache/fury/config/Config.java | 12 +- .../apache/fury/resolver/ClassResolver.java | 12 +- .../fury/resolver/SerializationContext.java | 18 ++- .../org/apache/fury/resolver/UserContext.java | 3 - .../apache/fury/resolver/UserContextTest.java | 116 ++++-------------- 9 files changed, 56 insertions(+), 151 deletions(-) diff --git a/docs/guide/java_serialization_guide.md b/docs/guide/java_serialization_guide.md index a86c39e408..e2b079c914 100644 --- a/docs/guide/java_serialization_guide.md +++ b/docs/guide/java_serialization_guide.md @@ -114,6 +114,7 @@ public class Example { | `codeGenEnabled` | Disabling may result in faster initial serialization but slower subsequent serializations. | `true` | | `asyncCompilationEnabled` | If enabled, serialization uses interpreter mode first and switches to JIT serialization after async serializer JIT for a class is finished. | `false` | | `scalaOptimizationEnabled` | Enables or disables Scala-specific serialization optimization. | `false` | +| `shareUserContext` | Enables or disables user context mode. ## Advanced Usage diff --git a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java index 945656c926..752a4dc22c 100644 --- a/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/AbstractThreadSafeFury.java @@ -21,7 +21,6 @@ import java.util.function.Consumer; import java.util.function.Function; -import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -66,10 +65,5 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { processCallback(fury -> fury.setSerializerFactory(serializerFactory)); } - @Override - public void registerUserContext(String name, Function userContextResolverCtr) { - processCallback(fury -> fury.registerUserContext(name, userContextResolverCtr)); - } - protected abstract void processCallback(Consumer callback); } diff --git a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java index 56b097856f..1ee1aec82a 100644 --- a/java/fury-core/src/main/java/org/apache/fury/BaseFury.java +++ b/java/fury-core/src/main/java/org/apache/fury/BaseFury.java @@ -24,7 +24,6 @@ import org.apache.fury.io.FuryInputStream; import org.apache.fury.io.FuryReadableChannel; import org.apache.fury.memory.MemoryBuffer; -import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.Serializer; import org.apache.fury.serializer.SerializerFactory; @@ -83,14 +82,6 @@ public interface BaseFury { void setSerializerFactory(SerializerFactory serializerFactory); - /** - * Register user context. - * - * @param name user context name to register - * @param userContextResolverCtr constructor for usr context - */ - void registerUserContext(String name, Function userContextResolverCtr); - /** Return serialized obj as a byte array. */ byte[] serialize(Object obj); diff --git a/java/fury-core/src/main/java/org/apache/fury/Fury.java b/java/fury-core/src/main/java/org/apache/fury/Fury.java index a91140dade..03fe143e2c 100644 --- a/java/fury-core/src/main/java/org/apache/fury/Fury.java +++ b/java/fury-core/src/main/java/org/apache/fury/Fury.java @@ -49,7 +49,6 @@ import org.apache.fury.resolver.NoRefResolver; import org.apache.fury.resolver.RefResolver; import org.apache.fury.resolver.SerializationContext; -import org.apache.fury.resolver.UserContext; import org.apache.fury.serializer.ArraySerializers; import org.apache.fury.serializer.BufferCallback; import org.apache.fury.serializer.BufferObject; @@ -187,11 +186,6 @@ public void setSerializerFactory(SerializerFactory serializerFactory) { classResolver.setSerializerFactory(serializerFactory); } - @Override - public void registerUserContext(String name, Function userContextResolverCtr) { - serializationContext.registerUserContextResolver(name, userContextResolverCtr.apply(this)); - } - public SerializerFactory getSerializerFactory() { return classResolver.getSerializerFactory(); } @@ -311,8 +305,8 @@ public void resetBuffer() { private void write(MemoryBuffer buffer, Object obj) { int startOffset = buffer.writerIndex(); - boolean shareGlobalContext = config.shareGlobalContext(); - if (shareGlobalContext) { + boolean shareContext = config.shareContext(); + if (shareContext) { buffer.writeInt32(-1); // preserve 4-byte for nativeObjects start offsets. } // reduce caller stack @@ -321,9 +315,9 @@ private void write(MemoryBuffer buffer, Object obj) { classResolver.writeClass(buffer, classInfo); writeData(buffer, classInfo, obj); } - if (shareGlobalContext) { + if (shareContext) { buffer.putInt32(startOffset, buffer.writerIndex()); - classResolver.writeGlobalContext(buffer); + classResolver.writeContext(buffer); } } @@ -760,8 +754,8 @@ public Object deserialize(MemoryBuffer buffer, Iterable outOfBandB if (isTargetXLang) { obj = xdeserializeInternal(buffer); } else { - if (config.shareGlobalContext()) { - classResolver.readGlobalContext(buffer); + if (config.shareContext()) { + classResolver.readContext(buffer); } obj = readRef(buffer); } @@ -1031,7 +1025,7 @@ public void serializeJavaObject(MemoryBuffer buffer, Object obj) { if (depth != 0) { throwDepthSerializationException(); } - if (config.shareGlobalContext()) { + if (config.shareContext()) { int startOffset = buffer.writerIndex(); buffer.writeInt32(-1); // preserve 4-byte for nativeObjects start offsets. if (!refResolver.writeRefOrNull(buffer, obj)) { @@ -1039,7 +1033,7 @@ public void serializeJavaObject(MemoryBuffer buffer, Object obj) { writeData(buffer, classInfo, obj); } buffer.putInt32(startOffset, buffer.writerIndex()); - classResolver.writeGlobalContext(buffer); + classResolver.writeContext(buffer); } else { if (!refResolver.writeRefOrNull(buffer, obj)) { ClassInfo classInfo = classResolver.getOrUpdateClassInfo(obj.getClass()); @@ -1076,8 +1070,8 @@ public T deserializeJavaObject(MemoryBuffer buffer, Class cls) { if (depth != 0) { throwDepthDeserializationException(); } - if (config.shareGlobalContext()) { - classResolver.readGlobalContext(buffer); + if (config.shareContext()) { + classResolver.readContext(buffer); } T obj; int nextReadRefId = refResolver.tryPreserveRefId(buffer); @@ -1190,8 +1184,8 @@ public Object deserializeJavaObjectAndClass(MemoryBuffer buffer) { if (depth != 0) { throwDepthDeserializationException(); } - if (config.shareGlobalContext()) { - classResolver.readGlobalContext(buffer); + if (config.shareContext()) { + classResolver.readContext(buffer); } return readRef(buffer); } catch (Throwable t) { diff --git a/java/fury-core/src/main/java/org/apache/fury/config/Config.java b/java/fury-core/src/main/java/org/apache/fury/config/Config.java index 7b0224299a..2d94b4f47e 100644 --- a/java/fury-core/src/main/java/org/apache/fury/config/Config.java +++ b/java/fury-core/src/main/java/org/apache/fury/config/Config.java @@ -49,7 +49,7 @@ public class Config implements Serializable { private final boolean requireClassRegistration; private final boolean suppressClassRegistrationWarnings; private final boolean registerGuavaTypes; - private final boolean shareGlobalContext; + private final boolean shareContext; private final boolean shareMetaContext; private final boolean shareUserContext; private final boolean asyncCompilationEnabled; @@ -78,7 +78,7 @@ public Config(FuryBuilder builder) { defaultJDKStreamSerializerType = builder.defaultJDKStreamSerializerType; shareMetaContext = builder.shareMetaContext; shareUserContext = builder.shareUserContext; - shareGlobalContext = shareMetaContext || shareUserContext; + shareContext = shareMetaContext || shareUserContext; deserializeUnexistedClass = builder.deserializeUnexistedClass; if (deserializeUnexistedClass) { // Only in meta share mode or compatibleMode, fury knows how to deserialize @@ -190,8 +190,8 @@ public boolean shareUserContext() { return shareUserContext; } - public boolean shareGlobalContext() { - return shareGlobalContext; + public boolean shareContext() { + return shareContext; } /** @@ -249,7 +249,7 @@ public boolean equals(Object o) { && registerGuavaTypes == config.registerGuavaTypes && shareMetaContext == config.shareMetaContext && shareUserContext == config.shareUserContext - && shareGlobalContext == config.shareGlobalContext + && shareContext == config.shareContext && asyncCompilationEnabled == config.asyncCompilationEnabled && deserializeUnexistedClass == config.deserializeUnexistedClass && scalaOptimizationEnabled == config.scalaOptimizationEnabled @@ -281,7 +281,7 @@ public int hashCode() { registerGuavaTypes, shareMetaContext, shareUserContext, - shareGlobalContext, + shareContext, asyncCompilationEnabled, deserializeUnexistedClass, scalaOptimizationEnabled); diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index 9b98ef9733..c19eedf2f8 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -1410,14 +1410,14 @@ public void writeClassDefs(MemoryBuffer buffer) { /** write user context by register order. */ public void writeUserContext(MemoryBuffer buffer) { - final Map userContexts = fury.getSerializationContext().getUserContexts(); - for (UserContext userContext : userContexts.values()) { + final List userContexts = fury.getSerializationContext().getUserContexts(); + for (UserContext userContext : userContexts) { userContext.write(buffer); } } /** after all data, write share meta context and user context. */ - public void writeGlobalContext(MemoryBuffer buffer) { + public void writeContext(MemoryBuffer buffer) { if (fury.getConfig().shareMetaContext()) { writeClassDefs(buffer); } @@ -1456,14 +1456,14 @@ public void readClassDefs(MemoryBuffer buffer) { /** read user context by register order. */ public void readUserContext(MemoryBuffer buffer) { - final Map userContexts = fury.getSerializationContext().getUserContexts(); - for (UserContext userContext : userContexts.values()) { + final List userContexts = fury.getSerializationContext().getUserContexts(); + for (UserContext userContext : userContexts) { userContext.read(buffer); } } /** read share meta context and user context before read data. */ - public void readGlobalContext(MemoryBuffer buffer) { + public void readContext(MemoryBuffer buffer) { int globalContextOffSet = buffer.readInt32(); int readerIndex = buffer.readerIndex(); buffer.readerIndex(globalContextOffSet); diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java index c49a8e586c..59a55a1e96 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/SerializationContext.java @@ -19,11 +19,10 @@ package org.apache.fury.resolver; +import java.util.ArrayList; import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.List; import org.apache.fury.config.FuryBuilder; -import org.apache.fury.util.Preconditions; /** * A context is used to add some context-related information, so that the serializers can set up @@ -33,7 +32,7 @@ public final class SerializationContext { private final IdentityHashMap objects = new IdentityHashMap<>(); private MetaContext metaContext; - private final Map userContexts = new LinkedHashMap<>(); + private final List userContexts = new ArrayList<>(); /** Return the previous value associated with key, or null. */ public Object add(Object key, Object value) { @@ -62,13 +61,12 @@ public void setMetaContext(MetaContext metaContext) { this.metaContext = metaContext; } - public Map getUserContexts() { + public List getUserContexts() { return userContexts; } - public void registerUserContextResolver(String name, UserContext userContext) { - Preconditions.checkState(!userContexts.containsKey(name)); - userContexts.put(name, userContext); + public void addUserContext(UserContext userContext) { + userContexts.add(userContext); } public void reset() { @@ -76,8 +74,6 @@ public void reset() { objects.clear(); } metaContext = null; - for (UserContext userContext : userContexts.values()) { - userContext.reset(); - } + userContexts.clear(); } } diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java index 989e78a2fe..25d282a1b9 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/UserContext.java @@ -34,7 +34,4 @@ public UserContext(Fury fury) { public abstract void write(MemoryBuffer buffer); public abstract void read(MemoryBuffer buffer); - - /** write/read end should clear user data. */ - public abstract void reset(); } diff --git a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java index 0b293e09e8..649f01e2fe 100644 --- a/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java +++ b/java/fury-core/src/test/java/org/apache/fury/resolver/UserContextTest.java @@ -19,126 +19,58 @@ package org.apache.fury.resolver; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.IntStream; import org.apache.fury.Fury; import org.apache.fury.FuryTestBase; +import org.apache.fury.config.CompatibleMode; import org.apache.fury.config.Language; import org.apache.fury.memory.MemoryBuffer; -import org.apache.fury.serializer.ObjectSerializer; -import org.apache.fury.serializer.Serializer; import org.apache.fury.test.bean.Foo; import org.testng.Assert; import org.testng.annotations.Test; public class UserContextTest extends FuryTestBase { - private static final int NUM = 10; + public class DataUserContext extends UserContext { + Object data = null; - public static class StringUserContext extends UserContext { - - public String data; - - public StringUserContext(Fury fury) { + public DataUserContext(Fury fury) { super(fury); } @Override public void write(MemoryBuffer buffer) { - fury.writeJavaStringRef(buffer, data); + fury.writeRef(buffer, data); } @Override public void read(MemoryBuffer buffer) { - data = fury.readJavaStringRef(buffer); - } - - @Override - public void reset() { - data = null; + data = fury.readRef(buffer); } } - public static class FooSerializer extends Serializer { - - private final ObjectSerializer serializer; - - public FooSerializer(Fury fury, Class type) { - super(fury, type); - serializer = new ObjectSerializer<>(fury, Foo.class); - } - - @Override - public void write(MemoryBuffer buffer, Foo value) { - final Map userContexts = - fury.getSerializationContext().getUserContexts(); - for (int i = 0; i < NUM; i++) { - final StringUserContext userContext = - (StringUserContext) userContexts.get(String.valueOf(i)); - userContext.data = getData(i); - } - serializer.write(buffer, value); - } - - @Override - public Foo read(MemoryBuffer buffer) { - final Map userContexts = - fury.getSerializationContext().getUserContexts(); - for (int i = 0; i < NUM; i++) { - final StringUserContext userContext = - (StringUserContext) userContexts.get(String.valueOf(i)); - Assert.assertEquals(userContext.data, getData(i)); - } - return serializer.read(buffer); - } - } - - private Fury buildFury() { - return Fury.builder() - .withLanguage(Language.JAVA) - .withUserContextShare(true) - .requireClassRegistration(false) - .build(); - } - @Test public void checkShareUserContext() { - Fury fury = buildFury(); - fury.registerSerializer(Foo.class, FooSerializer.class); - List resolvers = new ArrayList<>(NUM); - for (int i = 0; i < NUM; i++) { - final StringUserContext userContext = new StringUserContext(fury); - fury.registerUserContext(String.valueOf(i), StringUserContext::new); - resolvers.add(userContext); - } + Fury fury = + Fury.builder() + .withLanguage(Language.JAVA) + .requireClassRegistration(false) + .withCompatibleMode(CompatibleMode.COMPATIBLE) + .withMetaContextShare(true) + .withUserContextShare(true) + .build(); final Foo o = Foo.create(); + final SerializationContext serializationContext = fury.getSerializationContext(); + serializationContext.setMetaContext(new MetaContext()); + final DataUserContext userContext1 = new DataUserContext(fury); + userContext1.data = "test1"; + serializationContext.addUserContext(userContext1); final byte[] bytes = fury.serialize(o); - for (int i = 0; i < NUM; i++) { - Assert.assertNull(resolvers.get(i).data); - } - Assert.assertEquals(fury.deserialize(bytes), o); - for (int i = 0; i < NUM; i++) { - Assert.assertNull(resolvers.get(i).data); - } - } - private List getResolver(Fury fury, int num, boolean empty) { - return IntStream.range(0, num) - .mapToObj( - idx -> { - final StringUserContext userContextResolver = new StringUserContext(fury); - if (!empty) { - userContextResolver.data = getData(idx); - } - return userContextResolver; - }) - .collect(Collectors.toList()); - } + serializationContext.setMetaContext(new MetaContext()); + final DataUserContext userContext2 = new DataUserContext(fury); + serializationContext.addUserContext(userContext2); - private static String getData(int idx) { - return "data" + idx; + Assert.assertEquals(fury.deserialize(bytes), o); + Assert.assertEquals(userContext1.data, userContext2.data); } }