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