You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by mb...@apache.org on 2019/02/03 15:18:21 UTC

[asterixdb] branch master updated: [NO ISSUE] Compatibility improvements, misc cleanup / refactoring

This is an automated email from the ASF dual-hosted git repository.

mblow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 53a5c22  [NO ISSUE] Compatibility improvements, misc cleanup / refactoring
53a5c22 is described below

commit 53a5c223ca91fea664549ed61364c50a406ca35f
Author: Michael Blow <mb...@apache.org>
AuthorDate: Fri Feb 1 10:51:48 2019 -0500

    [NO ISSUE] Compatibility improvements, misc cleanup / refactoring
    
    Change-Id: I1839c585b254e5b4252f456b367b3a5db2dd53c8
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/3139
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Contrib: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Contrib: Michael Blow <mb...@apache.org>
    Reviewed-by: Till Westmann <ti...@apache.org>
---
 .../asterix/hyracks/bootstrap/NCApplication.java   |  3 +-
 .../org/apache/asterix/om/types/ARecordType.java   |  2 +-
 .../org/apache/asterix/om/types/AUnionType.java    |  5 +-
 .../asterix/om/types/AbstractCollectionType.java   |  2 +-
 .../org/apache/asterix/om/types/BuiltinType.java   | 66 ++++++++-------
 .../org/apache/asterix/om/types/TypeTagUtil.java   |  2 +-
 .../asterix/om/utils/JSONDeserializerForTypes.java | 34 ++++++--
 .../hyracks/api/application/INCApplication.java    |  3 +
 .../DefaultJavaSerializationProvider.java}         | 22 ++---
 .../hyracks/api/util/JavaSerializationUtils.java   | 34 ++++----
 .../hyracks/control/nc/BaseNCApplication.java      |  7 ++
 .../examples/btree/helper/TestNCApplication.java   |  7 +-
 .../apache/hyracks/util/CompatibilityLevel.java    | 97 ++++++++++++++++++++++
 .../org/apache/hyracks/util/CompatibilityUtil.java | 15 ++++
 14 files changed, 222 insertions(+), 77 deletions(-)

diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
index 97316d2..3857ac5 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/NCApplication.java
@@ -95,6 +95,7 @@ public class NCApplication extends BaseNCApplication {
     @Override
     public void init(IServiceContext serviceCtx) throws Exception {
         ncServiceCtx = (INCServiceContext) serviceCtx;
+        configureLoggingLevel(ncServiceCtx.getAppConfig().getLoggingLevel(ExternalProperties.Option.LOG_LEVEL));
         // set the node status initially to idle to indicate that it is pending booting
         ((NodeControllerService) serviceCtx.getControllerService()).setNodeStatus(NodeStatus.IDLE);
         ncServiceCtx.setThreadFactory(
@@ -112,8 +113,6 @@ public class NCApplication extends BaseNCApplication {
         if (LOGGER.isInfoEnabled()) {
             LOGGER.info("Starting Asterix node controller: " + nodeId);
         }
-        configureLoggingLevel(ncServiceCtx.getAppConfig().getLoggingLevel(ExternalProperties.Option.LOG_LEVEL));
-
         final NodeControllerService controllerService = (NodeControllerService) ncServiceCtx.getControllerService();
 
         if (System.getProperty("java.rmi.server.hostname") == null) {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
index 7d5e4c0..1c04986 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/ARecordType.java
@@ -312,7 +312,7 @@ public class ARecordType extends AbstractComplexType {
 
     @Override
     public IAType getType() {
-        return BuiltinType.ASTERIX_TYPE;
+        return BuiltinType.ALL_TYPE;
     }
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
index 9fdaca1..f8ae7f8 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AUnionType.java
@@ -22,8 +22,9 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.asterix.om.base.IAObject;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
@@ -161,7 +162,7 @@ public class AUnionType extends AbstractComplexType {
 
     @Override
     public IAType getType() {
-        return BuiltinType.ASTERIX_TYPE;
+        return BuiltinType.ALL_TYPE;
     }
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AbstractCollectionType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AbstractCollectionType.java
index 2902e18..f6f10f4 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AbstractCollectionType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/AbstractCollectionType.java
@@ -43,7 +43,7 @@ public abstract class AbstractCollectionType extends AbstractComplexType {
 
     @Override
     public IAType getType() {
-        return BuiltinType.ASTERIX_TYPE;
+        return BuiltinType.ALL_TYPE;
     }
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
index a36e0e4..6d8db59 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/BuiltinType.java
@@ -18,8 +18,10 @@
  */
 package org.apache.asterix.om.types;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.asterix.om.base.IAObject;
+import org.apache.hyracks.util.CompatibilityUtil;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
 public abstract class BuiltinType implements IAType {
@@ -36,7 +38,7 @@ public abstract class BuiltinType implements IAType {
     }
 
     /** the type of all types */
-    public final static BuiltinType ASTERIX_TYPE = new BuiltinType() {
+    public static final BuiltinType ALL_TYPE = new BuiltinType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -47,12 +49,12 @@ public abstract class BuiltinType implements IAType {
 
         @Override
         public String getDisplayName() {
-            return "AsterixType";
+            return "AllType";
         }
 
         @Override
         public String getTypeName() {
-            return "ASTERIX_TYPE";
+            return "ALL_TYPE";
         }
 
         @Override
@@ -64,12 +66,16 @@ public abstract class BuiltinType implements IAType {
         public ObjectNode toJSON() {
             ObjectMapper om = new ObjectMapper();
             ObjectNode type = om.createObjectNode();
-            type.put("type", "ASTERIX_TYPE");
+            if (CompatibilityUtil.isAtLeast035()) {
+                type.put("type", "ALL_TYPE");
+            } else {
+                type.put("type", "ASTERIX_TYPE");
+            }
             return type;
         }
     };
 
-    public final static BuiltinType AINT8 = new LowerCaseConstructorType() {
+    public static final BuiltinType AINT8 = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -97,7 +103,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AINT16 = new LowerCaseConstructorType() {
+    public static final BuiltinType AINT16 = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -125,7 +131,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AINT32 = new LowerCaseConstructorType() {
+    public static final BuiltinType AINT32 = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -181,7 +187,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ABINARY = new LowerCaseConstructorType() {
+    public static final BuiltinType ABINARY = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -209,7 +215,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AFLOAT = new LowerCaseConstructorType() {
+    public static final BuiltinType AFLOAT = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -237,7 +243,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ADOUBLE = new LowerCaseConstructorType() {
+    public static final BuiltinType ADOUBLE = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -265,7 +271,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ASTRING = new LowerCaseConstructorType() {
+    public static final BuiltinType ASTRING = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -293,7 +299,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AMISSING = new LowerCaseConstructorType() {
+    public static final BuiltinType AMISSING = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -321,7 +327,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ANULL = new LowerCaseConstructorType() {
+    public static final BuiltinType ANULL = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -349,7 +355,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ABOOLEAN = new LowerCaseConstructorType() {
+    public static final BuiltinType ABOOLEAN = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -377,7 +383,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ATIME = new LowerCaseConstructorType() {
+    public static final BuiltinType ATIME = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -405,7 +411,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ADATE = new LowerCaseConstructorType() {
+    public static final BuiltinType ADATE = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -433,7 +439,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ADATETIME = new LowerCaseConstructorType() {
+    public static final BuiltinType ADATETIME = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -461,7 +467,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ADURATION = new LowerCaseConstructorType() {
+    public static final BuiltinType ADURATION = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -489,7 +495,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AYEARMONTHDURATION = new LowerCaseConstructorType() {
+    public static final BuiltinType AYEARMONTHDURATION = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -517,7 +523,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ADAYTIMEDURATION = new LowerCaseConstructorType() {
+    public static final BuiltinType ADAYTIMEDURATION = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -545,7 +551,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AINTERVAL = new LowerCaseConstructorType() {
+    public static final BuiltinType AINTERVAL = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -570,7 +576,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType APOINT = new LowerCaseConstructorType() {
+    public static final BuiltinType APOINT = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -598,7 +604,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType APOINT3D = new LowerCaseConstructorType() {
+    public static final BuiltinType APOINT3D = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -626,7 +632,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ALINE = new LowerCaseConstructorType() {
+    public static final BuiltinType ALINE = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -654,7 +660,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType APOLYGON = new LowerCaseConstructorType() {
+    public static final BuiltinType APOLYGON = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -682,7 +688,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType AGEOMETRY = new LowerCaseConstructorType() {
+    public static final BuiltinType AGEOMETRY = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -709,7 +715,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ACIRCLE = new LowerCaseConstructorType() {
+    public static final BuiltinType ACIRCLE = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -737,7 +743,7 @@ public abstract class BuiltinType implements IAType {
         }
     };
 
-    public final static BuiltinType ARECTANGLE = new LowerCaseConstructorType() {
+    public static final BuiltinType ARECTANGLE = new LowerCaseConstructorType() {
 
         private static final long serialVersionUID = 1L;
 
@@ -890,7 +896,7 @@ public abstract class BuiltinType implements IAType {
 
     @Override
     public IAType getType() {
-        return ASTERIX_TYPE;
+        return ALL_TYPE;
     }
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
index 254dbee..5d97125 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/types/TypeTagUtil.java
@@ -63,7 +63,7 @@ public class TypeTagUtil {
             case POINT3D:
                 return BuiltinType.APOINT3D;
             case TYPE:
-                return BuiltinType.ASTERIX_TYPE;
+                return BuiltinType.ALL_TYPE;
             case ANY:
                 return BuiltinType.ANY;
             case LINE:
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/JSONDeserializerForTypes.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/JSONDeserializerForTypes.java
index 5b5249d..2ab44ae 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/JSONDeserializerForTypes.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/utils/JSONDeserializerForTypes.java
@@ -19,13 +19,12 @@
 
 package org.apache.asterix.om.utils;
 
-import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
-import com.fasterxml.jackson.databind.JsonNode;
-
-import com.google.common.collect.Lists;
 import org.apache.asterix.om.types.AOrderedListType;
 import org.apache.asterix.om.types.ARecordType;
 import org.apache.asterix.om.types.AUnionType;
@@ -33,7 +32,28 @@ import org.apache.asterix.om.types.AUnorderedListType;
 import org.apache.asterix.om.types.BuiltinType;
 import org.apache.asterix.om.types.IAType;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Lists;
+
 public class JSONDeserializerForTypes {
+    private static final Map<String, IAType> primitiveTypeMap;
+    static {
+        primitiveTypeMap = new HashMap<>();
+        Class<?> buildInTypeClass = BuiltinType.class;
+        Stream.of(buildInTypeClass.getDeclaredFields()).filter(f -> f.getType().isAssignableFrom(BuiltinType.class))
+                .forEach(f -> {
+                    try {
+                        primitiveTypeMap.put(f.getName().toUpperCase(), (IAType) f.get(null));
+                    } catch (IllegalAccessException e) {
+                        throw new IllegalStateException(e);
+                    }
+                });
+        // for backward-compatibility
+        primitiveTypeMap.put("ASTERIX_TYPE", BuiltinType.ALL_TYPE);
+    }
+
+    private JSONDeserializerForTypes() {
+    }
 
     /**
      * Deserialize an arbitrary JSON representation of a type.
@@ -59,7 +79,7 @@ public class JSONDeserializerForTypes {
 
         // Deals with Union Type.
         if (typeName.equals(AUnionType.class.getName())) {
-            List<IAType> unionTypes = new ArrayList<IAType>();
+            List<IAType> unionTypes = new ArrayList<>();
             JsonNode fields = typeInJSON.get("fields");
             for (int i = 0; i < fields.size(); i++) {
                 JsonNode fieldType = fields.get(i);
@@ -86,8 +106,6 @@ public class JSONDeserializerForTypes {
         }
 
         // Deals with primitive types.
-        Class<?> cl = BuiltinType.class;
-        Field typeField = cl.getDeclaredField(typeName.toUpperCase());
-        return (IAType) typeField.get(null);
+        return primitiveTypeMap.get(typeName.toUpperCase());
     }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java
index 919722d..e641497 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java
@@ -18,6 +18,7 @@
  */
 package org.apache.hyracks.api.application;
 
+import org.apache.hyracks.api.config.IConfigManager;
 import org.apache.hyracks.api.control.CcId;
 import org.apache.hyracks.api.io.IFileDeviceResolver;
 import org.apache.hyracks.api.job.resource.NodeCapacity;
@@ -35,4 +36,6 @@ public interface INCApplication extends IApplication {
     IFileDeviceResolver getFileDeviceResolver();
 
     void tasksCompleted(CcId ccId) throws Exception;
+
+    IConfigManager getConfigManager();
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/comm/DefaultJavaSerializationProvider.java
similarity index 58%
copy from hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java
copy to hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/comm/DefaultJavaSerializationProvider.java
index 919722d..0f42df2 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/application/INCApplication.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/comm/DefaultJavaSerializationProvider.java
@@ -16,23 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.hyracks.api.application;
+package org.apache.hyracks.api.comm;
 
-import org.apache.hyracks.api.control.CcId;
-import org.apache.hyracks.api.io.IFileDeviceResolver;
-import org.apache.hyracks.api.job.resource.NodeCapacity;
+public class DefaultJavaSerializationProvider implements IJavaSerializationProvider {
+    public static final IJavaSerializationProvider INSTANCE = new DefaultJavaSerializationProvider();
 
-public interface INCApplication extends IApplication {
-
-    void preStop() throws Exception; //NOSONAR
-
-    NodeCapacity getCapacity();
-
-    /**
-     * @return the file device resolver which resolves the relative path of a storage
-     *         file into an io device.
-     */
-    IFileDeviceResolver getFileDeviceResolver();
-
-    void tasksCompleted(CcId ccId) throws Exception;
+    private DefaultJavaSerializationProvider() {
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/JavaSerializationUtils.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/JavaSerializationUtils.java
index b38d343..56e15a4 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/JavaSerializationUtils.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/JavaSerializationUtils.java
@@ -29,41 +29,47 @@ import java.io.Serializable;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 
+import org.apache.hyracks.api.comm.DefaultJavaSerializationProvider;
 import org.apache.hyracks.api.comm.IJavaSerializationProvider;
 
 public class JavaSerializationUtils {
-    private static IJavaSerializationProvider serProvider = new IJavaSerializationProvider() {
-    };
+    private static IJavaSerializationProvider serProvider = DefaultJavaSerializationProvider.INSTANCE;
+
+    private JavaSerializationUtils() {
+    }
 
     public static byte[] serialize(Serializable jobSpec) throws IOException {
         if (jobSpec instanceof byte[]) {
             return (byte[]) jobSpec;
         }
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream oos = serProvider.newObjectOutputStream(baos);
-        oos.writeObject(jobSpec);
+        try (ObjectOutputStream oos = serProvider.newObjectOutputStream(baos)) {
+            oos.writeObject(jobSpec);
+        }
         return baos.toByteArray();
     }
 
     public static byte[] serialize(Serializable jobSpec, ClassLoader classLoader) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream oos = serProvider.newObjectOutputStream(baos);
-        ClassLoader ctxCL = Thread.currentThread().getContextClassLoader();
-        try {
-            Thread.currentThread().setContextClassLoader(classLoader);
-            oos.writeObject(jobSpec);
-            return baos.toByteArray();
-        } finally {
-            Thread.currentThread().setContextClassLoader(ctxCL);
+        try (ObjectOutputStream oos = serProvider.newObjectOutputStream(baos)) {
+            ClassLoader ctxCL = Thread.currentThread().getContextClassLoader();
+            try {
+                Thread.currentThread().setContextClassLoader(classLoader);
+                oos.writeObject(jobSpec);
+            } finally {
+                Thread.currentThread().setContextClassLoader(ctxCL);
+            }
         }
+        return baos.toByteArray();
     }
 
     public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
         if (bytes == null) {
             return null;
         }
-        ObjectInputStream ois = serProvider.newObjectInputStream(new ByteArrayInputStream(bytes));
-        return ois.readObject();
+        try (ObjectInputStream ois = serProvider.newObjectInputStream(new ByteArrayInputStream(bytes))) {
+            return ois.readObject();
+        }
     }
 
     public static Object deserialize(byte[] bytes, ClassLoader classLoader) throws IOException, ClassNotFoundException {
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/BaseNCApplication.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/BaseNCApplication.java
index 800721c..db7b533 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/BaseNCApplication.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/BaseNCApplication.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.api.control.CcId;
 import org.apache.hyracks.api.io.IFileDeviceResolver;
 import org.apache.hyracks.api.job.resource.NodeCapacity;
 import org.apache.hyracks.api.util.HyracksConstants;
+import org.apache.hyracks.control.common.config.ConfigManager;
 import org.apache.hyracks.control.common.controllers.CCConfig;
 import org.apache.hyracks.control.common.controllers.ControllerConfig;
 import org.apache.hyracks.control.common.controllers.NCConfig;
@@ -38,6 +39,7 @@ import org.apache.logging.log4j.Level;
 
 public class BaseNCApplication implements INCApplication {
     public static final BaseNCApplication INSTANCE = new BaseNCApplication();
+    private ConfigManager configManager;
 
     protected BaseNCApplication() {
     }
@@ -82,6 +84,7 @@ public class BaseNCApplication implements INCApplication {
 
     @Override
     public void registerConfig(IConfigManager configManager) {
+        this.configManager = (ConfigManager) configManager;
         configManager.addIniParamOptions(ControllerConfig.Option.CONFIG_FILE, ControllerConfig.Option.CONFIG_FILE_URL);
         configManager.addCmdLineSections(Section.NC, Section.COMMON, Section.LOCALNC);
         configManager.setUsageFilter(getUsageFilter());
@@ -102,4 +105,8 @@ public class BaseNCApplication implements INCApplication {
         LoggingConfigUtil.defaultIfMissing(HyracksConstants.HYRACKS_LOGGER_NAME, level);
     }
 
+    @Override
+    public ConfigManager getConfigManager() {
+        return configManager;
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-examples/btree-example/btreehelper/src/main/java/org/apache/hyracks/examples/btree/helper/TestNCApplication.java b/hyracks-fullstack/hyracks/hyracks-examples/btree-example/btreehelper/src/main/java/org/apache/hyracks/examples/btree/helper/TestNCApplication.java
index b13feda..5259856 100644
--- a/hyracks-fullstack/hyracks/hyracks-examples/btree-example/btreehelper/src/main/java/org/apache/hyracks/examples/btree/helper/TestNCApplication.java
+++ b/hyracks-fullstack/hyracks/hyracks-examples/btree-example/btreehelper/src/main/java/org/apache/hyracks/examples/btree/helper/TestNCApplication.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.api.job.resource.NodeCapacity;
 public class TestNCApplication implements INCApplication {
 
     private RuntimeContext rCtx;
+    private IConfigManager configManager;
 
     @Override
     public void init(IServiceContext serviceCtx) throws Exception {
@@ -67,7 +68,7 @@ public class TestNCApplication implements INCApplication {
 
     @Override
     public void registerConfig(IConfigManager configManager) {
-        // no-op
+        this.configManager = configManager;
     }
 
     @Override
@@ -80,4 +81,8 @@ public class TestNCApplication implements INCApplication {
         return null;
     }
 
+    @Override
+    public IConfigManager getConfigManager() {
+        return configManager;
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityLevel.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityLevel.java
new file mode 100644
index 0000000..2d0c8aa
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityLevel.java
@@ -0,0 +1,97 @@
+/*
+ * 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.hyracks.util;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.IntStream;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public final class CompatibilityLevel implements Serializable, Comparable {
+    public static final CompatibilityLevel V_0_3_4 = fromSegments(0, 3, 4);
+    public static final CompatibilityLevel V_0_3_5 = fromSegments(0, 3, 5);
+
+    public static final CompatibilityLevel DEFAULT = V_0_3_5;
+
+    private final int level;
+
+    private CompatibilityLevel(int level) {
+        this.level = level;
+    }
+
+    public static CompatibilityLevel fromInt(int version) {
+        return new CompatibilityLevel(version);
+    }
+
+    public static CompatibilityLevel fromSegments(int... versionSegments) {
+        if (versionSegments.length > 4) {
+            throw new IllegalArgumentException(
+                    "a maximum of four version segments is supported; (was: " + Arrays.toString(versionSegments) + ")");
+        }
+        if (IntStream.of(versionSegments).anyMatch(i -> i > 0xff)) {
+            throw new IllegalArgumentException(
+                    "a version segment cannot exceed 255 (was: " + Arrays.toString(versionSegments) + ")");
+        }
+        int version = (versionSegments[0] & 0xff) << 24;
+        if (versionSegments.length > 1) {
+            version |= (versionSegments[1] & 0xff) << 16;
+        }
+        if (versionSegments.length > 2) {
+            version |= (versionSegments[2] & 0xff) << 8;
+        }
+        if (versionSegments.length > 3) {
+            version |= versionSegments[3] & 0xff;
+        }
+        return fromInt(version);
+    }
+
+    @Override
+    public int compareTo(Object o) {
+        return Integer.compareUnsigned(level, ((CompatibilityLevel) o).level);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        CompatibilityLevel that = (CompatibilityLevel) o;
+        return level == that.level;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(level);
+    }
+
+    private Object writeReplace() throws ObjectStreamException {
+        return this;
+    }
+
+    public int intValue() {
+        return level;
+    }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityUtil.java
index 392955a..65da9fe 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/CompatibilityUtil.java
@@ -26,10 +26,21 @@ import org.apache.logging.log4j.Logger;
 
 public class CompatibilityUtil {
     private static final Logger LOGGER = LogManager.getLogger();
+    private static CompatibilityLevel compatLevel = CompatibilityLevel.DEFAULT;
 
     private CompatibilityUtil() {
     }
 
+    public static CompatibilityLevel getCompatibilityLevel() {
+        return compatLevel;
+    }
+
+    public static CompatibilityLevel setCompatibilityLevel(CompatibilityLevel newLevel) {
+        CompatibilityLevel prevLevel = compatLevel;
+        compatLevel = newLevel;
+        return prevLevel;
+    }
+
     public static Object readField(Object obj, String fieldName) throws IOException {
         Class<?> objClass = obj.getClass();
         LOGGER.debug("reading field '{}' on object of type {}", fieldName, objClass);
@@ -55,4 +66,8 @@ public class CompatibilityUtil {
             throw new IOException(e);
         }
     }
+
+    public static boolean isAtLeast035() {
+        return getCompatibilityLevel().intValue() >= CompatibilityLevel.V_0_3_5.intValue();
+    }
 }