IGNITE-1753 WIP on hashing.

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

Branch: refs/heads/ignite-1753-1282
Commit: d5355def68e5910251fd6083c1858dc19f712a88
Parents: 6c9c113
Author: Alexey Kuznetsov <akuznet...@apache.org>
Authored: Thu Oct 29 18:12:04 2015 +0700
Committer: Alexey Kuznetsov <akuznet...@apache.org>
Committed: Thu Oct 29 18:12:04 2015 +0700

----------------------------------------------------------------------
 .../store/jdbc/CacheAbstractJdbcStore.java      | 39 ++++++++++++----
 .../cache/store/jdbc/CacheJdbcPojoStore.java    | 49 +++++++++++---------
 .../jdbc/CacheJdbcPojoStoreConfiguration.java   | 26 +++++++++++
 .../ignite/cache/store/jdbc/JdbcType.java       |  3 ++
 .../store/jdbc/JdbcTypeDefaultHashBuilder.java  | 23 +++++++++
 .../jdbc/JdbcTypeDefaultHashBuilderFactory.java | 19 ++++++++
 .../cache/store/jdbc/JdbcTypeHashBuilder.java   | 38 +++++++++++++++
 7 files changed, 167 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
index 9a4ce75..c43a030 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
@@ -42,6 +42,7 @@ import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import javax.cache.Cache;
 import javax.cache.CacheException;
+import javax.cache.configuration.Factory;
 import javax.cache.integration.CacheLoaderException;
 import javax.cache.integration.CacheWriterException;
 import javax.sql.DataSource;
@@ -191,6 +192,9 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
     /** Types that store could process. */
     private JdbcType[] types;
 
+    /** Factory for.  */
+    protected Factory<JdbcTypeHashBuilder> hashBuilderFactory = 
JdbcTypeDefaultHashBuilderFactory.INSTANCE;
+
     /**
      * Get field value from object for use as query parameter.
      *
@@ -212,12 +216,13 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
      * @param typeName Type name.
      * @param fields Fields descriptors.
      * @param loadColIdxs Select query columns index.
+     * @param key {@code true}
      * @param rs ResultSet.
      * @return Constructed object.
      * @throws CacheLoaderException If failed to construct cache object.
      */
     protected abstract <R> R buildObject(@Nullable String cacheName, String 
typeName,
-        JdbcTypeField[] fields, Map<String, Integer> loadColIdxs, ResultSet rs)
+        JdbcTypeField[] fields, Map<String, Integer> loadColIdxs, boolean key, 
ResultSet rs)
         throws CacheLoaderException;
 
     /**
@@ -520,8 +525,8 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
                     ResultSet rs = stmt.executeQuery();
 
                     while (rs.next()) {
-                        K key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), em.loadColIdxs, rs);
-                        V val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, rs);
+                        K key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), em.loadColIdxs, true, rs);
+                        V val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, false, rs);
 
                         clo.apply(key, val);
                     }
@@ -910,7 +915,7 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
             ResultSet rs = stmt.executeQuery();
 
             if (rs.next())
-                return buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, rs);
+                return buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, false, rs);
         }
         catch (SQLException e) {
             throw new CacheLoaderException("Failed to load object [table=" + 
em.fullTableName() +
@@ -1578,6 +1583,24 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
     }
 
     /**
+     * Gets hash builder factory.
+     *
+     * @return Hash builder factory.
+     */
+    public Factory<JdbcTypeHashBuilder> getHashBuilderFactory() {
+        return hashBuilderFactory;
+    }
+
+    /**
+     * Sets hash builder factory..
+     *
+     * @param hashBuilderFactory Hash builder factory.
+     */
+    public void setHashBuilderFactory(Factory<JdbcTypeHashBuilder> 
hashBuilderFactory) {
+        this.hashBuilderFactory = hashBuilderFactory;
+    }
+
+    /**
      * Get maximum batch size for delete and delete operations.
      *
      * @return Maximum batch size.
@@ -1880,8 +1903,8 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
                     colIdxs.put(meta.getColumnLabel(i), i);
 
                 while (rs.next()) {
-                    K1 key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), colIdxs, rs);
-                    V1 val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), colIdxs, rs);
+                    K1 key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), colIdxs, true, rs);
+                    V1 val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), colIdxs, false, rs);
 
                     clo.apply(key, val);
                 }
@@ -1975,8 +1998,8 @@ public abstract class CacheAbstractJdbcStore<K, V> 
implements CacheStore<K, V>,
                 Map<K1, V1> entries = U.newHashMap(keys.size());
 
                 while (rs.next()) {
-                    K1 key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), em.loadColIdxs, rs);
-                    V1 val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, rs);
+                    K1 key = buildObject(em.cacheName, em.keyType(), 
em.keyColumns(), em.loadColIdxs, true, rs);
+                    V1 val = buildObject(em.cacheName, em.valueType(), 
em.valueColumns(), em.loadColIdxs, false, rs);
 
                     entries.put(key, val);
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
index 9a7996f..e29f6ca 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
@@ -119,23 +119,12 @@ public class CacheJdbcPojoStore<K, V> extends 
CacheAbstractJdbcStore<K, V> {
             obj.getClass() + ", property=" + fieldName + "]");
     }
 
-    /**
-     * Construct object from query result.
-     *
-     * @param <R> Type of result object.
-     * @param cacheName Cache name.
-     * @param typeName Type name.
-     * @param fields Fields descriptors.
-     * @param loadColIdxs Select query columns index.
-     * @param rs ResultSet.
-     * @return Constructed object.
-     * @throws CacheLoaderException If failed to construct cache object.
-     */
+    /** {@inheritDoc} */
     @Override protected <R> R buildObject(@Nullable String cacheName, String 
typeName,
-        JdbcTypeField[] fields, Map<String, Integer> loadColIdxs, ResultSet rs)
+        JdbcTypeField[] fields, Map<String, Integer> loadColIdxs, boolean key, 
ResultSet rs)
         throws CacheLoaderException {
         return (R)(isKeepSerialized(cacheName, typeName)
-            ? buildPortableObject(cacheName, typeName, fields, loadColIdxs, rs)
+            ? buildPortableObject(cacheName, typeName, fields, loadColIdxs, 
key, rs)
             : buildPojoObject(cacheName, typeName, fields, loadColIdxs, rs));
     }
 
@@ -212,12 +201,13 @@ public class CacheJdbcPojoStore<K, V> extends 
CacheAbstractJdbcStore<K, V> {
      * @param typeName Type name.
      * @param fields Fields descriptors.
      * @param loadColIdxs Select query columns index.
+     * @param hash If {@code true} then build object with hash.
      * @param rs ResultSet.
      * @return Constructed portable object.
      * @throws CacheLoaderException If failed to construct portable object.
      */
     protected Object buildPortableObject(String cacheName, String typeName, 
JdbcTypeField[] fields,
-        Map<String, Integer> loadColIdxs, ResultSet rs) throws 
CacheLoaderException {
+        Map<String, Integer> loadColIdxs, boolean hash, ResultSet rs) throws 
CacheLoaderException {
         Map<String, IgniteBiTuple<Boolean, Integer>> cacheTypeIds = 
portableTypeIds.get(cacheName);
 
         if (cacheTypeIds == null)
@@ -245,19 +235,34 @@ public class CacheJdbcPojoStore<K, V> extends 
CacheAbstractJdbcStore<K, V> {
             else {
                 PortableBuilder builder = 
ignite.portables().builder(tuple.get2());
 
-                int hashCode = 0; // TODO: IGNITE-1753 hash code calculation 
could change !!!
+                if (hash) {
+                    JdbcTypeHashBuilder hashBuilder = 
hashBuilderFactory.create();
 
-                for (JdbcTypeField field : fields) {
-                    Integer colIdx = 
loadColIdxs.get(field.getDatabaseFieldName());
+                    for (JdbcTypeField field : fields) {
+                        Integer colIdx = 
loadColIdxs.get(field.getDatabaseFieldName());
+
+                        String colName = field.getJavaFieldName();
 
-                    Object colVal = getColumnValue(rs, colIdx, 
field.getJavaFieldType());
+                        Object colVal = getColumnValue(rs, colIdx, 
field.getJavaFieldType());
 
-                    hashCode = 31 * hashCode + (colVal != null ? 
colVal.hashCode() : 0);
+                        hashBuilder.toHash(colVal, typeName, colName);
+
+                        builder.setField(colName, colVal);
+                    }
 
-                    builder.setField(field.getJavaFieldName(), colVal);
+                    return builder.hashCode(hashBuilder.hash()).build();
                 }
+                 else {
+                    for (JdbcTypeField field : fields) {
+                        Integer colIdx = 
loadColIdxs.get(field.getDatabaseFieldName());
 
-                return builder.hashCode(hashCode).build();
+                        Object colVal = getColumnValue(rs, colIdx, 
field.getJavaFieldType());
+
+                        builder.setField(field.getJavaFieldName(), colVal);
+                    }
+
+                    return builder.build();
+                }
             }
         }
         catch (SQLException e) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreConfiguration.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreConfiguration.java
index 206f1fe..1361e46 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreConfiguration.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.cache.store.jdbc;
 
+import javax.cache.configuration.Factory;
 import org.apache.ignite.cache.store.jdbc.dialect.*;
 
 import java.io.*;
@@ -55,6 +56,9 @@ public class CacheJdbcPojoStoreConfiguration implements 
Serializable {
     /** Parallel load cache minimum threshold. If {@code 0} then load 
sequentially. */
     private int parallelLoadCacheMinThreshold = 
DFLT_PARALLEL_LOAD_CACHE_MINIMUM_THRESHOLD;
 
+    /** Factory for.  */
+    private Factory<JdbcTypeHashBuilder> hashBuilderFactory = 
JdbcTypeDefaultHashBuilderFactory.INSTANCE;
+
     /** Types that store could process. */
     private JdbcType[] types;
 
@@ -79,6 +83,7 @@ public class CacheJdbcPojoStoreConfiguration implements 
Serializable {
         maxWrtAttempts = cfg.getMaximumWriteAttempts();
         parallelLoadCacheMinThreshold = 
cfg.getParallelLoadCacheMinimumThreshold();
         types = cfg.getTypes();
+        hashBuilderFactory = cfg.getHashBuilderFactory();
     }
 
     /**
@@ -227,4 +232,25 @@ public class CacheJdbcPojoStoreConfiguration implements 
Serializable {
 
         return this;
     }
+
+    /**
+     * Gets hash builder factory.
+     *
+     * @return Hash builder factory.
+     */
+    public Factory<JdbcTypeHashBuilder> getHashBuilderFactory() {
+        return hashBuilderFactory;
+    }
+
+    /**
+     * Sets hash builder factory..
+     *
+     * @param hashBuilderFactory Hash builder factory.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreConfiguration 
setHashBuilderFactory(Factory<JdbcTypeHashBuilder> hashBuilderFactory) {
+        this.hashBuilderFactory = hashBuilderFactory;
+
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
index 518ad8a..cee6263 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcType.java
@@ -54,6 +54,9 @@ public class JdbcType implements Serializable {
     /** If {@code true} object is stored as IgniteObject. */
     private boolean keepSerialized;
 
+    /** Custom type hasher. */
+    private JdbcTypeHashBuilder hasher;
+
     /**
      * Empty constructor (all values are initialized to their defaults).
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilder.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilder.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilder.java
new file mode 100644
index 0000000..e7330e8
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilder.java
@@ -0,0 +1,23 @@
+package org.apache.ignite.cache.store.jdbc;
+
+/**
+ * Default implementation of {@link JdbcTypeHashBuilder}.
+ *
+ * This implementation ignores type and field names.
+ */
+public class JdbcTypeDefaultHashBuilder implements JdbcTypeHashBuilder {
+    /** Hash code. */
+    private int hash = 0;
+
+    /** {@inheritDoc} */
+    @Override public int toHash(Object val, String typeName, String fieldName) 
{
+        hash = 31 * hash + (val != null ? val.hashCode() : 0);
+
+        return hash;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hash() {
+        return hash;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilderFactory.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilderFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilderFactory.java
new file mode 100644
index 0000000..6dea4d1
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeDefaultHashBuilderFactory.java
@@ -0,0 +1,19 @@
+package org.apache.ignite.cache.store.jdbc;
+
+import javax.cache.configuration.Factory;
+
+/**
+ * Factory for creating default hash builder.
+ */
+public class JdbcTypeDefaultHashBuilderFactory implements 
Factory<JdbcTypeHashBuilder> {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Instance of factory for reuse. */
+    public final static JdbcTypeDefaultHashBuilderFactory INSTANCE = new 
JdbcTypeDefaultHashBuilderFactory();
+
+    /** {@inheritDoc} */
+    @Override public JdbcTypeHashBuilder create() {
+        return new JdbcTypeDefaultHashBuilder();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/d5355def/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHashBuilder.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHashBuilder.java
 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHashBuilder.java
new file mode 100644
index 0000000..971ae06
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypeHashBuilder.java
@@ -0,0 +1,38 @@
+/*
+ * 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.cache.store.jdbc;
+
+/**
+ * API for implementing custom hashing logic for portable objects on server 
side.
+ */
+public interface JdbcTypeHashBuilder {
+    /**
+     * Calculate hash code for specified value and field name.
+     *
+     * @param val Value to calculate hash code for.
+     * @param typeName Type name hash is calculating for.
+     * @param fieldName Field name that should participate in hash code 
calculation.
+     * @return Hash code.
+     */
+    public int toHash(Object val, String typeName, String fieldName);
+
+    /**
+     * @return Calculated hash code.
+     */
+    public int hash();
+}

Reply via email to