private CompletableFuture<Void> visitSecondPhaseCommand( TxInvocationContext ctx, TransactionBoundaryCommand command, boolean commit, ExtendedStatistic duration, ExtendedStatistic counter) throws Throwable { GlobalTransaction globalTransaction = command.getGlobalTransaction(); if (trace) { log.tracef( "Visit 2nd phase command %s. Is it local? %s. Transaction is %s", command, ctx.isOriginLocal(), globalTransaction.globalId()); } long start = timeService.time(); return ctx.onReturn( (rCtx, rCommand, rv, throwable) -> { if (throwable != null) { throw throwable; } long end = timeService.time(); updateTime(duration, counter, start, end, globalTransaction, rCtx.isOriginLocal()); cacheStatisticManager.setTransactionOutcome( commit, globalTransaction, rCtx.isOriginLocal()); cacheStatisticManager.terminateTransaction(globalTransaction, true, true); return null; }); }
private void updateTime( ExtendedStatistic duration, ExtendedStatistic counter, long initTime, long endTime, GlobalTransaction globalTransaction, boolean local) { cacheStatisticManager.add( duration, timeService.timeDuration(initTime, endTime, NANOSECONDS), globalTransaction, local); cacheStatisticManager.increment(counter, globalTransaction, local); }
@ManagedOperation( description = "K-th percentile of remote write transactions execution time", displayName = "K-th Percentile Remote Write Transactions") public double getPercentileRemoteWriteTransaction( @Parameter(name = "percentile") int percentile) { return cacheStatisticManager.getPercentile(WR_REMOTE_EXECUTION, percentile); }
@ManagedOperation( description = "K-th percentile of local write transactions execution time", displayName = "K-th Percentile Local Write Transactions") public double getPercentileLocalRWriteTransaction( @Parameter(name = "percentile") int percentile) { return cacheStatisticManager.getPercentile(WR_LOCAL_EXECUTION, percentile); }
private void processWriteException( InvocationContext ctx, GlobalTransaction globalTransaction, Throwable throwable) { if (!ctx.isOriginLocal()) return; ExtendedStatistic stat = null; if (throwable instanceof TimeoutException) { if (isLockTimeout(((TimeoutException) throwable))) { stat = NUM_LOCK_FAILED_TIMEOUT; } } else if (throwable instanceof DeadlockDetectedException) { stat = NUM_LOCK_FAILED_DEADLOCK; } else if (throwable instanceof WriteSkewException) { stat = NUM_WRITE_SKEW; } else if (throwable instanceof RemoteException) { Throwable cause = throwable.getCause(); while (cause != null) { if (cause instanceof TimeoutException) { stat = NUM_LOCK_FAILED_TIMEOUT; break; } else if (cause instanceof DeadlockDetectedException) { stat = NUM_LOCK_FAILED_DEADLOCK; break; } else if (cause instanceof WriteSkewException) { stat = NUM_WRITE_SKEW; break; } cause = cause.getCause(); } } if (stat != null) { cacheStatisticManager.increment(stat, globalTransaction, true); } }
// public to be used by the tests public double getAttribute(ExtendedStatistic statistic) { try { return cacheStatisticManager.getAttribute(statistic); } catch (ExtendedStatisticNotFoundException e) { log.unableToGetStatistic(statistic, e); } return 0; }
@Override public CompletableFuture<Void> visitGetAllCommand(InvocationContext ctx, GetAllCommand command) throws Throwable { if (trace) { log.tracef( "Visit Get All Command %s. Is it in transaction scope? %s. Is it local? %s", command, ctx.isInTxScope(), ctx.isOriginLocal()); } if (!ctx.isInTxScope()) { return ctx.continueInvocation(); } long start = timeService.time(); return ctx.onReturn( (rCtx, rCommand, rv, throwable) -> { if (throwable != null) { throw throwable; } long end = timeService.time(); initStatsIfNecessary(rCtx); int numRemote = 0; Collection<?> keys = ((GetAllCommand) rCommand).getKeys(); for (Object key : keys) { if (isRemote(key)) numRemote++; } // TODO: tbh this seems like it doesn't work properly for statistics as each // one will have the duration of all the time for all gets... Maybe do an average // instead ? Either way this isn't very indicative if (numRemote > 0) { cacheStatisticManager.add( NUM_REMOTE_GET, numRemote, getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.add( REMOTE_GET_EXECUTION, timeService.timeDuration(start, end, NANOSECONDS), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); } cacheStatisticManager.add( ALL_GET_EXECUTION, timeService.timeDuration(start, end, NANOSECONDS), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.add( NUM_GET, keys.size(), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); return null; }); }
@Override public CompletableFuture<Void> visitPrepareCommand( TxInvocationContext ctx, PrepareCommand command) throws Throwable { GlobalTransaction globalTransaction = command.getGlobalTransaction(); if (trace) { log.tracef( "Visit Prepare command %s. Is it local?. Transaction is %s", command, ctx.isOriginLocal(), globalTransaction.globalId()); } initStatsIfNecessary(ctx); cacheStatisticManager.onPrepareCommand(globalTransaction, ctx.isOriginLocal()); if (command.hasModifications()) { cacheStatisticManager.markAsWriteTransaction(globalTransaction, ctx.isOriginLocal()); } long start = timeService.time(); return ctx.onReturn( (rCtx, rCommand, rv, throwable) -> { if (throwable != null) { processWriteException(rCtx, globalTransaction, throwable); } else { long end = timeService.time(); updateTime( PREPARE_EXECUTION_TIME, NUM_PREPARE_COMMAND, start, end, globalTransaction, rCtx.isOriginLocal()); } if (((PrepareCommand) rCommand).isOnePhaseCommit()) { boolean local = rCtx.isOriginLocal(); boolean success = throwable == null; cacheStatisticManager.setTransactionOutcome( success, globalTransaction, rCtx.isOriginLocal()); cacheStatisticManager.terminateTransaction(globalTransaction, local, !local); } return null; }); }
@Override public CompletableFuture<Void> visitGetKeyValueCommand( InvocationContext ctx, GetKeyValueCommand command) throws Throwable { if (trace) { log.tracef( "Visit Get Key Value command %s. Is it in transaction scope? %s. Is it local? %s", command, ctx.isInTxScope(), ctx.isOriginLocal()); } if (!ctx.isInTxScope()) { return ctx.continueInvocation(); } long start = timeService.time(); return ctx.onReturn( (rCtx, rCommand, rv, throwable) -> { if (throwable != null) { throw throwable; } long end = timeService.time(); initStatsIfNecessary(rCtx); Object key = ((GetKeyValueCommand) rCommand).getKey(); if (isRemote(key)) { cacheStatisticManager.increment( NUM_REMOTE_GET, getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.add( REMOTE_GET_EXECUTION, timeService.timeDuration(start, end, NANOSECONDS), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); } cacheStatisticManager.add( ALL_GET_EXECUTION, timeService.timeDuration(start, end, NANOSECONDS), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.increment( NUM_GET, getGlobalTransaction(rCtx), rCtx.isOriginLocal()); return null; }); }
private CompletableFuture<Void> visitWriteCommand( InvocationContext ctx, WriteCommand command, Object key) throws Throwable { if (trace) { log.tracef( "Visit write command %s. Is it in transaction scope? %s. Is it local? %s", command, ctx.isInTxScope(), ctx.isOriginLocal()); } if (!ctx.isInTxScope()) { return ctx.continueInvocation(); } long start = timeService.time(); return ctx.onReturn( (rCtx, rCommand, rv, throwable) -> { long end = timeService.time(); initStatsIfNecessary(rCtx); if (throwable != null) { processWriteException(rCtx, getGlobalTransaction(rCtx), throwable); } else { if (isRemote(key)) { cacheStatisticManager.add( REMOTE_PUT_EXECUTION, timeService.timeDuration(start, end, NANOSECONDS), getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.increment( NUM_REMOTE_PUT, getGlobalTransaction(rCtx), rCtx.isOriginLocal()); } } cacheStatisticManager.increment( NUM_PUT, getGlobalTransaction(rCtx), rCtx.isOriginLocal()); cacheStatisticManager.markAsWriteTransaction( getGlobalTransaction(rCtx), rCtx.isOriginLocal()); return null; }); }
@ManagedOperation( description = "Dumps the current cache statistic values to a file", displayName = "Dump cache Statistics to file") public final void dumpStatisticToFile(@Parameter(description = "The file path") String filePath) throws IOException { PrintStream stream = null; try { stream = new PrintStream(new File(filePath)); cacheStatisticManager.dumpCacheStatisticsTo(stream); } finally { if (stream != null) { stream.close(); } } }
private void initStatsIfNecessary(InvocationContext ctx) { if (ctx.isInTxScope()) cacheStatisticManager.beginTransaction(getGlobalTransaction(ctx), ctx.isOriginLocal()); }
@ManagedOperation( description = "Dumps the current cache statistic values to System.out", displayName = "Dump Cache Statistics to System.out") public final void dumpStatisticsToSystemOut() { cacheStatisticManager.dumpCacheStatisticsTo(System.out); }
@ManagedOperation( description = "Dumps the current cache statistic values", displayName = "Dump Cache Statistics") public final String dumpStatistics() { return cacheStatisticManager.dumpCacheStatistics(); }
@ManagedOperation( description = "Reset all the statistics collected", displayName = "Reset All Statistics") public void resetStatistics() { cacheStatisticManager.reset(); }