/*
 * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.jmx.remote.internal;

import java.io.IOException;
import java.io.InterruptedIOException;

import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;

public abstract class ClientCommunicatorAdmin {
    private static volatile long threadNo = 1;

    public ClientCommunicatorAdmin(long period) {
        this.period = period;

        if (period > 0) {
            checker = new Checker();

            Thread t = new Thread(checker, "JMX client heartbeat " + ++threadNo);
            t.setDaemon(true);
            t.start();
        } else
            checker = null;
    }

    /**
     * Called by a client to inform of getting an IOException.
     */
    public void gotIOException (IOException ioe) throws IOException {
        restart(ioe);
    }

    /**
     * Called by this class to check a client connection.
     */
    protected abstract void checkConnection() throws IOException;

    /**
     * Tells a client to re-start again.
     */
    protected abstract void doStart() throws IOException;

    /**
     * Tells a client to stop because failing to call checkConnection.
     */
    protected abstract void doStop();

    /**
     * Terminates this object.
     */
    public void terminate() {
        synchronized(lock) {
            if (state == TERMINATED) {
                return;
            }

            state = TERMINATED;

            lock.notifyAll();

            if (checker != null)
                checker.stop();
        }
    }

    private void restart(IOException ioe) throws IOException {
        // check state
        synchronized(lock) {
            if (state == TERMINATED) {
                throw new IOException("The client has been closed.");
            } else if (state == FAILED) { // already failed to re-start by another thread
                throw ioe;
            } else if (state == RE_CONNECTING) {
                // restart process has been called by another thread
                // we need to wait
                while(state == RE_CONNECTING) {
                    try {
                        lock.wait();
                    } catch (InterruptedException ire) {
                        // be asked to give up
                        InterruptedIOException iioe = new InterruptedIOException(ire.toString());
                        EnvHelp.initCause(iioe, ire);

                        throw iioe;
                    }
                }

                if (state == TERMINATED) {
                    throw new IOException("The client has been closed.");
                } else if (state != CONNECTED) {
                    // restarted is failed by another thread
                    throw ioe;
                }
            } else {
                state = RE_CONNECTING;
                lock.notifyAll();
            }
        }

        // re-starting
        try {
            doStart();
            synchronized(lock) {
                if (state == TERMINATED) {
                    throw new IOException("The client has been closed.");
                }

                state = CONNECTED;

                lock.notifyAll();
            }

            return;
        } catch (Exception e) {
            logger.warning("restart", "Failed to restart: " + e);
            logger.debug("restart",e);

            synchronized(lock) {
                if (state == TERMINATED) {
                    throw new IOException("The client has been closed.");
                }

                state = FAILED;

                lock.notifyAll();
            }

            try {
                doStop();
            } catch (Exception eee) {
                // OK.
                // We know there is a problem.
            }

            terminate();

            throw ioe;
        }
    }

// --------------------------------------------------------------
// private varaibles
// --------------------------------------------------------------
    private class Checker implements Runnable {
        public void run() {
            myThread = Thread.currentThread();

            while (state != TERMINATED && !myThread.isInterrupted()) {
                try {
                    Thread.sleep(period);
                } catch (InterruptedException ire) {
                    // OK.
                    // We will check the state at the following steps
                }

                if (state == TERMINATED || myThread.isInterrupted()) {
                    break;
                }

                try {
                    checkConnection();
                } catch (Exception e) {
                    synchronized(lock) {
                        if (state == TERMINATED || myThread.isInterrupted()) {
                            break;
                        }
                    }

                    e = (Exception)EnvHelp.getCause(e);

                    if (e instanceof IOException &&
                        !(e instanceof InterruptedIOException)) {
                        try {
                            restart((IOException)e);
                        } catch (Exception ee) {
                            logger.warning("Checker-run",
                                           "Failed to check connection: "+ e);
                            logger.warning("Checker-run", "stopping");
                            logger.debug("Checker-run",e);

                            break;
                        }
                    } else {
                        logger.warning("Checker-run",
                                     "Failed to check the connection: " + e);
                        logger.debug("Checker-run",e);

                        // XXX stop checking?

                        break;
                    }
                }
            }

            if (logger.traceOn()) {
                logger.trace("Checker-run", "Finished.");
            }
        }

        private void stop() {
            if (myThread != null && myThread != Thread.currentThread()) {
                myThread.interrupt();
            }
        }

        private Thread myThread;
    }

// --------------------------------------------------------------
// private variables
// --------------------------------------------------------------
    private final Checker checker;
    private long period;

    // state
    private final static int CONNECTED = 0;
    private final static int RE_CONNECTING = 1;
    private final static int FAILED = 2;
    private final static int TERMINATED = 3;

    private int state = CONNECTED;

    private final int[] lock = new int[0];

    private static final ClassLogger logger =
        new ClassLogger("javax.management.remote.misc",
                        "ClientCommunicatorAdmin");
}
