use of com.aws.greengrass.util.Pair in project aws-greengrass-nucleus by aws-greengrass.
the class MqttClientTest method GIVEN_incoming_message_WHEN_received_THEN_subscribers_are_called.
@Test
void GIVEN_incoming_message_WHEN_received_THEN_subscribers_are_called() throws ExecutionException, InterruptedException, TimeoutException {
MqttClient client = spy(new MqttClient(deviceConfiguration, (c) -> builder, ses, executorService));
AwsIotMqttClient mockIndividual = mock(AwsIotMqttClient.class);
when(mockIndividual.subscribe(any(), any())).thenReturn(CompletableFuture.completedFuture(0));
when(client.getNewMqttClient()).thenReturn(mockIndividual);
assertFalse(client.connected());
// Subscribe with wildcard first so that that is the active cloud subscription.
// Then subscribe to 2 other topics which are included in the wildcard.
// Then show that each subscription here is called only for the topic that it
// subscribed to.
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abPlus = asyncAssertOnConsumer((m) -> {
assertThat(m.getTopic(), either(is("A/B/C")).or(is("A/B/D")));
}, 2);
client.subscribe(SubscribeRequest.builder().topic("A/B/+").callback(abPlus.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abc = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/C", m.getTopic());
}, 2);
client.subscribe(SubscribeRequest.builder().topic("A/B/C").callback(abc.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abd = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/D", m.getTopic());
});
client.subscribe(SubscribeRequest.builder().topic("A/B/D").callback(abd.getRight()).build());
Consumer<MqttMessage> handler = client.getMessageHandlerForClient(mockIndividual);
handler.accept(new MqttMessage("A/B/C", new byte[0]));
handler.accept(new MqttMessage("A/B/D", new byte[0]));
// No subscribers for this one
handler.accept(new MqttMessage("A/X/Y", new byte[0]));
abPlus.getLeft().get(0, TimeUnit.SECONDS);
abd.getLeft().get(0, TimeUnit.SECONDS);
// Ensure, that even after removing the wildcard subscription, the other topics still get
// messages
client.unsubscribe(UnsubscribeRequest.builder().topic("A/B/+").callback(abPlus.getRight()).build());
handler.accept(new MqttMessage("A/B/C", new byte[0]));
abc.getLeft().get(0, TimeUnit.SECONDS);
}
use of com.aws.greengrass.util.Pair in project aws-greengrass-nucleus by aws-greengrass.
the class MqttClientTest method GIVEN_incoming_messages_to_2clients_WHEN_received_THEN_subscribers_are_called_without_duplication.
@Test
void GIVEN_incoming_messages_to_2clients_WHEN_received_THEN_subscribers_are_called_without_duplication() throws ExecutionException, InterruptedException, TimeoutException {
MqttClient client = spy(new MqttClient(deviceConfiguration, (c) -> builder, ses, executorService));
assertFalse(client.connected());
AwsIotMqttClient mockIndividual1 = mock(AwsIotMqttClient.class);
AwsIotMqttClient mockIndividual2 = mock(AwsIotMqttClient.class);
when(mockIndividual1.subscribe(any(), any())).thenReturn(CompletableFuture.completedFuture(0));
when(mockIndividual2.subscribe(any(), any())).thenReturn(CompletableFuture.completedFuture(0));
when(client.getNewMqttClient()).thenReturn(mockIndividual1).thenReturn(mockIndividual2);
when(mockIndividual1.canAddNewSubscription()).thenReturn(false);
when(mockIndividual2.canAddNewSubscription()).thenReturn(true);
when(mockIndividual1.subscriptionCount()).thenReturn(1);
when(mockIndividual2.subscriptionCount()).thenReturn(1);
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abc = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/C", m.getTopic());
}, 1);
client.subscribe(SubscribeRequest.builder().topic("A/B/C").callback(abc.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abd = asyncAssertOnConsumer((m) -> {
assertEquals("A/B/D", m.getTopic());
}, 1);
client.subscribe(SubscribeRequest.builder().topic("A/B/D").callback(abd.getRight()).build());
Pair<CompletableFuture<Void>, Consumer<MqttMessage>> abPlus = asyncAssertOnConsumer((m) -> {
assertThat(m.getTopic(), either(is("A/B/C")).or(is("A/B/D")).or(is("A/B/F")));
}, 3);
client.subscribe(SubscribeRequest.builder().topic("A/B/+").callback(abPlus.getRight()).build());
Consumer<MqttMessage> handler1 = client.getMessageHandlerForClient(mockIndividual1);
Consumer<MqttMessage> handler2 = client.getMessageHandlerForClient(mockIndividual2);
// Send messages to BOTH handler1 and handler2 to show that we appropriately route and don't duplicate
// messages when multiple overlapping subscriptions exist across individual clients
// Send all to handler1
handler1.accept(new MqttMessage("A/B/C", new byte[0]));
handler1.accept(new MqttMessage("A/B/D", new byte[0]));
handler1.accept(new MqttMessage("A/B/F", new byte[0]));
handler1.accept(new MqttMessage("A/X/Y", new byte[0]));
// Send all the same messages to handler2
handler2.accept(new MqttMessage("A/B/C", new byte[0]));
handler2.accept(new MqttMessage("A/B/D", new byte[0]));
handler2.accept(new MqttMessage("A/B/F", new byte[0]));
// No subscribers for this one
handler2.accept(new MqttMessage("A/X/Y", new byte[0]));
abPlus.getLeft().get(0, TimeUnit.SECONDS);
abd.getLeft().get(0, TimeUnit.SECONDS);
abc.getLeft().get(0, TimeUnit.SECONDS);
}
use of com.aws.greengrass.util.Pair in project aws-greengrass-nucleus by aws-greengrass.
the class UnixPlatform method getChildPids.
/**
* Get the child PIDs of a process.
* @param process process
* @return a set of PIDs
* @throws IOException IO exception
* @throws InterruptedException InterruptedException
*/
public Set<Integer> getChildPids(Process process) throws IOException, InterruptedException {
PidProcess pp = Processes.newPidProcess(process);
// Use PS to list process PID and parent PID so that we can identify the process tree
logger.atDebug().log("Running ps to identify child processes of pid {}", pp.getPid());
Process proc = Runtime.getRuntime().exec(new String[] { "ps", "-ax", "-o", "pid,ppid" });
proc.waitFor();
if (proc.exitValue() != 0) {
logger.atWarn().kv("pid", pp.getPid()).kv("exit-code", proc.exitValue()).kv(STDOUT, inputStreamToString(proc.getInputStream())).kv(STDERR, inputStreamToString(proc.getErrorStream())).log("ps exited non-zero");
throw new IOException("ps exited with " + proc.exitValue());
}
try (InputStreamReader reader = new InputStreamReader(proc.getInputStream(), StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(reader)) {
Stream<String> lines = br.lines();
Map<String, String> pidToParent = lines.map(s -> {
Matcher matches = PS_PID_PATTERN.matcher(s.trim());
if (matches.matches()) {
return new Pair<>(matches.group(1), matches.group(2));
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
Map<String, List<String>> parentToChildren = Utils.inverseMap(pidToParent);
List<String> childProcesses = children(Integer.toString(pp.getPid()), parentToChildren);
return childProcesses.stream().map(Integer::parseInt).collect(Collectors.toSet());
}
}
use of com.aws.greengrass.util.Pair in project aws-greengrass-nucleus by aws-greengrass.
the class ForcedGcMemoryProfiler method printNativeMemoryUsage.
public static List<Pair<String, Long>> printNativeMemoryUsage(PrintStream out) {
List<Pair<String, Long>> memList = new LinkedList<>();
try {
Process proc = Runtime.getRuntime().exec(new String[] { getJcmdExecutable(), Long.toString(Utils.getPid()), "VM.native_memory", "summary" });
InputStream in = proc.getInputStream();
String nativeMemoryOutput = new BufferedReader(new InputStreamReader(in)).lines().collect(Collectors.joining("\n"));
out.println(nativeMemoryOutput);
Matcher matcher = JCMD_NATIVE_COMMITTED_MEMORY_PATTERN.matcher(nativeMemoryOutput);
while (matcher.find()) {
// jcmd outputs data in KB, so translate that to B to match our other outputs
memList.add(new Pair<>(matcher.group(1), Long.parseLong(matcher.group(2)) * 1024));
}
} catch (Exception ex) {
System.err.println("ForcedGcMemoryProfiler: error attaching / reading native memory usage with jcmd");
ex.printStackTrace();
}
return memList;
}
use of com.aws.greengrass.util.Pair in project aws-greengrass-nucleus by aws-greengrass.
the class ForcedGcMemoryProfiler method recordUsedMemory.
/**
* Called from the benchmark when the objects are still referenced to record the
* used memory. Enforces a full garbage collection and records memory usage.
* Waits and triggers GC again, as long as the memory is still reducing. Some workloads
* needs some time until they drain queues and finish all the work.
*/
public static void recordUsedMemory() {
long t0 = System.currentTimeMillis();
UsageTuple usageAfterIteration = null;
long gcTimeMillis = -1;
if (runSystemGC()) {
usageAfterIteration = getUsage();
gcTimeMillis = System.currentTimeMillis() - t0;
}
long usedHeapViaHistogram = printHeapHistogram(System.out, 30);
List<Pair<String, Long>> nativeMemoryUsage = printNativeMemoryUsage(System.out);
dataPoints.addAll(Arrays.asList(new OptionalScalarResult(METRIC_PREFIX + ".gcTimeMillis", (double) gcTimeMillis, "ms", AggregationPolicy.AVG), new OptionalScalarResult(METRIC_PREFIX + ".heapUsed.jmap", (double) usedHeapViaHistogram, "bytes", AggregationPolicy.AVG)));
if (usageAfterIteration != null) {
dataPoints.addAll(Arrays.asList(new OptionalScalarResult(METRIC_PREFIX + ".nonHeapUsed", (double) usageAfterIteration.nonHeap.getUsed(), "bytes", AggregationPolicy.AVG), new OptionalScalarResult(METRIC_PREFIX + ".totalCommitted", (double) usageAfterIteration.getTotalCommitted(), "bytes", AggregationPolicy.AVG), new OptionalScalarResult(METRIC_PREFIX + ".heapUsed", (double) usageAfterIteration.heap.getUsed(), "bytes", AggregationPolicy.AVG)));
}
dataPoints.addAll(nativeMemoryUsage.stream().map(v -> new OptionalScalarResult(METRIC_PREFIX + ".jcmd." + v.getLeft(), (double) v.getRight(), "bytes", AggregationPolicy.AVG)).collect(Collectors.toList()));
// Record metaspace, code cache, and compressed class space (all are non-heap) usage
for (MemoryPoolMXBean memoryMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
if ("Metaspace".equals(memoryMXBean.getName())) {
dataPoints.add(new OptionalScalarResult(METRIC_PREFIX + ".metaspaceUsed", (double) memoryMXBean.getUsage().getUsed(), "bytes", AggregationPolicy.AVG));
} else if ("Code Cache".equals(memoryMXBean.getName())) {
dataPoints.add(new OptionalScalarResult(METRIC_PREFIX + ".codeCacheUsed", (double) memoryMXBean.getUsage().getUsed(), "bytes", AggregationPolicy.AVG));
} else if ("Compressed Class Space".equals(memoryMXBean.getName())) {
dataPoints.add(new OptionalScalarResult(METRIC_PREFIX + ".compressedClassSpaceUsed", (double) memoryMXBean.getUsage().getUsed(), "bytes", AggregationPolicy.AVG));
}
}
LinuxVmProfiler.addLinuxVmStats(METRIC_PREFIX + ".linuxVm", dataPoints);
}
Aggregations