Example usage for java.util LinkedList wait

List of usage examples for java.util LinkedList wait

Introduction

In this page you can find the example usage for java.util LinkedList wait.

Prototype

public final native void wait(long timeoutMillis) throws InterruptedException;

Source Link

Document

Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

Usage

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");
}