Skip to content
Merged
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
52 changes: 43 additions & 9 deletions src/qt/transactiontablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ struct TxLessThan {
}
};

struct ConvertTxToVectorResult
{
QList<TransactionRecord> records;
qint64 nFirstLoadedTxTime{0};
};

// Private implementation
class TransactionTablePriv
{
Expand All @@ -82,6 +88,12 @@ class TransactionTablePriv
QList<TransactionRecord> cachedWallet;
bool hasZcTxes = false;

/**
* Time of the oldest transaction loaded into the model.
* It can or not be the first tx in the wallet, the model only loads the last 20k txs.
*/
qint64 nFirstLoadedTxTime{0};

/* Query entire wallet anew from core.
*/
void refreshWallet()
Expand Down Expand Up @@ -116,7 +128,7 @@ class TransactionTablePriv
// Size of the tx subsets
std::size_t const subsetSize = txesSize / (threadsCount + 1);
std::size_t totalSumSize = 0;
QList<QFuture<QList<TransactionRecord>>> tasks;
QList<QFuture<ConvertTxToVectorResult>> tasks;

// Subsets + run task
for (std::size_t i = 0; i < threadsCount; ++i) {
Expand All @@ -136,20 +148,27 @@ class TransactionTablePriv
auto res = convertTxToRecords(this, wallet,
std::vector<CWalletTx>(walletTxes.end() - remainingSize, walletTxes.end())
);
cachedWallet.append(res);
cachedWallet.append(res.records);
nFirstLoadedTxTime = res.nFirstLoadedTxTime;

for (auto &future : tasks) {
future.waitForFinished();
cachedWallet.append(future.result());
ConvertTxToVectorResult convertRes = future.result();
cachedWallet.append(convertRes.records);
if (nFirstLoadedTxTime > convertRes.nFirstLoadedTxTime) {
nFirstLoadedTxTime = convertRes.nFirstLoadedTxTime;
}
}
} else {
// Single thread flow
cachedWallet.append(convertTxToRecords(this, wallet, walletTxes));
ConvertTxToVectorResult convertRes = convertTxToRecords(this, wallet, walletTxes);
cachedWallet.append(convertRes.records);
nFirstLoadedTxTime = convertRes.nFirstLoadedTxTime;
}
}

static QList<TransactionRecord> convertTxToRecords(TransactionTablePriv* tablePriv, const CWallet* wallet, const std::vector<CWalletTx>& walletTxes) {
QList<TransactionRecord> cachedWallet;
static ConvertTxToVectorResult convertTxToRecords(TransactionTablePriv* tablePriv, const CWallet* wallet, const std::vector<CWalletTx>& walletTxes) {
ConvertTxToVectorResult res;

bool hasZcTxes = tablePriv->hasZcTxes;
for (const auto &tx : walletTxes) {
Expand All @@ -162,13 +181,20 @@ class TransactionTablePriv
}
}

cachedWallet.append(records);
if (!records.isEmpty()) {
qint64 time = records.first().time;
if (res.nFirstLoadedTxTime == 0 || res.nFirstLoadedTxTime > time) {
res.nFirstLoadedTxTime = time;
}
}

res.records.append(records);
}

if (hasZcTxes) // Only update it if it's true, multi-thread operation.
tablePriv->hasZcTxes = true;

return cachedWallet;
return res;
}

static bool HasZcTxesIfNeeded(const TransactionRecord& record) {
Expand Down Expand Up @@ -221,9 +247,17 @@ class TransactionTablePriv
qWarning() << "TransactionTablePriv::updateWallet : Warning: Got CT_NEW, but transaction is not in wallet";
break;
}
const CWalletTx& wtx = mi->second;

// As old transactions are still getting updated (+20k range),
// do not add them if we deliberately didn't load them at startup.
if (cachedWallet.size() >= MAX_AMOUNT_LOADED_RECORDS && wtx.GetTxTime() < nFirstLoadedTxTime) {
return;
}

// Added -- insert at the right position
QList<TransactionRecord> toInsert =
TransactionRecord::decomposeTransaction(wallet, mi->second);
TransactionRecord::decomposeTransaction(wallet, wtx);
if (!toInsert.isEmpty()) { /* only if something to insert */
parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex + toInsert.size() - 1);
int insert_idx = lowerIndex;
Expand Down