Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java (revision 1724069) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java (working copy) @@ -511,7 +511,7 @@ 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) { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java (revision 1724069) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java (working copy) @@ -50,6 +50,16 @@ 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,8 +69,8 @@ } @Override - public String getCurrentTimeStampInMsSyntax() { - return "CURRENT_TIMESTAMP"; + public String getCurrentTimeStampInSecondsSyntax() { + return "values {fn timestampdiff(SQL_TSI_SECOND,timestamp('1970-1-1-00.00.00.000000'), current_timestamp)}"; } @Override @@ -76,6 +86,11 @@ } @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 +130,11 @@ 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 +202,11 @@ } @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 +253,11 @@ } @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 +358,8 @@ } @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 +422,13 @@ } /** - * 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 ""; } /** Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java (revision 1724069) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java (working copy) @@ -222,52 +222,45 @@ } } - 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()) { + // we don't know + return 0; + } + else { + PreparedStatement stmt = null; + ResultSet rs = null; + long result; + try { + stmt = connection.prepareStatement(sql); + long start = System.currentTimeMillis(); + rs = stmt.executeQuery(); + if (rs.next()) { + long roundtrip = System.currentTimeMillis() - start; + long serverTime = 1000l * rs.getInt(1); + long roundedTime = start + roundtrip / 2; + result = roundedTime - serverTime; + String msg = String.format("instance timestamp: %d, DB timestamp: %d, difference: %d", roundedTime, serverTime, + result); + System.err.println(msg); + if (Math.abs(result) >= 2000) { + LOG.info(msg); + } else { + LOG.debug(msg); + } } else { - LOG.debug(msg); + throw new DocumentStoreException("failed to determine server timestamp"); } - } else { - throw new DocumentStoreException("failed to determine server timestamp"); + return result; + } 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); } }