All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.utils.SDNotify Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.utils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import org.yamcs.logging.Log;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.epoll.EpollDomainDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.unix.DomainDatagramPacket;
import io.netty.channel.unix.DomainSocketAddress;

/**
 * Helper utility for sending systemd notification events about state changes.
 * 

* The primary use case is to send a notification to the systemd notification when Yamcs has finished starting. This can * be used when Yamcs runs as a service unit with {@code Type=notify} in its definition file. *

* See https://www.freedesktop.org/software/systemd/man/sd_notify.html */ public class SDNotify { private static final Log log = new Log(SDNotify.class); // If started through systemd with Type=notify, Yamcs will have NOTIFY_SOCKET // env set to the path of an AF_UNIX socket. private static final String NOTIFY_SOCKET = System.getenv("NOTIFY_SOCKET"); /** * Tell the service manager that Yamcs has finished starting. *

* This method requires that {@link #isSupported()} returns {@code true}. */ public static void sendStartupNotification() throws IOException { notify("READY=1", "MAINPID=" + ProcessHandle.current().pid()); } /** * Tell the service manager that Yamcs is beginning its shutdown. *

* This method requires that {@link #isSupported()} returns {@code true}. */ public static void sendStoppingNotification() { try { notify("STOPPING=1"); } catch (IOException e) { // Ignore } } private static void notify(String... notifications) throws IOException { if (!isSupported()) { throw new IllegalStateException("NOTIFY_SOCKET environment variable is not set"); } var recipient = new DomainSocketAddress(NOTIFY_SOCKET); var group = new EpollEventLoopGroup(1); try { try { var bootstrap = new Bootstrap(); bootstrap.group(group).channel(EpollDomainDatagramChannel.class) .handler(new ChannelOutboundHandlerAdapter()); var file = File.createTempFile("netty", "dsocket"); file.delete(); var domainSocketAddress = new DomainSocketAddress(file); var channel = bootstrap.bind(domainSocketAddress).sync().channel(); if (log.isDebugEnabled()) { for (var notification : notifications) { log.debug("Writing: " + notification); } } var message = String.join("\n", notifications); var buf = Unpooled.copiedBuffer(message, StandardCharsets.UTF_8); var packet = new DomainDatagramPacket(buf, recipient); channel.writeAndFlush(packet).sync(); file.delete(); } finally { group.shutdownGracefully().sync(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } public static boolean isSupported() { return NOTIFY_SOCKET != null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy