List of usage examples for java.util LinkedList wait
public final native void wait(long timeoutMillis) throws InterruptedException;
From source file:org.opennms.netmgt.eventd.adaptors.tcp.TcpStreamHandler.java
/** * 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.//from w w w. j a va 2 s .c om */ @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 List<Event> okEvents = new ArrayList<Event>(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(), "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"); }