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

bernardladenthin / BitcoinAddressFinder / #246

08 Apr 2025 06:29AM UTC coverage: 59.356% (-6.0%) from 65.404%
#246

push

bernardladenthin
Add timeout. Extract interruptAfterDelay. Ignore testRoundtrip_configurationsGiven_lmdbCreatedExportedAndRunFindSecretsFile for now.

1050 of 1769 relevant lines covered (59.36%)

0.59 hits per line

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

4.65
/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<>();
×
52

53
    private final CConfiguration configuration;
54
    
55
    CountDownLatch runLatch = new CountDownLatch(1);
×
56
    
57
    public Main(CConfiguration configuration) {
×
58
        this.configuration = configuration;
×
59
    }
×
60
    
61
    public static String readString(Path path) {
62
        try {
63
            String content = Files.readString(path, Charset.defaultCharset());
×
64
            return content;
×
65
        } catch (IOException e) {
×
66
            throw new RuntimeException(e);
×
67
        }
68
    }
69
    
70
    public static CConfiguration fromJson(String configurationString) {
71
        Gson gson = new Gson();
×
72
        CConfiguration configuration = gson.fromJson(configurationString, CConfiguration.class);
×
73
        return configuration;
×
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();
×
84
        String json = gson.toJson(configuration);
×
85
        return json;
×
86
    }
87
    
88
    public static String configurationToYAML(CConfiguration configuration) {
89
        final DumperOptions options = new DumperOptions();
×
90
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
×
91
        options.setPrettyFlow(true);
×
92
        final Yaml yaml = new Yaml(options);
×
93
        String yamlDump = yaml.dump(configuration);
×
94
        return yamlDump;
×
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]);
×
103
        String configurationAsString = readString(configurationPath);
×
104
        final CConfiguration configuration;
105
        if (configurationPath.toString().toLowerCase().endsWith(".js") || configurationPath.toString().toLowerCase().endsWith(".json")) {
×
106
            configuration = fromJson(configurationAsString);
×
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);
×
113
        main.logConfigurationTransformation();
×
114
        main.run();
×
115
    }
×
116

117
    public void logConfigurationTransformation() {
118
        String json = configurationToJson(configuration);
×
119
        String yaml = configurationToYAML(configuration);
×
120
        logger.info(
×
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
    }
×
131

132
    @Override
133
    public void run() {
134
        logger.info(configuration.command.name());
×
135
        
136
        addSchutdownHook();
×
137
        
138
        switch (configuration.command) {
×
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);
×
156
                interruptables.add(lmdbToAddressFile);
×
157
                lmdbToAddressFile.run();
×
158
                break;
×
159
            case AddressFilesToLMDB:
160
                AddressFilesToLMDB addressFilesToLMDB = new AddressFilesToLMDB(configuration.addressFilesToLMDB);
×
161
                interruptables.add(addressFilesToLMDB);
×
162
                addressFilesToLMDB.run();
×
163
                break;
×
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.");
×
173
        runLatch.countDown();
×
174
        
175
        if(false) {
176
            try {
177
                Thread.sleep(2000L);
178
            } catch (InterruptedException ex) {
179

180
            }
181
            Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
182
            for (Thread thread : threadSet) {
183
                System.out.println("##################################################");
184
                System.out.println("#thread: " + thread);
185
                StackTraceElement[] stackTrace = thread.getStackTrace();
186
                for (StackTraceElement stackTraceElement : stackTrace) {
187
                    System.out.println(stackTraceElement);
188
                }
189
            }
190
        }
191
    }
×
192
    
193
    private void addSchutdownHook() {
194
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
×
195
            logger.info("Shutdown received via hook.");
×
196
            interrupt();
×
197
            try {
198
                logger.info("runLatch await");
×
199
                runLatch.await(30, TimeUnit.SECONDS);
×
200
            } catch (InterruptedException ex) {
×
201
                throw new RuntimeException(ex);
×
202
            }
×
203
            logger.info("Finish shutdown hook.");
×
204
        }));
×
205
    }
×
206
    
207
    @Override
208
    public void interrupt() {
209
        for (Interruptable interruptable : interruptables) {
×
210
            interruptable.interrupt();
×
211
        }
×
212
    }
×
213
}
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