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.regionserver.wal; 019 020import static org.junit.Assert.assertArrayEquals; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertNotNull; 023import static org.junit.Assert.assertNull; 024import static org.junit.Assert.assertThrows; 025import static org.junit.Assert.assertTrue; 026 027import java.io.EOFException; 028import java.io.IOException; 029import java.util.stream.IntStream; 030import org.apache.hadoop.hbase.Cell; 031import org.apache.hadoop.hbase.CellUtil; 032import org.apache.hadoop.hbase.HConstants; 033import org.apache.hadoop.hbase.KeyValue; 034import org.apache.hadoop.hbase.TableName; 035import org.apache.hadoop.hbase.client.RegionInfo; 036import org.apache.hadoop.hbase.client.RegionInfoBuilder; 037import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl; 038import org.apache.hadoop.hbase.util.Bytes; 039import org.apache.hadoop.hbase.wal.WAL; 040import org.apache.hadoop.hbase.wal.WALEdit; 041import org.apache.hadoop.hbase.wal.WALKeyImpl; 042import org.apache.hadoop.hbase.wal.WALProvider; 043 044/** 045 * Helper class for testing protobuf log. 046 */ 047public final class ProtobufLogTestHelper { 048 049 private ProtobufLogTestHelper() { 050 } 051 052 private static byte[] toValue(int prefix, int suffix) { 053 return Bytes.toBytes(prefix + "-" + suffix); 054 } 055 056 private static RegionInfo toRegionInfo(TableName tableName) { 057 return RegionInfoBuilder.newBuilder(tableName).setRegionId(1024).build(); 058 } 059 060 private static WAL.Entry generateEdit(int i, RegionInfo hri, TableName tableName, byte[] row, 061 int columnCount, long timestamp, MultiVersionConcurrencyControl mvcc) { 062 WALKeyImpl key = new WALKeyImpl(hri.getEncodedNameAsBytes(), tableName, i, timestamp, 063 HConstants.DEFAULT_CLUSTER_ID, mvcc); 064 WALEdit edit = new WALEdit(); 065 int prefix = i; 066 IntStream.range(0, columnCount).mapToObj(j -> toValue(prefix, j)) 067 .map(value -> new KeyValue(row, row, row, timestamp, value)).forEachOrdered(edit::add); 068 return new WAL.Entry(key, edit); 069 } 070 071 public static void doWrite(WALProvider.Writer writer, boolean withTrailer, TableName tableName, 072 int columnCount, int recordCount, byte[] row, long timestamp) throws IOException { 073 RegionInfo hri = toRegionInfo(tableName); 074 for (int i = 0; i < recordCount; i++) { 075 writer.append(generateEdit(i, hri, tableName, row, columnCount, timestamp, null)); 076 } 077 writer.sync(false); 078 if (withTrailer) { 079 writer.close(); 080 } 081 } 082 083 public static void doWrite(WAL wal, RegionInfo hri, TableName tableName, int columnCount, 084 int recordCount, byte[] row, long timestamp, MultiVersionConcurrencyControl mvcc) 085 throws IOException { 086 for (int i = 0; i < recordCount; i++) { 087 WAL.Entry entry = generateEdit(i, hri, tableName, row, columnCount, timestamp, mvcc); 088 wal.appendData(hri, entry.getKey(), entry.getEdit()); 089 } 090 wal.sync(); 091 } 092 093 public static void doRead(ProtobufWALStreamReader reader, boolean withTrailer, RegionInfo hri, 094 TableName tableName, int columnCount, int recordCount, byte[] row, long timestamp) 095 throws IOException { 096 if (withTrailer) { 097 assertNotNull(reader.trailer); 098 } else { 099 assertNull(reader.trailer); 100 } 101 for (int i = 0; i < recordCount; ++i) { 102 WAL.Entry entry = reader.next(); 103 assertNotNull(entry); 104 assertEquals(columnCount, entry.getEdit().size()); 105 assertArrayEquals(hri.getEncodedNameAsBytes(), entry.getKey().getEncodedRegionName()); 106 assertEquals(tableName, entry.getKey().getTableName()); 107 int idx = 0; 108 for (Cell val : entry.getEdit().getCells()) { 109 assertTrue(Bytes.equals(row, 0, row.length, val.getRowArray(), val.getRowOffset(), 110 val.getRowLength())); 111 assertArrayEquals(toValue(i, idx), CellUtil.cloneValue(val)); 112 idx++; 113 } 114 } 115 if (withTrailer) { 116 // we can finish normally 117 assertNull(reader.next()); 118 } else { 119 // we will get an EOF since there is no trailer 120 assertThrows(EOFException.class, () -> reader.next()); 121 } 122 } 123 124 public static void doRead(ProtobufWALStreamReader reader, boolean withTrailer, 125 TableName tableName, int columnCount, int recordCount, byte[] row, long timestamp) 126 throws IOException { 127 doRead(reader, withTrailer, toRegionInfo(tableName), tableName, columnCount, recordCount, row, 128 timestamp); 129 } 130}