You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by re...@apache.org on 2016/01/12 12:36:24 UTC

svn commit: r1724210 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb: RDBDocumentStore.java RDBDocumentStoreDB.java RDBDocumentStoreJDBC.java

Author: reschke
Date: Tue Jan 12 11:36:24 2016
New Revision: 1724210

URL: http://svn.apache.org/viewvc?rev=1724210&view=rev
Log:
OAK-3645: RDBDocumentStore: change DB server time detection to fetch seconds-since-the-epoch (eliminating timezone issues)

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1724210&r1=1724209&r2=1724210&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java Tue Jan 12 11:36:24 2016
@@ -511,7 +511,7 @@ public class RDBDocumentStore implements
         Connection connection = null;
         try {
             connection = this.ch.getROConnection();
-            long result = this.db.determineServerTimeDifferenceMillis(connection, getTable(Collection.NODES));
+            long result = this.db.determineServerTimeDifferenceMillis(connection);
             connection.commit();
             return result;
         } catch (SQLException ex) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java?rev=1724210&r1=1724209&r2=1724210&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java Tue Jan 12 11:36:24 2016
@@ -50,6 +50,16 @@ public enum RDBDocumentStoreDB {
         public String checkVersion(DatabaseMetaData md) throws SQLException {
             return RDBJDBCTools.versionCheck(md, 1, 4, description);
         }
+
+        @Override
+        public String getInitializationStatement() {
+            return "create alias if not exists unix_timestamp as $$ long unix_timestamp() { return System.currentTimeMillis()/1000L; } $$;";
+        }
+
+        @Override
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select unix_timestamp()";
+        }
     },
 
     DERBY("Apache Derby") {
@@ -59,11 +69,6 @@ public enum RDBDocumentStoreDB {
         }
 
         @Override
-        public String getCurrentTimeStampInMsSyntax() {
-            return "CURRENT_TIMESTAMP";
-        }
-
-        @Override
         public boolean allowsCaseInSelect() {
             return false;
         }
@@ -76,6 +81,11 @@ public enum RDBDocumentStoreDB {
         }
 
         @Override
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select extract(epoch from now())::integer";
+        }
+
+        @Override
         public String getTableCreationStatement(String tableName) {
             return ("create table " + tableName + " (ID varchar(512) not null primary key, MODIFIED bigint, HASBINARY smallint, DELETEDONCE smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA bytea)");
         }
@@ -115,6 +125,11 @@ public enum RDBDocumentStoreDB {
             return RDBJDBCTools.versionCheck(md, 10, 1, description);
         }
 
+        @Override
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select cast (days(current_timestamp - current_timezone) - days('1970-01-01') as integer) * 86400 + midnight_seconds(current_timestamp - current_timezone) from sysibm.sysdummy1";
+        }
+
         public String getTableCreationStatement(String tableName) {
             return "create table " + tableName
                     + " (ID varchar(512) not null, MODIFIED bigint, HASBINARY smallint, DELETEDONCE smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA blob("
@@ -182,6 +197,11 @@ public enum RDBDocumentStoreDB {
         }
 
         @Override
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select (trunc(sys_extract_utc(systimestamp)) - to_date('01/01/1970', 'MM/DD/YYYY')) * 24 * 60 * 60 + to_number(to_char(sys_extract_utc(systimestamp), 'SSSSS')) from dual";
+        }
+
+        @Override
         public String getInitializationStatement() {
             // see https://issues.apache.org/jira/browse/OAK-1914
             // for some reason, the default for NLS_SORT is incorrect
@@ -228,6 +248,11 @@ public enum RDBDocumentStoreDB {
         }
 
         @Override
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select unix_timestamp()";
+        }
+
+        @Override
         public String getTableCreationStatement(String tableName) {
             // see https://issues.apache.org/jira/browse/OAK-1913
             return ("create table " + tableName + " (ID varbinary(512) not null primary key, MODIFIED bigint, HASBINARY smallint, DELETEDONCE smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16000), BDATA longblob)");
@@ -328,8 +353,8 @@ public enum RDBDocumentStoreDB {
         }
 
         @Override
-        public String getCurrentTimeStampInMsSyntax() {
-            return "CURRENT_TIMESTAMP";
+        public String getCurrentTimeStampInSecondsSyntax() {
+            return "select datediff(second, dateadd(second, datediff(second, getutcdate(), getdate()), '1970-01-01'), getdate())";
         }
 
         @Override
@@ -392,10 +417,13 @@ public enum RDBDocumentStoreDB {
     }
 
     /**
-     * Query syntax for current time in ms
+     * Query syntax for current time in ms since the epoch
+     * 
+     * @return the query syntax or empty string when no such syntax is available
      */
-    public String getCurrentTimeStampInMsSyntax() {
-        return "CURRENT_TIMESTAMP(4)";
+    public String getCurrentTimeStampInSecondsSyntax() {
+        // unfortunately, we don't have a portable statement for this
+        return "";
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java?rev=1724210&r1=1724209&r2=1724210&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java Tue Jan 12 11:36:24 2016
@@ -222,52 +222,42 @@ public class RDBDocumentStoreJDBC {
         }
     }
 
-    public long determineServerTimeDifferenceMillis(Connection connection, RDBTableMetaData tmd) {
-        PreparedStatement stmt = null;
-        ResultSet rs = null;
-        long result;
-        try {
-            String t = "select ";
-            if (this.dbInfo.getFetchFirstSyntax() == FETCHFIRSTSYNTAX.TOP) {
-                t += "TOP 1 ";
-            }
-            t += this.dbInfo.getCurrentTimeStampInMsSyntax() + " from " + tmd.getName();
-            switch (this.dbInfo.getFetchFirstSyntax()) {
-                case LIMIT:
-                    t += " LIMIT 1";
-                    break;
-                case FETCHFIRST:
-                    t += " FETCH FIRST 1 ROWS ONLY";
-                    break;
-                default:
-                    break;
-            }
+    public long determineServerTimeDifferenceMillis(Connection connection) {
+        String sql = this.dbInfo.getCurrentTimeStampInSecondsSyntax();
 
-            stmt = connection.prepareStatement(t);
-            long start = System.currentTimeMillis();
-            rs = stmt.executeQuery();
-            if (rs.next()) {
-                long roundtrip = System.currentTimeMillis() - start;
-                long serverTime = rs.getTimestamp(1).getTime();
-                long roundedTime = start + roundtrip / 2;
-                result = roundedTime - serverTime;
-                String msg = String.format("instance timestamp: %d, DB timestamp: %d, difference: %d", roundedTime, serverTime,
-                        result);
-                if (Math.abs(result) >= 2000) {
-                    LOG.info(msg);
+        if (sql.isEmpty()) {
+            LOG.debug("{}: unsupported database, skipping DB server time check", this.dbInfo.toString());
+            return 0;
+        } else {
+            PreparedStatement stmt = null;
+            ResultSet rs = null;
+            try {
+                stmt = connection.prepareStatement(sql);
+                long start = System.currentTimeMillis();
+                rs = stmt.executeQuery();
+                if (rs.next()) {
+                    long roundtrip = System.currentTimeMillis() - start;
+                    long serverTimeSec = rs.getInt(1);
+                    long roundedTimeSec = ((start + roundtrip / 2) + 500) / 1000;
+                    long resultSec = roundedTimeSec - serverTimeSec;
+                    String message = String.format("instance timestamp: %d, DB timestamp: %d, difference: %d", roundedTimeSec,
+                            serverTimeSec, resultSec);
+                    if (Math.abs(resultSec) >= 2) {
+                        LOG.info(message);
+                    } else {
+                        LOG.debug(message);
+                    }
+                    return resultSec * 1000;
                 } else {
-                    LOG.debug(msg);
+                    throw new DocumentStoreException("failed to determine server timestamp");
                 }
-            } else {
-                throw new DocumentStoreException("failed to determine server timestamp");
+            } catch (Exception ex) {
+                LOG.error("Trying to determine time difference to server", ex);
+                throw new DocumentStoreException(ex);
+            } finally {
+                closeResultSet(rs);
+                closeStatement(stmt);
             }
-            return result;
-        } catch (Exception ex) {
-            LOG.error("Trying to determine time difference to server", ex);
-            throw new DocumentStoreException(ex);
-        } finally {
-            closeResultSet(rs);
-            closeStatement(stmt);
         }
     }