From 5959a1bf76786aed364c5cf3828507c3cfdcd307 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 21 Mar 2023 16:40:41 +0800 Subject: [PATCH 1/9] feat(config):add support for dynamically loading configuration --- .../common/parameter/CommonParameter.java | 5 + .../src/main/java/org/tron/core/Constant.java | 2 + .../common/application/ApplicationImpl.java | 6 + .../java/org/tron/core/config/args/Args.java | 8 +- .../tron/core/config/args/DynamicArgs.java | 163 ++++++++++++++++++ .../org/tron/core/net/TronNetService.java | 4 +- 6 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 framework/src/main/java/org/tron/core/config/args/DynamicArgs.java diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index ab04ca3e7a4..ef1bff15d16 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -30,6 +30,7 @@ public class CommonParameter { public static CommonParameter PARAMETER = new CommonParameter(); @Setter public static boolean ENERGY_LIMIT_HARD_FORK = false; + @Getter @Parameter(names = {"-c", "--config"}, description = "Config file (default:config.conf)") public String shellConfFileName = ""; @Getter @@ -608,6 +609,10 @@ public class CommonParameter { @Setter public long dynamicEnergyMaxFactor = 0L; + @Getter + @Setter + public boolean dynamicConfigEnable; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 408782752f2..59d69bfecfd 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -343,4 +343,6 @@ public class Constant { public static final String NODE_SHUTDOWN_BLOCK_COUNT = "node.shutdown.BlockCount"; public static final String BLOCK_CACHE_TIMEOUT = "node.blockCacheTimeout"; + + public static final String DYNAMIC_CONFIG_ENABLE = "dynamicConfigEnable"; } diff --git a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java index 235ece75835..174dc92b25d 100644 --- a/framework/src/main/java/org/tron/common/application/ApplicationImpl.java +++ b/framework/src/main/java/org/tron/common/application/ApplicationImpl.java @@ -7,6 +7,7 @@ import org.tron.common.parameter.CommonParameter; import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; +import org.tron.core.config.args.DynamicArgs; import org.tron.core.consensus.ConsensusService; import org.tron.core.db.Manager; import org.tron.core.metrics.MetricsUtil; @@ -32,6 +33,9 @@ public class ApplicationImpl implements Application { @Autowired private ConsensusService consensusService; + @Autowired + private DynamicArgs dynamicArgs; + @Override public void setOptions(Args args) { // not used @@ -62,6 +66,7 @@ public void startup() { } consensusService.start(); MetricsUtil.init(); + dynamicArgs.init(); } @Override @@ -80,6 +85,7 @@ public void shutdown() { dbManager.stopRePushTriggerThread(); EventPluginLoader.getInstance().stopPlugin(); dbManager.stopFilterProcessThread(); + dynamicArgs.close(); logger.info("******** end to shutdown ********"); FullNode.shutDownSign = true; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 8e6a7526362..b9cfde485da 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -221,6 +221,7 @@ public static void clearParam() { PARAMETER.allowNewRewardAlgorithm = 0; PARAMETER.allowNewReward = 0; PARAMETER.memoFee = 0; + PARAMETER.dynamicConfigEnable = false; } /** @@ -1122,6 +1123,9 @@ public static void setParam(final String[] args, final String confFileName) { Math.max(PARAMETER.dynamicEnergyMaxFactor, 0); } + PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) + && config.getBoolean(Constant.DYNAMIC_CONFIG_ENABLE); + logConfig(); } @@ -1174,7 +1178,7 @@ private static RateLimiterInitialization getRateLimiterFromConfig( return initialization; } - private static List getInetSocketAddress( + public static List getInetSocketAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { @@ -1195,7 +1199,7 @@ private static List getInetSocketAddress( return ret; } - private static List getInetAddress( + public static List getInetAddress( final com.typesafe.config.Config config, String path) { List ret = new ArrayList<>(); if (!config.hasPath(path)) { diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java new file mode 100644 index 00000000000..e441bc527a2 --- /dev/null +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -0,0 +1,163 @@ +package org.tron.core.config.args; + +import static org.apache.commons.lang3.StringUtils.isNoneBlank; + +import com.typesafe.config.Config; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.tron.common.parameter.CommonParameter; +import org.tron.core.Constant; +import org.tron.core.config.Configuration; +import org.tron.core.net.TronNetService; + + +@Slf4j(topic = "app") +@Component +public class DynamicArgs { + private final CommonParameter parameter = Args.getInstance(); + + private volatile boolean shutdown = false; + + public void init() { + if (parameter.isDynamicConfigEnable()) { + new Thread(this::start, "DynamicArgs").start(); + } + } + + public void start() { + WatchService watchService; + Path path; + String confFileName; + try { + logger.info("Start the dynamic loading configuration service"); + String confFile; + if (isNoneBlank(parameter.getShellConfFileName())) { + confFile = parameter.getShellConfFileName(); + } else { + confFile = Constant.TESTNET_CONF; + // + //logger.warn("Configuration path is required!"); + //return; + } + + File confDir = new File(confFile); + confFileName = confDir.getName(); + if (confFile.contains(File.separator)) { + path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); + } else { + File directory = new File(""); + path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); + } + + logger.info("confDirString = {}", confDir); + watchService = FileSystems.getDefault().newWatchService(); + path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); + logger.info("watch path : {}", path.toString()); + } catch (Exception e) { + logger.error("Exception caught when register the watch key", e.getCause()); + return; + } + + while (!shutdown) { + try { + WatchKey wk = watchService.take(); + long changeCount = 0; + for (WatchEvent event : wk.pollEvents()) { + final Path changed = (Path)event.context(); + if (changed.endsWith(confFileName)) { + reload(); + logger.info("Config was modify and we reload it"); + } + changeCount++; + } + logger.info("change count : {}", changeCount); + + boolean valid = wk.reset(); + if (!valid) { + path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); + } + } catch (InterruptedException e) { + logger.warn(""); + break; + } catch (IOException e) { + break; + } + } + } + + public void reload() { + logger.info("reloading ... "); + Config config = Configuration.getByFileName(parameter.getShellConfFileName(), + Constant.TESTNET_CONF); + + updateActiveNodes(config); + + updateTrustNodes(config); + } + + private void updateActiveNodes(Config config) { + if (parameter.isWitness() || parameter.isFastForward()) { + return; + } + + List lastActiveNodes = parameter.getActiveNodes(); + List newActiveNodes = + Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); + parameter.setActiveNodes(newActiveNodes); + parameter.getActiveNodes().forEach(n -> { + logger.info("active node : {}", n.toString()); + if (!lastActiveNodes.contains(n)) { + TronNetService.getP2pConfig().getActiveNodes().add(n); + if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { + TronNetService.getP2pConfig().getTrustNodes().add(n.getAddress()); + } + } + }); + + lastActiveNodes.forEach(ln -> { + if (!parameter.getActiveNodes().contains(ln)) { + TronNetService.getP2pConfig().getActiveNodes().remove(ln); + TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); + } + }); + } + + private void updateTrustNodes(Config config) { + if (parameter.isWitness() || parameter.isFastForward()) { + return; + } + + List lastPassiveNodes = parameter.getPassiveNodes(); + List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); + parameter.setPassiveNodes(newPassiveNodes); + parameter.getPassiveNodes().forEach(n -> { + logger.info("passive node : {}", n.toString()); + if (!lastPassiveNodes.contains(n) + || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { + TronNetService.getP2pConfig().getTrustNodes().add(n); + } + }); + + lastPassiveNodes.forEach(ln -> { + if (!parameter.getPassiveNodes().contains(ln)) { + TronNetService.getP2pConfig().getTrustNodes().remove(ln); + } + }); + } + + public void close() { + logger.info("Closing watchService ..."); + shutdown = true; + } +} \ No newline at end of file diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index dcee7ecc7b2..5e32d834d67 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -136,8 +136,8 @@ private P2pConfig getConfig() { P2pConfig config = new P2pConfig(); config.setSeedNodes(seeds); - config.setActiveNodes(parameter.getActiveNodes()); - config.setTrustNodes(parameter.getPassiveNodes()); + config.getActiveNodes().addAll(parameter.getActiveNodes()); + config.getTrustNodes().addAll(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections(); From 3799c16f3719fd70b451e636a353688051cdb194 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 23 Mar 2023 18:20:54 +0800 Subject: [PATCH 2/9] feat(config):optimize logs for dynamic loading configuration --- .../tron/core/config/args/DynamicArgs.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index e441bc527a2..6e7aabe1119 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -46,12 +46,15 @@ public void start() { confFile = parameter.getShellConfFileName(); } else { confFile = Constant.TESTNET_CONF; - // //logger.warn("Configuration path is required!"); //return; } File confDir = new File(confFile); + if (!confDir.exists()) { + logger.warn("Configuration path is required! No such file {}", confFile); + return; + } confFileName = confDir.getName(); if (confFile.contains(File.separator)) { path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); @@ -60,10 +63,10 @@ public void start() { path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); } - logger.info("confDirString = {}", confDir); + logger.debug("confDirString = {}", confDir); watchService = FileSystems.getDefault().newWatchService(); path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - logger.info("watch path : {}", path.toString()); + logger.debug("watch path : {}", path.toString()); } catch (Exception e) { logger.error("Exception caught when register the watch key", e.getCause()); return; @@ -77,27 +80,28 @@ public void start() { final Path changed = (Path)event.context(); if (changed.endsWith(confFileName)) { reload(); - logger.info("Config was modify and we reload it"); + logger.info("The configuration was modified and we reloaded it"); } changeCount++; } - logger.info("change count : {}", changeCount); + logger.debug("change count : {}", changeCount); boolean valid = wk.reset(); if (!valid) { path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); } } catch (InterruptedException e) { - logger.warn(""); + logger.warn("WatchService was interrupted"); break; } catch (IOException e) { + logger.error("Exception caught when register the watch key", e.getCause()); break; } } } public void reload() { - logger.info("reloading ... "); + logger.debug("Reloading ... "); Config config = Configuration.getByFileName(parameter.getShellConfFileName(), Constant.TESTNET_CONF); @@ -116,7 +120,6 @@ private void updateActiveNodes(Config config) { Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); parameter.setActiveNodes(newActiveNodes); parameter.getActiveNodes().forEach(n -> { - logger.info("active node : {}", n.toString()); if (!lastActiveNodes.contains(n)) { TronNetService.getP2pConfig().getActiveNodes().add(n); if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { @@ -131,6 +134,8 @@ private void updateActiveNodes(Config config) { TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); } }); + logger.debug("p2p active nodes : {}", + TronNetService.getP2pConfig().getActiveNodes().toString()); } private void updateTrustNodes(Config config) { @@ -142,7 +147,6 @@ private void updateTrustNodes(Config config) { List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); parameter.setPassiveNodes(newPassiveNodes); parameter.getPassiveNodes().forEach(n -> { - logger.info("passive node : {}", n.toString()); if (!lastPassiveNodes.contains(n) || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { TronNetService.getP2pConfig().getTrustNodes().add(n); @@ -154,6 +158,7 @@ private void updateTrustNodes(Config config) { TronNetService.getP2pConfig().getTrustNodes().remove(ln); } }); + logger.debug("p2p trust nodes : {}", TronNetService.getP2pConfig().getTrustNodes().toString()); } public void close() { From ef6b5349f2489c151c1a78458e0a06609a658753 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Fri, 24 Mar 2023 14:28:42 +0800 Subject: [PATCH 3/9] feat(config):add dynamic loading configuration test case --- .../tron/core/config/args/DynamicArgs.java | 1 + .../core/config/args/DynamicArgsTest.java | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 6e7aabe1119..9da606e680a 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -92,6 +92,7 @@ public void start() { } } catch (InterruptedException e) { logger.warn("WatchService was interrupted"); + Thread.currentThread().interrupt(); break; } catch (IOException e) { logger.error("Exception caught when register the watch key", e.getCause()); diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java new file mode 100644 index 00000000000..c544a545e16 --- /dev/null +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -0,0 +1,55 @@ +package org.tron.core.config.args; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.tron.common.application.TronApplicationContext; +import org.tron.common.parameter.CommonParameter; +import org.tron.common.utils.FileUtil; +import org.tron.common.utils.ReflectUtils; +import org.tron.core.Constant; +import org.tron.core.config.DefaultConfig; +import org.tron.core.net.TronNetService; +import org.tron.p2p.P2pConfig; + +import java.io.File; + +public class DynamicArgsTest { + protected TronApplicationContext context; + private DynamicArgs dynamicArgs; + private String dbPath = "output-dynamic-config-test"; + + @Before + public void init() { + Args.setParam(new String[]{"--output-directory", dbPath}, + Constant.TEST_CONF); + context = new TronApplicationContext(DefaultConfig.class); + dynamicArgs = context.getBean(DynamicArgs.class); + + } + + @After + public void destroy() { + Args.clearParam(); + context.destroy(); + FileUtil.deleteDir(new File(dbPath)); + } + + @Test + public void get() { + CommonParameter parameter = Args.getInstance(); + Assert.assertFalse(parameter.isDynamicConfigEnable()); + + } + + @Test + public void start() { + dynamicArgs.start(); + TronNetService tronNetService = context.getBean(TronNetService.class); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); + dynamicArgs.reload(); + dynamicArgs.close(); + Assert.assertTrue((boolean)ReflectUtils.getFieldObject(dynamicArgs, "shutdown")); + } +} From ec5ac7069cea0b5837f77dc2d2a72afc5f62a6c8 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Tue, 28 Mar 2023 14:58:23 +0800 Subject: [PATCH 4/9] feat(config):change the method of getting configuration file changes --- .../tron/core/config/args/DynamicArgs.java | 161 ++++++------------ .../core/config/args/DynamicArgsTest.java | 19 ++- 2 files changed, 63 insertions(+), 117 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 9da606e680a..c0f08f61148 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -4,16 +4,13 @@ import com.typesafe.config.Config; import java.io.File; -import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.StandardWatchEventKinds; -import java.nio.file.WatchEvent; -import java.nio.file.WatchKey; -import java.nio.file.WatchService; import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.tron.common.parameter.CommonParameter; @@ -27,78 +24,54 @@ public class DynamicArgs { private final CommonParameter parameter = Args.getInstance(); - private volatile boolean shutdown = false; + private long lastModified = 0; + + private ScheduledExecutorService reloadExecutor = Executors.newSingleThreadScheduledExecutor(); public void init() { if (parameter.isDynamicConfigEnable()) { - new Thread(this::start, "DynamicArgs").start(); + File config = getConfigFile(); + if (config != null) { + lastModified = config.lastModified(); + } else { + return; + } + logger.info("Start the dynamic loading configuration service"); + reloadExecutor.scheduleWithFixedDelay(() -> { + try { + run(); + } catch (Exception e) { + logger.error("Exception caught when reloading configuration", e); + } + }, 100, 10, TimeUnit.SECONDS); } } - public void start() { - WatchService watchService; - Path path; - String confFileName; - try { - logger.info("Start the dynamic loading configuration service"); - String confFile; - if (isNoneBlank(parameter.getShellConfFileName())) { - confFile = parameter.getShellConfFileName(); - } else { - confFile = Constant.TESTNET_CONF; - //logger.warn("Configuration path is required!"); - //return; + public void run() { + File config = getConfigFile(); + if (config != null) { + long lastModifiedTime = config.lastModified(); + if (lastModifiedTime > lastModified) { + reload(); + lastModified = lastModifiedTime; } - - File confDir = new File(confFile); - if (!confDir.exists()) { - logger.warn("Configuration path is required! No such file {}", confFile); - return; - } - confFileName = confDir.getName(); - if (confFile.contains(File.separator)) { - path = FileSystems.getDefault().getPath(confDir.getPath()).getParent(); - } else { - File directory = new File(""); - path = FileSystems.getDefault().getPath(directory.getAbsolutePath()); - } - - logger.debug("confDirString = {}", confDir); - watchService = FileSystems.getDefault().newWatchService(); - path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - logger.debug("watch path : {}", path.toString()); - } catch (Exception e) { - logger.error("Exception caught when register the watch key", e.getCause()); - return; } + } - while (!shutdown) { - try { - WatchKey wk = watchService.take(); - long changeCount = 0; - for (WatchEvent event : wk.pollEvents()) { - final Path changed = (Path)event.context(); - if (changed.endsWith(confFileName)) { - reload(); - logger.info("The configuration was modified and we reloaded it"); - } - changeCount++; - } - logger.debug("change count : {}", changeCount); + private File getConfigFile() { + String confFilePath; + if (isNoneBlank(parameter.getShellConfFileName())) { + confFilePath = parameter.getShellConfFileName(); + } else { + confFilePath = Constant.TESTNET_CONF; + } - boolean valid = wk.reset(); - if (!valid) { - path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY); - } - } catch (InterruptedException e) { - logger.warn("WatchService was interrupted"); - Thread.currentThread().interrupt(); - break; - } catch (IOException e) { - logger.error("Exception caught when register the watch key", e.getCause()); - break; - } + File confFile = new File(confFilePath); + if (!confFile.exists()) { + logger.warn("Configuration path is required! No such file {}", confFile); + return null; } + return confFile; } public void reload() { @@ -112,58 +85,30 @@ public void reload() { } private void updateActiveNodes(Config config) { - if (parameter.isWitness() || parameter.isFastForward()) { - return; - } - - List lastActiveNodes = parameter.getActiveNodes(); List newActiveNodes = Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); parameter.setActiveNodes(newActiveNodes); - parameter.getActiveNodes().forEach(n -> { - if (!lastActiveNodes.contains(n)) { - TronNetService.getP2pConfig().getActiveNodes().add(n); - if (!TronNetService.getP2pConfig().getTrustNodes().contains(n.getAddress())) { - TronNetService.getP2pConfig().getTrustNodes().add(n.getAddress()); - } - } - }); - - lastActiveNodes.forEach(ln -> { - if (!parameter.getActiveNodes().contains(ln)) { - TronNetService.getP2pConfig().getActiveNodes().remove(ln); - TronNetService.getP2pConfig().getTrustNodes().remove(ln.getAddress()); - } - }); + List activeNodes = TronNetService.getP2pConfig().getActiveNodes(); + activeNodes.clear(); + activeNodes.addAll(newActiveNodes); logger.debug("p2p active nodes : {}", TronNetService.getP2pConfig().getActiveNodes().toString()); } private void updateTrustNodes(Config config) { - if (parameter.isWitness() || parameter.isFastForward()) { - return; - } - - List lastPassiveNodes = parameter.getPassiveNodes(); List newPassiveNodes = Args.getInetAddress(config, Constant.NODE_PASSIVE); parameter.setPassiveNodes(newPassiveNodes); - parameter.getPassiveNodes().forEach(n -> { - if (!lastPassiveNodes.contains(n) - || !TronNetService.getP2pConfig().getTrustNodes().contains(n)) { - TronNetService.getP2pConfig().getTrustNodes().add(n); - } - }); - - lastPassiveNodes.forEach(ln -> { - if (!parameter.getPassiveNodes().contains(ln)) { - TronNetService.getP2pConfig().getTrustNodes().remove(ln); - } - }); - logger.debug("p2p trust nodes : {}", TronNetService.getP2pConfig().getTrustNodes().toString()); + List trustNodes = TronNetService.getP2pConfig().getTrustNodes(); + trustNodes.clear(); + trustNodes.addAll(newPassiveNodes); + parameter.getActiveNodes().forEach(n -> trustNodes.add(n.getAddress())); + parameter.getFastForwardNodes().forEach(f -> trustNodes.add(f.getAddress())); + logger.debug("p2p trust nodes : {}", + TronNetService.getP2pConfig().getTrustNodes().toString()); } public void close() { - logger.info("Closing watchService ..."); - shutdown = true; + logger.info("Closing the dynamic loading configuration service ..."); + reloadExecutor.shutdown(); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index c544a545e16..0dcb755894f 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -1,5 +1,6 @@ package org.tron.core.config.args; +import java.io.File; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -10,10 +11,8 @@ import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; -import org.tron.core.net.TronNetService; -import org.tron.p2p.P2pConfig; - -import java.io.File; +//import org.tron.core.net.TronNetService; +//import org.tron.p2p.P2pConfig; public class DynamicArgsTest { protected TronApplicationContext context; @@ -45,11 +44,13 @@ public void get() { @Test public void start() { - dynamicArgs.start(); - TronNetService tronNetService = context.getBean(TronNetService.class); - ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); - dynamicArgs.reload(); + dynamicArgs.init(); + Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); + + dynamicArgs.run(); +// TronNetService tronNetService = context.getBean(TronNetService.class); +// ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); +// dynamicArgs.reload(); dynamicArgs.close(); - Assert.assertTrue((boolean)ReflectUtils.getFieldObject(dynamicArgs, "shutdown")); } } From 83ed16c03b2ff1655c96204c882be14da27d99fe Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 16:21:34 +0800 Subject: [PATCH 5/9] feat(config):add test case --- .../common/parameter/CommonParameter.java | 4 +++ .../src/main/java/org/tron/core/Constant.java | 3 ++- .../java/org/tron/core/config/args/Args.java | 10 +++++++ .../tron/core/config/args/DynamicArgs.java | 10 +++---- .../core/config/args/DynamicArgsTest.java | 27 ++++++++++++++----- framework/src/test/resources/config-test.conf | 4 ++- 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index 9ff70a42a30..c878acd943e 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -618,6 +618,10 @@ public class CommonParameter { @Setter public boolean dynamicConfigEnable; + @Getter + @Setter + public long dynamicConfigCheckInterval; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index 59d69bfecfd..7f572058218 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -344,5 +344,6 @@ public class Constant { public static final String BLOCK_CACHE_TIMEOUT = "node.blockCacheTimeout"; - public static final String DYNAMIC_CONFIG_ENABLE = "dynamicConfigEnable"; + public static final String DYNAMIC_CONFIG_ENABLE = "node.dynamicConfig.enable"; + public static final String DYNAMIC_CONFIG_CHECK_INTERVAL = "node.dynamicConfig.checkInterval"; } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 78be66c6576..e18984ed7f7 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -223,6 +223,7 @@ public static void clearParam() { PARAMETER.memoFee = 0; PARAMETER.p2pDisable = false; PARAMETER.dynamicConfigEnable = false; + PARAMETER.dynamicConfigCheckInterval = 600; } /** @@ -1126,6 +1127,15 @@ public static void setParam(final String[] args, final String confFileName) { PARAMETER.dynamicConfigEnable = config.hasPath(Constant.DYNAMIC_CONFIG_ENABLE) && config.getBoolean(Constant.DYNAMIC_CONFIG_ENABLE); + if (config.hasPath(Constant.DYNAMIC_CONFIG_CHECK_INTERVAL)) { + PARAMETER.dynamicConfigCheckInterval + = config.getLong(Constant.DYNAMIC_CONFIG_CHECK_INTERVAL); + if (PARAMETER.dynamicConfigCheckInterval <= 0) { + PARAMETER.dynamicConfigCheckInterval = 600; + } + } else { + PARAMETER.dynamicConfigCheckInterval = 600; + } logConfig(); } diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index c0f08f61148..4834bb6bdff 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -31,19 +31,19 @@ public class DynamicArgs { public void init() { if (parameter.isDynamicConfigEnable()) { File config = getConfigFile(); - if (config != null) { - lastModified = config.lastModified(); - } else { + if (config == null) { return; } + lastModified = config.lastModified(); logger.info("Start the dynamic loading configuration service"); + long checkInterval = parameter.getDynamicConfigCheckInterval(); reloadExecutor.scheduleWithFixedDelay(() -> { try { run(); } catch (Exception e) { logger.error("Exception caught when reloading configuration", e); } - }, 100, 10, TimeUnit.SECONDS); + }, 10, checkInterval, TimeUnit.SECONDS); } } @@ -108,7 +108,7 @@ private void updateTrustNodes(Config config) { } public void close() { - logger.info("Closing the dynamic loading configuration service ..."); + logger.info("Closing the dynamic loading configuration service"); reloadExecutor.shutdown(); } } \ No newline at end of file diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 0dcb755894f..09f527fdd08 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -11,8 +11,8 @@ import org.tron.common.utils.ReflectUtils; import org.tron.core.Constant; import org.tron.core.config.DefaultConfig; -//import org.tron.core.net.TronNetService; -//import org.tron.p2p.P2pConfig; +import org.tron.core.net.TronNetService; +import org.tron.p2p.P2pConfig; public class DynamicArgsTest { protected TronApplicationContext context; @@ -39,7 +39,7 @@ public void destroy() { public void get() { CommonParameter parameter = Args.getInstance(); Assert.assertFalse(parameter.isDynamicConfigEnable()); - + Assert.assertEquals(600, parameter.getDynamicConfigCheckInterval()); } @Test @@ -47,10 +47,23 @@ public void start() { dynamicArgs.init(); Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); - dynamicArgs.run(); -// TronNetService tronNetService = context.getBean(TronNetService.class); -// ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); -// dynamicArgs.reload(); + TronNetService tronNetService = context.getBean(TronNetService.class); + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); + File config = new File(Constant.TESTNET_CONF); + if (!config.exists()) { + try { + config.createNewFile(); + } catch (Exception e) { + return; + } + dynamicArgs.run(); + try { + config.delete(); + } catch (Exception e) { + return; + } + } + dynamicArgs.close(); } } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index 2cd108bf966..2dcb7daa34a 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -286,4 +286,6 @@ vm = { } committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 -} \ No newline at end of file +} + +node.dynamicConfig.checkInterval = 0 \ No newline at end of file From d0adfa06be9f89480e7f059682ea10ccebe645c5 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 16:30:58 +0800 Subject: [PATCH 6/9] feat(config):fix merge issue --- .../src/main/java/org/tron/core/config/args/DynamicArgs.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 4834bb6bdff..5e2725c8322 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -86,7 +86,7 @@ public void reload() { private void updateActiveNodes(Config config) { List newActiveNodes = - Args.getInetSocketAddress(config, Constant.NODE_ACTIVE); + Args.getInetSocketAddress(config, Constant.NODE_ACTIVE, true); parameter.setActiveNodes(newActiveNodes); List activeNodes = TronNetService.getP2pConfig().getActiveNodes(); activeNodes.clear(); From 88565009844905ad6c727ff2a0afa7408b53c28e Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Wed, 29 Mar 2023 17:53:18 +0800 Subject: [PATCH 7/9] feat(config):change libp2p version --- common/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/build.gradle b/common/build.gradle index 6ce3c0bef41..5c70edf0b65 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -53,7 +53,7 @@ dependencies { compile 'org.aspectj:aspectjrt:1.8.13' compile 'org.aspectj:aspectjweaver:1.8.13' compile 'org.aspectj:aspectjtools:1.8.13' - compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.19' + compile group: 'com.github.tronprotocol', name: 'libp2p', version: 'test-v0.2.20' compile project(":protocol") } From 1467908dc009b85601e694a466632dbbd819ef53 Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 30 Mar 2023 10:11:12 +0800 Subject: [PATCH 8/9] feat(config):add unit test for DynamicArgs --- .../java/org/tron/core/config/args/DynamicArgs.java | 4 ++-- .../org/tron/core/config/args/DynamicArgsTest.java | 12 +++++++----- framework/src/test/resources/config-test.conf | 1 + 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java index 5e2725c8322..cbf167cb955 100644 --- a/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java +++ b/framework/src/main/java/org/tron/core/config/args/DynamicArgs.java @@ -30,13 +30,13 @@ public class DynamicArgs { public void init() { if (parameter.isDynamicConfigEnable()) { + logger.info("Start the dynamic loading configuration service"); + long checkInterval = parameter.getDynamicConfigCheckInterval(); File config = getConfigFile(); if (config == null) { return; } lastModified = config.lastModified(); - logger.info("Start the dynamic loading configuration service"); - long checkInterval = parameter.getDynamicConfigCheckInterval(); reloadExecutor.scheduleWithFixedDelay(() -> { try { run(); diff --git a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java index 09f527fdd08..2ca95239ad7 100644 --- a/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java +++ b/framework/src/test/java/org/tron/core/config/args/DynamicArgsTest.java @@ -36,14 +36,11 @@ public void destroy() { } @Test - public void get() { + public void start() { CommonParameter parameter = Args.getInstance(); - Assert.assertFalse(parameter.isDynamicConfigEnable()); + Assert.assertTrue(parameter.isDynamicConfigEnable()); Assert.assertEquals(600, parameter.getDynamicConfigCheckInterval()); - } - @Test - public void start() { dynamicArgs.init(); Assert.assertEquals(0, (long) ReflectUtils.getFieldObject(dynamicArgs, "lastModified")); @@ -63,6 +60,11 @@ public void start() { return; } } + try { + dynamicArgs.reload(); + } catch (Exception e) { + // no need to deal with + } dynamicArgs.close(); } diff --git a/framework/src/test/resources/config-test.conf b/framework/src/test/resources/config-test.conf index f800fb2486b..76e99c8d4a1 100644 --- a/framework/src/test/resources/config-test.conf +++ b/framework/src/test/resources/config-test.conf @@ -342,4 +342,5 @@ committee = { allowCreationOfContracts = 1 //mainnet:0 (reset by committee),test:1 } +node.dynamicConfig.enable = true node.dynamicConfig.checkInterval = 0 \ No newline at end of file From e0c8ba5e41fbbe7268d17024a0b4afcc5fbe7c2c Mon Sep 17 00:00:00 2001 From: chengtx01 Date: Thu, 30 Mar 2023 10:15:01 +0800 Subject: [PATCH 9/9] feat(config):resolve code conflicts --- framework/src/main/java/org/tron/core/net/TronNetService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/src/main/java/org/tron/core/net/TronNetService.java b/framework/src/main/java/org/tron/core/net/TronNetService.java index 95a3cc869c6..561c3cbae9e 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetService.java +++ b/framework/src/main/java/org/tron/core/net/TronNetService.java @@ -149,8 +149,8 @@ private P2pConfig getConfig() { } P2pConfig config = new P2pConfig(); config.setSeedNodes(seeds); - config.getActiveNodes().addAll(parameter.getActiveNodes()); - config.getTrustNodes().addAll(parameter.getPassiveNodes()); + config.setActiveNodes(parameter.getActiveNodes()); + config.setTrustNodes(parameter.getPassiveNodes()); config.getActiveNodes().forEach(n -> config.getTrustNodes().add(n.getAddress())); parameter.getFastForwardNodes().forEach(f -> config.getTrustNodes().add(f.getAddress())); int maxConnections = parameter.getMaxConnections();