Refactor TableModState to use nanoTime refactor (#1720)

* #1719 - Refactor TableModState to use nanoTime

* Tests only - reduce logging
This commit is contained in:
Rob Bygrave
2019-05-21 00:42:17 +12:00
committed by GitHub
parent cf4d45befb
commit 7fbdab6220
18 changed files with 59 additions and 90 deletions
+2 -9
View File
@@ -10,22 +10,15 @@ import java.util.Set;
*/
public class ServerCacheNotification {
private final long modifyTimestamp;
private final Set<String> dependentTables;
public ServerCacheNotification(long modifyTimestamp, Set<String> dependentTables) {
this.modifyTimestamp = modifyTimestamp;
public ServerCacheNotification(Set<String> dependentTables) {
this.dependentTables = dependentTables;
}
@Override
public String toString() {
return "ts:" + modifyTimestamp + " tables:" + dependentTables;
}
public long getModifyTimestamp() {
return modifyTimestamp;
return "tables:" + dependentTables;
}
public Set<String> getDependentTables() {
@@ -98,7 +98,7 @@ public interface SpiTransaction extends Transaction {
/**
* Return the start timestamp for the transaction (JVM side).
*/
long getStartMillis();
long getStartNanoTime();
/**
* Return true if this transaction has updateAllLoadedProperties set.
@@ -29,8 +29,8 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
}
@Override
public long getStartMillis() {
return transaction.getStartMillis();
public long getStartNanoTime() {
return transaction.getStartNanoTime();
}
@Override
@@ -30,8 +30,6 @@ public class TransactionEvent implements Serializable {
*/
private final transient boolean local;
private final long startMillis;
private TransactionEventTable eventTables;
private transient List<PersistRequestBean<?>> listenerNotify;
@@ -43,8 +41,7 @@ public class TransactionEvent implements Serializable {
/**
* Create the TransactionEvent, one per Transaction.
*/
public TransactionEvent(long startMillis) {
this.startMillis = startMillis;
public TransactionEvent() {
this.local = true;
}
@@ -119,7 +116,7 @@ public class TransactionEvent implements Serializable {
}
if (changeSet == null) {
changeSet = new CacheChangeSet(manager.clockNowMillis());
changeSet = new CacheChangeSet();
}
if (eventTables != null && !eventTables.isEmpty()) {
// notify cache with table based changes
@@ -154,7 +151,7 @@ public class TransactionEvent implements Serializable {
*/
public CacheChangeSet obtainCacheChangeSet() {
if (changeSet == null) {
changeSet = new CacheChangeSet(startMillis);
changeSet = new CacheChangeSet();
}
return changeSet;
}
@@ -28,13 +28,10 @@ public class CacheChangeSet {
private final Map<ManyKey, ManyChange> manyChangeMap = new HashMap<>();
private final long modificationTimestamp;
/**
* Construct specifying if we also need to process invalidation for entities based on views.
*/
public CacheChangeSet(long modificationTimestamp) {
this.modificationTimestamp = modificationTimestamp;
public CacheChangeSet() {
}
/**
@@ -172,13 +169,6 @@ public class CacheChangeSet {
return manyChangeMap.computeIfAbsent(key, ManyChange::new);
}
/**
* Return the modification timestamp for these changes.
*/
public long modificationTimestamp() {
return modificationTimestamp;
}
/**
* Changes for a specific many property.
*/
@@ -169,7 +169,7 @@ public class InternalConfiguration {
this.online = online;
this.serverConfig = serverConfig;
this.clockService = new ClockService(serverConfig.getClock());
this.tableModState = new TableModState(clockService);
this.tableModState = new TableModState();
this.logManager = initLogManager();
this.docStoreFactory = initDocStoreFactory(serverConfig.service(DocStoreFactory.class));
this.jsonFactory = serverConfig.getJsonFactory();
@@ -696,9 +696,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
public void putToQueryCache(Object result) {
// use transaction start where as query statement start would be better at READ_COMMITTED
long asOfTimestamp = transaction.getStartMillis();
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, asOfTimestamp));
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.getStartNanoTime()));
}
/**
@@ -65,7 +65,6 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
private Map<String, Object> userObjects;
private long startNanos;
private long startMillis;
/**
* Create without a tenantId.
@@ -78,7 +77,6 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
this.connection = connection;
this.persistenceContext = new DefaultPersistenceContext();
this.startNanos = System.nanoTime();
this.startMillis = manager.clockNowMillis();
}
/**
@@ -90,9 +88,9 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
}
@Override
public long getStartMillis() {
public long getStartNanoTime() {
// not used on read only transaction
return startMillis;
return startNanos;
}
@Override
@@ -185,7 +185,6 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
protected ProfileLocation profileLocation;
protected final long startNanos;
private final long startMillis;
/**
* Create a new JdbcTransaction.
@@ -202,7 +201,6 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
this.startNanos = System.nanoTime();
if (manager == null) {
this.startMillis = System.currentTimeMillis();
this.logSql = false;
this.logSummary = false;
this.skipCacheAfterWrite = true;
@@ -210,7 +208,6 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
this.batchOnCascadeMode = false;
this.onQueryOnly = OnQueryOnly.ROLLBACK;
} else {
this.startMillis = manager.clockNowMillis();
this.logSql = manager.isLogSql();
this.logSummary = manager.isLogSummary();
this.skipCacheAfterWrite = manager.isSkipCacheAfterWrite();
@@ -237,8 +234,8 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
}
@Override
public long getStartMillis() {
return startMillis;
public long getStartNanoTime() {
return startNanos;
}
@Override
@@ -827,7 +824,7 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
public TransactionEvent getEvent() {
queryOnly = false;
if (event == null) {
event = new TransactionEvent(startMillis);
event = new TransactionEvent();
}
return event;
}
@@ -1024,7 +1021,7 @@ public class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
// the event has been sent to the transaction manager
// for postCommit processing (l2 cache updates etc)
// start a new transaction event
event = new TransactionEvent(startMillis);
event = new TransactionEvent();
} catch (Exception e) {
doRollback(e);
@@ -46,9 +46,9 @@ class NoTransaction implements SpiTransaction {
}
@Override
public long getStartMillis() {
public long getStartNanoTime() {
// not used
return System.currentTimeMillis();
return System.nanoTime();
}
@Override
@@ -145,9 +145,9 @@ final class PostCommitProcessing {
if (cacheChanges != null) {
Set<String> touched = cacheChanges.touchedTables();
if (touched != null && !touched.isEmpty()) {
manager.processTouchedTables(touched, cacheChanges.modificationTimestamp());
manager.processTouchedTables(touched);
if (remoteTransactionEvent != null) {
remoteTransactionEvent.addRemoteTableMod(new RemoteTableMod(cacheChanges.modificationTimestamp(), touched));
remoteTransactionEvent.addRemoteTableMod(new RemoteTableMod(touched));
}
}
cacheChanges.apply();
@@ -15,7 +15,12 @@ public class RemoteTableMod implements BinaryWritable {
private final Set<String> tables;
public RemoteTableMod(long timestamp, Set<String> tables) {
public RemoteTableMod(Set<String> tables) {
this.tables = tables;
this.timestamp = System.currentTimeMillis();
}
private RemoteTableMod(long timestamp, Set<String> tables) {
this.timestamp = timestamp;
this.tables = tables;
}
@@ -4,7 +4,6 @@ import io.ebean.cache.QueryCacheEntry;
import io.ebean.cache.QueryCacheEntryValidate;
import io.ebean.cache.ServerCacheNotification;
import io.ebean.cache.ServerCacheNotify;
import io.ebeaninternal.server.core.ClockService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,33 +21,31 @@ public class TableModState implements QueryCacheEntryValidate, ServerCacheNotify
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.TABLEMOD");
private final ClockService clockService;
private Map<String, Long> tableModStamp = new ConcurrentHashMap<>();
private Map<String,Long> tableModStamp = new ConcurrentHashMap<>();
public TableModState(ClockService clockService) {
this.clockService = clockService;
public TableModState() {
}
/**
* Set the modified timestamp on the tables that have been touched.
*/
void touch(Set<String> touchedTables, long modTimestamp) {
void touch(Set<String> touchedTables) {
long modNanoTime = System.nanoTime();
for (String tableName : touchedTables) {
tableModStamp.put(tableName, modTimestamp);
tableModStamp.put(tableName, modNanoTime);
}
if (log.isDebugEnabled()) {
log.debug("TableModState updated - touched:{} modTimestamp:{}", touchedTables, modTimestamp);
log.debug("TableModState updated - touched:{} modNanoTime:{}", touchedTables, modNanoTime);
}
}
/**
* Return true if all the tables are valid based on timestamp comparison.
*/
boolean isValid(Set<String> tables, long sinceTimestamp) {
boolean isValid(Set<String> tables, long sinceNanoTime) {
for (String tableName : tables) {
Long modTime = tableModStamp.get(tableName);
if (modTime != null && modTime >= sinceTimestamp ) {
if (modTime != null && modTime >= sinceNanoTime) {
if (log.isTraceEnabled()) {
log.trace("Invalidate on table:{}", tableName);
}
@@ -81,7 +78,7 @@ public class TableModState implements QueryCacheEntryValidate, ServerCacheNotify
if (log.isDebugEnabled()) {
log.debug("ServerCacheNotification:{}", notification);
}
touch(notification.getDependentTables(), clockService.nowMillis());
touch(notification.getDependentTables());
}
/**
@@ -97,6 +94,6 @@ public class TableModState implements QueryCacheEntryValidate, ServerCacheNotify
if (log.isDebugEnabled()) {
log.debug("RemoteTableMod:{}", tableMod);
}
touch(tableMod.getTables(), clockService.nowMillis());
touch(tableMod.getTables());
}
}
@@ -452,7 +452,7 @@ public class TransactionManager implements SpiTransactionManager {
private void externalModificationEvent(TransactionEventTable tableEvents) {
TransactionEvent event = new TransactionEvent(clockNowMillis());
TransactionEvent event = new TransactionEvent();
event.add(tableEvents);
PostCommitProcessing postCommit = new PostCommitProcessing(clusterManager, this, event);
@@ -469,7 +469,7 @@ public class TransactionManager implements SpiTransactionManager {
clusterLogger.debug("processing {}", remoteEvent);
}
CacheChangeSet changeSet = new CacheChangeSet(clockNowMillis());
CacheChangeSet changeSet = new CacheChangeSet();
RemoteTableMod tableMod = remoteEvent.getRemoteTableMod();
if (tableMod != null) {
@@ -522,12 +522,12 @@ public class TransactionManager implements SpiTransactionManager {
/**
* Invalidate the query caches for entities based on views.
*/
public void processTouchedTables(Set<String> touchedTables, long modTimestamp) {
tableModState.touch(touchedTables, modTimestamp);
public void processTouchedTables(Set<String> touchedTables) {
tableModState.touch(touchedTables);
if (viewInvalidation) {
beanDescriptorManager.processViewInvalidation(touchedTables);
}
cacheNotify.notify(new ServerCacheNotification(modTimestamp, touchedTables));
cacheNotify.notify(new ServerCacheNotification(touchedTables));
}
/**