Merge branch 'StressTest' into Development

This commit is contained in:
Manfred Karrer 2016-06-13 19:08:59 +02:00
commit dfc5c27e65
34 changed files with 203 additions and 35 deletions

View file

@ -6,8 +6,7 @@ import org.slf4j.LoggerFactory;
public class DevFlags { public class DevFlags {
private static final Logger log = LoggerFactory.getLogger(DevFlags.class); private static final Logger log = LoggerFactory.getLogger(DevFlags.class);
public static final boolean STRESS_TEST_MODE = false; public static final boolean STRESS_TEST_MODE = true;
public static final boolean DEV_MODE = STRESS_TEST_MODE || false; public static final boolean DEV_MODE = STRESS_TEST_MODE || false;
public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true; public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true;
} }

View file

@ -24,8 +24,12 @@ import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy; import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy; import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;
import io.bitsquare.common.util.Profiler;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Log { public class Log {
private static SizeBasedTriggeringPolicy triggeringPolicy; private static SizeBasedTriggeringPolicy triggeringPolicy;
private static Logger logbackLogger; private static Logger logbackLogger;
@ -105,4 +109,11 @@ public class Log {
LoggerFactory.getLogger(className).trace("Called: {} [{}]", methodName, message); LoggerFactory.getLogger(className).trace("Called: {} [{}]", methodName, message);
} }
} }
public static void logIfStressTests(String msg) {
if (DevFlags.STRESS_TEST_MODE)
System.err.println(new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) +
" - " + msg +
" / Memory(MB): " + Profiler.getUsedMemory());
}
} }

View file

@ -8,6 +8,7 @@ public class ProgramArguments {
// program arg names // program arg names
public static final String TOR_DIR = "torDir"; public static final String TOR_DIR = "torDir";
public static final String USE_LOCALHOST = "useLocalhost"; public static final String USE_LOCALHOST = "useLocalhost";
public static final String MAX_CONNECTIONS = "maxConnections";
public static final String NAME_KEY = "node.name"; public static final String NAME_KEY = "node.name";

View file

@ -20,15 +20,24 @@ package io.bitsquare.common.util;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
class Profiler { public class Profiler {
private static final Logger log = LoggerFactory.getLogger(Profiler.class); private static final Logger log = LoggerFactory.getLogger(Profiler.class);
public static void printSystemLoad(Logger log) { public static void printSystemLoad(Logger log) {
String msg = printSystemLoadString();
log.info(msg);
}
public static String printSystemLoadString() {
long used = getUsedMemory();
return "System load (nr. threads/used memory (MB)): " + Thread.activeCount() + "/" + used;
}
public static long getUsedMemory() {
Runtime runtime = Runtime.getRuntime(); Runtime runtime = Runtime.getRuntime();
long free = runtime.freeMemory() / 1024 / 1024; long free = runtime.freeMemory() / 1024 / 1024;
long total = runtime.totalMemory() / 1024 / 1024; long total = runtime.totalMemory() / 1024 / 1024;
long used = total - free; return total - free;
log.info("System load (nr. threads/used memory (MB)): " + Thread.activeCount() + "/" + used);
} }
} }

View file

@ -124,6 +124,7 @@ public class CurrencyUtil {
result.add(new CryptoCurrency("SHIFT", "Shift")); result.add(new CryptoCurrency("SHIFT", "Shift"));
result.add(new CryptoCurrency("ERC", "Europecoin")); result.add(new CryptoCurrency("ERC", "Europecoin"));
result.add(new CryptoCurrency("POST", "PostCoin")); result.add(new CryptoCurrency("POST", "PostCoin"));
result.add(new CryptoCurrency("LSK", "Lisk"));
return result; return result;
} }

View file

@ -17,6 +17,7 @@
package io.bitsquare.trade.offer; package io.bitsquare.trade.offer;
import io.bitsquare.app.DevFlags;
import io.bitsquare.app.Version; import io.bitsquare.app.Version;
import io.bitsquare.btc.Restrictions; import io.bitsquare.btc.Restrictions;
import io.bitsquare.btc.pricefeed.MarketPrice; import io.bitsquare.btc.pricefeed.MarketPrice;
@ -59,7 +60,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
@JsonExclude @JsonExclude
private static final Logger log = LoggerFactory.getLogger(Offer.class); private static final Logger log = LoggerFactory.getLogger(Offer.class);
public static final long TTL = TimeUnit.MINUTES.toMillis(6); public static final long TTL = TimeUnit.MINUTES.toMillis(DevFlags.STRESS_TEST_MODE ? 6 : 6);
public final static String TAC_OFFERER = "With placing that offer I agree to trade " + public final static String TAC_OFFERER = "With placing that offer I agree to trade " +
"with any trader who fulfills the conditions as defined above."; "with any trader who fulfills the conditions as defined above.";
public static final String TAC_TAKER = "With taking that offer I agree to the trade conditions as defined above."; public static final String TAC_TAKER = "With taking that offer I agree to the trade conditions as defined above.";

View file

@ -18,6 +18,7 @@
package io.bitsquare.trade.offer; package io.bitsquare.trade.offer;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.app.DevFlags;
import io.bitsquare.app.Log; import io.bitsquare.app.Log;
import io.bitsquare.btc.AddressEntry; import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.TradeWalletService; import io.bitsquare.btc.TradeWalletService;
@ -67,8 +68,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
private static final long RETRY_REPUBLISH_DELAY_SEC = 10; private static final long RETRY_REPUBLISH_DELAY_SEC = 10;
private static final long REPUBLISH_AGAIN_AT_STARTUP_DELAY_SEC = 10; private static final long REPUBLISH_AGAIN_AT_STARTUP_DELAY_SEC = 10;
private static final long REPUBLISH_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15); private static final long REPUBLISH_INTERVAL_MS = TimeUnit.MINUTES.toMillis(DevFlags.STRESS_TEST_MODE ? 12 : 12);
private static final long REFRESH_INTERVAL_MS = TimeUnit.MINUTES.toMillis(4); private static final long REFRESH_INTERVAL_MS = TimeUnit.MINUTES.toMillis(DevFlags.STRESS_TEST_MODE ? 4 : 4);
private final KeyRing keyRing; private final KeyRing keyRing;
private final User user; private final User user;

View file

@ -102,7 +102,7 @@ public class BitsquareApp extends Application {
log.info("Log files under: " + logPath); log.info("Log files under: " + logPath);
Version.printVersion(); Version.printVersion();
Utilities.printSysInfo(); Utilities.printSysInfo();
Log.setLevel(!DevFlags.IS_RELEASE_VERSION); Log.setLevel(!DevFlags.IS_RELEASE_VERSION && !DevFlags.STRESS_TEST_MODE);
UserThread.setExecutor(Platform::runLater); UserThread.setExecutor(Platform::runLater);
UserThread.setTimerClass(UITimer.class); UserThread.setTimerClass(UITimer.class);

View file

@ -20,6 +20,7 @@ package io.bitsquare.app;
import io.bitsquare.BitsquareException; import io.bitsquare.BitsquareException;
import io.bitsquare.btc.BitcoinNetwork; import io.bitsquare.btc.BitcoinNetwork;
import io.bitsquare.btc.RegTestHost; import io.bitsquare.btc.RegTestHost;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.util.joptsimple.EnumValueConverter; import io.bitsquare.util.joptsimple.EnumValueConverter;
import joptsimple.OptionException; import joptsimple.OptionException;
import joptsimple.OptionParser; import joptsimple.OptionParser;
@ -106,6 +107,9 @@ public class BitsquareAppMain extends BitsquareExecutable {
parser.accepts(ProgramArguments.USE_LOCALHOST, description("Use localhost network for development", false)) parser.accepts(ProgramArguments.USE_LOCALHOST, description("Use localhost network for development", false))
.withRequiredArg() .withRequiredArg()
.ofType(boolean.class); .ofType(boolean.class);
parser.accepts(ProgramArguments.MAX_CONNECTIONS, description("Max. connections a peer will try to keep", P2PService.MAX_CONNECTIONS_DEFAULT))
.withRequiredArg()
.ofType(int.class);
parser.accepts(BitcoinNetwork.KEY, description("Bitcoin network", BitcoinNetwork.DEFAULT)) parser.accepts(BitcoinNetwork.KEY, description("Bitcoin network", BitcoinNetwork.DEFAULT))
.withRequiredArg() .withRequiredArg()
.ofType(BitcoinNetwork.class) .ofType(BitcoinNetwork.class)

View file

@ -460,6 +460,12 @@ textfield */
-fx-text-fill: #333000; -fx-text-fill: #333000;
} }
/* Offer book */
#num-offers {
-fx-font-size: 12;
}
/* Create offer */ /* Create offer */
#direction-icon-label { #direction-icon-label {
-fx-font-weight: bold; -fx-font-weight: bold;

View file

@ -19,6 +19,7 @@ package io.bitsquare.gui.main;
import io.bitsquare.BitsquareException; import io.bitsquare.BitsquareException;
import io.bitsquare.app.BitsquareApp; import io.bitsquare.app.BitsquareApp;
import io.bitsquare.app.DevFlags;
import io.bitsquare.btc.pricefeed.PriceFeed; import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2; import io.bitsquare.common.util.Tuple2;
@ -67,10 +68,12 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
} }
public static void blurLight() { public static void blurLight() {
if (!DevFlags.STRESS_TEST_MODE)
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 5); transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 5);
} }
public static void blurUltraLight() { public static void blurUltraLight() {
if (!DevFlags.STRESS_TEST_MODE)
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 2); transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 2);
} }
@ -335,7 +338,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
}; };
model.walletServiceErrorMsg.addListener(walletServiceErrorMsgListener); model.walletServiceErrorMsg.addListener(walletServiceErrorMsgListener);
btcSyncIndicator = new ProgressBar(-1); btcSyncIndicator = new ProgressBar();
btcSyncIndicator.setPrefWidth(120); btcSyncIndicator.setPrefWidth(120);
btcSyncIndicator.progressProperty().bind(model.btcSyncProgress); btcSyncIndicator.progressProperty().bind(model.btcSyncProgress);

View file

@ -110,7 +110,7 @@ public class MainViewModel implements ViewModel {
// BTC network // BTC network
final StringProperty btcInfo = new SimpleStringProperty("Initializing"); final StringProperty btcInfo = new SimpleStringProperty("Initializing");
final DoubleProperty btcSyncProgress = new SimpleDoubleProperty(-1); final DoubleProperty btcSyncProgress = new SimpleDoubleProperty(DevFlags.STRESS_TEST_MODE ? 0 : -1);
final StringProperty walletServiceErrorMsg = new SimpleStringProperty(); final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
final StringProperty btcSplashSyncIconId = new SimpleStringProperty(); final StringProperty btcSplashSyncIconId = new SimpleStringProperty();
final StringProperty marketPrice = new SimpleStringProperty("N/A"); final StringProperty marketPrice = new SimpleStringProperty("N/A");
@ -126,7 +126,7 @@ public class MainViewModel implements ViewModel {
// P2P network // P2P network
final StringProperty p2PNetworkInfo = new SimpleStringProperty(); final StringProperty p2PNetworkInfo = new SimpleStringProperty();
private MonadicBinding<String> p2PNetworkInfoBinding; private MonadicBinding<String> p2PNetworkInfoBinding;
final DoubleProperty splashP2PNetworkProgress = new SimpleDoubleProperty(-1); final DoubleProperty splashP2PNetworkProgress = new SimpleDoubleProperty(DevFlags.STRESS_TEST_MODE ? 0 : -1);
final StringProperty p2pNetworkWarnMsg = new SimpleStringProperty(); final StringProperty p2pNetworkWarnMsg = new SimpleStringProperty();
final StringProperty p2PNetworkIconId = new SimpleStringProperty(); final StringProperty p2PNetworkIconId = new SimpleStringProperty();
final BooleanProperty bootstrapComplete = new SimpleBooleanProperty(); final BooleanProperty bootstrapComplete = new SimpleBooleanProperty();

View file

@ -28,6 +28,7 @@ import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.*; import io.bitsquare.gui.components.*;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.account.AccountView; import io.bitsquare.gui.main.account.AccountView;
import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView; import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView;
@ -91,7 +92,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private AddressTextField addressTextField; private AddressTextField addressTextField;
private BalanceTextField balanceTextField; private BalanceTextField balanceTextField;
private TitledGroupBg payFundsPane; private TitledGroupBg payFundsPane;
private ProgressIndicator spinner; private ConfidenceProgressIndicator spinner;
private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton; private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton;
private InputTextField amountTextField, minAmountTextField, fixedPriceTextField, marketBasedPriceTextField, volumeTextField; private InputTextField amountTextField, minAmountTextField, fixedPriceTextField, marketBasedPriceTextField, volumeTextField;
private TextField currencyTextField; private TextField currencyTextField;
@ -580,7 +581,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
errorMessageListener = (o, oldValue, newValue) -> { errorMessageListener = (o, oldValue, newValue) -> {
if (newValue != null) if (newValue != null)
UserThread.runAfter(() -> new Popup().error(BSResources.get("createOffer.amountPriceBox.error.message", model.errorMessage.get()) + UserThread.runAfter(() -> new Popup().error(BSResources.get("createOffer.amountPriceBox.error.message", model.errorMessage.get()) +
"\n\nThere have no funds left your wallet yet.\n" + "\n\nNo funds have left your wallet yet.\n" +
"Please try to restart you application and check your network connection to see if you can resolve the issue.") "Please try to restart you application and check your network connection to see if you can resolve the issue.")
.show(), 100, TimeUnit.MILLISECONDS); .show(), 100, TimeUnit.MILLISECONDS);
}; };
@ -871,7 +872,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
fundFromExternalWalletButton = new Button("Open your external wallet for funding"); fundFromExternalWalletButton = new Button("Open your external wallet for funding");
fundFromExternalWalletButton.setDefaultButton(false); fundFromExternalWalletButton.setDefaultButton(false);
fundFromExternalWalletButton.setOnAction(e -> GUIUtil.showFeeInfoBeforeExecute(this::openWallet)); fundFromExternalWalletButton.setOnAction(e -> GUIUtil.showFeeInfoBeforeExecute(this::openWallet));
spinner = new ProgressIndicator(0); spinner = new ConfidenceProgressIndicator(0);
spinner.setPrefHeight(18); spinner.setPrefHeight(18);
spinner.setPrefWidth(18); spinner.setPrefWidth(18);
spinnerInfoLabel = new Label(); spinnerInfoLabel = new Label();

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.offer.offerbook; package io.bitsquare.gui.main.offer.offerbook;
import io.bitsquare.app.Log;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.offer.OfferBookService; import io.bitsquare.trade.offer.OfferBookService;
@ -56,8 +57,11 @@ public class OfferBook {
@Override @Override
public void onAdded(Offer offer) { public void onAdded(Offer offer) {
OfferBookListItem offerBookListItem = new OfferBookListItem(offer); OfferBookListItem offerBookListItem = new OfferBookListItem(offer);
if (!offerBookListItems.contains(offerBookListItem)) if (!offerBookListItems.contains(offerBookListItem)) {
offerBookListItems.add(offerBookListItem); offerBookListItems.add(offerBookListItem);
Log.logIfStressTests("Offer added: Nr. of offers = " + offerBookListItems.size());
}
} }
@Override @Override
@ -72,8 +76,11 @@ public class OfferBook {
if (candidate.isPresent()) { if (candidate.isPresent()) {
OfferBookListItem item = candidate.get(); OfferBookListItem item = candidate.get();
synchronized (offerBookListItems) { synchronized (offerBookListItems) {
if (offerBookListItems.contains(item)) if (offerBookListItems.contains(item)) {
offerBookListItems.remove(item); offerBookListItems.remove(item);
Log.logIfStressTests("Offer removed: Nr. of offers = " + offerBookListItems.size());
}
} }
} }
} }
@ -95,6 +102,8 @@ public class OfferBook {
offerBookListItems.addAll(list); offerBookListItems.addAll(list);
Log.logIfStressTests("Offer filled: Nr. of offers = " + offerBookListItems.size());
log.debug("offerBookListItems " + offerBookListItems.size()); log.debug("offerBookListItems " + offerBookListItems.size());
} }
} }

View file

@ -43,6 +43,7 @@ import io.bitsquare.trade.offer.Offer;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.geometry.HPos; import javafx.geometry.HPos;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.VPos; import javafx.geometry.VPos;
@ -75,6 +76,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private OfferView.OfferActionHandler offerActionHandler; private OfferView.OfferActionHandler offerActionHandler;
private int gridRow = 0; private int gridRow = 0;
private TitledGroupBg offerBookTitle; private TitledGroupBg offerBookTitle;
private Label nrOfOffersLabel;
private ListChangeListener<OfferBookListItem> offerListListener;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -181,7 +184,17 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod())); paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod()));
avatarColumn.setComparator((o1, o2) -> o1.getOffer().getOwnerNodeAddress().hostName.compareTo(o2.getOffer().getOwnerNodeAddress().hostName)); avatarColumn.setComparator((o1, o2) -> o1.getOffer().getOwnerNodeAddress().hostName.compareTo(o2.getOffer().getOwnerNodeAddress().hostName));
createOfferButton = addButton(root, ++gridRow, ""); nrOfOffersLabel = new Label("Nr. of offers: -");
nrOfOffersLabel.setId("num-offers");
GridPane.setHalignment(nrOfOffersLabel, HPos.LEFT);
GridPane.setVgrow(nrOfOffersLabel, Priority.NEVER);
GridPane.setValignment(nrOfOffersLabel, VPos.TOP);
GridPane.setRowIndex(nrOfOffersLabel, ++gridRow);
GridPane.setColumnIndex(nrOfOffersLabel, 0);
GridPane.setMargin(nrOfOffersLabel, new Insets(10, 0, 0, -5));
root.getChildren().add(nrOfOffersLabel);
createOfferButton = addButton(root, gridRow, "");
createOfferButton.setMinHeight(40); createOfferButton.setMinHeight(40);
createOfferButton.setPadding(new Insets(0, 20, 0, 20)); createOfferButton.setPadding(new Insets(0, 20, 0, 20));
createOfferButton.setGraphicTextGap(10); createOfferButton.setGraphicTextGap(10);
@ -233,6 +246,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
tableView.setItems(model.getOfferList()); tableView.setItems(model.getOfferList());
priceColumn.setSortType((model.getDirection() == Offer.Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING); priceColumn.setSortType((model.getDirection() == Offer.Direction.BUY) ? TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
offerListListener = c -> nrOfOffersLabel.setText("Nr. of offers: " + model.getOfferList().size());
model.getOfferList().addListener(offerListListener);
nrOfOffersLabel.setText("Nr. of offers: " + model.getOfferList().size());
} }
@Override @Override
@ -245,6 +262,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
priceColumn.sortableProperty().unbind(); priceColumn.sortableProperty().unbind();
amountColumn.sortableProperty().unbind(); amountColumn.sortableProperty().unbind();
model.getOfferList().removeListener(offerListListener);
} }

View file

@ -324,7 +324,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
String appendMsg = ""; String appendMsg = "";
switch (trade.getState().getPhase()) { switch (trade.getState().getPhase()) {
case PREPARATION: case PREPARATION:
appendMsg = "\n\nThere have no funds left your wallet yet.\n" + appendMsg = "\n\nNo funds have left your wallet yet.\n" +
"Please try to restart you application and check your network connection to see if you can resolve the issue."; "Please try to restart you application and check your network connection to see if you can resolve the issue.";
break; break;
case TAKER_FEE_PAID: case TAKER_FEE_PAID:

View file

@ -43,7 +43,7 @@ public class SellerStep1View extends TradeStepView {
@Override @Override
protected String getInfoText() { protected String getInfoText() {
return "Deposit transaction has been published.\n" + return "Deposit transaction has been published.\n" +
"The bitcoin buyer need to wait for at least one blockchain confirmation before " + "The bitcoin buyer needs to wait for at least one blockchain confirmation before " +
"starting the payment."; "starting the payment.";
} }

View file

@ -24,8 +24,8 @@ import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class Profiler { public class GUIProfiler {
private static final Logger log = LoggerFactory.getLogger(Profiler.class); private static final Logger log = LoggerFactory.getLogger(GUIProfiler.class);
private static final Stopwatch globalStopwatch = Stopwatch.createStarted(); private static final Stopwatch globalStopwatch = Stopwatch.createStarted();
private static final ThreadLocal<Stopwatch> threadStopwatch = ThreadLocal.withInitial(Stopwatch::createStarted); private static final ThreadLocal<Stopwatch> threadStopwatch = ThreadLocal.withInitial(Stopwatch::createStarted);

View file

@ -96,8 +96,9 @@ public class OsData {
return OsType.Linux64; return OsType.Linux64;
} }
// armv8 is 64 bit, armv7l is 32 bit
if (unameOutput.contains("arm")) if (unameOutput.contains("arm"))
return unameOutput.contains("64") ? OsType.Linux64 : OsType.Linux32; return unameOutput.contains("64") || unameOutput.contains("v8") ? OsType.Linux64 : OsType.Linux32;
throw new RuntimeException("Could not understand uname output, not sure what bitness"); throw new RuntimeException("Could not understand uname output, not sure what bitness");
} catch (IOException e) { } catch (IOException e) {

View file

@ -50,6 +50,9 @@ public class P2PModule extends AppModule {
Integer port = env.getProperty(ProgramArguments.PORT_KEY, int.class, 9999); Integer port = env.getProperty(ProgramArguments.PORT_KEY, int.class, 9999);
bind(int.class).annotatedWith(Names.named(ProgramArguments.PORT_KEY)).toInstance(port); bind(int.class).annotatedWith(Names.named(ProgramArguments.PORT_KEY)).toInstance(port);
Integer maxConnections = env.getProperty(ProgramArguments.MAX_CONNECTIONS, int.class, P2PService.MAX_CONNECTIONS_DEFAULT);
bind(int.class).annotatedWith(Names.named(ProgramArguments.MAX_CONNECTIONS)).toInstance(maxConnections);
Integer networkId = env.getProperty(ProgramArguments.NETWORK_ID, int.class, 1); Integer networkId = env.getProperty(ProgramArguments.NETWORK_ID, int.class, 1);
bind(int.class).annotatedWith(Names.named(ProgramArguments.NETWORK_ID)).toInstance(networkId); bind(int.class).annotatedWith(Names.named(ProgramArguments.NETWORK_ID)).toInstance(networkId);
} }

View file

@ -102,13 +102,15 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
@Named(ProgramArguments.TOR_DIR) File torDir, @Named(ProgramArguments.TOR_DIR) File torDir,
@Named(ProgramArguments.USE_LOCALHOST) boolean useLocalhost, @Named(ProgramArguments.USE_LOCALHOST) boolean useLocalhost,
@Named(ProgramArguments.NETWORK_ID) int networkId, @Named(ProgramArguments.NETWORK_ID) int networkId,
@Named(ProgramArguments.MAX_CONNECTIONS) int maxConnections,
@Named("storage.dir") File storageDir, @Named("storage.dir") File storageDir,
Clock clock, Clock clock,
@Nullable EncryptionService encryptionService, @Nullable EncryptionService encryptionService,
@Nullable KeyRing keyRing) { @Nullable KeyRing keyRing) {
this( this(
seedNodesRepository, seedNodesRepository,
port, MAX_CONNECTIONS_DEFAULT, port,
maxConnections,
torDir, torDir,
useLocalhost, useLocalhost,
networkId, networkId,

View file

@ -23,7 +23,7 @@ public enum CloseConnectionReason {
UNKNOWN_PEER_ADDRESS(true, true), UNKNOWN_PEER_ADDRESS(true, true),
// illegal requests // illegal requests
RULE_VIOLATION(true, true); RULE_VIOLATION(true, false);
public final boolean sendCloseMessage; public final boolean sendCloseMessage;
public boolean isIntended; public boolean isIntended;

View file

@ -69,7 +69,7 @@ public class Connection implements MessageListener {
//TODO decrease limits again after testing //TODO decrease limits again after testing
static final int MSG_THROTTLE_PER_SEC = 70; // With MAX_MSG_SIZE of 500kb results in bandwidth of 35 mbit/sec static final int MSG_THROTTLE_PER_SEC = 70; // With MAX_MSG_SIZE of 500kb results in bandwidth of 35 mbit/sec
static final int MSG_THROTTLE_PER_10_SEC = 500; // With MAX_MSG_SIZE of 100kb results in bandwidth of 50 mbit/sec for 10 sec static final int MSG_THROTTLE_PER_10_SEC = 500; // With MAX_MSG_SIZE of 100kb results in bandwidth of 50 mbit/sec for 10 sec
private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60); private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(120);
public static int getMaxMsgSize() { public static int getMaxMsgSize() {
return MAX_MSG_SIZE; return MAX_MSG_SIZE;

View file

@ -155,6 +155,9 @@ public class PeerManager implements ConnectionListener {
@Override @Override
public void onConnection(Connection connection) { public void onConnection(Connection connection) {
Log.logIfStressTests("onConnection to peer " +
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
" / Nr. of connections: " + networkNode.getAllConnections().size());
if (isSeedNode(connection)) if (isSeedNode(connection))
connection.setPeerType(Connection.PeerType.SEED_NODE); connection.setPeerType(Connection.PeerType.SEED_NODE);
@ -169,6 +172,9 @@ public class PeerManager implements ConnectionListener {
@Override @Override
public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) { public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) {
Log.logIfStressTests("onDisconnect of peer " +
(connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown") +
" / Nr. of connections: " + networkNode.getAllConnections().size());
handleConnectionFault(connection); handleConnectionFault(connection);
lostAllConnections = networkNode.getAllConnections().isEmpty(); lostAllConnections = networkNode.getAllConnections().isEmpty();
@ -211,6 +217,7 @@ public class PeerManager implements ConnectionListener {
Set<Connection> allConnections = networkNode.getAllConnections(); Set<Connection> allConnections = networkNode.getAllConnections();
int size = allConnections.size(); int size = allConnections.size();
log.info("We have {} connections open. Our limit is {}", size, limit); log.info("We have {} connections open. Our limit is {}", size, limit);
if (size > limit) { if (size > limit) {
log.info("We have too many connections open.\n\t" + log.info("We have too many connections open.\n\t" +
"Lets try first to remove the inbound connections of type PEER."); "Lets try first to remove the inbound connections of type PEER.");

View file

@ -34,10 +34,10 @@ public class SeedNodesRepository {
new NodeAddress("b66vnevaljo6xt5a.onion:8000"),*/ new NodeAddress("b66vnevaljo6xt5a.onion:8000"),*/
// v0.4.2 // v0.4.2
DevFlags.STRESS_TEST_MODE ? new NodeAddress("TBD.onion:8000") : new NodeAddress("uadzuib66jupaept.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("uadzuib66jupaept.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("TBD.onion:8000") : new NodeAddress("hbma455xxbqhcuqh.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("hbma455xxbqhcuqh.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("TBD.onion:8000") : new NodeAddress("wgthuiqn3aoiovbm.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("wgthuiqn3aoiovbm.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("TBD.onion:8000") : new NodeAddress("2zxtnprnx5wqr7a3.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("2zxtnprnx5wqr7a3.onion:8000"),
// testnet // testnet
new NodeAddress("znmy44wcstn2rkva.onion:8001"), new NodeAddress("znmy44wcstn2rkva.onion:8001"),

View file

@ -159,6 +159,14 @@ public class P2PDataStorage implements MessageListener, ConnectionListener {
if (containsKey) { if (containsKey) {
log.info("We remove the data as the data owner got disconnected with " + log.info("We remove the data as the data owner got disconnected with " +
"closeConnectionReason=" + closeConnectionReason); "closeConnectionReason=" + closeConnectionReason);
Log.logIfStressTests("We remove the data as the data owner got disconnected with " +
"closeConnectionReason=" + closeConnectionReason +
" / isIntended=" + closeConnectionReason.isIntended +
" / peer=" + (connection.getPeersNodeAddressOptional().isPresent() ? connection.getPeersNodeAddressOptional().get() : "PeersNode unknown"));
// TODO We get closeConnectionReason TERMINATED which removes offers which should not be removed
// TODO investigate why EOFException happens
doRemoveProtectedExpirableData(protectedData, hashOfPayload); doRemoveProtectedExpirableData(protectedData, hashOfPayload);
} else { } else {
log.debug("Remove data ignored as we don't have an entry for that data."); log.debug("Remove data ignored as we don't have an entry for that data.");

View file

@ -131,7 +131,7 @@ public class TestUtils {
} }
P2PService p2PService = new P2PService(seedNodesRepository, port, new File("seed_node_" + port), useLocalhost, P2PService p2PService = new P2PService(seedNodesRepository, port, new File("seed_node_" + port), useLocalhost,
2, new File("dummy"), new Clock(), encryptionService, keyRing); 2, P2PService.MAX_CONNECTIONS_DEFAULT, new File("dummy"), new Clock(), encryptionService, keyRing);
p2PService.start(new P2PServiceListener() { p2PService.start(new P2PServiceListener() {
@Override @Override
public void onRequestingDataCompleted() { public void onRequestingDataCompleted() {

View file

@ -323,7 +323,7 @@ public class NetworkStressTest {
final EncryptionService peerEncryptionService = new EncryptionService(peerKeyRing); final EncryptionService peerEncryptionService = new EncryptionService(peerKeyRing);
return new P2PService(seedNodesRepository, port, peerTorDir, useLocalhost, return new P2PService(seedNodesRepository, port, peerTorDir, useLocalhost,
REGTEST_NETWORK_ID, peerStorageDir, new Clock(), peerEncryptionService, peerKeyRing); REGTEST_NETWORK_ID, P2PService.MAX_CONNECTIONS_DEFAULT, peerStorageDir, new Clock(), peerEncryptionService, peerKeyRing);
} }
// ## TEST SETUP: P2P service listener classes // ## TEST SETUP: P2P service listener classes

11
package/stresstest/cleanup.sh Executable file
View file

@ -0,0 +1,11 @@
#!/bin/bash
cd /home/bs/.local/share
find . -name \*.DS_Store -type f -delete
find . -name \*._.DS_Store -type f -delete
find . -name \*SequenceNumberMap -type f -delete
find . -name \*PersistedPeers -type f -delete
find . -name \*bitsquare.log -type f -delete
find . -name \*__MACOSX -type d -delete
find . -name \*backup -type d -exec rm -R -f {} +

10
package/stresstest/copyDir.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
cd /Users/mk/Library/Application\ Support
for i in `seq 101 500`;
do
dir=BS_$i
mkdir $dir
cp -av BS_/* $dir/
done

22
package/stresstest/init.sh Executable file
View file

@ -0,0 +1,22 @@
#!/bin/bash
cd ../../seednode/target
logpath=/Users/mk/Documents/_intellij/bitsquare/logs
datapath="/Users/mk/Library/Application Support"
mkdir -p $logpath
# rm "$datapath/Bitsquare_seed_node_hlitt7z4bec4kdh4.onion_8000/db/SequenceNumberMap"
# rm "$datapath/Bitsquare_seed_node_hlitt7z4bec4kdh4.onion_8000/db/PersistedPeers"
# rm "$datapath/BS_arb/mainnet/db/SequenceNumberMap"
# rm "$datapath/BS_arb/mainnet/db/PersistedPeers"
nohup java -jar SeedNode.jar hlitt7z4bec4kdh4.onion:8000 0 500 >/dev/null 2>$logpath/ST_0_seednode.log &
sleep 40
cd ../../gui/target
nohup java -jar shaded.jar --app.name=BS_arb --maxConnections=12 >/dev/null 2>$logpath/ST_0_arb.log &
# kill `ps -ef | grep java | grep -v grep | awk '{print $2}'`

View file

@ -0,0 +1,20 @@
#!/bin/bash
dir=/Users/mk/Desktop/10_offers
for i in `seq 1 20`;
do
echo $i
rm $dir/BS_$i/mainnet/tor/tor.real
rm $dir/BS_$i/mainnet/tor/geoip
rm $dir/BS_$i/mainnet/tor/geoip6
rm $dir/BS_$i/mainnet/tor/cached-microdescs
rm $dir/BS_$i/mainnet/tor/cached-microdesc-consensus
rm $dir/BS_$i/mainnet/db/SequenceNumberMap
rm $dir/BS_$i/mainnet/db/PersistedPeers
rm -R -f $dir/BS_$i/mainnet/tor/__MACOSX
rm -R -f $dir/BS_$i/mainnet/tor/hiddenservice/backup
rm -R -f $dir/BS_$i/mainnet/keys/backup
rm -R -f $dir/BS_$i/mainnet/db/backup
rm -R -f $dir/BS_$i/mainnet/bitcoin/backup
done

20
package/stresstest/start.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/bash
logpath=/home/bs/bitsquare/logs
datapath=/home/bs/.local/share
mkdir -p $logpath
cd ../../gui/target
delay=40
# edit start end index
for i in `seq 0 0`;
do
echo $i
nohup java -jar shaded.jar --app.name=BS_$i --maxConnections=12 >/dev/null 2>$logpath/ST_$i.log &
sleep $delay
done
# kill `ps -ef | grep java | grep -v grep | awk '{print $2}'`