1 /*
2  * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @bug 4638365
26  * @summary Test FileChannel.transferFrom and transferTo for 4GB files
27  * @run testng/timeout=300 Transfer4GBFile
28  */
29 
30 import java.io.BufferedWriter;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.OutputStreamWriter;
36 import java.io.PrintStream;
37 import java.io.RandomAccessFile;
38 import java.nio.ByteBuffer;
39 import java.nio.channels.FileChannel;
40 import java.nio.file.StandardOpenOption;
41 import java.nio.file.FileAlreadyExistsException;
42 import java.util.concurrent.TimeUnit;
43 
44 import org.testng.annotations.Test;
45 
46 public class Transfer4GBFile {
47 
48     private static PrintStream err = System.err;
49     private static PrintStream out = System.out;
50 
51     // Test transferTo with large file
52     @Test
xferTest04()53     public void xferTest04() throws Exception { // for bug 4638365
54         File source = File.createTempFile("blah", null);
55         source.deleteOnExit();
56         long testSize = ((long)Integer.MAX_VALUE) * 2;
57         initTestFile(source, 10);
58         RandomAccessFile raf = new RandomAccessFile(source, "rw");
59         FileChannel fc = raf.getChannel();
60         out.println("  Writing large file...");
61         long t0 = System.nanoTime();
62         fc.write(ByteBuffer.wrap("Use the source!".getBytes()), testSize - 40);
63         long t1 = System.nanoTime();
64         out.printf("  Wrote large file in %d ns (%d ms) %n",
65             t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
66 
67         fc.close();
68         raf.close();
69 
70         File sink = File.createTempFile("sink", null);
71         sink.deleteOnExit();
72 
73         FileInputStream fis = new FileInputStream(source);
74         FileChannel sourceChannel = fis.getChannel();
75 
76         raf = new RandomAccessFile(sink, "rw");
77         FileChannel sinkChannel = raf.getChannel();
78 
79         long bytesWritten = sourceChannel.transferTo(testSize -40, 10,
80                                                      sinkChannel);
81         if (bytesWritten != 10) {
82             throw new RuntimeException("Transfer test 4 failed " +
83                                        bytesWritten);
84         }
85         sourceChannel.close();
86         sinkChannel.close();
87 
88         source.delete();
89         sink.delete();
90     }
91 
92     // Test transferFrom with large file
93     @Test
xferTest05()94     public void xferTest05() throws Exception { // for bug 4638365
95         // Create a source file & large sink file for the test
96         File source = File.createTempFile("blech", null);
97         source.deleteOnExit();
98         initTestFile(source, 100);
99 
100         // Create the sink file as a sparse file if possible
101         File sink = null;
102         FileChannel fc = null;
103         while (fc == null) {
104             sink = File.createTempFile("sink", null);
105             // re-create as a sparse file
106             sink.delete();
107             try {
108                 fc = FileChannel.open(sink.toPath(),
109                                       StandardOpenOption.CREATE_NEW,
110                                       StandardOpenOption.WRITE,
111                                       StandardOpenOption.SPARSE);
112             } catch (FileAlreadyExistsException ignore) {
113                 // someone else got it
114             }
115         }
116         sink.deleteOnExit();
117 
118         long testSize = ((long)Integer.MAX_VALUE) * 2;
119         try {
120             out.println("  Writing large file...");
121             long t0 = System.nanoTime();
122             fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
123                      testSize - 40);
124             long t1 = System.nanoTime();
125             out.printf("  Wrote large file in %d ns (%d ms) %n",
126             t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
127         } catch (IOException e) {
128             // Can't set up the test, abort it
129             err.println("xferTest05 was aborted.");
130             return;
131         } finally {
132             fc.close();
133         }
134 
135         // Get new channels for the source and sink and attempt transfer
136         FileChannel sourceChannel = new FileInputStream(source).getChannel();
137         try {
138             FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
139             try {
140                 long bytesWritten = sinkChannel.transferFrom(sourceChannel,
141                                                              testSize - 40, 10);
142                 if (bytesWritten != 10) {
143                     throw new RuntimeException("Transfer test 5 failed " +
144                                                bytesWritten);
145                 }
146             } finally {
147                 sinkChannel.close();
148             }
149         } finally {
150             sourceChannel.close();
151         }
152 
153         source.delete();
154         sink.delete();
155     }
156 
157     /**
158      * Creates file blah of specified size in bytes.
159      */
initTestFile(File blah, long size)160     private static void initTestFile(File blah, long size) throws Exception {
161         if (blah.exists())
162             blah.delete();
163         FileOutputStream fos = new FileOutputStream(blah);
164         BufferedWriter awriter
165             = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
166 
167         for(int i=0; i<size; i++) {
168             awriter.write("e");
169         }
170         awriter.flush();
171         awriter.close();
172     }
173 }
174