001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase;
019
020import java.io.IOException;
021import java.util.Arrays;
022import java.util.Collections;
023import java.util.HashSet;
024import java.util.Set;
025import org.apache.hadoop.hbase.client.Durability;
026import org.apache.hadoop.hbase.client.Put;
027import org.apache.hadoop.hbase.client.Table;
028import org.apache.hadoop.hbase.regionserver.Region;
029import org.apache.hadoop.hbase.regionserver.RegionAsTable;
030import org.apache.hadoop.hbase.util.Bytes;
031
032/**
033 * Similar to {@link HConstants} but for tests. Also provides some simple static utility functions
034 * to generate test data.
035 */
036public class HTestConst {
037
038  private HTestConst() {
039  }
040
041  public static final String DEFAULT_TABLE_STR = "MyTestTable";
042  public static final byte[] DEFAULT_TABLE_BYTES = Bytes.toBytes(DEFAULT_TABLE_STR);
043  public static final TableName DEFAULT_TABLE = TableName.valueOf(DEFAULT_TABLE_BYTES);
044
045  public static final String DEFAULT_CF_STR = "MyDefaultCF";
046  public static final byte[] DEFAULT_CF_BYTES = Bytes.toBytes(DEFAULT_CF_STR);
047
048  public static final Set<String> DEFAULT_CF_STR_SET =
049    Collections.unmodifiableSet(new HashSet<>(Arrays.asList(new String[] { DEFAULT_CF_STR })));
050
051  public static final String DEFAULT_ROW_STR = "MyTestRow";
052  public static final byte[] DEFAULT_ROW_BYTES = Bytes.toBytes(DEFAULT_ROW_STR);
053
054  public static final String DEFAULT_QUALIFIER_STR = "MyColumnQualifier";
055  public static final byte[] DEFAULT_QUALIFIER_BYTES = Bytes.toBytes(DEFAULT_QUALIFIER_STR);
056
057  public static String DEFAULT_VALUE_STR = "MyTestValue";
058  public static byte[] DEFAULT_VALUE_BYTES = Bytes.toBytes(DEFAULT_VALUE_STR);
059
060  private static final char FIRST_CHAR = 'a';
061  private static final char LAST_CHAR = 'z';
062  private static final byte[] START_KEY_BYTES = { FIRST_CHAR, FIRST_CHAR, FIRST_CHAR };
063
064  /**
065   * Generate the given number of unique byte sequences by appending numeric suffixes (ASCII
066   * representations of decimal numbers).
067   */
068  public static byte[][] makeNAscii(byte[] base, int n) {
069    byte[][] ret = new byte[n][];
070    for (int i = 0; i < n; i++) {
071      byte[] tail = Bytes.toBytes(Integer.toString(i));
072      ret[i] = Bytes.add(base, tail);
073    }
074    return ret;
075  }
076
077  /**
078   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
079   * from 'aaa', 'aab', etc where key and value are the same.
080   * @return count of what we added.
081   */
082  public static long addContent(final Region r, final byte[] columnFamily, final byte[] column)
083    throws IOException {
084    byte[] startKey = r.getRegionInfo().getStartKey();
085    byte[] endKey = r.getRegionInfo().getEndKey();
086    byte[] startKeyBytes = startKey;
087    if (startKeyBytes == null || startKeyBytes.length == 0) {
088      startKeyBytes = START_KEY_BYTES;
089    }
090    return addContent(new RegionAsTable(r), Bytes.toString(columnFamily), Bytes.toString(column),
091      startKeyBytes, endKey, -1);
092  }
093
094  public static long addContent(final Region r, final byte[] columnFamily) throws IOException {
095    return addContent(r, columnFamily, null);
096  }
097
098  /**
099   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
100   * from 'aaa', 'aab', etc where key and value are the same.
101   * @return count of what we added.
102   */
103  public static long addContent(Table updater, String columnFamily) throws IOException {
104    return addContent(updater, columnFamily, START_KEY_BYTES, null);
105  }
106
107  public static long addContent(Table updater, String family, String column) throws IOException {
108    return addContent(updater, family, column, START_KEY_BYTES, null);
109  }
110
111  /**
112   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
113   * from 'aaa', 'aab', etc where key and value are the same.
114   * @return count of what we added.
115   */
116  public static long addContent(Table updater, String columnFamily, byte[] startKeyBytes,
117    byte[] endKey) throws IOException {
118    return addContent(updater, columnFamily, null, startKeyBytes, endKey, -1);
119  }
120
121  public static long addContent(Table updater, String family, String column, byte[] startKeyBytes,
122    byte[] endKey) throws IOException {
123    return addContent(updater, family, column, startKeyBytes, endKey, -1);
124  }
125
126  /**
127   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
128   * from 'aaa', 'aab', etc where key and value are the same.
129   * @return count of what we added.
130   */
131  public static long addContent(Table updater, String columnFamily, String column,
132    byte[] startKeyBytes, byte[] endKey, long ts) throws IOException {
133    long count = 0;
134    // Add rows of three characters. The first character starts with the
135    // 'a' character and runs up to 'z'. Per first character, we run the
136    // second character over same range. And same for the third so rows
137    // (and values) look like this: 'aaa', 'aab', 'aac', etc.
138    char secondCharStart = (char) startKeyBytes[1];
139    char thirdCharStart = (char) startKeyBytes[2];
140    EXIT: for (char c = (char) startKeyBytes[0]; c <= LAST_CHAR; c++) {
141      for (char d = secondCharStart; d <= LAST_CHAR; d++) {
142        for (char e = thirdCharStart; e <= LAST_CHAR; e++) {
143          byte[] t = new byte[] { (byte) c, (byte) d, (byte) e };
144          if (endKey != null && endKey.length > 0 && Bytes.compareTo(endKey, t) <= 0) {
145            break EXIT;
146          }
147          Put put;
148          if (ts != -1) {
149            put = new Put(t, ts);
150          } else {
151            put = new Put(t);
152          }
153          StringBuilder sb = new StringBuilder();
154          if (column != null && column.contains(":")) {
155            sb.append(column);
156          } else {
157            if (columnFamily != null) {
158              sb.append(columnFamily);
159              if (!columnFamily.endsWith(":")) {
160                sb.append(":");
161              }
162              if (column != null) {
163                sb.append(column);
164              }
165            }
166          }
167          byte[][] split = CellUtil.parseColumn(Bytes.toBytes(sb.toString()));
168          if (split.length == 1) {
169            byte[] qualifier = new byte[0];
170            put.addColumn(split[0], qualifier, t);
171          } else {
172            put.addColumn(split[0], split[1], t);
173          }
174          put.setDurability(Durability.SKIP_WAL);
175          updater.put(put);
176          count++;
177        }
178        // Set start character back to FIRST_CHAR after we've done first loop.
179        thirdCharStart = FIRST_CHAR;
180      }
181      secondCharStart = FIRST_CHAR;
182    }
183    return count;
184  }
185}