use of org.aion.mcf.db.ContractDetailsCacheImpl in project aion by aionnetwork.
the class AionRepositoryImpl method updateBatch.
@Override
public synchronized void updateBatch(Map<Address, AccountState> stateCache, Map<Address, IContractDetails<DataWord>> detailsCache) {
for (Map.Entry<Address, AccountState> entry : stateCache.entrySet()) {
Address address = entry.getKey();
AccountState accountState = entry.getValue();
IContractDetails<DataWord> contractDetails = detailsCache.get(address);
if (accountState.isDeleted()) {
// TODO-A: batch operations here
rwLock.readLock().lock();
try {
worldState.delete(address.toBytes());
} catch (Exception e) {
LOG.error("key deleted exception [{}]", e.toString());
} finally {
rwLock.readLock().unlock();
}
LOG.debug("key deleted <key={}>", Hex.toHexString(address.toBytes()));
} else {
if (!contractDetails.isDirty()) {
// ContractState class
if (accountState.isDirty()) {
updateAccountState(address, accountState);
if (LOG.isTraceEnabled()) {
LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
}
}
continue;
}
ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl) contractDetails;
if (contractDetailsCache.origContract == null) {
contractDetailsCache.origContract = this.cfg.contractDetailsImpl();
try {
contractDetailsCache.origContract.setAddress(address);
} catch (Exception e) {
e.printStackTrace();
LOG.error("contractDetailsCache setAddress exception [{}]", e.toString());
}
contractDetailsCache.commit();
}
contractDetails = contractDetailsCache.origContract;
updateContractDetails(address, contractDetails);
if (!Arrays.equals(accountState.getCodeHash(), EMPTY_TRIE_HASH)) {
accountState.setStateRoot(contractDetails.getStorageHash());
}
updateAccountState(address, accountState);
if (LOG.isTraceEnabled()) {
LOG.trace("update: [{}],nonce: [{}] balance: [{}] [{}]", Hex.toHexString(address.toBytes()), accountState.getNonce(), accountState.getBalance(), contractDetails.getStorage());
}
}
}
LOG.trace("updated: detailsCache.size: {}", detailsCache.size());
stateCache.clear();
detailsCache.clear();
}
use of org.aion.mcf.db.ContractDetailsCacheImpl in project aion by aionnetwork.
the class AionRepositoryImpl method loadAccountState.
/**
* @implNote The loaded objects are fresh copies of the original account
* state and contract details.
*/
@Override
public synchronized void loadAccountState(Address address, Map<Address, AccountState> cacheAccounts, Map<Address, IContractDetails<DataWord>> cacheDetails) {
AccountState account = getAccountState(address);
IContractDetails<DataWord> details = getContractDetails(address);
account = (account == null) ? new AccountState() : new AccountState(account);
details = new ContractDetailsCacheImpl(details);
// details.setAddress(addr);
cacheAccounts.put(address, account);
cacheDetails.put(address, details);
}
use of org.aion.mcf.db.ContractDetailsCacheImpl in project aion by aionnetwork.
the class AionRepositoryCache method flush.
/**
* @implNote To maintain intended functionality this method does not call
* the parent's {@code flush()} method. The changes are propagated
* to the parent through calling the parent's
* {@code updateBatch()} method.
*/
@Override
public synchronized void flush() {
// determine which accounts should get stored
HashMap<Address, AccountState> cleanedCacheAccounts = new HashMap<>();
for (Map.Entry<Address, AccountState> entry : cachedAccounts.entrySet()) {
AccountState account = entry.getValue();
if (account != null && account.isDirty() && account.isEmpty()) {
// ignore contract state for empty accounts at storage
cachedDetails.remove(entry.getKey());
} else {
cleanedCacheAccounts.put(entry.getKey(), entry.getValue());
}
}
// determine which contracts should get stored
for (Map.Entry<Address, IContractDetails<DataWord>> entry : cachedDetails.entrySet()) {
IContractDetails<DataWord> ctd = entry.getValue();
// different ContractDetails implementation
if (ctd != null && ctd instanceof ContractDetailsCacheImpl) {
ContractDetailsCacheImpl contractDetailsCache = (ContractDetailsCacheImpl) ctd;
contractDetailsCache.commit();
if (contractDetailsCache.origContract == null && repository.hasContractDetails(entry.getKey())) {
// in forked block the contract account might not exist thus
// it is created without
// origin, but on the main chain details can contain data
// which should be merged
// into a single storage trie so both branches with
// different stateRoots are valid
contractDetailsCache.origContract = repository.getContractDetails(entry.getKey());
contractDetailsCache.commit();
}
}
}
repository.updateBatch(cleanedCacheAccounts, cachedDetails);
cachedAccounts.clear();
cachedDetails.clear();
}
Aggregations