View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements. See the NOTICE file distributed with this
6    * work for additional information regarding copyright ownership. The ASF
7    * licenses this file to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16   * License for the specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.hadoop.hbase.io.hfile.bucket;
20  
21  import static org.junit.Assert.assertArrayEquals;
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertNotNull;
24  
25  import java.io.File;
26  import java.io.IOException;
27  import java.nio.ByteBuffer;
28  import java.nio.channels.FileChannel;
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.junit.After;
34  import org.junit.Before;
35  import org.junit.Test;
36  import org.junit.experimental.categories.Category;
37  
38  /**
39   * Basic test for {@link FileIOEngine}
40   */
41  @Category(SmallTests.class)
42  public class TestFileIOEngine {
43  
44    private static final long TOTAL_CAPACITY = 6 * 1024 * 1024; // 6 MB
45    private static final String[] FILE_PATHS = {"testFileIOEngine1", "testFileIOEngine2",
46        "testFileIOEngine3"};
47    private static final long SIZE_PER_FILE = TOTAL_CAPACITY / FILE_PATHS.length; // 2 MB per File
48    private final static List<Long> boundaryStartPositions = new ArrayList<Long>();
49    private final static List<Long> boundaryStopPositions = new ArrayList<Long>();
50  
51    private FileIOEngine fileIOEngine;
52  
53    static {
54      boundaryStartPositions.add(0L);
55      for (int i = 1; i < FILE_PATHS.length; i++) {
56        boundaryStartPositions.add(SIZE_PER_FILE * i - 1);
57        boundaryStartPositions.add(SIZE_PER_FILE * i);
58        boundaryStartPositions.add(SIZE_PER_FILE * i + 1);
59      }
60      for (int i = 1; i < FILE_PATHS.length; i++) {
61        boundaryStopPositions.add(SIZE_PER_FILE * i - 1);
62        boundaryStopPositions.add(SIZE_PER_FILE * i);
63        boundaryStopPositions.add(SIZE_PER_FILE * i + 1);
64      }
65      boundaryStopPositions.add(SIZE_PER_FILE * FILE_PATHS.length - 1);
66    }
67  
68    @Before
69    public void setUp() throws IOException {
70      fileIOEngine = new FileIOEngine(TOTAL_CAPACITY, FILE_PATHS);
71    }
72  
73    @After
74    public void cleanUp() throws IOException {
75      fileIOEngine.shutdown();
76      for (String filePath : FILE_PATHS) {
77        File file = new File(filePath);
78        if (file.exists()) {
79          file.delete();
80        }
81      }
82    }
83  
84    @Test
85    public void testFileIOEngine() throws IOException {
86      for (int i = 0; i < 500; i++) {
87        int len = (int) Math.floor(Math.random() * 100) + 1;
88        long offset = (long) Math.floor(Math.random() * TOTAL_CAPACITY % (TOTAL_CAPACITY - len));
89        if (i < boundaryStartPositions.size()) {
90          // make the boundary start positon
91          offset = boundaryStartPositions.get(i);
92        } else if ((i - boundaryStartPositions.size()) < boundaryStopPositions.size()) {
93          // make the boundary stop positon
94          offset = boundaryStopPositions.get(i - boundaryStartPositions.size()) - len + 1;
95        } else if (i % 2 == 0) {
96          // make the cross-files block writing/reading
97          offset = Math.max(1, i % FILE_PATHS.length) * SIZE_PER_FILE - len / 2;
98        }
99        byte[] data1 = new byte[len];
100       for (int j = 0; j < data1.length; ++j) {
101         data1[j] = (byte) (Math.random() * 255);
102       }
103       byte[] data2 = new byte[len];
104       fileIOEngine.write(ByteBuffer.wrap(data1), offset);
105       fileIOEngine.read(ByteBuffer.wrap(data2), offset);
106       assertArrayEquals(data1, data2);
107     }
108   }
109 
110   @Test
111   public void testFileIOEngineHandlesZeroLengthInput() throws IOException {
112     byte[] data1 = new byte[0];
113 
114 
115     byte[] data2 = new byte[0];
116     fileIOEngine.write(ByteBuffer.wrap(data1), 0);
117     fileIOEngine.read(ByteBuffer.wrap(data2), 0);
118     assertArrayEquals(data1, data2);
119   }
120 
121   @Test
122   public void testClosedChannelException() throws IOException {
123     fileIOEngine.closeFileChannels();
124     int len = 5;
125     long offset = 0L;
126     byte[] data1 = new byte[len];
127     for (int j = 0; j < data1.length; ++j) {
128       data1[j] = (byte) (Math.random() * 255);
129     }
130     byte[] data2 = new byte[len];
131     fileIOEngine.write(ByteBuffer.wrap(data1), offset);
132     fileIOEngine.read(ByteBuffer.wrap(data2), offset);
133     assertArrayEquals(data1, data2);
134   }
135 
136   @Test
137   public void testRefreshFileConnectionClosesConnections() throws IOException {
138     FileChannel fileChannel = fileIOEngine.getFileChannels()[0];
139     assertNotNull(fileChannel);
140     fileIOEngine.refreshFileConnection(0);
141     assertFalse(fileChannel.isOpen());
142   }
143 }