From 689d60b8549c090e8a56819c7fd0164041b6d23f Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Thu, 26 Mar 2015 17:05:35 +0100 Subject: [PATCH] Remove offer on close app --- .../java/io/bitsquare/BitsquareModule.java | 14 ++++--- .../io/bitsquare/app/BitsquareAppModule.java | 38 +++++++++++-------- .../java/io/bitsquare/btc/BitcoinModule.java | 6 ++- .../main/java/io/bitsquare/offer/Offer.java | 1 - .../io/bitsquare/offer/OfferBookService.java | 2 + .../offer/tomp2p/TomP2POfferBookService.java | 17 +++++++++ .../io/bitsquare/p2p/tomp2p/TomP2PModule.java | 5 +++ .../io/bitsquare/storage/FileManager.java | 4 +- .../java/io/bitsquare/trade/TradeManager.java | 27 ++++++++++++- .../java/io/bitsquare/trade/TradeModule.java | 12 ++++++ 10 files changed, 100 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/io/bitsquare/BitsquareModule.java b/core/src/main/java/io/bitsquare/BitsquareModule.java index 1b57041f53..abd63ff5bb 100644 --- a/core/src/main/java/io/bitsquare/BitsquareModule.java +++ b/core/src/main/java/io/bitsquare/BitsquareModule.java @@ -17,22 +17,24 @@ package io.bitsquare; -import com.google.common.collect.Sets; - import com.google.inject.AbstractModule; import com.google.inject.Injector; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import static com.google.common.base.Preconditions.checkNotNull; public abstract class BitsquareModule extends AbstractModule { - + private static final Logger log = LoggerFactory.getLogger(BitsquareModule.class); protected final Environment env; - private final Set modules = Sets.newHashSet(); + private final List modules = new ArrayList(); protected BitsquareModule(Environment env) { checkNotNull(env, "Environment must not be null"); @@ -41,6 +43,7 @@ public abstract class BitsquareModule extends AbstractModule { protected void install(BitsquareModule module) { super.install(module); + log.trace("install " + module.getClass().getSimpleName()); modules.add(module); } @@ -65,5 +68,6 @@ public abstract class BitsquareModule extends AbstractModule { * @param injector the Injector originally initialized with this module */ protected void doClose(Injector injector) { + log.trace("doClose " + getClass().getSimpleName()); } } diff --git a/core/src/main/java/io/bitsquare/app/BitsquareAppModule.java b/core/src/main/java/io/bitsquare/app/BitsquareAppModule.java index e0eefde76f..3a37f1fe81 100644 --- a/core/src/main/java/io/bitsquare/app/BitsquareAppModule.java +++ b/core/src/main/java/io/bitsquare/app/BitsquareAppModule.java @@ -40,11 +40,15 @@ import java.io.File; import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.core.env.Environment; import static com.google.inject.name.Names.named; class BitsquareAppModule extends BitsquareModule { + private static final Logger log = LoggerFactory.getLogger(BitsquareAppModule.class); private final Stage primaryStage; @@ -65,44 +69,46 @@ class BitsquareAppModule extends BitsquareModule { bind(Environment.class).toInstance(env); bind(UpdateProcess.class).in(Singleton.class); - install(networkModule()); - install(bitcoinModule()); + // ordering is used for shut down sequence + install(tradeModule()); install(cryptoModule()); - install(tradeMessageModule()); + install(arbitratorModule()); install(offerModule()); - install(arbitratorMessageModule()); + install(p2pModule()); + install(bitcoinModule()); install(guiModule()); } - protected ArbitratorModule arbitratorMessageModule() { - return new TomP2PArbitratorModule(env); - } - - protected P2PModule networkModule() { - return new TomP2PModule(env); - } - - protected BitcoinModule bitcoinModule() { - return new BitcoinModule(env); + protected TradeModule tradeModule() { + return new TradeModule(env); } protected CryptoModule cryptoModule() { return new CryptoModule(env); } - protected TradeModule tradeMessageModule() { - return new TradeModule(env); + protected ArbitratorModule arbitratorModule() { + return new TomP2PArbitratorModule(env); } protected OfferModule offerModule() { return new TomP2POfferModule(env); } + protected P2PModule p2pModule() { + return new TomP2PModule(env); + } + + protected BitcoinModule bitcoinModule() { + return new BitcoinModule(env); + } + protected GuiModule guiModule() { return new GuiModule(env, primaryStage); } @Override protected void doClose(Injector injector) { + log.trace("doClose " + getClass().getSimpleName()); } } diff --git a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java index 64e308708b..cf9af57aae 100644 --- a/core/src/main/java/io/bitsquare/btc/BitcoinModule.java +++ b/core/src/main/java/io/bitsquare/btc/BitcoinModule.java @@ -24,12 +24,15 @@ import com.google.inject.Singleton; import java.io.File; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.core.env.Environment; import static com.google.inject.name.Names.named; public class BitcoinModule extends BitsquareModule { - + private static final Logger log = LoggerFactory.getLogger(BitcoinModule.class); public BitcoinModule(Environment env) { super(env); @@ -56,6 +59,7 @@ public class BitcoinModule extends BitsquareModule { @Override protected void doClose(Injector injector) { + log.trace("doClose "+getClass().getSimpleName()); injector.getInstance(WalletService.class).shutDown(); } } diff --git a/core/src/main/java/io/bitsquare/offer/Offer.java b/core/src/main/java/io/bitsquare/offer/Offer.java index a355617e73..d3f4fb10fe 100644 --- a/core/src/main/java/io/bitsquare/offer/Offer.java +++ b/core/src/main/java/io/bitsquare/offer/Offer.java @@ -279,7 +279,6 @@ public class Offer implements Serializable { ", fiatPrice=" + fiatPrice + ", amount=" + amount + ", minAmount=" + minAmount + - ", p2pSigPubKey=" + p2pSigPubKey + ", fiatAccountType=" + fiatAccountType + ", bankAccountCountry=" + bankAccountCountry + ", securityDeposit=" + securityDeposit + diff --git a/core/src/main/java/io/bitsquare/offer/OfferBookService.java b/core/src/main/java/io/bitsquare/offer/OfferBookService.java index e418fbeabb..f52f5da95b 100644 --- a/core/src/main/java/io/bitsquare/offer/OfferBookService.java +++ b/core/src/main/java/io/bitsquare/offer/OfferBookService.java @@ -33,6 +33,8 @@ public interface OfferBookService extends DHTService { void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler); + void removeOfferAtShutDown(Offer offer); + void addListener(Listener listener); void removeListener(Listener listener); diff --git a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java b/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java index fdc5926053..1d6e57b2bb 100644 --- a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java +++ b/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java @@ -157,6 +157,23 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo } } + public void removeOfferAtShutDown(Offer offer) { + log.debug("removeOfferAtShutDown " + offer); + Number160 locationKey = Number160.createHash(offer.getCurrencyCode()); + try { + final Data offerData = new Data(offer); + log.trace("Remove offer from DHT requested. Removed data: [locationKey: " + locationKey + + ", hash: " + offerData.hash().toString() + "]"); + FutureRemove futureRemove = removeProtectedDataFromMap(locationKey, offerData); + writeInvalidationTimestampToDHT(offer.getCurrencyCode()); + futureRemove.awaitUninterruptibly(1000); + log.trace("isRemoved? " + futureRemove.isRemoved()); + } catch (IOException e) { + e.printStackTrace(); + log.error("Remove offer from DHT failed. Error: " + e.getMessage()); + } + } + public void getOffers(String currencyCode) { Number160 locationKey = Number160.createHash(currencyCode); log.trace("Get offers from DHT requested for locationKey: " + locationKey); diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java index 5475ff549f..6d044d0bda 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PModule.java @@ -29,11 +29,15 @@ import com.google.inject.Injector; import com.google.inject.Singleton; import com.google.inject.name.Names; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.core.env.Environment; import static io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder.*; public class TomP2PModule extends P2PModule { + private static final Logger log = LoggerFactory.getLogger(TomP2PModule.class); public static final String BOOTSTRAP_NODE_NAME_KEY = "bootstrap.node.name"; public static final String BOOTSTRAP_NODE_IP_KEY = "bootstrap.node.ip"; public static final String BOOTSTRAP_NODE_PORT_KEY = "bootstrap.node.port"; @@ -71,6 +75,7 @@ public class TomP2PModule extends P2PModule { @Override protected void doClose(Injector injector) { + log.trace("doClose " + getClass().getSimpleName()); // First shut down AddressService to remove address from DHT injector.getInstance(AddressService.class).shutDown(); injector.getInstance(BootstrappedPeerBuilder.class).shutDown(); diff --git a/core/src/main/java/io/bitsquare/storage/FileManager.java b/core/src/main/java/io/bitsquare/storage/FileManager.java index 4c3516883f..a38bad7428 100644 --- a/core/src/main/java/io/bitsquare/storage/FileManager.java +++ b/core/src/main/java/io/bitsquare/storage/FileManager.java @@ -197,10 +197,10 @@ public class FileManager { * Shut down auto-saving. */ public void shutdown() { - if (serializable != null) + /* if (serializable != null) log.debug("shutDown " + serializable.getClass().getSimpleName()); else - log.debug("shutDown"); + log.debug("shutDown");*/ executor.shutdown(); try { diff --git a/core/src/main/java/io/bitsquare/trade/TradeManager.java b/core/src/main/java/io/bitsquare/trade/TradeManager.java index 01ba0ddd49..11b0f9c737 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/core/src/main/java/io/bitsquare/trade/TradeManager.java @@ -95,6 +95,7 @@ public class TradeManager { private final TradeList openOfferTrades; private final TradeList pendingTrades; private final TradeList closedTrades; + private boolean shutDownRequested; /////////////////////////////////////////////////////////////////////////////////////////// @@ -122,6 +123,10 @@ public class TradeManager { this.openOfferTrades = new TradeList<>(storageDir, "OpenOfferTrades"); this.pendingTrades = new TradeList<>(storageDir, "PendingTrades"); this.closedTrades = new TradeList<>(storageDir, "ClosedTrades"); + + // In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook + Thread shutDownHookThread = new Thread(TradeManager.this::shutDown, "TradeManager:ShutDownHook"); + Runtime.getRuntime().addShutdownHook(shutDownHookThread); } @@ -129,10 +134,30 @@ public class TradeManager { // Public API /////////////////////////////////////////////////////////////////////////////////////////// + + public void shutDown() { + if (!shutDownRequested) { + log.debug("shutDown"); + shutDownRequested = true; + // we remove own offers form offerbook when we go offline + for (OffererTrade offererTrade : openOfferTrades) { + Offer offer = offererTrade.getOffer(); + offerBookService.removeOfferAtShutDown(offer); + } + } + } + // When all services are initialized we create the protocols for our open offers and persisted not completed pendingTrades // OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early. public void onAllServicesInitialized() { + for (OffererTrade offererTrade : openOfferTrades) { + Offer offer = offererTrade.getOffer(); + // we add own offers to offerbook when we go online again + offerBookService.addOffer(offer, + () -> log.debug("Successful removed open offer from DHT"), + (message, throwable) -> log.error("Remove open offer from DHT failed. " + message)); + OffererAsBuyerProtocol protocol = createOffererAsBuyerProtocol(offererTrade); offererTrade.setProtocol(protocol); } @@ -310,7 +335,7 @@ public class TradeManager { } } - + /////////////////////////////////////////////////////////////////////////////////////////// // Called from Offerbook when offer gets removed from DHT /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/io/bitsquare/trade/TradeModule.java b/core/src/main/java/io/bitsquare/trade/TradeModule.java index acab0b98ca..6dd12c5b26 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeModule.java +++ b/core/src/main/java/io/bitsquare/trade/TradeModule.java @@ -19,11 +19,16 @@ package io.bitsquare.trade; import io.bitsquare.BitsquareModule; +import com.google.inject.Injector; import com.google.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.core.env.Environment; public class TradeModule extends BitsquareModule { + private static final Logger log = LoggerFactory.getLogger(TradeModule.class); public TradeModule(Environment env) { super(env); @@ -33,4 +38,11 @@ public class TradeModule extends BitsquareModule { protected void configure() { bind(TradeManager.class).in(Singleton.class); } + + @Override + protected void doClose(Injector injector) { + log.trace("doClose " + getClass().getSimpleName()); + // First shut down AddressService to remove address from DHT + injector.getInstance(TradeManager.class).shutDown(); + } }