/*
 * Copyright (c) 2010, 2011, 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.
 *
 * 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.
 */

/* @test
 * @bug 6979009
 * @summary Ensure ClosedByInterruptException is thrown when I/O operation
 *     interrupted by Thread.interrupt
 */

import java.io.*;
import java.util.Random;
import java.nio.ByteBuffer;
import java.nio.channels.*;

public class ClosedByInterrupt {

    static final int K = 1024;
    static final Random rand = new Random();

    static volatile boolean failed;

    public static void main(String[] args) throws Exception {
        File f = File.createTempFile("blah", null);
        f.deleteOnExit();

        // create 1MB file.
        byte[] b = new byte[K*K];
        rand.nextBytes(b);
        ByteBuffer bb = ByteBuffer.wrap(b);
        try (FileChannel fc = new FileOutputStream(f).getChannel()) {
            while (bb.hasRemaining())
                fc.write(bb);
        }

        // test with 1-16 concurrent threads
        for (int i=1; i<=16; i++) {
            System.out.format("%d thread(s)%n", i);
            test(f, i);
            if (failed)
                break;
        }

        if (failed)
            throw new RuntimeException("Test failed");
    }

    /**
     * Starts "nThreads" that do I/O on the given file concurrently. Continuously
     * interrupts one of the threads to cause the file to be closed and
     * ClosedByInterruptException to be thrown. The other threads should "fail" with
     * ClosedChannelException (or the more specific AsynchronousCloseException).
     */
    static void test(File f, int nThreads) throws Exception {
        try (FileChannel fc = new RandomAccessFile(f, "rwd").getChannel()) {
            Thread[] threads = new Thread[nThreads];

            // start threads
            for (int i=0; i<nThreads; i++) {
                boolean interruptible = (i==0);
                ReaderWriter task = new ReaderWriter(fc, interruptible);
                Thread t = new Thread(task);
                t.start();
                threads[i] = t;
            }

            // give time for threads to start
            Thread.sleep(500 + rand.nextInt(1000));

            // interrupt thread until channel is closed
            while (fc.isOpen()) {
                threads[0].interrupt();
                Thread.sleep(rand.nextInt(50));
            }

            // wait for test to finish
            for (int i=0; i<nThreads; i++) {
                threads[i].join();
            }
        }
    }

    /**
     * A task that continuously reads or writes to random areas of a file
     * until the channel is closed. An "interruptible" task expects the
     * channel to be closed by an interupt, a "non-interruptible" thread
     * does not.
     */
    static class ReaderWriter implements Runnable {
        final FileChannel fc;
        final boolean interruptible;
        final boolean writer;

        ReaderWriter(FileChannel fc, boolean interruptible) {
            this.fc = fc;
            this.interruptible = interruptible;
            this.writer = rand.nextBoolean();
        }

        public void run() {
            ByteBuffer bb = ByteBuffer.allocate(K);
            if (writer)
                rand.nextBytes(bb.array());

            try {
                for (;;) {
                    long position = rand.nextInt(K*K - bb.capacity());
                    if (writer) {
                        bb.position(0).limit(bb.capacity());
                        fc.write(bb, position);
                    } else {
                        bb.clear();
                        fc.read(bb, position);
                    }
                    if (!interruptible) {
                        // give the interruptible thread a chance
                        try {
                            Thread.sleep(rand.nextInt(50));
                        } catch (InterruptedException e) {
                            unexpected(e);
                        }
                    }
                }
            } catch (ClosedByInterruptException e) {
                if (interruptible) {
                    if (Thread.interrupted()) {
                        expected(e + " thrown and interrupt status set");
                    } else {
                        unexpected(e + " thrown but interrupt status not set");
                    }
                } else {
                    unexpected(e);
                }
            } catch (ClosedChannelException e) {
                if (interruptible) {
                    unexpected(e);
                } else {
                    expected(e);
                }
            } catch (Exception e) {
                unexpected(e);
            }
        }
    }

    static void expected(Exception e) {
        System.out.format("%s (expected)%n", e);
    }

    static void expected(String msg) {
        System.out.format("%s (expected)%n", msg);
    }

    static void unexpected(Exception e) {
        System.err.format("%s (not expected)%n", e);
        failed = true;
    }

    static void unexpected(String msg) {
        System.err.println(msg);
        failed = true;
    }
}
