Skip to content

Commit

Permalink
IGNITE-8601 Add to control.sh utility information about transaction s…
Browse files Browse the repository at this point in the history
…tart time - Fixes apache#4070.
  • Loading branch information
a-polyakov authored and agoncharuk committed Jun 18, 2018
1 parent 82d533d commit 4776a1a
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 25 deletions.
Expand Up @@ -25,7 +25,6 @@
import java.util.UUID;
import java.util.stream.Collectors;
import org.apache.ignite.IgniteCompute;
import org.apache.ignite.IgniteException;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
Expand Down Expand Up @@ -107,6 +106,7 @@ else if ("SIZE".equals(order))
w.println(" Tx: [xid=" + info.getXid() +
", label=" + info.getLabel() +
", state=" + info.getState() +
", startTime=" + info.getFormattedStartTime() +
", duration=" + info.getDuration() / 1000 +
", isolation=" + info.getIsolation() +
", concurrency=" + info.getConcurrency() +
Expand Down
Expand Up @@ -236,6 +236,9 @@ public class CommandHandler {
/** */
private static final String TX_ORDER = "order";

/** */
public static final String CMD_TX_ORDER_START_TIME="START_TIME";

/** */
private static final String TX_SERVERS = "servers";

Expand Down Expand Up @@ -1079,6 +1082,7 @@ else if (arg.getOperation() == VisorTxOperation.KILL)
log(" Tx: [xid=" + info.getXid() +
", label=" + info.getLabel() +
", state=" + info.getState() +
", startTime=" + info.getFormattedStartTime() +
", duration=" + info.getDuration() / 1000 +
", isolation=" + info.getIsolation() +
", concurrency=" + info.getConcurrency() +
Expand Down Expand Up @@ -1826,7 +1830,7 @@ public int execute(List<String> rawArgs) {
usage(" Set baseline topology based on version:", BASELINE, " version topologyVersion [--force]");
usage(" List or kill transactions:", TX, " [xid XID] [minDuration SECONDS] " +
"[minSize SIZE] [label PATTERN_REGEX] [servers|clients] " +
"[nodes consistentId1[,consistentId2,....,consistentIdN] [limit NUMBER] [order DURATION|SIZE] [kill] [--force]");
"[nodes consistentId1[,consistentId2,....,consistentIdN] [limit NUMBER] [order DURATION|SIZE|", CMD_TX_ORDER_START_TIME, "] [kill] [--force]");

if(enableExperimental) {
usage(" Print absolute paths of unused archived wal segments on each node:", WAL,
Expand Down
Expand Up @@ -20,8 +20,11 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.TimeZone;
import java.util.UUID;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
Expand All @@ -37,9 +40,17 @@ public class VisorTxInfo extends VisorDataTransferObject {
/** */
private static final long serialVersionUID = 0L;

/** */
private static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");

/** */
private IgniteUuid xid;

/**
* Transaction start time.
*/
private long startTime;

/** */
private long duration;

Expand Down Expand Up @@ -73,6 +84,7 @@ public VisorTxInfo() {

/**
* @param xid Xid.
* @param startTime Start time of transaction.
* @param duration Duration.
* @param isolation Isolation.
* @param concurrency Concurrency.
Expand All @@ -82,10 +94,11 @@ public VisorTxInfo() {
* @param state State.
* @param size Size.
*/
public VisorTxInfo(IgniteUuid xid, long duration, TransactionIsolation isolation,
public VisorTxInfo(IgniteUuid xid, long startTime, long duration, TransactionIsolation isolation,
TransactionConcurrency concurrency, long timeout, String lb, Collection<UUID> primaryNodes,
TransactionState state, int size) {
this.xid = xid;
this.startTime = startTime;
this.duration = duration;
this.isolation = isolation;
this.concurrency = concurrency;
Expand All @@ -101,6 +114,16 @@ public IgniteUuid getXid() {
return xid;
}

/** */
public long getStartTime() {
return startTime;
}

/** */
public String getFormattedStartTime() {
return dateTimeFormatter.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(startTime), TimeZone.getDefault().toZoneId()));
}

/** */
public long getDuration() {
return duration;
Expand Down Expand Up @@ -141,6 +164,11 @@ public int getSize() {
return size;
}

/** {@inheritDoc} */
@Override public byte getProtocolVersion() {
return V2;
}

/** {@inheritDoc} */
@Override protected void writeExternalData(ObjectOutput out) throws IOException {
U.writeGridUuid(out, xid);
Expand All @@ -152,10 +180,12 @@ public int getSize() {
U.writeCollection(out, primaryNodes);
U.writeEnum(out, state);
out.writeInt(size);
out.writeLong(startTime);
}

/** {@inheritDoc} */
@Override protected void readExternalData(byte protoVer, ObjectInput in) throws IOException, ClassNotFoundException {
@Override protected void readExternalData(byte protoVer,
ObjectInput in) throws IOException, ClassNotFoundException {
xid = U.readGridUuid(in);
duration = in.readLong();
isolation = TransactionIsolation.fromOrdinal(in.readByte());
Expand All @@ -165,6 +195,7 @@ public int getSize() {
primaryNodes = U.readCollection(in);
state = TransactionState.fromOrdinal(in.readByte());
size = in.readInt();
startTime = protoVer >= V2 ? in.readLong() : 0L;
}

/** {@inheritDoc} */
Expand Down
Expand Up @@ -17,6 +17,7 @@

package org.apache.ignite.internal.visor.tx;

import org.apache.ignite.internal.commandline.CommandHandler;
import org.jetbrains.annotations.Nullable;

/**
Expand All @@ -25,7 +26,9 @@ public enum VisorTxSortOrder {
/** Sort by duration. */
DURATION,
/** Sort by size. */
SIZE;
SIZE,
/** Sort by startTime */
START_TIME;

/** Enumerated values. */
private static final VisorTxSortOrder[] VALS = values();
Expand All @@ -50,6 +53,9 @@ public static VisorTxSortOrder fromString(String name) {
if (SIZE.toString().equals(name))
return SIZE;

if (CommandHandler.CMD_TX_ORDER_START_TIME.equals(name))
return START_TIME;

throw new IllegalArgumentException("Sort order is unknown: " + name);
}
}
Expand Up @@ -194,7 +194,7 @@ private VisorTxJob(VisorTxTaskArg arg, boolean debug) {
if (arg.getMinSize() != null && size < arg.getMinSize())
continue;

infos.add(new VisorTxInfo(locTx.xid(), duration, locTx.isolation(), locTx.concurrency(),
infos.add(new VisorTxInfo(locTx.xid(), locTx.startTime(), duration, locTx.isolation(), locTx.concurrency(),
locTx.timeout(), locTx.label(), mappings, locTx.state(), size));

if (arg.getOperation() == VisorTxOperation.KILL)
Expand All @@ -218,6 +218,11 @@ private VisorTxJob(VisorTxTaskArg arg, boolean debug) {

break;

case START_TIME:
comp = TxStartTimeComparator.INSTANCE;

break;

default:
}
}
Expand All @@ -228,6 +233,19 @@ private VisorTxJob(VisorTxTaskArg arg, boolean debug) {
}
}

/**
*
*/
private static class TxStartTimeComparator implements Comparator<VisorTxInfo> {
/** Instance. */
public static final TxStartTimeComparator INSTANCE = new TxStartTimeComparator();

/** {@inheritDoc} */
@Override public int compare(VisorTxInfo o1, VisorTxInfo o2) {
return Long.compare(o2.getStartTime(), o1.getStartTime());
}
}

/**
*
*/
Expand Down
Expand Up @@ -456,16 +456,13 @@ else if (entry.getKey().equals(node2)) {
validate(h, map -> {
VisorTxTaskResult res = map.get(grid(0).localNode());

for (VisorTxInfo info:res.getInfos()){
for (VisorTxInfo info : res.getInfos())
assertNull(info.getLabel());

}

}, "--tx", "label", "null");


// test check minSize
int minSize=10;
int minSize = 10;

validate(h, map -> {
VisorTxTaskResult res = map.get(grid(0).localNode());
Expand All @@ -482,18 +479,26 @@ else if (entry.getKey().equals(node2)) {
validate(h, map -> {
VisorTxTaskResult res = map.get(grid(0).localNode());

assertTrue(res.getInfos().get(0).getSize() >= res.getInfos().get(1).getSize());
assertTrue(res.getInfos().get(0).getSize() >= res.getInfos().get(1).getSize());

}, "--tx", "order", "SIZE");

// test order by duration.
validate(h, map -> {
VisorTxTaskResult res = map.get(grid(0).localNode());

assertTrue(res.getInfos().get(0).getDuration() >= res.getInfos().get(1).getDuration());
assertTrue(res.getInfos().get(0).getDuration() >= res.getInfos().get(1).getDuration());

}, "--tx", "order", "DURATION");

// test order by start_time.
validate(h, map -> {
VisorTxTaskResult res = map.get(grid(0).localNode());

for (int i = res.getInfos().size() - 1; i > 1; i--)
assertTrue(res.getInfos().get(i - 1).getStartTime() >= res.getInfos().get(i).getStartTime());
}, "--tx", "order", CommandHandler.CMD_TX_ORDER_START_TIME);

// Trigger topology change and test connection.
IgniteInternalFuture<?> startFut = multithreadedAsync(() -> {
try {
Expand Down Expand Up @@ -846,16 +851,16 @@ private void validate(CommandHandler h, IgniteInClosure<Map<ClusterNode, VisorTx
private Map<Object, Object> generate(int from, int cnt) {
Map<Object, Object> map = new TreeMap<>();

for (int i = 0; i < cnt; i++ )
for (int i = 0; i < cnt; i++)
map.put(i + from, i + from);

return map;
}

/**
* Test execution of --wal print command.
* Test execution of --wal print command.
*
* @throws Exception if failed.
* @throws Exception if failed.
*/
public void testUnusedWalPrint() throws Exception {
Ignite ignite = startGrids(2);
Expand All @@ -864,14 +869,14 @@ public void testUnusedWalPrint() throws Exception {

List<String> nodes = new ArrayList<>(2);

for (ClusterNode node: ignite.cluster().forServers().nodes())
for (ClusterNode node : ignite.cluster().forServers().nodes())
nodes.add(node.consistentId().toString());

injectTestSystemOut();

assertEquals(EXIT_CODE_OK, execute("--wal", "print"));

for(String id: nodes)
for (String id : nodes)
assertTrue(testOut.toString().contains(id));

assertTrue(!testOut.toString().contains("error"));
Expand All @@ -886,9 +891,9 @@ public void testUnusedWalPrint() throws Exception {
}

/**
* Test execution of --wal delete command.
* Test execution of --wal delete command.
*
* @throws Exception if failed.
* @throws Exception if failed.
*/
public void testUnusedWalDelete() throws Exception {
Ignite ignite = startGrids(2);
Expand All @@ -897,14 +902,14 @@ public void testUnusedWalDelete() throws Exception {

List<String> nodes = new ArrayList<>(2);

for (ClusterNode node: ignite.cluster().forServers().nodes())
for (ClusterNode node : ignite.cluster().forServers().nodes())
nodes.add(node.consistentId().toString());

injectTestSystemOut();

assertEquals(EXIT_CODE_OK, execute("--wal", "delete"));

for(String id: nodes)
for (String id : nodes)
assertTrue(testOut.toString().contains(id));

assertTrue(!testOut.toString().contains("error"));
Expand All @@ -919,11 +924,11 @@ public void testUnusedWalDelete() throws Exception {
}

/**
*
* @param lockLatch Lock latch.
* @param unlockLatch Unlock latch.
*/
private IgniteInternalFuture<?> startTransactions(CountDownLatch lockLatch, CountDownLatch unlockLatch) throws Exception {
private IgniteInternalFuture<?> startTransactions(CountDownLatch lockLatch,
CountDownLatch unlockLatch) throws Exception {
IgniteEx client = grid("client");

AtomicInteger idx = new AtomicInteger();
Expand Down

0 comments on commit 4776a1a

Please sign in to comment.