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.nio.ByteBuffer;
021import java.util.Collection;
022import java.util.List;
023import org.apache.commons.lang3.StringUtils;
024import org.apache.hadoop.hbase.util.Bytes;
025import org.apache.hadoop.hbase.util.Strings;
026import org.apache.yetus.audience.InterfaceAudience;
027
028import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
029import org.apache.hbase.thirdparty.org.apache.commons.collections4.IterableUtils;
030
031@InterfaceAudience.Private
032public class KeyValueTestUtil {
033
034  public static KeyValue create(String row, String family, String qualifier, long timestamp,
035    String value) {
036    return create(row, family, qualifier, timestamp, KeyValue.Type.Put, value);
037  }
038
039  public static KeyValue create(String row, String family, String qualifier, long timestamp,
040    KeyValue.Type type, String value) {
041    return new KeyValue(Bytes.toBytes(row), Bytes.toBytes(family), Bytes.toBytes(qualifier),
042      timestamp, type, Bytes.toBytes(value));
043  }
044
045  public static ByteBuffer toByteBufferAndRewind(final Iterable<? extends KeyValue> kvs,
046    boolean includeMemstoreTS) {
047    int totalBytes = KeyValueUtil.totalLengthWithMvccVersion(kvs, includeMemstoreTS);
048    ByteBuffer bb = ByteBuffer.allocate(totalBytes);
049    for (KeyValue kv : IterableUtils.emptyIfNull(kvs)) {
050      KeyValueUtil.appendToByteBuffer(bb, kv, includeMemstoreTS);
051    }
052    bb.rewind();
053    return bb;
054  }
055
056  /**
057   * Checks whether KeyValues from kvCollection2 are contained in kvCollection1. The comparison is
058   * made without distinguishing MVCC version of the KeyValues
059   * @return true if KeyValues from kvCollection2 are contained in kvCollection1
060   */
061  public static boolean containsIgnoreMvccVersion(Collection<? extends Cell> kvCollection1,
062    Collection<? extends Cell> kvCollection2) {
063    for (Cell kv1 : kvCollection1) {
064      boolean found = false;
065      for (Cell kv2 : kvCollection2) {
066        if (PrivateCellUtil.equalsIgnoreMvccVersion((ExtendedCell) kv1, (ExtendedCell) kv2)) {
067          found = true;
068        }
069      }
070      if (!found) {
071        return false;
072      }
073    }
074    return true;
075  }
076
077  public static List<KeyValue> rewindThenToList(final ByteBuffer bb,
078    final boolean includesMemstoreTS, final boolean useTags) {
079    bb.rewind();
080    List<KeyValue> kvs = Lists.newArrayList();
081    KeyValue kv = null;
082    while (true) {
083      kv = KeyValueUtil.nextShallowCopy(bb, includesMemstoreTS, useTags);
084      if (kv == null) {
085        break;
086      }
087      kvs.add(kv);
088    }
089    return kvs;
090  }
091
092  /********************* toString ************************************/
093
094  public static String toStringWithPadding(final Collection<? extends KeyValue> kvs,
095    final boolean includeMeta) {
096    int maxRowStringLength = 0;
097    int maxFamilyStringLength = 0;
098    int maxQualifierStringLength = 0;
099    int maxTimestampLength = 0;
100    for (KeyValue kv : kvs) {
101      maxRowStringLength = Math.max(maxRowStringLength, getRowString(kv).length());
102      maxFamilyStringLength = Math.max(maxFamilyStringLength, getFamilyString(kv).length());
103      maxQualifierStringLength =
104        Math.max(maxQualifierStringLength, getQualifierString(kv).length());
105      maxTimestampLength =
106        Math.max(maxTimestampLength, Long.valueOf(kv.getTimestamp()).toString().length());
107    }
108    StringBuilder sb = new StringBuilder();
109    for (KeyValue kv : kvs) {
110      if (sb.length() > 0) {
111        sb.append("\n");
112      }
113      String row = toStringWithPadding(kv, maxRowStringLength, maxFamilyStringLength,
114        maxQualifierStringLength, maxTimestampLength, includeMeta);
115      sb.append(row);
116    }
117    return sb.toString();
118  }
119
120  protected static String toStringWithPadding(final KeyValue kv, final int maxRowLength,
121    int maxFamilyLength, int maxQualifierLength, int maxTimestampLength, boolean includeMeta) {
122    String leadingLengths = "";
123    String familyLength = kv.getFamilyLength() + " ";
124    if (includeMeta) {
125      leadingLengths += Strings.padFront(kv.getKeyLength() + "", '0', 4);
126      leadingLengths += " ";
127      leadingLengths += Strings.padFront(kv.getValueLength() + "", '0', 4);
128      leadingLengths += " ";
129      leadingLengths += Strings.padFront(kv.getRowLength() + "", '0', 2);
130      leadingLengths += " ";
131    }
132    int spacesAfterRow = maxRowLength - getRowString(kv).length() + 2;
133    int spacesAfterFamily = maxFamilyLength - getFamilyString(kv).length() + 2;
134    int spacesAfterQualifier = maxQualifierLength - getQualifierString(kv).length() + 1;
135    int spacesAfterTimestamp =
136      maxTimestampLength - Long.valueOf(kv.getTimestamp()).toString().length() + 1;
137    return leadingLengths + getRowString(kv) + StringUtils.repeat(' ', spacesAfterRow)
138      + familyLength + getFamilyString(kv) + StringUtils.repeat(' ', spacesAfterFamily)
139      + getQualifierString(kv) + StringUtils.repeat(' ', spacesAfterQualifier)
140      + getTimestampString(kv) + StringUtils.repeat(' ', spacesAfterTimestamp) + getTypeString(kv)
141      + " " + getValueString(kv);
142  }
143
144  protected static String getRowString(final KeyValue kv) {
145    return Bytes.toStringBinary(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength());
146  }
147
148  protected static String getFamilyString(final KeyValue kv) {
149    return Bytes.toStringBinary(kv.getFamilyArray(), kv.getFamilyOffset(), kv.getFamilyLength());
150  }
151
152  protected static String getQualifierString(final KeyValue kv) {
153    return Bytes.toStringBinary(kv.getQualifierArray(), kv.getQualifierOffset(),
154      kv.getQualifierLength());
155  }
156
157  protected static String getTimestampString(final KeyValue kv) {
158    return kv.getTimestamp() + "";
159  }
160
161  protected static String getTypeString(final KeyValue kv) {
162    return KeyValue.Type.codeToType(kv.getTypeByte()).toString();
163  }
164
165  protected static String getValueString(final KeyValue kv) {
166    return Bytes.toStringBinary(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
167  }
168
169}