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.io.hfile;
019
020import java.util.Random;
021import org.apache.hadoop.hbase.KeyValue;
022import org.apache.hadoop.hbase.util.Bytes;
023
024/**
025 * These helper methods generate random byte[]'s data for KeyValues
026 */
027public class RandomKeyValueUtil {
028  public static final String COLUMN_FAMILY_NAME = "_-myColumnFamily-_";
029  private static final int MIN_ROW_OR_QUALIFIER_LENGTH = 64;
030  private static final int MAX_ROW_OR_QUALIFIER_LENGTH = 128;
031
032  public static final char randomReadableChar(Random rand) {
033    int i = rand.nextInt(26 * 2 + 10 + 1);
034    if (i < 26) return (char) ('A' + i);
035    i -= 26;
036
037    if (i < 26) return (char) ('a' + i);
038    i -= 26;
039
040    if (i < 10) return (char) ('0' + i);
041    i -= 10;
042
043    assert i == 0;
044    return '_';
045  }
046
047  public static KeyValue randomKeyValue(Random rand) {
048    return new KeyValue(randomRowOrQualifier(rand), Bytes.toBytes(COLUMN_FAMILY_NAME),
049      randomRowOrQualifier(rand), randomValue(rand));
050  }
051
052  public static byte[] randomRowOrQualifier(Random rand) {
053    StringBuilder field = new StringBuilder();
054    int fieldLen = MIN_ROW_OR_QUALIFIER_LENGTH
055      + rand.nextInt(MAX_ROW_OR_QUALIFIER_LENGTH - MIN_ROW_OR_QUALIFIER_LENGTH + 1);
056    for (int i = 0; i < fieldLen; ++i)
057      field.append(randomReadableChar(rand));
058    return Bytes.toBytes(field.toString());
059  }
060
061  public static byte[] randomValue(Random rand) {
062    StringBuilder v = new StringBuilder();
063    for (int j = 0; j < 1 + rand.nextInt(2000); ++j) {
064      v.append((char) (32 + rand.nextInt(95)));
065    }
066
067    byte[] valueBytes = Bytes.toBytes(v.toString());
068    return valueBytes;
069  }
070
071  /**
072   * Generates a random key that is guaranteed to increase as the given index i increases. The
073   * result consists of a prefix, which is a deterministic increasing function of i, and a random
074   * suffix.
075   * @param rand random number generator to use
076   * @return the random key
077   */
078  public static byte[] randomOrderedKey(Random rand, int i) {
079    StringBuilder k = new StringBuilder();
080
081    // The fixed-length lexicographically increasing part of the key.
082    for (int bitIndex = 31; bitIndex >= 0; --bitIndex) {
083      if ((i & (1 << bitIndex)) == 0) k.append("a");
084      else k.append("b");
085    }
086
087    // A random-length random suffix of the key.
088    for (int j = 0; j < rand.nextInt(50); ++j)
089      k.append(randomReadableChar(rand));
090
091    byte[] keyBytes = Bytes.toBytes(k.toString());
092    return keyBytes;
093  }
094
095  public static byte[] randomOrderedFixedLengthKey(Random rand, int i, int suffixLength) {
096    StringBuilder k = new StringBuilder();
097
098    // The fixed-length lexicographically increasing part of the key.
099    for (int bitIndex = 31; bitIndex >= 0; --bitIndex) {
100      if ((i & (1 << bitIndex)) == 0) k.append("a");
101      else k.append("b");
102    }
103
104    // A random suffix of the key.
105    for (int j = 0; j < suffixLength; ++j)
106      k.append(randomReadableChar(rand));
107
108    byte[] keyBytes = Bytes.toBytes(k.toString());
109    return keyBytes;
110  }
111
112  public static byte[] randomFixedLengthValue(Random rand, int valueLength) {
113    StringBuilder v = new StringBuilder();
114    for (int j = 0; j < valueLength; ++j) {
115      v.append((char) (32 + rand.nextInt(95)));
116    }
117
118    byte[] valueBytes = Bytes.toBytes(v.toString());
119    return valueBytes;
120  }
121}