Repository: ignite
Updated Branches:
  refs/heads/ignite-1803 [created] 7ab23028b


IGNITE-1803: WIP.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e80d69d8
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e80d69d8
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e80d69d8

Branch: refs/heads/ignite-1803
Commit: e80d69d88baa5bccaa061826964c36e204d25c26
Parents: 7eedab1
Author: vozerov-gridgain <[email protected]>
Authored: Thu Oct 29 16:07:13 2015 +0300
Committer: vozerov-gridgain <[email protected]>
Committed: Thu Oct 29 16:07:13 2015 +0300

----------------------------------------------------------------------
 .../internal/portable/PortableSchema.java       | 223 +++++++++++++++++++
 .../portable/PortableSchemaRegistry.java        | 171 ++++++++++++++
 .../apache/ignite/portable/PortableObject.java  |   9 +
 .../portable/PortableObjectFieldDescriptor.java |  39 ++++
 4 files changed, 442 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e80d69d8/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
new file mode 100644
index 0000000..09bfe35
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Schema describing portable object content. We rely on the following 
assumptions:
+ * - When amount of fields in the object is low, it is better to inline these 
values into int fields thus allowing
+ * for quick comparisons performed within already fetched L1 cache line.
+ * - When there are more fields, we store them inside a hash map.
+ */
+public class PortableSchema {
+    /** Inline flag. */
+    private final boolean inline;
+
+    /** Map with offsets. */
+    private final HashMap<Integer, Integer> map;
+
+    /** ID 1. */
+    private final int id1;
+
+    /** Offset 1. */
+    private final int offset1;
+
+    /** ID 2. */
+    private final int id2;
+
+    /** Offset 2. */
+    private final int offset2;
+
+    /** ID 3. */
+    private final int id3;
+
+    /** Offset 3. */
+    private final int offset3;
+
+    /** ID 4. */
+    private final int id4;
+
+    /** Offset 4. */
+    private final int offset4;
+
+    /** ID 1. */
+    private final int id5;
+
+    /** Offset 1. */
+    private final int offset5;
+
+    /** ID 2. */
+    private final int id6;
+
+    /** Offset 2. */
+    private final int offset6;
+
+    /** ID 3. */
+    private final int id7;
+
+    /** Offset 3. */
+    private final int offset7;
+
+    /** ID 4. */
+    private final int id8;
+
+    /** Offset 4. */
+    private final int offset8;
+
+    /**
+     * Constructor.
+     *
+     * @param vals Values.
+     */
+    public PortableSchema(LinkedHashMap<Integer, Integer> vals) {
+        if (vals.size() <= 8) {
+            inline = true;
+
+            Iterator<Map.Entry<Integer, Integer>> iter = 
vals.entrySet().iterator();
+
+            Map.Entry<Integer, Integer> entry = iter.hasNext() ? iter.next() : 
null;
+
+            if (entry != null) {
+                id1 = entry.getKey();
+                offset1 = entry.getValue();
+            }
+            else{
+                id1 = 0;
+                offset1 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id2 = entry.getKey();
+                offset2 = entry.getValue();
+            }
+            else{
+                id2 = 0;
+                offset2 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id3 = entry.getKey();
+                offset3 = entry.getValue();
+            }
+            else{
+                id3 = 0;
+                offset3 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id4 = entry.getKey();
+                offset4 = entry.getValue();
+            }
+            else{
+                id4 = 0;
+                offset4 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id5 = entry.getKey();
+                offset5 = entry.getValue();
+            }
+            else{
+                id5 = 0;
+                offset5 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id6 = entry.getKey();
+                offset6 = entry.getValue();
+            }
+            else{
+                id6 = 0;
+                offset6 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id7 = entry.getKey();
+                offset7 = entry.getValue();
+            }
+            else{
+                id7 = 0;
+                offset7 = 0;
+            }
+
+            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
+                id8 = entry.getKey();
+                offset8 = entry.getValue();
+            }
+            else{
+                id8 = 0;
+                offset8 = 0;
+            }
+
+            map = null;
+        }
+        else {
+            inline = false;
+
+            id1 = id2 = id3 = id4 = id5 = id6 = id7 = id8 = 0;
+            offset1 = offset2 = offset3 = offset4 = offset5 = offset6 = 
offset7 = offset8 = 0;
+
+            map = new HashMap<>(vals);
+        }
+    }
+
+    /**
+     * Get offset for the given field ID.
+     *
+     * @param id Field ID.
+     * @return Offset or {@code 0} if there is no such field.
+     */
+    public int offset(int id) {
+        if (inline) {
+            if (id == id1)
+                return offset1;
+
+            if (id == id2)
+                return offset2;
+
+            if (id == id3)
+                return offset3;
+
+            if (id == id4)
+                return offset4;
+
+            if (id == id5)
+                return offset5;
+
+            if (id == id6)
+                return offset6;
+
+            if (id == id7)
+                return offset7;
+
+            if (id == id8)
+                return offset8;
+
+            return 0;
+        }
+        else {
+            Integer off = map.get(id);
+
+            return off != null ? off : 0;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e80d69d8/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchemaRegistry.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchemaRegistry.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchemaRegistry.java
new file mode 100644
index 0000000..88c3cce
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchemaRegistry.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.portable;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+
+/**
+ * Portable schema registry. Contains all well-known object schemas.
+ * <p>
+ * We rely on the fact that usually object has only few different schemas. For 
this reason we inline several
+ * of them with optional fallback to normal hash map lookup.
+ *
+ */
+public class PortableSchemaRegistry {
+    /** Empty schema ID. */
+    private static final int EMPTY = 0;
+
+    /** Whether registry still works in inline mode. */
+    private volatile boolean inline = true;
+
+    /** First schema ID. */
+    private int schemaId1;
+
+    /** Second schema ID. */
+    private int schemaId2;
+
+    /** Third schema ID. */
+    private int schemaId3;
+
+    /** Fourth schema ID. */
+    private int schemaId4;
+
+    /** First schema. */
+    private PortableSchema schema1;
+
+    /** Second schema. */
+    private PortableSchema schema2;
+
+    /** Third schema. */
+    private PortableSchema schema3;
+
+    /** Fourth schema. */
+    private PortableSchema schema4;
+
+    /** Schemas with COW semantics. */
+    private volatile HashMap<Integer, PortableSchema> schemas;
+
+    /**
+     * Get schema for the given ID. We rely on very relaxed memory semantics 
here assuming that it is not critical
+     * to return false-positive {@code null} values.
+     *
+     * @param schemaId Schema ID.
+     * @return Schema or {@code null}.
+     */
+    @Nullable public PortableSchema schema(int schemaId) {
+        if (inline) {
+            if (schemaId == schemaId1)
+                return schema1;
+            else if (schemaId == schemaId2)
+                return schema2;
+            else if (schemaId == schemaId3)
+                return schema3;
+            else if (schemaId == schemaId4)
+                return schema4;
+        }
+        else {
+            HashMap<Integer, PortableSchema> schemas0 = schemas;
+
+            // Null can be observed here due to either data race or race 
condition when switching to non-inlined mode.
+            // Both of them are benign for us because they lead only to 
unnecessary schema re-calc.
+            if (schemas0 != null)
+                return schemas0.get(schemaId);
+        }
+
+        return null;
+    }
+
+    /**
+     * Add schema.
+     *
+     * @param schemaId Schema ID.
+     * @param schema Schema.
+     */
+    public void addSchema(int schemaId, PortableSchema schema) {
+        synchronized (this) {
+            if (inline) {
+                // Check if this is already known schema.
+                if (schemaId == schemaId1 || schemaId == schemaId2 || schemaId 
== schemaId3 || schemaId == schemaId4)
+                    return;
+
+                // Try positioning new schema in inline mode.
+                if (schemaId1 == EMPTY) {
+                    schemaId1 = schemaId;
+
+                    schema1 = schema;
+
+                    inline = true; // Forcing HB edge just in case.
+
+                    return;
+                }
+
+                if (schemaId2 == EMPTY) {
+                    schemaId2 = schemaId;
+
+                    schema2 = schema;
+
+                    inline = true; // Forcing HB edge just in case.
+
+                    return;
+                }
+
+                if (schemaId3 == EMPTY) {
+                    schemaId3 = schemaId;
+
+                    schema3 = schema;
+
+                    inline = true; // Forcing HB edge just in case.
+
+                    return;
+                }
+
+                if (schemaId4 == EMPTY) {
+                    schemaId4 = schemaId;
+
+                    schema4 = schema;
+
+                    inline = true; // Forcing HB edge just in case.
+
+                    return;
+                }
+
+                // No luck, switching to hash map mode.
+                HashMap<Integer, PortableSchema> newSchemas = new HashMap<>();
+
+                newSchemas.put(schemaId1, schema1);
+                newSchemas.put(schemaId2, schema2);
+                newSchemas.put(schemaId3, schema3);
+                newSchemas.put(schemaId4, schema4);
+                newSchemas.put(schemaId, schema);
+
+                schemas = newSchemas;
+
+                inline = false;
+            }
+            else {
+                HashMap<Integer, PortableSchema> newSchemas = new 
HashMap<>(schemas);
+
+                newSchemas.put(schemaId, schema);
+
+                schemas = newSchemas;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e80d69d8/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java 
b/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
index 66b8f76..08c6622 100644
--- a/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/portable/PortableObject.java
@@ -137,6 +137,15 @@ public interface PortableObject extends Serializable, 
Cloneable {
     public boolean hasField(String fieldName);
 
     /**
+     * Gets field descriptor.
+     *
+     * @param fieldName Field name.
+     * @return Field descriptor.
+     * @throws PortableException If failed.
+     */
+    public PortableObjectFieldDescriptor fieldDescriptor(String fieldName) 
throws PortableException;
+
+    /**
      * Gets fully deserialized instance of portable object.
      *
      * @return Fully deserialized instance of portable object.

http://git-wip-us.apache.org/repos/asf/ignite/blob/e80d69d8/modules/core/src/main/java/org/apache/ignite/portable/PortableObjectFieldDescriptor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/portable/PortableObjectFieldDescriptor.java
 
b/modules/core/src/main/java/org/apache/ignite/portable/PortableObjectFieldDescriptor.java
new file mode 100644
index 0000000..182233a
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/portable/PortableObjectFieldDescriptor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.portable;
+
+/**
+ * Portable object field. Can be used to speed object field lookup.
+ */
+public interface PortableObjectFieldDescriptor {
+    /**
+     * Check whether field exists in the object.
+     *
+     * @param obj Object.
+     * @return {@code True} if exists.
+     */
+    public boolean exists(PortableObject obj);
+
+    /**
+     * Get field's value from the given object.
+     *
+     * @param obj Object.
+     * @return Value.
+     */
+    public <T> T value(PortableObject obj);
+}

Reply via email to