/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hbase.replication; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.wal.WAL.Entry; import org.apache.hadoop.hbase.wal.WALKey; import org.apache.hadoop.hbase.regionserver.wal.WALEdit; import org.apache.hadoop.hbase.util.Bytes; import org.junit.Assert; import org.junit.Test; import org.junit.experimental.categories.Category; import com.google.common.collect.Lists; import static org.junit.Assert.*; import static org.mockito.Mockito.*; @Category(SmallTests.class) public class TestReplicationWALEntryFilters { static byte[] a = new byte[] {'a'}; static byte[] b = new byte[] {'b'}; static byte[] c = new byte[] {'c'}; static byte[] d = new byte[] {'d'}; @Test public void testSystemTableWALEntryFilter() { SystemTableWALEntryFilter filter = new SystemTableWALEntryFilter(); // meta WALKey key1 = new WALKey( HRegionInfo.FIRST_META_REGIONINFO.getEncodedNameAsBytes(), TableName.META_TABLE_NAME); Entry metaEntry = new Entry(key1, null); assertNull(filter.filter(metaEntry)); // ns table WALKey key2 = new WALKey(new byte[] {}, TableName.NAMESPACE_TABLE_NAME); Entry nsEntry = new Entry(key2, null); assertNull(filter.filter(nsEntry)); // user table WALKey key3 = new WALKey(new byte[] {}, TableName.valueOf("foo")); Entry userEntry = new Entry(key3, null); assertEquals(userEntry, filter.filter(userEntry)); } @Test public void testScopeWALEntryFilter() { ScopeWALEntryFilter filter = new ScopeWALEntryFilter(); Entry userEntry = createEntry(a, b); Entry userEntryA = createEntry(a); Entry userEntryB = createEntry(b); Entry userEntryEmpty = createEntry(); // no scopes assertEquals(null, filter.filter(userEntry)); // empty scopes TreeMap<byte[], Integer> scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); assertEquals(null, filter.filter(userEntry)); // different scope scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); scopes.put(c, HConstants.REPLICATION_SCOPE_GLOBAL); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); // all kvs should be filtered assertEquals(userEntryEmpty, filter.filter(userEntry)); // local scope scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); assertEquals(userEntryEmpty, filter.filter(userEntry)); scopes.put(b, HConstants.REPLICATION_SCOPE_LOCAL); assertEquals(userEntryEmpty, filter.filter(userEntry)); // only scope a scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); scopes.put(a, HConstants.REPLICATION_SCOPE_GLOBAL); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); assertEquals(userEntryA, filter.filter(userEntry)); scopes.put(b, HConstants.REPLICATION_SCOPE_LOCAL); assertEquals(userEntryA, filter.filter(userEntry)); // only scope b scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); scopes.put(b, HConstants.REPLICATION_SCOPE_GLOBAL); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); assertEquals(userEntryB, filter.filter(userEntry)); scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL); assertEquals(userEntryB, filter.filter(userEntry)); // scope a and b scopes = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR); scopes.put(b, HConstants.REPLICATION_SCOPE_GLOBAL); userEntry = createEntry(a, b); userEntry.getKey().setScopes(scopes); assertEquals(userEntryB, filter.filter(userEntry)); scopes.put(a, HConstants.REPLICATION_SCOPE_LOCAL); assertEquals(userEntryB, filter.filter(userEntry)); } WALEntryFilter nullFilter = new WALEntryFilter() { @Override public Entry filter(Entry entry) { return null; } }; WALEntryFilter passFilter = new WALEntryFilter() { @Override public Entry filter(Entry entry) { return entry; } }; @Test public void testChainWALEntryFilter() { Entry userEntry = createEntry(a, b, c); ChainWALEntryFilter filter = new ChainWALEntryFilter(passFilter); assertEquals(createEntry(a,b,c), filter.filter(userEntry)); filter = new ChainWALEntryFilter(passFilter, passFilter); assertEquals(createEntry(a,b,c), filter.filter(userEntry)); filter = new ChainWALEntryFilter(passFilter, passFilter, passFilter); assertEquals(createEntry(a,b,c), filter.filter(userEntry)); filter = new ChainWALEntryFilter(nullFilter); assertEquals(null, filter.filter(userEntry)); filter = new ChainWALEntryFilter(nullFilter, passFilter); assertEquals(null, filter.filter(userEntry)); filter = new ChainWALEntryFilter(passFilter, nullFilter); assertEquals(null, filter.filter(userEntry)); filter = new ChainWALEntryFilter(nullFilter, passFilter, nullFilter); assertEquals(null, filter.filter(userEntry)); filter = new ChainWALEntryFilter(nullFilter, nullFilter); assertEquals(null, filter.filter(userEntry)); // flatten filter = new ChainWALEntryFilter( new ChainWALEntryFilter(passFilter, new ChainWALEntryFilter(passFilter, passFilter), new ChainWALEntryFilter(passFilter), new ChainWALEntryFilter(passFilter)), new ChainWALEntryFilter(passFilter)); assertEquals(createEntry(a,b,c), filter.filter(userEntry)); filter = new ChainWALEntryFilter( new ChainWALEntryFilter(passFilter, new ChainWALEntryFilter(passFilter, new ChainWALEntryFilter(nullFilter))), new ChainWALEntryFilter(passFilter)); assertEquals(null, filter.filter(userEntry)); } @Test public void testTableCfWALEntryFilter() { ReplicationPeer peer = mock(ReplicationPeer.class); when(peer.getTableCFs()).thenReturn(null); Entry userEntry = createEntry(a, b, c); TableCfWALEntryFilter filter = new TableCfWALEntryFilter(peer); assertEquals(createEntry(a,b,c), filter.filter(userEntry)); // empty map userEntry = createEntry(a, b, c); Map<TableName, List<String>> tableCfs = new HashMap<TableName, List<String>>(); when(peer.getTableCFs()).thenReturn(tableCfs); filter = new TableCfWALEntryFilter(peer); assertEquals(null, filter.filter(userEntry)); // table bar userEntry = createEntry(a, b, c); tableCfs = new HashMap<TableName, List<String>>(); tableCfs.put(TableName.valueOf("bar"), null); when(peer.getTableCFs()).thenReturn(tableCfs); filter = new TableCfWALEntryFilter(peer); assertEquals(null, filter.filter(userEntry)); // table foo:a userEntry = createEntry(a, b, c); tableCfs = new HashMap<TableName, List<String>>(); tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a")); when(peer.getTableCFs()).thenReturn(tableCfs); filter = new TableCfWALEntryFilter(peer); assertEquals(createEntry(a), filter.filter(userEntry)); // table foo:a,c userEntry = createEntry(a, b, c, d); tableCfs = new HashMap<TableName, List<String>>(); tableCfs.put(TableName.valueOf("foo"), Lists.newArrayList("a", "c")); when(peer.getTableCFs()).thenReturn(tableCfs); filter = new TableCfWALEntryFilter(peer); assertEquals(createEntry(a,c), filter.filter(userEntry)); } private Entry createEntry(byte[]... kvs) { WALKey key1 = new WALKey(new byte[] {}, TableName.valueOf("foo")); WALEdit edit1 = new WALEdit(); for (byte[] kv : kvs) { edit1.add(new KeyValue(kv, kv, kv)); } return new Entry(key1, edit1); } private void assertEquals(Entry e1, Entry e2) { Assert.assertEquals(e1 == null, e2 == null); if (e1 == null) { return; } // do not compare WALKeys // compare kvs Assert.assertEquals(e1.getEdit() == null, e2.getEdit() == null); if (e1.getEdit() == null) { return; } List<Cell> cells1 = e1.getEdit().getCells(); List<Cell> cells2 = e2.getEdit().getCells(); Assert.assertEquals(cells1.size(), cells2.size()); for (int i = 0; i < cells1.size(); i++) { KeyValue.COMPARATOR.compare(cells1.get(i), cells2.get(i)); } } }