use of org.opennms.netmgt.xml.event.EventReceipt in project opennms by OpenNMS.
the class UdpUuidSender method run.
/**
* <p>run</p>
*/
@Override
public void run() {
// get the context
m_context = Thread.currentThread();
Logging.putPrefix(m_logPrefix);
if (m_stop) {
LOG.debug("Stop flag set before thread started, exiting");
return;
} else {
LOG.debug("Thread context started");
}
/*
* This loop is labeled so that it can be
* exited quickly when the thread is interrupted.
*/
List<UdpReceivedEvent> eventHold = new ArrayList<UdpReceivedEvent>(30);
Map<UdpReceivedEvent, EventReceipt> receipts = new HashMap<UdpReceivedEvent, EventReceipt>();
RunLoop: while (!m_stop) {
LOG.debug("Waiting on event receipts to be generated");
synchronized (m_eventUuidsOut) {
// wait for an event to show up. wait in 1 second intervals
while (m_eventUuidsOut.isEmpty()) {
try {
// use wait instead of sleep to release the lock!
m_eventUuidsOut.wait(1000);
} catch (InterruptedException ie) {
LOG.debug("Thread context interrupted");
break RunLoop;
}
}
eventHold.addAll(m_eventUuidsOut);
m_eventUuidsOut.clear();
}
LOG.debug("Received {} event receipts to process", eventHold.size());
LOG.debug("Processing receipts");
// build an event-receipt
for (UdpReceivedEvent re : eventHold) {
for (Event e : re.getAckedEvents()) {
if (e.getUuid() != null) {
EventReceipt receipt = receipts.get(re);
if (receipt == null) {
receipt = new EventReceipt();
receipts.put(re, receipt);
}
receipt.addUuid(e.getUuid());
}
}
}
eventHold.clear();
LOG.debug("Event receipts sorted, transmitting receipts");
// turn them into XML and send it out the socket
for (Map.Entry<UdpReceivedEvent, EventReceipt> entry : receipts.entrySet()) {
UdpReceivedEvent re = entry.getKey();
EventReceipt receipt = entry.getValue();
StringWriter writer = new StringWriter();
try {
JaxbUtils.marshal(receipt, writer);
} catch (DataAccessException e) {
LOG.warn("Failed to build event receipt for agent {}:{}", InetAddressUtils.str(re.getSender()), re.getPort(), e);
}
String xml = writer.getBuffer().toString();
try {
byte[] xml_bytes = xml.getBytes(StandardCharsets.US_ASCII);
DatagramPacket pkt = new DatagramPacket(xml_bytes, xml_bytes.length, re.getSender(), re.getPort());
LOG.debug("Transmitting receipt to destination {}:{}", InetAddressUtils.str(re.getSender()), re.getPort());
m_dgSock.send(pkt);
synchronized (m_handlers) {
for (EventHandler handler : m_handlers) {
try {
handler.receiptSent(receipt);
} catch (Throwable t) {
LOG.warn("Error processing event receipt", t);
}
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Receipt transmitted OK {");
LOG.debug(xml);
LOG.debug("}");
}
} catch (IOException e) {
LOG.warn("Failed to send packet to host {}:{}", InetAddressUtils.str(re.getSender()), re.getPort(), e);
}
}
receipts.clear();
}
LOG.debug("Context finished, returning");
}
use of org.opennms.netmgt.xml.event.EventReceipt in project opennms by OpenNMS.
the class TcpStreamHandler method run.
/**
* The main execution context for processing a remote XML document. Once the
* document is processed and an event receipt is returned to the client the
* thread will exit.
*/
@Override
public void run() {
// get the context and stop if necessary
m_context = Thread.currentThread();
synchronized (m_context) {
m_context.notifyAll();
}
// check the stop flag
if (m_stop) {
LOG.debug("The stop flag was set prior to thread entry, closing connection");
try {
m_connection.close();
} catch (final IOException e) {
LOG.error("An error occured while closing the connection.", e);
}
LOG.debug("Thread context exiting");
return;
}
// Log the startup of this stream handler
final InetAddress sender = m_connection.getInetAddress();
LOG.debug("Event Log Stream Handler Started for {}", sender);
/*
* This linked list is used to exchange
* instances of PipedOutputStreams. Whenever a
* pipe output stream is recovered it must be
* signaled to inform the EOT thread of the
* ability to write to the pipe. Also, when
* the descriptor is close a EOFException is
* passed on the list.
*/
final LinkedList<Object> pipeXchange = new LinkedList<Object>();
final TcpRecordHandler chunker = new TcpRecordHandler(m_connection, pipeXchange);
final Thread tchunker = new Thread(chunker, "TCPRecord Chunker[" + InetAddressUtils.str(m_connection.getInetAddress()) + ":" + m_connection.getPort() + "]");
synchronized (tchunker) {
tchunker.start();
try {
tchunker.wait();
} catch (final InterruptedException e) {
LOG.error("The thread was interrupted.", e);
}
}
MAINLOOP: while (!m_stop && m_parent.getStatus() != Fiber.STOP_PENDING && m_parent.getStatus() != Fiber.STOPPED && m_recsPerConn != 0) {
// get a new pipe input stream
PipedInputStream pipeIn = null;
synchronized (pipeXchange) {
while (pipeXchange.isEmpty()) {
if (chunker.isAlive()) {
try {
pipeXchange.wait(500);
} catch (final InterruptedException e) {
LOG.error("The thread was interrupted.", e);
break MAINLOOP;
}
} else {
break MAINLOOP;
}
}
// if an exception occured then just exit the BAL (Big Ass Loop)
final Object o = pipeXchange.removeFirst();
if (o instanceof Throwable) {
break MAINLOOP;
}
// construct the other end of the pipe
try {
pipeIn = new PipedInputStream((PipedOutputStream) o);
} catch (final IOException e) {
LOG.error("An I/O exception occured construction a record reader.", e);
break MAINLOOP;
}
// signal that we got the stream
synchronized (o) {
o.notify();
}
}
// decrement the record count if greater than zero
m_recsPerConn -= (m_recsPerConn > 0 ? 1 : 0);
// convert the pipe input stream into a buffered input stream
final InputStream stream = new BufferedInputStream(pipeIn);
// Unmarshal the XML document
Log eLog = null;
boolean doCleanup = false;
try {
eLog = JaxbUtils.unmarshal(Log.class, new InputSource(stream));
LOG.debug("Event record converted");
} catch (final Exception e) {
LOG.error("Could not unmarshall the XML record.", e);
doCleanup = true;
} finally {
if (stream != null) {
IOUtils.closeQuietly(stream);
}
}
// clean up the data on the current pipe if necessary
if (doCleanup) {
/*
* Cleanup a failed record. Need to read
* the remaining bytes from the other thread
* to synchronize up. The other thread might
* be blocked writing.
*/
try {
while (stream.read() != -1) {
/* do nothing */
;
}
} catch (final IOException e) {
// do nothing
}
// start from the top!
continue MAINLOOP;
}
// Now that we have a list of events, process them
final Event[] events = eLog.getEvents().getEvent();
// sort the events by time
Arrays.sort(events, new Comparator<Event>() {
@Override
public int compare(final Event e1, final Event e2) {
final boolean e1t = (e1.getTime() != null);
final boolean e2t = (e2.getTime() != null);
if (e1t && !e2t) {
return 1;
} else if (!e1t && e2t) {
return -1;
} else if (!e1t && !e2t) {
return 0;
}
Date de1 = e1.getTime();
Date de2 = e2.getTime();
if (de1 != null && de2 != null) {
return (int) (de1.getTime() - de2.getTime());
} else if (de1 == null && de2 != null) {
return -1;
} else if (de1 != null && de2 == null) {
return 1;
} else {
return 0;
}
}
});
// process the events
if (events != null && events.length != 0) {
final Collection<Event> okEvents = new LinkedHashSet<>(events.length);
/*
* This synchronization loop will hold onto the lock
* for a while. If the handlers are going to change
* often, which is shouldn't then might want to consider
* duplicating the handlers into an array before processing
* the events.
*
* Doing the synchronization in the outer loop prevents spending
* lots of cycles doing synchronization when it should not
* normally be necesary.
*/
synchronized (m_handlers) {
for (final EventHandler hdl : m_handlers) {
/*
* get the handler and then have it process all
* the events in the document before moving to the
* next event handler.
*/
for (final Event event : events) {
/*
* Process the event and log any errors,
* but don't die on these errors
*/
try {
LOG.debug("handling event: {}", event);
// shortcut and BOTH parts MUST execute!
if (hdl.processEvent(event)) {
if (!okEvents.contains(event)) {
okEvents.add(event);
}
}
} catch (final Throwable t) {
LOG.warn("An exception occured while processing an event.", t);
}
}
}
}
// Now process the good events and send a receipt message
boolean hasReceipt = false;
final EventReceipt receipt = new EventReceipt();
for (final Event event : okEvents) {
if (event.getUuid() != null) {
receipt.addUuid(event.getUuid());
hasReceipt = true;
}
}
if (hasReceipt) {
// Transform it to XML and send it to the socket in one call
try {
final Writer writer = new BufferedWriter(new OutputStreamWriter(m_connection.getOutputStream(), StandardCharsets.UTF_8));
JaxbUtils.marshal(receipt, writer);
writer.flush();
synchronized (m_handlers) {
for (final EventHandler hdl : m_handlers) {
/*
* Get the handler and then have it process all
* the events in the document before moving to
* the next event hander.
*/
try {
hdl.receiptSent(receipt);
} catch (final Throwable t) {
LOG.warn("An exception occured while processing an event receipt.", t);
}
}
}
if (LOG.isDebugEnabled()) {
try {
final StringWriter swriter = new StringWriter();
JaxbUtils.marshal(receipt, swriter);
LOG.debug("Sent Event Receipt {");
LOG.debug(swriter.getBuffer().toString());
LOG.debug("}");
} catch (final Throwable e) {
LOG.error("An error occured during marshalling of event receipt for the log.", e);
}
}
} catch (final IOException e) {
LOG.warn("Failed to send event-receipt XML document.", e);
break MAINLOOP;
}
}
} else {
LOG.debug("The agent sent an empty event stream");
}
}
try {
LOG.debug("stopping record handler");
chunker.stop();
LOG.debug("record handler stopped");
} catch (final InterruptedException e) {
LOG.warn("The thread was interrupted while trying to close the record handler.", e);
}
// regardless of any errors, be sure to release the socket.
try {
LOG.debug("closing connnection");
m_connection.close();
LOG.debug("connnection closed ");
} catch (final IOException e) {
LOG.warn("An I/O exception occured while closing the TCP/IP connection.", e);
}
LOG.debug("Thread exiting");
}
Aggregations