1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.coprocessor;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23
24 import java.io.IOException;
25 import java.util.Iterator;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.Cell;
30 import org.apache.hadoop.hbase.CellUtil;
31 import org.apache.hadoop.hbase.DoNotRetryIOException;
32 import org.apache.hadoop.hbase.HBaseTestingUtility;
33 import org.apache.hadoop.hbase.HColumnDescriptor;
34 import org.apache.hadoop.hbase.HTableDescriptor;
35 import org.apache.hadoop.hbase.TableName;
36 import org.apache.hadoop.hbase.Tag;
37 import org.apache.hadoop.hbase.TagType;
38 import org.apache.hadoop.hbase.client.Append;
39 import org.apache.hadoop.hbase.client.Connection;
40 import org.apache.hadoop.hbase.client.Get;
41 import org.apache.hadoop.hbase.client.Increment;
42 import org.apache.hadoop.hbase.client.Mutation;
43 import org.apache.hadoop.hbase.client.Result;
44 import org.apache.hadoop.hbase.client.Table;
45 import org.apache.hadoop.hbase.client.TestFromClientSide;
46 import org.apache.hadoop.hbase.security.access.AccessController;
47 import org.apache.hadoop.hbase.security.access.Permission;
48 import org.apache.hadoop.hbase.testclassification.CoprocessorTests;
49 import org.apache.hadoop.hbase.testclassification.MediumTests;
50 import org.apache.hadoop.hbase.util.Bytes;
51 import org.junit.AfterClass;
52 import org.junit.BeforeClass;
53 import org.junit.Rule;
54 import org.junit.Test;
55 import org.junit.experimental.categories.Category;
56 import org.junit.rules.TestName;
57
58
59
60
61
62
63
64
65 @Category({ CoprocessorTests.class, MediumTests.class })
66 public class TestPostMutationBeforeWAL {
67
68 @Rule
69 public TestName name = new TestName();
70
71 private static final Log LOG = LogFactory.getLog(TestFromClientSide.class);
72
73 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
74
75 private static Connection connection;
76
77 private static final byte [] ROW = Bytes.toBytes("row");
78 private static final String CF1 = "cf1";
79 private static final byte[] CF1_BYTES = Bytes.toBytes(CF1);
80 private static final String CF2 = "cf2";
81 private static final byte[] CF2_BYTES = Bytes.toBytes(CF2);
82 private static final byte[] CQ1 = Bytes.toBytes("cq1");
83 private static final byte[] CQ2 = Bytes.toBytes("cq2");
84 private static final byte[] VALUE = Bytes.toBytes("value");
85 private static final byte[] VALUE2 = Bytes.toBytes("valuevalue");
86 private static final String USER = "User";
87 private static final Permission PERMS = new Permission(Permission.Action.READ);
88
89 @BeforeClass
90 public static void setupBeforeClass() throws Exception {
91 UTIL.startMiniCluster();
92 connection = UTIL.getConnection();
93 }
94
95 @AfterClass
96 public static void tearDownAfterClass() throws Exception {
97 connection.close();
98 UTIL.shutdownMiniCluster();
99 }
100
101 private void createTableWithCoprocessor(TableName tableName, String coprocessor)
102 throws IOException {
103 HTableDescriptor tableDesc = new HTableDescriptor(tableName);
104 tableDesc.addFamily(new HColumnDescriptor(CF1_BYTES));
105 tableDesc.addFamily(new HColumnDescriptor(CF2_BYTES));
106 tableDesc.addCoprocessor(coprocessor);
107 connection.getAdmin().createTable(tableDesc);
108 }
109
110 @Test
111 public void testIncrementTTLWithACLTag() throws Exception {
112 TableName tableName = TableName.valueOf(name.getMethodName());
113 createTableWithCoprocessor(tableName, ChangeCellWithACLTagObserver.class.getName());
114 try (Table table = connection.getTable(tableName)) {
115
116 Increment firstIncrement = new Increment(ROW).addColumn(CF1_BYTES, CQ1, 1)
117 .setACL(USER, PERMS);
118 Result result = table.increment(firstIncrement);
119 assertEquals(1, result.size());
120 assertEquals(1, Bytes.toLong(result.getValue(CF1_BYTES, CQ1)));
121
122
123 Get get = new Get(ROW).addColumn(CF1_BYTES, CQ1);
124 result = table.get(get);
125 assertEquals(1, result.size());
126 assertEquals(1, Bytes.toLong(result.getValue(CF1_BYTES, CQ1)));
127
128
129 Increment secondIncrement = new Increment(ROW).addColumn(CF1_BYTES, CQ1, 1).setTTL(1000)
130 .setACL(USER, PERMS);
131 result = table.increment(secondIncrement);
132
133
134 assertEquals(1, result.size());
135 assertEquals(2, Bytes.toLong(result.getValue(CF1_BYTES, CQ1)));
136
137
138 Thread.sleep(4000);
139 get = new Get(ROW).addColumn(CF1_BYTES, CQ1);
140 result = table.get(get);
141
142
143 assertEquals(1, result.size());
144 assertEquals(1, Bytes.toLong(result.getValue(CF1_BYTES, CQ1)));
145 }
146 }
147
148 @Test
149 public void testAppendTTLWithACLTag() throws Exception {
150 TableName tableName = TableName.valueOf(name.getMethodName());
151 createTableWithCoprocessor(tableName, ChangeCellWithACLTagObserver.class.getName());
152 try (Table table = connection.getTable(tableName)) {
153
154 Append firstAppend = new Append(ROW).add(CF1_BYTES, CQ2, VALUE).setACL(USER, PERMS);
155 Result result = table.append(firstAppend);
156 assertEquals(1, result.size());
157 assertTrue(Bytes.equals(VALUE, result.getValue(CF1_BYTES, CQ2)));
158
159
160 Get get = new Get(ROW).addColumn(CF1_BYTES, CQ2);
161 result = table.get(get);
162 assertEquals(1, result.size());
163 assertTrue(Bytes.equals(VALUE, result.getValue(CF1_BYTES, CQ2)));
164
165
166 Append secondAppend = new Append(ROW).add(CF1_BYTES, CQ2, VALUE).setTTL(1000)
167 .setACL(USER, PERMS);
168 result = table.append(secondAppend);
169
170
171 assertEquals(1, result.size());
172 assertTrue(Bytes.equals(VALUE2, result.getValue(CF1_BYTES, CQ2)));
173
174
175 Thread.sleep(4000);
176 get = new Get(ROW).addColumn(CF1_BYTES, CQ2);
177 result = table.get(get);
178
179
180 assertEquals(1, result.size());
181 assertTrue(Bytes.equals(VALUE, result.getValue(CF1_BYTES, CQ2)));
182 }
183 }
184
185 private static boolean checkAclTag(byte[] acl, Cell cell) {
186 Iterator<Tag> iter = CellUtil.tagsIterator(cell.getTagsArray(),
187 cell.getTagsOffset(), cell.getTagsLength());
188 while (iter.hasNext()) {
189 Tag tag = iter.next();
190 if (tag.getType() == TagType.ACL_TAG_TYPE) {
191 return Bytes.equals(acl, tag.getValue());
192 }
193 }
194 return false;
195 }
196
197 public static class ChangeCellWithACLTagObserver extends AccessController {
198
199 @Override
200 public Cell postMutationBeforeWAL(ObserverContext<RegionCoprocessorEnvironment> ctx,
201 MutationType mutationType, Mutation mutation, Cell oldCell, Cell newCell)
202 throws IOException {
203 Cell result = super.postMutationBeforeWAL(ctx, mutationType, mutation, oldCell, newCell);
204 if (mutation.getACL() != null && !checkAclTag(mutation.getACL(), result)) {
205 throw new DoNotRetryIOException("Unmatched ACL tag.");
206 }
207 return result;
208 }
209 }
210 }