View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  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,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.util;
20  
21  import org.apache.hadoop.conf.Configuration;
22  import org.apache.hadoop.fs.FileSystem;
23  import org.apache.hadoop.fs.Path;
24  import org.apache.hadoop.hbase.Cell;
25  import org.apache.hadoop.hbase.KeyValue;
26  import org.apache.hadoop.hbase.Tag;
27  import org.apache.hadoop.hbase.TagType;
28  import org.apache.hadoop.hbase.client.Result;
29  import org.apache.hadoop.hbase.client.ResultScanner;
30  import org.apache.hadoop.hbase.client.Scan;
31  import org.apache.hadoop.hbase.client.Table;
32  import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
33  import org.apache.hadoop.hbase.io.hfile.CacheConfig;
34  import org.apache.hadoop.hbase.io.hfile.HFile;
35  import org.apache.hadoop.hbase.io.hfile.HFileContext;
36  import org.apache.hadoop.hbase.io.hfile.HFileContextBuilder;
37  import org.apache.hadoop.hbase.regionserver.StoreFile;
38  
39  import java.io.IOException;
40  import java.util.ArrayList;
41  import java.util.List;
42  
43  import static org.junit.Assert.assertArrayEquals;
44  import static org.junit.Assert.fail;
45  
46  /**
47   * Utility class for HFile-related testing.
48   */
49  public class HFileTestUtil {
50  
51    /**
52     * Create an HFile with the given number of rows between a given
53     * start key and end key @ family:qualifier.  The value will be the key value.
54     * This file will not have tags.
55     */
56    public static void createHFile(
57        Configuration configuration,
58        FileSystem fs, Path path,
59        byte[] family, byte[] qualifier,
60        byte[] startKey, byte[] endKey, int numRows) throws IOException {
61        createHFile(configuration, fs, path, DataBlockEncoding.NONE, family, qualifier,
62          startKey, endKey, numRows, false);
63    }
64  
65    /**
66     * Create an HFile with the given number of rows between a given
67     * start key and end key @ family:qualifier.  The value will be the key value.
68     * This file will use certain data block encoding algorithm.
69     */
70    public static void createHFileWithDataBlockEncoding(
71        Configuration configuration,
72        FileSystem fs, Path path, DataBlockEncoding encoding,
73        byte[] family, byte[] qualifier,
74        byte[] startKey, byte[] endKey, int numRows) throws IOException {
75        createHFile(configuration, fs, path, encoding, family, qualifier, startKey, endKey,
76          numRows, false);
77    }
78  
79    /**
80     * Create an HFile with the given number of rows between a given
81     * start key and end key @ family:qualifier.  The value will be the key value.
82     * This cells will also have a tag whose value is the key.
83     */
84    public static void createHFileWithTags(
85        Configuration configuration,
86        FileSystem fs, Path path,
87        byte[] family, byte[] qualifier,
88        byte[] startKey, byte[] endKey, int numRows) throws IOException {
89        createHFile(configuration, fs, path, DataBlockEncoding.NONE, family, qualifier,
90          startKey, endKey, numRows, true);
91    }
92  
93    /**
94     * Create an HFile with the given number of rows between a given
95     * start key and end key @ family:qualifier.
96     * If withTag is true, we add the rowKey as the tag value for
97     * tagtype ACL_TAG_TYPE
98     */
99    public static void createHFile(
100       Configuration configuration,
101       FileSystem fs, Path path, DataBlockEncoding encoding,
102       byte[] family, byte[] qualifier,
103       byte[] startKey, byte[] endKey, int numRows, boolean withTag) throws IOException {
104     HFileContext meta = new HFileContextBuilder()
105         .withIncludesTags(withTag)
106         .withDataBlockEncoding(encoding)
107         .withColumnFamily(family)
108         .build();
109     HFile.Writer writer = HFile.getWriterFactory(configuration, new CacheConfig(configuration))
110         .withPath(fs, path)
111         .withFileContext(meta)
112         .create();
113     long now = System.currentTimeMillis();
114     try {
115       // subtract 2 since iterateOnSplits doesn't include boundary keys
116       for (byte[] key : Bytes.iterateOnSplits(startKey, endKey, numRows - 2)) {
117         KeyValue kv = new KeyValue(key, family, qualifier, now, key);
118         if (withTag) {
119           // add a tag.  Arbitrarily chose mob tag since we have a helper already.
120           List<Tag> tags = new ArrayList<Tag>();
121           tags.add(new Tag(TagType.ACL_TAG_TYPE, key));
122           kv = new KeyValue(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength(),
123               kv.getFamilyArray(), kv.getFamilyOffset(), kv.getFamilyLength(),
124               kv.getQualifierArray(), kv.getQualifierOffset(), kv.getQualifierLength(),
125               kv.getTimestamp(), KeyValue.Type.Put, kv.getValueArray(), kv.getValueOffset(),
126               kv.getValueLength(), tags);
127 
128           // verify that the kv has the tag.
129           byte[] ta = kv.getTagsArray();
130           int toff = kv.getTagsOffset();
131           int tlen = kv.getTagsLength();
132           Tag t = Tag.getTag(ta, toff, tlen, TagType.ACL_TAG_TYPE);
133           if (t == null) {
134             throw new IllegalStateException("Tag didn't stick to KV " + kv.toString());
135           }
136         }
137         writer.append(kv);
138       }
139     } finally {
140       writer.appendFileInfo(StoreFile.BULKLOAD_TIME_KEY,
141           Bytes.toBytes(System.currentTimeMillis()));
142       writer.close();
143     }
144   }
145 
146   /**
147    * This verifies that each cell has a tag that is equal to its rowkey name.  For this to work
148    * the hbase instance must have HConstants.RPC_CODEC_CONF_KEY set to
149    * KeyValueCodecWithTags.class.getCanonicalName());
150    * @param table table containing tagged cells
151    * @throws IOException if problems reading table
152    */
153   public static void verifyTags(Table table) throws IOException {
154     ResultScanner s = table.getScanner(new Scan());
155     for (Result r : s) {
156       for (Cell c : r.listCells()) {
157         byte[] ta = c.getTagsArray();
158         int toff = c.getTagsOffset();
159         int tlen = c.getTagsLength();
160         Tag t = Tag.getTag(ta, toff, tlen, TagType.ACL_TAG_TYPE);
161         if (t == null) {
162           fail(c.toString() + " has null tag");
163           continue;
164         }
165         byte[] tval = t.getValue();
166         assertArrayEquals(c.toString() + " has tag" + Bytes.toString(tval),
167             r.getRow(), tval);
168       }
169     }
170   }
171 }