View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.giraph.utils;
20  
21  import java.io.IOException;
22  import java.lang.reflect.Field;
23  
24  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_BOOLEAN;
25  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_BYTE;
26  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_CHAR;
27  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_SHORT;
28  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_INT;
29  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_LONG;
30  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_FLOAT;
31  import static org.apache.giraph.utils.ByteUtils.SIZE_OF_DOUBLE;
32  
33  /**
34   * Byte array input stream that uses Unsafe methods to deserialize
35   * much faster
36   */
37  public class UnsafeArrayReads extends UnsafeReads {
38    /** Access to the unsafe class */
39    private static final sun.misc.Unsafe UNSAFE;
40    static {
41      try {
42        Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
43        field.setAccessible(true);
44        UNSAFE = (sun.misc.Unsafe) field.get(null);
45        // Checkstyle exception due to needing to check if unsafe is allowed
46        // CHECKSTYLE: stop IllegalCatch
47      } catch (Exception e) {
48        // CHECKSTYLE: resume IllegalCatch
49        throw new RuntimeException("UnsafeArrayReads: Failed to " +
50            "get unsafe", e);
51      }
52    }
53    /** Offset of a byte array */
54    private static final long BYTE_ARRAY_OFFSET  =
55        UNSAFE.arrayBaseOffset(byte[].class);
56  
57    /**
58     * Constructor
59     *
60     * @param buf Buffer to read from
61     */
62    public UnsafeArrayReads(byte[] buf) {
63      super(buf.length);
64      this.buffer = buf;
65    }
66  
67    /**
68     * Constructor.
69     *
70     * @param buf Buffer to read from
71     * @param offset Offsetin the buffer to start reading from
72     * @param length Max length of the buffer to read
73     */
74    public UnsafeArrayReads(byte[] buf, int offset, int length) {
75      super(offset, length);
76      this.buffer = buf;
77    }
78  
79    @Override
80    public int available() {
81      return (int) (limit - position);
82    }
83  
84    @Override
85    public boolean endOfInput() {
86      return available() == 0;
87    }
88  
89  
90    @Override
91    public int getPos() {
92      return (int) position;
93    }
94  
95    @Override
96    public void readFully(byte[] b) throws IOException {
97      require(b.length);
98      System.arraycopy(buffer, (int) position, b, 0, b.length);
99      position += b.length;
100   }
101 
102   @Override
103   public void readFully(byte[] b, int off, int len) throws IOException {
104     require(len);
105     System.arraycopy(buffer, (int) position, b, off, len);
106     position += len;
107   }
108 
109   @Override
110   public boolean readBoolean() {
111     require(SIZE_OF_BOOLEAN);
112     boolean value = UNSAFE.getBoolean(buffer,
113         BYTE_ARRAY_OFFSET + position);
114     position += SIZE_OF_BOOLEAN;
115     return value;
116   }
117 
118   @Override
119   public byte readByte() {
120     require(SIZE_OF_BYTE);
121     byte value = UNSAFE.getByte(buffer,
122         BYTE_ARRAY_OFFSET + position);
123     position += SIZE_OF_BYTE;
124     return value;
125   }
126 
127   @Override
128   public int readUnsignedByte() throws IOException {
129     return (short) (readByte() & 0xFF);
130   }
131 
132   @Override
133   public short readShort() {
134     require(SIZE_OF_SHORT);
135     short value = UNSAFE.getShort(buffer,
136         BYTE_ARRAY_OFFSET + position);
137     position += SIZE_OF_SHORT;
138     return value;
139   }
140 
141   @Override
142   public int readUnsignedShort() throws IOException {
143     return readShort() & 0xFFFF;
144   }
145 
146   @Override
147   public char readChar() {
148     require(SIZE_OF_CHAR);
149     char value = UNSAFE.getChar(buffer,
150         BYTE_ARRAY_OFFSET + position);
151     position += SIZE_OF_CHAR;
152     return value;
153   }
154 
155   @Override
156   public int readInt() {
157     require(SIZE_OF_INT);
158     int value = UNSAFE.getInt(buffer,
159         BYTE_ARRAY_OFFSET + position);
160     position += SIZE_OF_INT;
161     return value;
162   }
163 
164   @Override
165   public long readLong() {
166     require(SIZE_OF_LONG);
167     long value = UNSAFE.getLong(buffer,
168         BYTE_ARRAY_OFFSET + position);
169     position += SIZE_OF_LONG;
170     return value;
171   }
172 
173   @Override
174   public float readFloat() {
175     require(SIZE_OF_FLOAT);
176     float value = UNSAFE.getFloat(buffer,
177         BYTE_ARRAY_OFFSET + position);
178     position += SIZE_OF_FLOAT;
179     return value;
180   }
181 
182   @Override
183   public double readDouble() {
184     require(SIZE_OF_DOUBLE);
185     double value = UNSAFE.getDouble(buffer,
186         BYTE_ARRAY_OFFSET + position);
187     position += SIZE_OF_DOUBLE;
188     return value;
189   }
190 
191   /**
192    * Get an int at an arbitrary position in a byte[]
193    *
194    * @param buf Buffer to get the int from
195    * @param pos Position in the buffer to get the int from
196    * @return Int at the buffer position
197    */
198   public static int getInt(byte[] buf, int pos) {
199     return UNSAFE.getInt(buf,
200         BYTE_ARRAY_OFFSET + pos);
201   }
202 }