Define efficient serialization proxies
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / persisted / DatastoreSnapshot.java
index 9b58eb17235cd34a04181091d6a3666d0f4078eb..31e4356bbce4816916c17a418c52423c08e427d2 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.cluster.datastore.persisted;
 
+import static com.google.common.base.Verify.verifyNotNull;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.collect.ImmutableList;
@@ -27,24 +28,31 @@ import org.opendaylight.controller.cluster.raft.persisted.Snapshot;
  * @author Thomas Pantelis
  */
 public final class DatastoreSnapshot implements Serializable {
-    private static final class Proxy implements Externalizable {
-        private static final long serialVersionUID = 1L;
+    interface SerialForm extends Externalizable {
 
-        private DatastoreSnapshot datastoreSnapshot;
+        DatastoreSnapshot datastoreSnapshot();
 
-        // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
-        // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
-        @SuppressWarnings("checkstyle:RedundantModifier")
-        public Proxy() {
-            // For Externalizable
-        }
+        Object readResolve();
 
-        Proxy(final DatastoreSnapshot datastoreSnapshot) {
-            this.datastoreSnapshot = datastoreSnapshot;
+        void resolveTo(@NonNull DatastoreSnapshot newDatastoreSnapshot);
+
+        @Override
+        default void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            final var type = (String)in.readObject();
+            final var snapshot = (ShardManagerSnapshot) in.readObject();
+
+            final int size = in.readInt();
+            var localShardSnapshots = new ArrayList<ShardSnapshot>(size);
+            for (int i = 0; i < size; i++) {
+                localShardSnapshots.add((ShardSnapshot) in.readObject());
+            }
+
+            resolveTo(new DatastoreSnapshot(type, snapshot, localShardSnapshots));
         }
 
         @Override
-        public void writeExternal(ObjectOutput out) throws IOException {
+        default void writeExternal(ObjectOutput out) throws IOException {
+            final var datastoreSnapshot = datastoreSnapshot();
             out.writeObject(datastoreSnapshot.type);
             out.writeObject(datastoreSnapshot.shardManagerSnapshot);
 
@@ -53,31 +61,45 @@ public final class DatastoreSnapshot implements Serializable {
                 out.writeObject(shardSnapshot);
             }
         }
+    }
 
-        @Override
-        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-            String localType = (String)in.readObject();
-            ShardManagerSnapshot localShardManagerSnapshot = (ShardManagerSnapshot) in.readObject();
+    private static final class Proxy implements SerialForm {
+        private static final long serialVersionUID = 1L;
 
-            int size = in.readInt();
-            List<ShardSnapshot> localShardSnapshots = new ArrayList<>(size);
-            for (int i = 0; i < size; i++) {
-                localShardSnapshots.add((ShardSnapshot) in.readObject());
-            }
+        private DatastoreSnapshot datastoreSnapshot;
+
+        // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
+        // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
+        @SuppressWarnings("checkstyle:RedundantModifier")
+        public Proxy() {
+            // For Externalizable
+        }
 
-            datastoreSnapshot = new DatastoreSnapshot(localType, localShardManagerSnapshot, localShardSnapshots);
+        Proxy(final DatastoreSnapshot datastoreSnapshot) {
+            this.datastoreSnapshot = requireNonNull(datastoreSnapshot);
         }
 
-        private Object readResolve() {
+        @Override
+        public DatastoreSnapshot datastoreSnapshot() {
             return datastoreSnapshot;
         }
+
+        @Override
+        public void resolveTo(DatastoreSnapshot newDatastoreSnapshot) {
+            datastoreSnapshot = requireNonNull(newDatastoreSnapshot);
+        }
+
+        @Override
+        public Object readResolve() {
+            return verifyNotNull(datastoreSnapshot);
+        }
     }
 
     private static final long serialVersionUID = 1L;
 
-    private final String type;
+    private final @NonNull String type;
     private final ShardManagerSnapshot shardManagerSnapshot;
-    private final List<ShardSnapshot> shardSnapshots;
+    private final @NonNull ImmutableList<ShardSnapshot> shardSnapshots;
 
     public DatastoreSnapshot(@NonNull String type, @Nullable ShardManagerSnapshot shardManagerSnapshot,
             @NonNull List<ShardSnapshot> shardSnapshots) {
@@ -103,9 +125,28 @@ public final class DatastoreSnapshot implements Serializable {
     }
 
     public static final class ShardSnapshot implements Serializable {
-        private static final long serialVersionUID = 1L;
+        interface SerialForm extends Externalizable {
+
+            ShardSnapshot shardSnapshot();
+
+            Object readResolve();
 
-        private static final class Proxy implements Externalizable {
+            void resolveTo(String name, Snapshot snapshot);
+
+            @Override
+            default void writeExternal(ObjectOutput out) throws IOException {
+                final var shardSnapshot = shardSnapshot();
+                out.writeObject(shardSnapshot.name);
+                out.writeObject(shardSnapshot.snapshot);
+            }
+
+            @Override
+            default void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+                resolveTo((String) in.readObject(), (Snapshot) in.readObject());
+            }
+        }
+
+        private static final class Proxy implements SerialForm {
             private static final long serialVersionUID = 1L;
 
             private ShardSnapshot shardSnapshot;
@@ -122,21 +163,23 @@ public final class DatastoreSnapshot implements Serializable {
             }
 
             @Override
-            public void writeExternal(ObjectOutput out) throws IOException {
-                out.writeObject(shardSnapshot.name);
-                out.writeObject(shardSnapshot.snapshot);
+            public ShardSnapshot shardSnapshot() {
+                return shardSnapshot;
             }
 
             @Override
-            public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-                shardSnapshot = new ShardSnapshot((String)in.readObject(), (Snapshot) in.readObject());
+            public void resolveTo(final String name, final Snapshot snapshot) {
+                shardSnapshot = new ShardSnapshot(name, snapshot);
             }
 
-            private Object readResolve() {
-                return shardSnapshot;
+            @Override
+            public Object readResolve() {
+                return verifyNotNull(shardSnapshot);
             }
         }
 
+        private static final long serialVersionUID = 1L;
+
         private final @NonNull String name;
         private final @NonNull Snapshot snapshot;