Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AKI-668 fixes TxPoolV1 ConcurrentModificationException #1124

Merged
merged 1 commit into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions modTxPool/src/org/aion/txpool/v1/TxPoolV1.java
Original file line number Diff line number Diff line change
Expand Up @@ -444,22 +444,46 @@ private BigInteger getAccountFirstPickingNonce(AionAddress sender) {
public List<PooledTransaction> clearOutDateTransaction() {
lock.lock();
try {
List<PooledTransaction> clearedTransactions = new ArrayList<>();
Map<Long, Set<ByteArrayWrapper>> timeoutTxHashes = timeView.headMap(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
return clearOutDateTransaction(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
} finally {
lock.unlock();
}
}

for (Set<ByteArrayWrapper> hashes : timeoutTxHashes.values()) {
for (ByteArrayWrapper hash : hashes) {
PooledTransaction pTx = poolRemove(hash);
if (pTx != null) {
clearedTransactions.add(pTx);
}
List<PooledTransaction> clearOutDateTransaction(long outDateTime) {
List<PooledTransaction> clearedTransactions = new ArrayList<>();

for (Set<ByteArrayWrapper> set : timeView.headMap(outDateTime).values()) {
for (ByteArrayWrapper txHash : set) {
PooledTransaction removedTx = poolTransactions.remove(txHash);
if (removedTx == null) {
LOG_TXPOOL.debug("Did not find the transaction hash:{} in the pool", txHash);
continue;
}
}

return clearedTransactions;
} finally {
lock.unlock();
LOG_TXPOOL.debug("Removing tx[{}]", removedTx.tx);

Set<ByteArrayWrapper> feeSet = feeView.get(removedTx.tx.getEnergyPrice());
feeSet.remove(txHash);
if (feeSet.isEmpty()) {
feeView.remove(removedTx.tx.getEnergyPrice());
}

SortedMap<BigInteger, ByteArrayWrapper> accountInfo =
accountView.get(removedTx.tx.getSenderAddress());

accountInfo.remove(removedTx.tx.getNonceBI());
if (accountInfo.isEmpty()) {
accountView.remove(removedTx.tx.getSenderAddress());
}

clearedTransactions.add(removedTx);
LOG_TXPOOL.debug("Removed tx[{}]", removedTx.tx);
}
}
timeView.headMap(outDateTime).clear();

return clearedTransactions;
}

/**
Expand Down Expand Up @@ -623,10 +647,8 @@ public List<Long> getFeeList() {
public List<AionTransaction> snapshot(long outDateTime) {
lock.lock();
try {
Map<Long, Set<ByteArrayWrapper>> timeoutTxHashes = timeView.headMap(outDateTime);

for (Set<ByteArrayWrapper> hashes : timeoutTxHashes.values()) {
for (ByteArrayWrapper hash : hashes) {
for (Set<ByteArrayWrapper> hashes : new ArrayList<>(timeView.headMap(outDateTime).values())) {
for (ByteArrayWrapper hash : new ArrayList<>(hashes)) {
PooledTransaction pTx = poolRemove(hash);
if (pTx == null) {
throw new IllegalStateException("The pool data has broken, cannot find the txHash:" + hash);
Expand Down
22 changes: 22 additions & 0 deletions modTxPool/test/org/aion/txpool/v1/TxPoolV1Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -1223,4 +1223,26 @@ public void getDroppedTxTest() {
assertEquals(pooledTx, drppedPtx);

}

@Test
public void clearOutDateTransactionTest() {
Properties config = new Properties();
config.put(TXPOOL_PROPERTY.PROP_TX_TIMEOUT, "10"); // 10 sec

TxPoolV1 tp = new TxPoolV1(config);
List<PooledTransaction> txl = new ArrayList<>();
int cnt = 2;
for (int i = 0; i < cnt; i++) {
PooledTransaction tx =
genTransaction(BigInteger.valueOf(i).toByteArray(), Constant.MIN_ENERGY_CONSUME);
txl.add(tx);
}
tp.add(txl);

tp.clearOutDateTransaction(TimeUnit.MICROSECONDS.toSeconds(txl.get(0).tx.getTimeStampBI().longValue()) + 10);
Assert.assertEquals(cnt, tp.size());

tp.clearOutDateTransaction(TimeUnit.MICROSECONDS.toSeconds(txl.get(0).tx.getTimeStampBI().longValue()) + 11);
Assert.assertEquals(0, tp.size());
}
}