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.assertFalse; 021import static org.junit.Assert.assertNull; 022import static org.junit.Assert.assertTrue; 023 024import java.io.IOException; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.FileSystem; 027import org.apache.hadoop.fs.Path; 028import org.apache.hadoop.hbase.HBaseTestingUtility; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.Durability; 031import org.apache.hadoop.hbase.client.Put; 032import org.apache.hadoop.hbase.regionserver.ChunkCreator; 033import org.apache.hadoop.hbase.regionserver.HRegion; 034import org.apache.hadoop.hbase.regionserver.MemStoreLAB; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.apache.hadoop.hbase.wal.WAL; 037import org.junit.After; 038import org.junit.Before; 039import org.junit.Rule; 040import org.junit.Test; 041import org.junit.rules.TestName; 042 043/** 044 * Tests for WAL write durability - hflush vs hsync 045 */ 046public abstract class WALDurabilityTestBase<T extends WAL> { 047 048 private static final String COLUMN_FAMILY = "MyCF"; 049 private static final byte[] COLUMN_FAMILY_BYTES = Bytes.toBytes(COLUMN_FAMILY); 050 051 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 052 private Configuration conf; 053 private String dir; 054 @Rule 055 public TestName name = new TestName(); 056 057 // Test names 058 protected TableName tableName; 059 060 @Before 061 public void setUp() throws IOException { 062 conf = TEST_UTIL.getConfiguration(); 063 dir = TEST_UTIL.getDataTestDir("TestHRegion").toString(); 064 tableName = TableName.valueOf(name.getMethodName()); 065 } 066 067 @After 068 public void tearDown() throws IOException { 069 TEST_UTIL.cleanupTestDir(); 070 } 071 072 protected abstract T getWAL(FileSystem fs, Path root, String logDir, Configuration conf) 073 throws IOException; 074 075 protected abstract void resetSyncFlag(T wal); 076 077 protected abstract Boolean getSyncFlag(T wal); 078 079 protected abstract Boolean getWriterSyncFlag(T wal); 080 081 @Test 082 public void testWALDurability() throws IOException { 083 byte[] bytes = Bytes.toBytes(getName()); 084 Put put = new Put(bytes); 085 put.addColumn(COLUMN_FAMILY_BYTES, Bytes.toBytes("1"), bytes); 086 087 // global hbase.wal.hsync false, no override in put call - hflush 088 conf.set(HRegion.WAL_HSYNC_CONF_KEY, "false"); 089 FileSystem fs = FileSystem.get(conf); 090 Path rootDir = new Path(dir + getName()); 091 T wal = getWAL(fs, rootDir, getName(), conf); 092 HRegion region = initHRegion(tableName, null, null, conf, wal); 093 try { 094 resetSyncFlag(wal); 095 assertNull(getSyncFlag(wal)); 096 assertNull(getWriterSyncFlag(wal)); 097 region.put(put); 098 assertFalse(getSyncFlag(wal)); 099 assertFalse(getWriterSyncFlag(wal)); 100 101 // global hbase.wal.hsync false, durability set in put call - fsync 102 put.setDurability(Durability.FSYNC_WAL); 103 resetSyncFlag(wal); 104 assertNull(getSyncFlag(wal)); 105 assertNull(getWriterSyncFlag(wal)); 106 region.put(put); 107 assertTrue(getSyncFlag(wal)); 108 assertTrue(getWriterSyncFlag(wal)); 109 } finally { 110 HBaseTestingUtility.closeRegionAndWAL(region); 111 } 112 113 // global hbase.wal.hsync true, no override in put call 114 conf.set(HRegion.WAL_HSYNC_CONF_KEY, "true"); 115 fs = FileSystem.get(conf); 116 wal = getWAL(fs, rootDir, getName(), conf); 117 region = initHRegion(tableName, null, null, conf, wal); 118 119 try { 120 resetSyncFlag(wal); 121 assertNull(getSyncFlag(wal)); 122 assertNull(getWriterSyncFlag(wal)); 123 region.put(put); 124 assertTrue(getSyncFlag(wal)); 125 assertTrue(getWriterSyncFlag(wal)); 126 127 // global hbase.wal.hsync true, durability set in put call - fsync 128 put.setDurability(Durability.FSYNC_WAL); 129 resetSyncFlag(wal); 130 assertNull(getSyncFlag(wal)); 131 assertNull(getWriterSyncFlag(wal)); 132 region.put(put); 133 assertTrue(getSyncFlag(wal)); 134 assertTrue(getWriterSyncFlag(wal)); 135 136 // global hbase.wal.hsync true, durability set in put call - sync 137 put = new Put(bytes); 138 put.addColumn(COLUMN_FAMILY_BYTES, Bytes.toBytes("1"), bytes); 139 put.setDurability(Durability.SYNC_WAL); 140 resetSyncFlag(wal); 141 assertNull(getSyncFlag(wal)); 142 assertNull(getWriterSyncFlag(wal)); 143 region.put(put); 144 assertFalse(getSyncFlag(wal)); 145 assertFalse(getWriterSyncFlag(wal)); 146 } finally { 147 HBaseTestingUtility.closeRegionAndWAL(region); 148 } 149 } 150 151 private String getName() { 152 return name.getMethodName(); 153 } 154 155 /** 156 * @return A region on which you must call {@link HBaseTestingUtility#closeRegionAndWAL(HRegion)} 157 * when done. 158 */ 159 public static HRegion initHRegion(TableName tableName, byte[] startKey, byte[] stopKey, 160 Configuration conf, WAL wal) throws IOException { 161 ChunkCreator.initialize(MemStoreLAB.CHUNK_SIZE_DEFAULT, false, 0, 0, 0, null, 162 MemStoreLAB.INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT); 163 return TEST_UTIL.createLocalHRegion(tableName, startKey, stopKey, conf, false, 164 Durability.USE_DEFAULT, wal, COLUMN_FAMILY_BYTES); 165 } 166}