burstcoin.jminer.JMinerCommandLine.java Source code

Java tutorial

Introduction

Here is the source code for burstcoin.jminer.JMinerCommandLine.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 by luxe - https://github.com/de-luxe - BURST-LUXE-RED2-G6JW-H4HG5
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

package burstcoin.jminer;

import burstcoin.jminer.core.CoreProperties;
import burstcoin.jminer.core.network.Network;
import burstcoin.jminer.core.network.event.NetworkDevResultConfirmedEvent;
import burstcoin.jminer.core.network.event.NetworkLastWinnerEvent;
import burstcoin.jminer.core.network.event.NetworkPoolInfoEvent;
import burstcoin.jminer.core.network.event.NetworkResultConfirmedEvent;
import burstcoin.jminer.core.network.event.NetworkResultErrorEvent;
import burstcoin.jminer.core.network.event.NetworkStateChangeEvent;
import burstcoin.jminer.core.network.model.DevPoolResult;
import burstcoin.jminer.core.reader.event.ReaderCorruptFileEvent;
import burstcoin.jminer.core.reader.event.ReaderDriveFinishEvent;
import burstcoin.jminer.core.reader.event.ReaderDriveInterruptedEvent;
import burstcoin.jminer.core.reader.event.ReaderProgressChangedEvent;
import burstcoin.jminer.core.round.event.RoundFinishedEvent;
import burstcoin.jminer.core.round.event.RoundSingleResultEvent;
import burstcoin.jminer.core.round.event.RoundSingleResultSkippedEvent;
import burstcoin.jminer.core.round.event.RoundStartedEvent;
import burstcoin.jminer.core.round.event.RoundStoppedEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;

import java.math.BigDecimal;
import java.math.MathContext;

public class JMinerCommandLine implements CommandLineRunner {
    private static final Logger LOG = LoggerFactory.getLogger(JMinerCommandLine.class);

    private static final int NUMBER_OF_PROGRESS_LOGS_PER_ROUND = CoreProperties.getReadProgressPerRound();

    private static final int SIZE_DIVISOR = CoreProperties.isByteUnitDecimal() ? 1000 : 1024;
    private static final String T_UNIT = CoreProperties.isByteUnitDecimal() ? "TB" : "TiB";
    private static final String G_UNIT = CoreProperties.isByteUnitDecimal() ? "GB" : "GiB";
    private static final String M_UNIT = CoreProperties.isByteUnitDecimal() ? "MB" : "MiB";

    private static long blockNumber;
    private static int progressLogStep;
    private static long previousRemainingCapacity = 0;
    private static long previousElapsedTime = 0;

    private ConfigurableApplicationContext context;

    public JMinerCommandLine(ConfigurableApplicationContext context) {
        this.context = context;
    }

    @Override
    public void run(String... args) throws Exception {
        initApplicationListeners();

        LOG.info("-------------------------------------------------------");
        LOG.info("                            Burstcoin (BURST)");
        LOG.info("            __         __   GPU assisted PoC-Miner");
        LOG.info("           |__| _____ |__| ____   ___________ ");
        LOG.info("   version |  |/     \\|  |/    \\_/ __ \\_  __ \\");
        LOG.info("     0.4.4 |  |  Y Y  \\  |   |  \\  ___/|  | \\/");
        LOG.info("       /\\__|  |__|_|  /__|___|  /\\___  >__| ");
        LOG.info("       \\______|     \\/        \\/     \\/");
        LOG.info("      mining engine: BURST-LUXE-RED2-G6JW-H4HG5");
        LOG.info("     openCL checker: BURST-QHCJ-9HB5-PTGC-5Q8J9");

        Network network = context.getBean(Network.class);
        network.checkPoolInfo();
        network.startMining();
    }

    private void initApplicationListeners() {
        context.addApplicationListener(new ApplicationListener<RoundFinishedEvent>() {
            @Override
            public void onApplicationEvent(RoundFinishedEvent event) {
                previousRemainingCapacity = 0;
                previousElapsedTime = 0;

                long s = event.getRoundTime() / 1000;
                long ms = event.getRoundTime() % 1000;

                String bestDeadline = Long.MAX_VALUE == event.getBestCommittedDeadline() ? "N/A"
                        : String.valueOf(event.getBestCommittedDeadline());
                LOG.info("FINISH block '" + event.getBlockNumber() + "', " + "best deadline '" + bestDeadline
                        + "', " + "round time '" + s + "s " + ms + "ms'");
            }
        });

        context.addApplicationListener(new ApplicationListener<RoundStoppedEvent>() {
            @Override
            public void onApplicationEvent(RoundStoppedEvent event) {
                previousRemainingCapacity = 0;
                previousElapsedTime = 0;

                long s = event.getElapsedTime() / 1000;
                long ms = event.getElapsedTime() % 1000;

                BigDecimal totalCapacity = new BigDecimal(event.getCapacity());
                BigDecimal factor = BigDecimal.ONE.divide(totalCapacity, MathContext.DECIMAL32);
                BigDecimal progress = factor
                        .multiply(new BigDecimal(event.getCapacity() - event.getRemainingCapacity()));
                int percentage = (int) Math.ceil(progress.doubleValue() * 100);
                percentage = percentage > 100 ? 100 : percentage;

                String bestDeadline = Long.MAX_VALUE == event.getBestCommittedDeadline() ? "N/A"
                        : String.valueOf(event.getBestCommittedDeadline());
                LOG.info("STOP block '" + event.getBlockNumber() + "', " + String.valueOf(percentage) + "% done, "
                        + "best deadline '" + bestDeadline + "', " + "elapsed time '" + s + "s " + ms + "ms'");
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkLastWinnerEvent>() {
            @Override
            public void onApplicationEvent(NetworkLastWinnerEvent event) {
                if (blockNumber - 1 == event.getLastBlockNumber()) {
                    LOG.info(
                            "      winner block '" + event.getLastBlockNumber() + "', '" + event.getWinner() + "'");
                } else {
                    LOG.error("Error: NetworkLastWinnerEvent for block: " + event.getLastBlockNumber()
                            + " is outdated!");
                }
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkStateChangeEvent>() {
            @Override
            public void onApplicationEvent(NetworkStateChangeEvent event) {
                blockNumber = event.getBlockNumber();
            }
        });

        context.addApplicationListener(new ApplicationListener<RoundStartedEvent>() {
            @Override
            public void onApplicationEvent(RoundStartedEvent event) {
                progressLogStep = NUMBER_OF_PROGRESS_LOGS_PER_ROUND;

                LOG.info("-------------------------------------------------------");
                LOG.info("START block '" + event.getBlockNumber() + "', " + "scoopNumber '" + event.getScoopNumber()
                        + "', " + "capacity '" + event.getCapacity() / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR
                        + " " + G_UNIT + "'");
                String target = event.getTargetDeadline() == Long.MAX_VALUE ? "N/A"
                        : String.valueOf(event.getTargetDeadline());
                LOG.info("      targetDeadline '" + target + "', " + "baseTarget '"
                        + String.valueOf(event.getBaseTarget()) + "'");
            }
        });

        context.addApplicationListener(new ApplicationListener<ReaderProgressChangedEvent>() {
            @Override
            public void onApplicationEvent(ReaderProgressChangedEvent event) {
                long logStepCapacity = event.getCapacity() / NUMBER_OF_PROGRESS_LOGS_PER_ROUND;

                if (event.getRemainingCapacity() < logStepCapacity * progressLogStep
                        || event.getRemainingCapacity() == 0) {
                    progressLogStep--;

                    // trigger garbage collection on every progress step
                    System.gc();

                    BigDecimal totalCapacity = new BigDecimal(event.getCapacity());
                    BigDecimal factor = BigDecimal.ONE.divide(totalCapacity, MathContext.DECIMAL32);
                    BigDecimal progress = factor
                            .multiply(new BigDecimal(event.getCapacity() - event.getRemainingCapacity()));
                    int percentage = (int) Math.ceil(progress.doubleValue() * 100);
                    percentage = percentage > 100 ? 100 : percentage;

                    // calculate capacity
                    long effMBPerSec = 0;
                    if (previousRemainingCapacity > 0) {
                        long effDoneBytes = previousRemainingCapacity - event.getRemainingCapacity();

                        // calculate current reading speed (since last info)
                        long effBytesPerMs = (effDoneBytes / 4096) / (event.getElapsedTime() - previousElapsedTime);
                        effMBPerSec = (effBytesPerMs * 1000) / SIZE_DIVISOR / SIZE_DIVISOR;
                    }

                    // calculate capacity
                    long doneBytes = event.getCapacity() - event.getRemainingCapacity();
                    long doneTB = doneBytes / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR;
                    long doneGB = doneBytes / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR % SIZE_DIVISOR;

                    // calculate reading speed (average)
                    long averageBytesPerMs = (doneBytes / 4096) / event.getElapsedTime();
                    long averageMBPerSec = (averageBytesPerMs * 1000) / SIZE_DIVISOR / SIZE_DIVISOR;

                    previousRemainingCapacity = event.getRemainingCapacity();
                    previousElapsedTime = event.getElapsedTime();

                    LOG.info(String.valueOf(percentage) + "% done (" + doneTB + T_UNIT + " " + doneGB + G_UNIT
                            + "), avg.'" + averageMBPerSec + " " + M_UNIT + "/s'"
                            + (effMBPerSec > 0 ? ", eff.'" + effMBPerSec + " " + M_UNIT + "/s'" : ""));
                }
            }
        });

        context.addApplicationListener(new ApplicationListener<RoundSingleResultEvent>() {
            @Override
            public void onApplicationEvent(RoundSingleResultEvent event) {
                LOG.info("dl '" + event.getCalculatedDeadline() + "' send ("
                        + (event.isPoolMining() ? "pool" : "solo") + ")");
            }
        });

        context.addApplicationListener(new ApplicationListener<RoundSingleResultSkippedEvent>() {
            @Override
            public void onApplicationEvent(RoundSingleResultSkippedEvent event) {
                LOG.info(
                        "dl '" + event.getCalculatedDeadline() + "' > '" + event.getTargetDeadline() + "' skipped");
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkResultConfirmedEvent>() {
            @Override
            public void onApplicationEvent(NetworkResultConfirmedEvent event) {
                LOG.info("dl '" + event.getDeadline() + "' confirmed!  [ " + getDeadlineTime(event.getDeadline())
                        + " ]");
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkDevResultConfirmedEvent>() {
            @Override
            public void onApplicationEvent(NetworkDevResultConfirmedEvent event) {
                LOG.info("devPool response '" + event.getResponse() + "', block '" + event.getBlockNumber() + "'");
                for (DevPoolResult devPoolResult : event.getDevPoolResults()) {
                    LOG.info("dl '" + devPoolResult.getCalculatedDeadline() + "' successful committed!  [ "
                            + getDeadlineTime(devPoolResult.getCalculatedDeadline()) + " ]");
                }
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkResultErrorEvent>() {
            @Override
            public void onApplicationEvent(NetworkResultErrorEvent event) {
                LOG.info("strange dl result '" + event.getStrangeDeadline() + "', calculated '"
                        + event.getCalculatedDeadline() + "' " + "block '" + event.getBlockNumber() + "' nonce '"
                        + event.getNonce() + "'");
            }
        });

        context.addApplicationListener(new ApplicationListener<ReaderCorruptFileEvent>() {
            @Override
            public void onApplicationEvent(ReaderCorruptFileEvent event) {
                LOG.info("strange dl source '" + event.getFilePath() + "' (try replotting!?)");
                LOG.info("strange dl file chunks '" + event.getNumberOfChunks() + "', " + "parts per chunk '"
                        + event.getNumberOfParts() + "', " + "block '" + event.getBlockNumber() + "'");
            }
        });

        context.addApplicationListener(new ApplicationListener<ReaderDriveFinishEvent>() {
            @Override
            public void onApplicationEvent(ReaderDriveFinishEvent event) {
                if (blockNumber == event.getBlockNumber()) {
                    // calculate capacity
                    long doneBytes = event.getSize();
                    long doneTB = doneBytes / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR;
                    long doneGB = doneBytes / SIZE_DIVISOR / SIZE_DIVISOR / SIZE_DIVISOR % SIZE_DIVISOR;

                    long s = event.getTime() / 1000;
                    long ms = event.getTime() % 1000;

                    LOG.info("read '" + event.getDirectory() + "' (" + doneTB + T_UNIT + " " + doneGB + G_UNIT
                            + ") in '" + s + "s " + ms + "ms'");
                }
            }
        });

        context.addApplicationListener(new ApplicationListener<ReaderDriveInterruptedEvent>() {
            @Override
            public void onApplicationEvent(ReaderDriveInterruptedEvent event) {
                LOG.info("stopped '" + event.getDirectory() + "' for block '" + event.getBlockNumber() + "'.");
            }
        });

        context.addApplicationListener(new ApplicationListener<NetworkPoolInfoEvent>() {
            @Override
            public void onApplicationEvent(NetworkPoolInfoEvent event) {
                String value = event.getPoolBalanceNQT();
                String amount = value.length() > 8 ? value.substring(0, value.length() - 8) : value;
                value = event.getPoolForgedBalanceNQT();
                String totalForget = value.length() > 8 ? value.substring(0, value.length() - 8) : value;
                LOG.info("-------------------------------------------------------");
                LOG.info("POOL account '" + event.getPoolAccountRS() + "', assigned miners '"
                        + event.getPoolNumberOfMiningAccounts() + "'");
                LOG.info("     balance '" + amount + " BURST', total mined '" + totalForget + " BURST'");
            }
        });
    }

    private String getDeadlineTime(Long calculatedDeadline) {
        long sec = calculatedDeadline;
        long min = sec / 60;
        sec = sec % 60;
        long hours = min / 60;
        min = min % 60;
        long days = hours / 24;
        hours = hours % 24;
        return days + "d " + hours + "h " + min + "m " + sec + "s";
    }
}