MappedReadBuffer.java revision 2224:2a8815d86b93
1181624Skmacy/*
2181624Skmacy * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
3181624Skmacy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4183375Skmacy *
5181624Skmacy * This code is free software; you can redistribute it and/or modify it
6181624Skmacy * under the terms of the GNU General Public License version 2 only, as
7181624Skmacy * published by the Free Software Foundation.  Oracle designates this
8181624Skmacy * particular file as subject to the "Classpath" exception as provided
9181624Skmacy * by Oracle in the LICENSE file that accompanied this code.
10181624Skmacy *
11181624Skmacy * This code is distributed in the hope that it will be useful, but WITHOUT
12181624Skmacy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13181624Skmacy * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14181624Skmacy * version 2 for more details (a copy is included in the LICENSE file that
15181624Skmacy * accompanied this code).
16181624Skmacy *
17181624Skmacy * You should have received a copy of the GNU General Public License version
18181624Skmacy * 2 along with this work; if not, write to the Free Software Foundation,
19181624Skmacy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20181624Skmacy *
21181624Skmacy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22181624Skmacy * or visit www.oracle.com if you need additional information or have any
23181624Skmacy * questions.
24181624Skmacy */
25181624Skmacy
26181624Skmacy
27181624Skmacy/*
28181624Skmacy * The Original Code is HAT. The Initial Developer of the
29181624Skmacy * Original Code is Bill Foote, with contributions from others
30181624Skmacy * at JavaSoft/Sun.
31181624Skmacy */
32181624Skmacy
33181624Skmacypackage jdk.test.lib.hprof.parser;
34181624Skmacy
35181624Skmacyimport java.io.IOException;
36181624Skmacyimport java.io.RandomAccessFile;
37181624Skmacyimport java.nio.MappedByteBuffer;
38181624Skmacyimport java.nio.channels.FileChannel;
39181624Skmacy
40181624Skmacy/**
41181624Skmacy * Implementation of ReadBuffer using mapped file buffer
42181624Skmacy *
43181624Skmacy * @author A. Sundararajan
44181624Skmacy */
45181624Skmacyclass MappedReadBuffer implements ReadBuffer {
46181624Skmacy    private MappedByteBuffer buf;
47181624Skmacy    private RandomAccessFile file;
48181624Skmacy
49181624Skmacy    MappedReadBuffer(RandomAccessFile file, MappedByteBuffer buf) {
50181624Skmacy        this.file = file;
51181624Skmacy        this.buf = buf;
52181624Skmacy    }
53181624Skmacy
54181624Skmacy    /**
55181624Skmacy     * Factory method to create correct ReadBuffer for a given file.
56181624Skmacy     *
57181624Skmacy     * The initial purpose of this method was to choose how to read hprof file for parsing
58181624Skmacy     * depending on the size of the file and the system property 'jhat.disableFileMap':
59181624Skmacy     * "If file size is more than 2 GB and when file mapping is configured (default),
60181624Skmacy     * use mapped file reader".
61181624Skmacy     *
62181624Skmacy     * However, it has been discovered a problem with this approach.
63181624Skmacy     * Creating java.nio.MappedByteBuffer from inside the test leads to hprof file
64181624Skmacy     * is locked on Windows until test process dies since there is no good way to
65181624Skmacy     * release this resource.
66181624Skmacy     *
67181624Skmacy     * java.nio.MappedByteBuffer will be used only if 'jhat.enableFileMap' is set to true.
68181624Skmacy     * Per default 'jhat.enableFileMap' is not set.
69181624Skmacy     */
70181624Skmacy    static ReadBuffer create(RandomAccessFile file) throws IOException {
71181624Skmacy        if (canUseFileMap()) {
72181624Skmacy            MappedByteBuffer buf;
73181624Skmacy            try {
74181624Skmacy                FileChannel ch = file.getChannel();
75181624Skmacy                long size = ch.size();
76181624Skmacy                buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size);
77181624Skmacy                ch.close();
78181624Skmacy                return new MappedReadBuffer(file, buf);
79181624Skmacy            } catch (IOException exp) {
80181624Skmacy                exp.printStackTrace();
81181624Skmacy                System.err.println("File mapping failed, will use direct read");
82181624Skmacy                // fall through
83181624Skmacy            }
84181624Skmacy        } // else fall through
85181624Skmacy        return new FileReadBuffer(file);
86181624Skmacy    }
87181624Skmacy
88181624Skmacy    /**
89181624Skmacy     * Set system property 'jhat.enableFileMap' to 'true' to enable file mapping.
90181624Skmacy     */
91181624Skmacy    private static boolean canUseFileMap() {
92181624Skmacy        String prop = System.getProperty("jhat.enableFileMap");
93181624Skmacy        return prop != null && prop.equals("true");
94181624Skmacy    }
95181624Skmacy
96181624Skmacy    private void seek(long pos) throws IOException {
97181624Skmacy        assert pos <= Integer.MAX_VALUE :  "position overflow";
98181624Skmacy        buf.position((int)pos);
99181624Skmacy    }
100181624Skmacy
101181624Skmacy    public synchronized void get(long pos, byte[] res) throws IOException {
102181624Skmacy        seek(pos);
103181624Skmacy        buf.get(res);
104181624Skmacy    }
105181624Skmacy
106181624Skmacy    public synchronized char getChar(long pos) throws IOException {
107181624Skmacy        seek(pos);
108181624Skmacy        return buf.getChar();
109181624Skmacy    }
110181624Skmacy
111181624Skmacy    public synchronized byte getByte(long pos) throws IOException {
112181624Skmacy        seek(pos);
113183375Skmacy        return buf.get();
114183375Skmacy    }
115183375Skmacy
116183375Skmacy    public synchronized short getShort(long pos) throws IOException {
117183375Skmacy        seek(pos);
118183375Skmacy        return buf.getShort();
119183375Skmacy    }
120183375Skmacy
121183375Skmacy    public synchronized int getInt(long pos) throws IOException {
122183375Skmacy        seek(pos);
123181624Skmacy        return buf.getInt();
124181624Skmacy    }
125181624Skmacy
126181624Skmacy    public synchronized long getLong(long pos) throws IOException {
127181624Skmacy        seek(pos);
128181624Skmacy        return buf.getLong();
129181624Skmacy    }
130181624Skmacy
131181624Skmacy    @Override
132181624Skmacy    public void close() throws Exception {
133181624Skmacy        file.close();
134181624Skmacy    }
135181624Skmacy
136181624Skmacy}
137181624Skmacy