import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
/** The logger. */
private static final Logger logger = Logger.getLogger(Core.class.getName());
+ private final Instant startup = Instant.now();
private final Object syncObject = new Object();
/** The event bus. */
private final EventBus eventBus;
Network network = entry.getKey();
Collection<Bot> bots = networkBots.row(network).values();
int packCount = bots.stream().mapToInt((bot) -> bot.packs().size()).reduce((a, b) -> a + b).orElse(0);
- return new ConnectedNetwork(network, entry.getValue().hostname(),
- entry.getValue().port(), entry.getValue().nickname(),
+ Connection connection = entry.getValue();
+ return new ConnectedNetwork(network, connection.hostname(),
+ connection.port(),
+ connection.getUptime().get(),
+ connection.nickname(),
channels.stream()
.filter((channel) -> channel.network()
.equals(network))
return downloads.values();
}
+ public Duration getUptime() {
+ return Duration.between(startup, Instant.now());
+ }
+
//
// ACTIONS
//
package net.pterodactylus.xdcc.data;
+import java.time.Duration;
import java.util.Collection;
/**
private final Network network;
private final String hostname;
private final int port;
+ private final Duration uptime;
private final String nickname;
private final Collection<String> channels;
private final Collection<String> forcedChannels;
private final int packCount;
public ConnectedNetwork(Network network, String hostname, int port,
- String nickname, Collection<String> channels,
+ Duration uptime, String nickname, Collection<String> channels,
Collection<String> forcedChannels, int botCount, int packCount) {
this.network = network;
this.hostname = hostname;
this.port = port;
+ this.uptime = uptime;
this.nickname = nickname;
this.channels = channels;
this.forcedChannels = forcedChannels;
return network;
}
+ public Duration getUptime() {
+ return uptime;
+ }
+
public String getHostname() {
return hostname;
}
commandBuilder.add(new FailedDownloadsCommand(failedDownloads));
commandBuilder.add(new RestartCommand(core, failedDownloads));
commandBuilder.add(new ResearchCommand(core));
+ commandBuilder.add(new UptimeCommand(core));
commands = commandBuilder.build();
}
--- /dev/null
+package net.pterodactylus.xdcc.ui.stdin;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import net.pterodactylus.xdcc.core.Core;
+import net.pterodactylus.xdcc.data.ConnectedNetwork;
+
+/**
+ * {@link Command} that writes uptime information.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class UptimeCommand implements Command {
+
+ private final DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME;
+ private final Core core;
+
+ public UptimeCommand(Core core) {
+ this.core = core;
+ }
+
+ @Override
+ public String getName() {
+ return "uptime";
+ }
+
+ @Override
+ public Collection<String> getAliases() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public State execute(State state, List<String> parameters, Writer outputWriter)
+ throws IOException {
+ OffsetDateTime now = OffsetDateTime.now();
+ outputWriter.write(String.format("Core running since %s, %s ago.\n",
+ formatter.format(core.getUptime().subtractFrom(now)),
+ formatTime(core.getUptime())));
+ for (ConnectedNetwork network : core.connectedNetworks()) {
+ outputWriter.write(String.format("%s connected since %s, %s ago.\n",
+ network.getNetwork().name(),
+ formatter.format(network.getUptime().subtractFrom(now)),
+ formatTime(network.getUptime())));
+ }
+ return state;
+ }
+
+ private String formatTime(Duration uptime) {
+ long uptimeSeconds = uptime.getSeconds();
+ long seconds = uptimeSeconds % 60;
+ long minutes = (uptimeSeconds / 60) % 60;
+ long hours = (uptimeSeconds / (60 * 60)) % 24;
+ long days = (uptimeSeconds / (60 * 60 * 24)) % 7;
+ long weeks = (uptimeSeconds / (60 * 60 * 24 * 7));
+ String uptimeString = Stream
+ .of(weeks + "w", days + "d", hours + "h", minutes + "m", seconds + "s")
+ .filter(v -> !v.startsWith("0"))
+ .collect(Collectors.joining(" "));
+ return uptimeString.isEmpty() ? "0s" : uptimeString;
+ }
+
+}
import java.io.IOException;
import java.io.StringWriter;
+import java.time.Duration;
import net.pterodactylus.xdcc.core.Core;
import net.pterodactylus.xdcc.data.ConnectedNetwork;
builder("TestNet").build(),
"irc.test.net",
6667,
+ Duration.ofMinutes(1),
"Nickname1",
asList("#channel1", "#channel2"),
emptyList(),
builder("DummyNet").build(),
"irc.dummy.net",
6789,
+ Duration.ofMinutes(1),
"Nickname2",
asList("#dummy1", "#dummy2"),
asList("#foo", "#bar"),
builder("FooNet").build(),
"irc.foo.net",
7000,
+ Duration.ofMinutes(1),
"Nickname3",
emptyList(),
emptyList(),
builder("BarNet").build(),
"irc.bar.net",
7001,
+ Duration.ofMinutes(1),
"Nickname4",
emptyList(),
asList("#foo", "#bar"),
--- /dev/null
+package net.pterodactylus.xdcc.ui.stdin;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.time.Duration;
+import java.util.Arrays;
+import java.util.Collections;
+
+import net.pterodactylus.xdcc.core.Core;
+import net.pterodactylus.xdcc.data.ConnectedNetwork;
+import net.pterodactylus.xdcc.data.Network;
+
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+/**
+ * Unit test for {@link UptimeCommand}.
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class UptimeCommandTest {
+
+ private final Core core = Mockito.mock(Core.class);
+ private final UptimeCommand uptimeCommand = new UptimeCommand(core);
+ private final State state = Mockito.mock(State.class);
+ private final Writer writer = new StringWriter();
+
+ @Test
+ public void commandNameIsCorrect() {
+ MatcherAssert.assertThat(uptimeCommand.getName(), Matchers.is("uptime"));
+ }
+
+ @Test
+ public void aliasesAreEmpty() {
+ MatcherAssert.assertThat(uptimeCommand.getAliases(), Matchers.empty());
+ }
+
+ @Test
+ public void connectionUptimeIsWritten() throws IOException {
+ Mockito.when(core.getUptime()).thenReturn(createDuration(1, 2, 3, 4, 5));
+ uptimeCommand.execute(state, Collections.<String>emptyList(), writer);
+ MatcherAssert.assertThat(writer.toString(), Matchers.containsString("1w 2d 3h 4m 5s"));
+ }
+
+ @Test
+ public void connectionUptimeIsWrittenIfItIsZeroSeconds() throws IOException {
+ Mockito.when(core.getUptime()).thenReturn(createDuration(0, 0, 0, 0, 0));
+ uptimeCommand.execute(state, Collections.<String>emptyList(), writer);
+ MatcherAssert.assertThat(writer.toString(), Matchers.containsString("0s"));
+ }
+
+ @Test
+ public void networkUptimeIsWritten() throws IOException {
+ Mockito.when(core.getUptime()).thenReturn(createDuration(1, 2, 3, 4, 5));
+ ConnectedNetwork connectedNetwork = Mockito.mock(ConnectedNetwork.class);
+ Network network = Mockito.mock(Network.class);
+ Mockito.when(network.name()).thenReturn("Test");
+ Mockito.when(connectedNetwork.getNetwork()).thenReturn(network);
+ Mockito.when(connectedNetwork.getUptime()).thenReturn(createDuration(2, 3, 4, 5, 6));
+ Mockito.when(core.connectedNetworks()).thenReturn(Arrays.asList(connectedNetwork));
+ uptimeCommand.execute(state, Collections.<String>emptyList(), writer);
+ MatcherAssert.assertThat(writer.toString(), Matchers.containsString("2w 3d 4h 5m 6s"));
+ }
+
+ private Duration createDuration(int weeks, int days, int hours, int minutes, int seconds) {
+ return Duration.ofSeconds(
+ weeks * (7 * 24 * 60 * 60) +
+ days * (24 * 60 * 60) +
+ hours * (60 * 60) +
+ minutes * 60 +
+ seconds);
+ }
+
+}