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