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

feat(db): optimize old rewards withdrawal #5406

Merged
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
686f45e
feat(db): add methods for DBIterator
halibobo1205 Jul 28, 2023
6b88acf
feat(db): add reward-cache db
halibobo1205 Jul 28, 2023
6f0488c
feat(db): add rewardCalService
halibobo1205 Jul 28, 2023
f0d7e01
feat(metric): add metrics
halibobo1205 Jul 28, 2023
41a8bc4
feat(db): code clear up
halibobo1205 Jul 28, 2023
90c175a
feat(db): add @PreDestroy for service
halibobo1205 Jul 28, 2023
1c3a0ad
feat(db): check cache data
halibobo1205 Jul 28, 2023
66dcb82
fix(db): lastKey -> lastAccount
halibobo1205 Jul 28, 2023
aaaa8cd
fix ieee 754 double computing
halibobo1205 Aug 9, 2023
8e64450
fix iterator close twice
halibobo1205 Aug 9, 2023
09b7d72
add test
halibobo1205 Aug 9, 2023
5b62a2e
fix the checking if the computing is complete
halibobo1205 Aug 9, 2023
b25d2f3
fix CI
halibobo1205 Aug 9, 2023
c70fd48
refactor computeReward
halibobo1205 Aug 30, 2023
79c4895
remove unnecessary code
halibobo1205 Aug 30, 2023
38e48fd
fix getting last account address
halibobo1205 Aug 30, 2023
309cf54
check if the delegation is still valid
halibobo1205 Nov 21, 2023
0435e58
change getting data from root db
halibobo1205 Nov 23, 2023
6576d48
use account db to scan instead of delegation for vote before 2019-10-…
halibobo1205 Dec 6, 2023
7a7bcfe
change old cal to new cal
halibobo1205 Dec 15, 2023
f0c38df
add a proposal for old reward opt
halibobo1205 Dec 20, 2023
a7246e6
ensure checkpoint write-back
halibobo1205 Dec 26, 2023
b47b18f
fix the case that require a service restart for cache computation
halibobo1205 Dec 26, 2023
e255a40
add reward-vi root check and query
halibobo1205 Dec 26, 2023
4f831af
enhances the proposal activation checking logic
halibobo1205 Dec 26, 2023
6c26b53
remove unnecessary queries
halibobo1205 Dec 27, 2023
4fdfb46
add proposal [ALLOW_OLD_REWARD_OPT]
halibobo1205 Dec 29, 2023
6008ecc
rename service
halibobo1205 Dec 29, 2023
74cd4fe
remove query reward-vi root from node-info
halibobo1205 Dec 29, 2023
5bfc303
if cal is not done, wait it when quering
halibobo1205 Jan 1, 2024
2c1861e
fix Proposal test
halibobo1205 Jan 2, 2024
cd76dd3
fix sonar code smells
halibobo1205 Jan 2, 2024
320493a
rename getMerkleHash to getHash
halibobo1205 Jan 4, 2024
2c5db36
wait for the reward calculation for test
halibobo1205 Jan 4, 2024
6dff8d4
fix concurrency issue
halibobo1205 Jan 4, 2024
d85cce8
rethrow InterruptedException
halibobo1205 Jan 4, 2024
5d6f09c
ensure that the checkpoint flush is over before startRewardCal
halibobo1205 Jan 5, 2024
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
23 changes: 22 additions & 1 deletion actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,26 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
case ALLOW_OLD_REWARD_OPT: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7_4)) {
throw new ContractValidateException(
"Bad chain parameter id [ALLOW_OLD_REWARD_OPT]");
}
if (value != 1) {
throw new ContractValidateException(
"This value[ALLOW_OLD_REWARD_OPT] is only allowed to be 1");
}
if (!dynamicPropertiesStore.useNewRewardAlgorithm()) {
throw new ContractValidateException(
"[ALLOW_NEW_REWARD] proposal must be approved "
+ "before [ALLOW_OLD_REWARD_OPT] can be proposed");
}
if (dynamicPropertiesStore.useNewRewardAlgorithmFromStart()) {
throw new ContractValidateException(
"no need old reward opt, ALLOW_NEW_REWARD from start cycle 1");
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -803,7 +823,8 @@ public enum ProposalType { // current value, value range
DYNAMIC_ENERGY_MAX_FACTOR(75), // 0, [0, 100_000]
ALLOW_TVM_SHANGHAI(76), // 0, 1
ALLOW_CANCEL_ALL_UNFREEZE_V2(77), // 0, 1
MAX_DELEGATE_LOCK_PERIOD(78); // (86400, 10512000]
MAX_DELEGATE_LOCK_PERIOD(78), // (86400, 10512000]
ALLOW_OLD_REWARD_OPT(79); // 0, 1

private long code;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,77 @@
package org.tron.core.db.common.iterator;

import com.google.common.collect.Iterators;
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.primitives.Bytes;
import java.io.Closeable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.NoSuchElementException;

public interface DBIterator extends Iterator<Entry<byte[], byte[]>>, Closeable {
public interface DBIterator extends Iterator<Entry<byte[], byte[]>>, AutoCloseable, Closeable {

void seek(byte[] key);

void seekToFirst();

void seekToLast();

default UnmodifiableIterator<Entry<byte[], byte[]>> prefixQueryAfterThat
(byte[] key, byte[] afterThat) {
this.seek(afterThat == null ? key : afterThat);
return Iterators.filter(this, entry -> Bytes.indexOf(entry.getKey(), key) == 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I have doubt, whether this iterator will still access all data in the database but just return the data that matched the filter.
If so, it will do a lot of useless read-op?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not All, iterates over all data after the prefix. I can't think of a better way for now. It takes 2 minutes to iterate the database.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the default iterator and move the filter logic into startRewardCal, or re-implement a prefix iterator.
Seems 2 minutes is not a big deal, depends on you

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefix does not work is fixed.

}

/**
* An iterator is either positioned at a key/value pair, or
* not valid. This method returns true iff the iterator is valid.
*
* REQUIRES: iterator not closed
*
* @throws IllegalStateException if the iterator is closed.
* @return an iterator is either positioned at a key/value pair
*/
boolean valid();

/**
* The underlying storage for
* the returned slice is valid only until the next modification of
* the iterator.
*
* REQUIRES: valid() && !closed
*
* @throws IllegalStateException if the iterator is closed.
* @throws NoSuchElementException if the iterator is not valid.
*
* @return the key for the current entry
*/
byte[] getKey();

/**
* The underlying storage for
* the returned slice is valid only until the next modification of
* the iterator.
*
* REQUIRES: valid() && !closed
*
* @throws IllegalStateException if the iterator is closed.
* @throws NoSuchElementException if the iterator is not valid.
*
* @return the value for the current entry
*/
byte[] getValue();

/**
* @throws IllegalStateException if the iterator is closed.
*/
void checkState();

/**
* @throws NoSuchElementException if the iterator is not valid.
*/
default void checkValid() {
if (!valid()) {
throw new NoSuchElementException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.extern.slf4j.Slf4j;
import org.rocksdb.RocksIterator;

Expand All @@ -13,20 +14,22 @@ public final class RockStoreIterator implements DBIterator {
private final RocksIterator dbIterator;
private boolean first = true;

private boolean valid = true;
private final AtomicBoolean close = new AtomicBoolean(false);

public RockStoreIterator(RocksIterator dbIterator) {
this.dbIterator = dbIterator;
}

@Override
public void close() throws IOException {
dbIterator.close();
if (close.compareAndSet(false, true)) {
dbIterator.close();
}
}

@Override
public boolean hasNext() {
if (!valid) {
if (close.get()) {
return false;
}
boolean hasNext = false;
Expand All @@ -37,13 +40,12 @@ public boolean hasNext() {
first = false;
}
if (!(hasNext = dbIterator.isValid())) { // false is last item
dbIterator.close();
valid = false;
close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
try {
dbIterator.close();
close();
} catch (Exception e1) {
logger.error(e.getMessage(), e);
}
Expand All @@ -53,7 +55,7 @@ public boolean hasNext() {

@Override
public Entry<byte[], byte[]> next() {
if (!valid) {
if (close.get()) {
throw new NoSuchElementException();
}
byte[] key = dbIterator.key();
Expand All @@ -76,4 +78,52 @@ public byte[] setValue(byte[] value) {
}
};
}
}

@Override
public void seek(byte[] key) {
checkState();
dbIterator.seek(key);
this.first = false;
}

@Override
public void seekToFirst() {
checkState();
dbIterator.seekToFirst();
this.first = false;
}

@Override
public void seekToLast() {
checkState();
dbIterator.seekToLast();
this.first = false;
}

@Override
public boolean valid() {
checkState();
return dbIterator.isValid();
}

@Override
public byte[] getKey() {
checkState();
checkValid();
return dbIterator.key();
}

@Override
public byte[] getValue() {
checkState();
checkValid();
return dbIterator.value();
}

@Override
public void checkState() {
if (close.get()) {
throw new IllegalStateException("iterator has been closed");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.IOException;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.extern.slf4j.Slf4j;
import org.iq80.leveldb.DBIterator;

Expand All @@ -13,20 +14,22 @@ public final class StoreIterator implements org.tron.core.db.common.iterator.DBI
private final DBIterator dbIterator;
private boolean first = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a simpler way by just setting first false when invoking seek() & seekToLast() to solve the problem of pointer confusion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's exactly how it's handled.


private boolean valid = true;
private final AtomicBoolean close = new AtomicBoolean(false);

public StoreIterator(DBIterator dbIterator) {
this.dbIterator = dbIterator;
}

@Override
public void close() throws IOException {
dbIterator.close();
if (close.compareAndSet(false, true)) {
dbIterator.close();
}
}

@Override
public boolean hasNext() {
if (!valid) {
if (close.get()) {
return false;
}

Expand All @@ -39,8 +42,7 @@ public boolean hasNext() {
}

if (!(hasNext = dbIterator.hasNext())) { // false is last item
dbIterator.close();
valid = false;
close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
Expand All @@ -51,7 +53,7 @@ public boolean hasNext() {

@Override
public Entry<byte[], byte[]> next() {
if (!valid) {
if (close.get()) {
throw new NoSuchElementException();
}
return dbIterator.next();
Expand All @@ -61,4 +63,53 @@ public Entry<byte[], byte[]> next() {
public void remove() {
throw new UnsupportedOperationException();
}

@Override
public void seek(byte[] key) {
checkState();
dbIterator.seek(key);
this.first = false;
}

@Override
public void seekToFirst() {
checkState();
dbIterator.seekToFirst();
this.first = false;
}

@Override
public void seekToLast() {
checkState();
dbIterator.seekToLast();
this.first = false;
}

@Override
public boolean valid() {
checkState();
return dbIterator.hasNext();
}

@Override
public byte[] getKey() {
checkState();
checkValid();
return dbIterator.peekNext().getKey();
}

@Override
public byte[] getValue() {
checkState();
checkValid();
return dbIterator.peekNext().getValue();
}

@Override
public void checkState() {
if (close.get()) {
throw new IllegalStateException("iterator has been closed");
}
}
}

Loading