• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bernardladenthin / BitcoinAddressFinder / #248

08 Apr 2025 07:18AM UTC coverage: 64.326% (+5.0%) from 59.356%
#248

push

bernardladenthin
Add timeout.

1145 of 1780 relevant lines covered (64.33%)

0.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.92
/src/main/java/net/ladenthin/bitcoinaddressfinder/cli/Main.java
1
// @formatter:off
2
/**
3
 * Copyright 2020 Bernard Ladenthin bernard.ladenthin@gmail.com
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *    http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
// @formatter:on
19
package net.ladenthin.bitcoinaddressfinder.cli;
20

21
import com.google.common.annotations.VisibleForTesting;
22
import com.google.gson.Gson;
23
import com.google.gson.GsonBuilder;
24
import java.io.IOException;
25
import java.nio.charset.Charset;
26
import java.nio.file.Files;
27
import java.nio.file.Path;
28
import java.util.ArrayList;
29
import java.util.List;
30
import java.util.Set;
31
import java.util.concurrent.CountDownLatch;
32
import java.util.concurrent.TimeUnit;
33
import net.ladenthin.bitcoinaddressfinder.AddressFilesToLMDB;
34
import net.ladenthin.bitcoinaddressfinder.Finder;
35
import net.ladenthin.bitcoinaddressfinder.Interruptable;
36
import net.ladenthin.bitcoinaddressfinder.LMDBToAddressFile;
37
import net.ladenthin.bitcoinaddressfinder.configuration.CConfiguration;
38
import net.ladenthin.bitcoinaddressfinder.opencl.OpenCLBuilder;
39
import net.ladenthin.bitcoinaddressfinder.opencl.OpenCLPlatform;
40
import org.slf4j.Logger;
41
import org.slf4j.LoggerFactory;
42
import org.yaml.snakeyaml.DumperOptions;
43
import org.yaml.snakeyaml.Yaml;
44

45
// VM option: -Dorg.slf4j.simpleLogger.defaultLogLevel=trace
46
public class Main implements Runnable, Interruptable {
47

48
    @VisibleForTesting
49
    public static Logger logger = LoggerFactory.getLogger(Main.class);
1✔
50

51
    private final List<Interruptable> interruptables = new ArrayList<>();
1✔
52

53
    private final CConfiguration configuration;
54
    
55
    CountDownLatch runLatch = new CountDownLatch(1);
1✔
56
    
57
    public Main(CConfiguration configuration) {
1✔
58
        this.configuration = configuration;
1✔
59
    }
1✔
60
    
61
    public static String readString(Path path) {
62
        try {
63
            String content = Files.readString(path, Charset.defaultCharset());
1✔
64
            return content;
1✔
65
        } catch (IOException e) {
×
66
            throw new RuntimeException(e);
×
67
        }
68
    }
69
    
70
    public static CConfiguration fromJson(String configurationString) {
71
        Gson gson = new Gson();
1✔
72
        CConfiguration configuration = gson.fromJson(configurationString, CConfiguration.class);
1✔
73
        return configuration;
1✔
74
    }
75
    
76
    public static CConfiguration fromYaml(String configurationString) {
77
        Yaml yaml = new Yaml();
×
78
        CConfiguration configuration = yaml.loadAs(configurationString, CConfiguration.class);
×
79
        return configuration;
×
80
    }
81
    
82
    public static String configurationToJson(CConfiguration configuration) {
83
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
1✔
84
        String json = gson.toJson(configuration);
1✔
85
        return json;
1✔
86
    }
87
    
88
    public static String configurationToYAML(CConfiguration configuration) {
89
        final DumperOptions options = new DumperOptions();
1✔
90
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
1✔
91
        options.setPrettyFlow(true);
1✔
92
        final Yaml yaml = new Yaml(options);
1✔
93
        String yamlDump = yaml.dump(configuration);
1✔
94
        return yamlDump;
1✔
95
    }
96

97
    public static void main(String[] args) {
98
        if (args.length != 1) {
1✔
99
            logger.error("Invalid arguments. Pass path to configuration as first argument.");
1✔
100
            return;
1✔
101
        }
102
        final Path configurationPath = Path.of(args[0]);
1✔
103
        String configurationAsString = readString(configurationPath);
1✔
104
        final CConfiguration configuration;
105
        if (configurationPath.toString().toLowerCase().endsWith(".js") || configurationPath.toString().toLowerCase().endsWith(".json")) {
1✔
106
            configuration = fromJson(configurationAsString);
1✔
107
        } else if(configurationPath.toString().toLowerCase().endsWith(".yaml")) {
×
108
            configuration = fromYaml(configurationAsString);
×
109
        } else {
110
            throw new IllegalArgumentException("Unknown file ending for: " + configurationPath);
×
111
        }
112
        Main main = new Main(configuration);
1✔
113
        main.logConfigurationTransformation();
1✔
114
        main.run();
1✔
115
    }
1✔
116

117
    public void logConfigurationTransformation() {
118
        String json = configurationToJson(configuration);
1✔
119
        String yaml = configurationToYAML(configuration);
1✔
120
        logger.info(
1✔
121
                "Please review the transformed configuration to ensure it aligns with your expectations and requirements before proceeding.:\n" +
122
                        "########## BEGIN transformed JSON configuration ##########\n" +
123
                        json + "\n" +
124
                        "########## END   transformed JSON configuration ##########\n" +
125
                        "\n" + 
126
                        "########## BEGIN transformed YAML configuration ##########\n" +
127
                        yaml + "\n" +
128
                        "########## END   transformed YAML configuration ##########\n"
129
        );
130
    }
1✔
131

132
    @Override
133
    public void run() {
134
        logger.info(configuration.command.name());
1✔
135
        
136
        addSchutdownHook();
1✔
137
        
138
        switch (configuration.command) {
1✔
139
            case Find:
140
                Finder finder = new Finder(configuration.finder);
×
141
                interruptables.add(finder);
×
142
                // key producer first
143
                finder.startKeyProducer();
×
144
                
145
                // consumer second
146
                finder.startConsumer();
×
147
                
148
                // producer last
149
                finder.configureProducer();
×
150
                finder.initProducer();
×
151
                finder.startProducer();
×
152
                finder.shutdownAndAwaitTermination();
×
153
                break;
×
154
            case LMDBToAddressFile:
155
                LMDBToAddressFile lmdbToAddressFile = new LMDBToAddressFile(configuration.lmdbToAddressFile);
1✔
156
                interruptables.add(lmdbToAddressFile);
1✔
157
                lmdbToAddressFile.run();
1✔
158
                break;
1✔
159
            case AddressFilesToLMDB:
160
                AddressFilesToLMDB addressFilesToLMDB = new AddressFilesToLMDB(configuration.addressFilesToLMDB);
1✔
161
                interruptables.add(addressFilesToLMDB);
1✔
162
                addressFilesToLMDB.run();
1✔
163
                break;
1✔
164
            case OpenCLInfo:
165
                OpenCLBuilder openCLBuilder = new OpenCLBuilder();
×
166
                List<OpenCLPlatform> openCLPlatforms = openCLBuilder.build();
×
167
                System.out.println(openCLPlatforms);
×
168
                break;
×
169
            default:
170
                throw new UnsupportedOperationException("Command: " + configuration.command.name() + " currently not supported." );
×
171
        }
172
        logger.info("Main#run end.");
1✔
173
        runLatch.countDown();
1✔
174
        
175
        if (false) {
176
            printAllStackTracesWithDelay(2_000L);
177
        }
178
    }
1✔
179
    
180
    public static void printAllStackTracesWithDelay(long delayMillis) {
181
        try {
182
            Thread.sleep(delayMillis);
×
183
        } catch (InterruptedException ignored) {
×
184
            // Intentionally ignored
185
        }
×
186

187
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
×
188
        for (Thread thread : threadSet) {
×
189
            System.out.println("##################################################");
×
190
            System.out.println("# Thread: " + thread);
×
191
            for (StackTraceElement element : thread.getStackTrace()) {
×
192
                System.out.println(element);
×
193
            }
194
        }
×
195
    }
×
196
    
197
    private void addSchutdownHook() {
198
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
1✔
199
            logger.info("Shutdown received via hook.");
1✔
200
            interrupt();
1✔
201
            try {
202
                logger.info("runLatch await");
1✔
203
                runLatch.await(30, TimeUnit.SECONDS);
1✔
204
            } catch (InterruptedException ex) {
×
205
                throw new RuntimeException(ex);
×
206
            }
1✔
207
            logger.info("Finish shutdown hook.");
1✔
208
        }));
1✔
209
    }
1✔
210
    
211
    @Override
212
    public void interrupt() {
213
        for (Interruptable interruptable : interruptables) {
1✔
214
            interruptable.interrupt();
1✔
215
        }
1✔
216
    }
1✔
217
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc