Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public interface Application {

void startServices();

// DO NOT USE THIS METHOD IN TEST CASES MAIN-THREAD
default void blockUntilShutdown() {
}

void shutdownServices();

void addService(Service service);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.common.logsfilter.EventPluginLoader;
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;
Expand All @@ -31,9 +29,6 @@ public class ApplicationImpl implements Application {
@Autowired
private ConsensusService consensusService;

@Autowired
private DynamicArgs dynamicArgs;

@Override
public void setOptions(Args args) {
// not used
Expand Down Expand Up @@ -64,35 +59,30 @@ public void startup() {
}
consensusService.start();
MetricsUtil.init();
dynamicArgs.init();
this.initServices(Args.getInstance());
this.startServices();
}

@Override
public void shutdown() {
logger.info("******** start to shutdown ********");
this.shutdownServices();
consensusService.stop();
if (!Args.getInstance().isSolidityNode() && (!Args.getInstance().p2pDisable)) {
tronNetService.close();
}
consensusService.stop();
synchronized (dbManager.getRevokingStore()) {
dbManager.getSession().reset();
closeRevokingStore();
}
dbManager.stopRePushThread();
dbManager.stopRePushTriggerThread();
EventPluginLoader.getInstance().stopPlugin();
dbManager.stopFilterProcessThread();
dbManager.stopValidateSignThread();
getChainBaseManager().shutdown();
dynamicArgs.close();
logger.info("******** end to shutdown ********");
dbManager.close();
}

@Override
public void startServices() {
services.start();
}

@Override
public void blockUntilShutdown() {
services.blockUntilShutdown();
}

@Override
public void shutdownServices() {
services.stop();
Expand All @@ -108,9 +98,4 @@ public ChainBaseManager getChainBaseManager() {
return chainBaseManager;
}

private void closeRevokingStore() {
logger.info("******** start to closeRevokingStore ********");
dbManager.getRevokingStore().shutdown();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* java-tron is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* java-tron is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.tron.common.application;

import com.google.common.base.Objects;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jetty.server.Server;

@Slf4j(topic = "rpc")
public abstract class HttpService implements Service {

protected Server apiServer;
protected int port;

@Override
public void blockUntilShutdown() {
if (apiServer != null) {
try {
apiServer.join();
} catch (InterruptedException e) {
logger.warn("{}", e.getMessage());
Thread.currentThread().interrupt();
}
}
}

@Override
public void start() {
if (apiServer != null) {
try {
apiServer.start();
logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port);
} catch (Exception e) {
logger.error("{}", this.getClass().getSimpleName(), e);
}
}
}

@Override
public void stop() {
if (apiServer != null) {
logger.info("{} shutdown...", this.getClass().getSimpleName());
try {
apiServer.stop();
} catch (Exception e) {
logger.warn("{}", this.getClass().getSimpleName(), e);
}
logger.info("{} shutdown complete", this.getClass().getSimpleName());
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
HttpService that = (HttpService) o;
return port == that.port;
}

@Override
public int hashCode() {
return Objects.hashCode(getClass().getSimpleName(), port);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* java-tron is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* java-tron is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.tron.common.application;

import com.google.common.base.Objects;
import io.grpc.Server;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;

@Slf4j(topic = "rpc")
public abstract class RpcService implements Service {

protected Server apiServer;
protected int port;

@Override
public void blockUntilShutdown() {
if (apiServer != null) {
try {
apiServer.awaitTermination();
} catch (InterruptedException e) {
logger.warn("{}", e.getMessage());
Thread.currentThread().interrupt();
}
}
}

@Override
public void start() {
if (apiServer != null) {
try {
apiServer.start();
logger.info("{} started, listening on {}", this.getClass().getSimpleName(), port);
} catch (IOException e) {
logger.error("{}", this.getClass().getSimpleName(), e);
}
}
}

@Override
public void stop() {
if (apiServer != null) {
logger.info("{} shutdown...", this.getClass().getSimpleName());
try {
apiServer.shutdown().awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.warn("{}", this.getClass().getSimpleName(), e);
}
logger.info("{} shutdown complete", this.getClass().getSimpleName());
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RpcService that = (RpcService) o;
return port == that.port;
}

@Override
public int hashCode() {
return Objects.hashCode(getClass().getSimpleName(), port);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ public interface Service {

void init(CommonParameter parameter);

/**
* Start the service.
* {@link Service#init(CommonParameter parameter) init(CommonParameter parameter)} must be called
* before this method.
*/
void start();

void stop();

void blockUntilShutdown();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@

package org.tron.common.application;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.tron.common.parameter.CommonParameter;

@Slf4j(topic = "app")
public class ServiceContainer {

private ArrayList<Service> services;
private final Set<Service> services;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the purpose of changing List to Set, if two objects execute init() with the same class and port but without executing start(), they will be equal according to the above modification?

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, block duplicate service.


public ServiceContainer() {
this.services = new ArrayList<>();
this.services = Collections.synchronizedSet(new LinkedHashSet<>());
}

public void add(Service service) {
Expand All @@ -34,31 +36,38 @@ public void add(Service service) {


public void init() {
for (Service service : this.services) {
this.services.forEach(service -> {
logger.debug("Initing {}.", service.getClass().getSimpleName());
service.init();
}
});
}

public void init(CommonParameter parameter) {
for (Service service : this.services) {
this.services.forEach(service -> {
logger.debug("Initing {}.", service.getClass().getSimpleName());
service.init(parameter);
}
});
}

public void start() {
logger.debug("Starting services.");
for (Service service : this.services) {
logger.info("Starting api services.");
this.services.forEach(service -> {
logger.debug("Starting {}.", service.getClass().getSimpleName());
service.start();
}
});
logger.info("All api services started.");
}

public void stop() {
for (Service service : this.services) {
logger.info("Stopping api services.");
this.services.forEach(service -> {
logger.debug("Stopping {}.", service.getClass().getSimpleName());
service.stop();
}
});
logger.info("All api services stopped.");
}

public void blockUntilShutdown() {
this.services.stream().findFirst().ifPresent(Service::blockUntilShutdown);
Copy link
Contributor

Choose a reason for hiding this comment

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

Only check the first service is stopped?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

blockUntilShutdown synchronously blocks the current thread, usually the main thread.

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.tron.program.FullNode;
import org.tron.core.config.TronLogShutdownHook;

public class TronApplicationContext extends AnnotationConfigApplicationContext {

Expand All @@ -25,10 +25,15 @@ public TronApplicationContext(String... basePackages) {
public void doClose() {
Copy link
Contributor

Choose a reason for hiding this comment

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

As I see, all singletons' close logic was delivered to Spring, is there any dependency between them, or may occur any exceptions when the close order was not as expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The bean dependencies are managed by spring, and initialization and destroy are in reverse order.

logger.info("******** start to close ********");
Application appT = ApplicationFactory.create(this);
appT.shutdownServices();
appT.shutdown();
super.doClose();
logger.info("******** close end ********");
FullNode.shutDownSign = true;
TronLogShutdownHook.shutDown = true;
}

@Override
public void registerShutdownHook() {
super.registerShutdownHook();
TronLogShutdownHook.shutDown = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public DefaultConfig() {
Thread.setDefaultUncaughtExceptionHandler((t, e) -> logger.error("Uncaught exception", e));
}

@Bean
@Bean(destroyMethod = "")
public RevokingDatabase revokingDatabase() {
try {
return new SnapshotManager(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ public class TronLogShutdownHook extends ShutdownHookBase {
*/
private final long check_times = 60 * 1000 / CHECK_SHUTDOWN_DELAY.getMilliseconds();

// if true, shutdown hook will be executed , for example, 'java -jar FullNode.jar -[v|h]'.
public static volatile boolean shutDown = true;

public TronLogShutdownHook() {
}

@Override
public void run() {
try {
for (int i = 0; i < check_times; i++) {
if (FullNode.shutDownSign) {
if (shutDown) {
break;
}
addInfo("Sleeping for " + CHECK_SHUTDOWN_DELAY);
Expand Down
Loading