View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.regionserver;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertTrue;
22  
23  import java.io.IOException;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.Cell;
29  import org.apache.hadoop.hbase.CellScanner;
30  import org.apache.hadoop.hbase.HBaseTestingUtility;
31  import org.apache.hadoop.hbase.HColumnDescriptor;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.HTableDescriptor;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.KeyValueUtil;
36  import org.apache.hadoop.hbase.MediumTests;
37  import org.apache.hadoop.hbase.TableName;
38  import org.apache.hadoop.hbase.Tag;
39  import org.apache.hadoop.hbase.client.Append;
40  import org.apache.hadoop.hbase.client.Durability;
41  import org.apache.hadoop.hbase.client.HBaseAdmin;
42  import org.apache.hadoop.hbase.client.HTable;
43  import org.apache.hadoop.hbase.client.Increment;
44  import org.apache.hadoop.hbase.client.Mutation;
45  import org.apache.hadoop.hbase.client.Put;
46  import org.apache.hadoop.hbase.client.Result;
47  import org.apache.hadoop.hbase.client.ResultScanner;
48  import org.apache.hadoop.hbase.client.Scan;
49  import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
50  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
51  import org.apache.hadoop.hbase.coprocessor.ObserverContext;
52  import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
53  import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
54  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse.CompactionState;
55  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
56  import org.apache.hadoop.hbase.util.Bytes;
57  import org.junit.After;
58  import org.junit.AfterClass;
59  import org.junit.BeforeClass;
60  import org.junit.Rule;
61  import org.junit.Test;
62  import org.junit.experimental.categories.Category;
63  import org.junit.rules.TestName;
64  
65  /**
66   *  Class that test tags
67   */
68  @Category(MediumTests.class)
69  public class TestTags {
70    static boolean useFilter = false;
71  
72    private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
73  
74    @Rule
75    public final TestName TEST_NAME = new TestName();
76  
77    @BeforeClass
78    public static void setUpBeforeClass() throws Exception {
79      Configuration conf = TEST_UTIL.getConfiguration();
80      conf.setInt("hfile.format.version", 3);
81      conf.setStrings(CoprocessorHost.USER_REGION_COPROCESSOR_CONF_KEY,
82          TestCoprocessorForTags.class.getName());
83      TEST_UTIL.startMiniCluster(1, 2);
84    }
85  
86    @AfterClass
87    public static void tearDownAfterClass() throws Exception {
88      TEST_UTIL.shutdownMiniCluster();
89    }
90  
91    @After
92    public void tearDown() {
93      useFilter = false;
94    }
95  
96    @Test
97    public void testTags() throws Exception {
98      HTable table = null;
99      try {
100       TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
101       byte[] fam = Bytes.toBytes("info");
102       byte[] row = Bytes.toBytes("rowa");
103       // column names
104       byte[] qual = Bytes.toBytes("qual");
105 
106       byte[] row1 = Bytes.toBytes("rowb");
107 
108       byte[] row2 = Bytes.toBytes("rowc");
109 
110       HTableDescriptor desc = new HTableDescriptor(tableName);
111       HColumnDescriptor colDesc = new HColumnDescriptor(fam);
112       colDesc.setBlockCacheEnabled(true);
113       // colDesc.setDataBlockEncoding(DataBlockEncoding.NONE);
114       colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE);
115       desc.addFamily(colDesc);
116       HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
117       admin.createTable(desc);
118       byte[] value = Bytes.toBytes("value");
119       table = new HTable(TEST_UTIL.getConfiguration(), tableName);
120       Put put = new Put(row);
121       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
122       put.setAttribute("visibility", Bytes.toBytes("myTag"));
123       table.put(put);
124       admin.flush(tableName.getName());
125       List<HRegion> regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
126       for(HRegion region : regions) {
127         Store store = region.getStore(fam);
128         while(!(store.getStorefilesCount() > 0)) {
129           Thread.sleep(10);
130         }
131       }
132 
133       Put put1 = new Put(row1);
134       byte[] value1 = Bytes.toBytes("1000dfsdf");
135       put1.add(fam, qual, HConstants.LATEST_TIMESTAMP, value1);
136       // put1.setAttribute("visibility", Bytes.toBytes("myTag3"));
137       table.put(put1);
138       admin.flush(tableName.getName());
139       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
140       for(HRegion region : regions) {
141         Store store = region.getStore(fam);
142         while(!(store.getStorefilesCount() > 1)) {
143           Thread.sleep(10);
144         }
145       }
146 
147       Put put2 = new Put(row2);
148       byte[] value2 = Bytes.toBytes("1000dfsdf");
149       put2.add(fam, qual, HConstants.LATEST_TIMESTAMP, value2);
150       put2.setAttribute("visibility", Bytes.toBytes("myTag3"));
151       table.put(put2);
152 
153       admin.flush(tableName.getName());
154       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
155       for(HRegion region : regions) {
156         Store store = region.getStore(fam);
157         while(!(store.getStorefilesCount() > 2)) {
158           Thread.sleep(10);
159         }
160       }
161       result(fam, row, qual, row2, table, value, value2, row1, value1);
162       admin.compact(tableName.getName());
163       while(admin.getCompactionState(tableName.getName()) != CompactionState.NONE) {
164         Thread.sleep(10);
165       }
166       result(fam, row, qual, row2, table, value, value2, row1, value1);
167     } finally {
168       if (table != null) {
169         table.close();
170       }
171     }
172   }
173 
174   @Test
175   public void testFlushAndCompactionWithoutTags() throws Exception {
176     HTable table = null;
177     try {
178       TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
179       byte[] fam = Bytes.toBytes("info");
180       byte[] row = Bytes.toBytes("rowa");
181       // column names
182       byte[] qual = Bytes.toBytes("qual");
183 
184       byte[] row1 = Bytes.toBytes("rowb");
185 
186       byte[] row2 = Bytes.toBytes("rowc");
187 
188       HTableDescriptor desc = new HTableDescriptor(tableName);
189       HColumnDescriptor colDesc = new HColumnDescriptor(fam);
190       colDesc.setBlockCacheEnabled(true);
191       // colDesc.setDataBlockEncoding(DataBlockEncoding.NONE);
192       colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE);
193       desc.addFamily(colDesc);
194       HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
195       admin.createTable(desc);
196 
197       table = new HTable(TEST_UTIL.getConfiguration(), tableName);
198       Put put = new Put(row);
199       byte[] value = Bytes.toBytes("value");
200       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
201       table.put(put);
202       admin.flush(tableName.getName());
203       List<HRegion> regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
204       for(HRegion region : regions) {
205         Store store = region.getStore(fam);
206         while(!(store.getStorefilesCount() > 0)) {
207           Thread.sleep(10);
208         }
209       }
210 
211       Put put1 = new Put(row1);
212       byte[] value1 = Bytes.toBytes("1000dfsdf");
213       put1.add(fam, qual, HConstants.LATEST_TIMESTAMP, value1);
214       table.put(put1);
215       admin.flush(tableName.getName());
216       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
217       for(HRegion region : regions) {
218         Store store = region.getStore(fam);
219         while(!(store.getStorefilesCount() > 1)) {
220           Thread.sleep(10);
221         }
222       }
223 
224       Put put2 = new Put(row2);
225       byte[] value2 = Bytes.toBytes("1000dfsdf");
226       put2.add(fam, qual, HConstants.LATEST_TIMESTAMP, value2);
227       table.put(put2);
228 
229       admin.flush(tableName.getName());
230       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
231       for(HRegion region : regions) {
232         Store store = region.getStore(fam);
233         while(!(store.getStorefilesCount() > 2)) {
234           Thread.sleep(10);
235         }
236       }
237       Scan s = new Scan(row);
238       ResultScanner scanner = table.getScanner(s);
239       try {
240         Result[] next = scanner.next(3);
241         for (Result result : next) {
242           CellScanner cellScanner = result.cellScanner();
243           boolean advance = cellScanner.advance();
244           KeyValue current = (KeyValue) cellScanner.current();
245           assertTrue(current.getValueOffset() + current.getValueLength() == current.getLength());
246         }
247       } finally {
248         if (scanner != null)
249           scanner.close();
250       }
251       admin.compact(tableName.getName());
252       while(admin.getCompactionState(tableName.getName()) != CompactionState.NONE) {
253         Thread.sleep(10);
254       }
255       s = new Scan(row);
256       scanner = table.getScanner(s);
257       try {
258         Result[] next = scanner.next(3);
259         for (Result result : next) {
260           CellScanner cellScanner = result.cellScanner();
261           boolean advance = cellScanner.advance();
262           KeyValue current = (KeyValue) cellScanner.current();
263           assertTrue(current.getValueOffset() + current.getValueLength() == current.getLength());
264         }
265       } finally {
266         if (scanner != null) {
267           scanner.close();
268         }
269       }
270     } finally {
271       if (table != null) {
272         table.close();
273       }
274     }
275   }
276   @Test
277   public void testFlushAndCompactionwithCombinations() throws Exception {
278     HTable table = null;
279     try {
280       TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
281       byte[] fam = Bytes.toBytes("info");
282       byte[] row = Bytes.toBytes("rowa");
283       // column names
284       byte[] qual = Bytes.toBytes("qual");
285 
286       byte[] row1 = Bytes.toBytes("rowb");
287 
288       byte[] row2 = Bytes.toBytes("rowc");
289       byte[] rowd = Bytes.toBytes("rowd");
290       byte[] rowe = Bytes.toBytes("rowe");
291 
292       HTableDescriptor desc = new HTableDescriptor(tableName);
293       HColumnDescriptor colDesc = new HColumnDescriptor(fam);
294       colDesc.setBlockCacheEnabled(true);
295       // colDesc.setDataBlockEncoding(DataBlockEncoding.NONE);
296       colDesc.setDataBlockEncoding(DataBlockEncoding.PREFIX_TREE);
297       desc.addFamily(colDesc);
298       HBaseAdmin admin = TEST_UTIL.getHBaseAdmin();
299       admin.createTable(desc);
300 
301       table = new HTable(TEST_UTIL.getConfiguration(), tableName);
302       Put put = new Put(row);
303       byte[] value = Bytes.toBytes("value");
304       put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
305       put.setAttribute("visibility", Bytes.toBytes("ram"));
306       table.put(put);
307       Put put1 = new Put(row1);
308       byte[] value1 = Bytes.toBytes("1000dfsdf");
309       put1.add(fam, qual, HConstants.LATEST_TIMESTAMP, value1);
310       table.put(put1);
311       admin.flush(tableName.getName());
312       List<HRegion> regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
313       for(HRegion region : regions) {
314         Store store = region.getStore(fam);
315         while(!(store.getStorefilesCount() > 0)) {
316           Thread.sleep(10);
317         }
318       }
319 
320       put1 = new Put(row2);
321       value1 = Bytes.toBytes("1000dfsdf");
322       put1.add(fam, qual, HConstants.LATEST_TIMESTAMP, value1);
323       table.put(put1);
324       admin.flush(tableName.getName());
325       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
326       for(HRegion region : regions) {
327         Store store = region.getStore(fam);
328         while(!(store.getStorefilesCount() > 1)) {
329           Thread.sleep(10);
330         }
331       }
332       Put put2 = new Put(rowd);
333       byte[] value2 = Bytes.toBytes("1000dfsdf");
334       put2.add(fam, qual, HConstants.LATEST_TIMESTAMP, value2);
335       table.put(put2);
336       put2 = new Put(rowe);
337       value2 = Bytes.toBytes("1000dfsddfdf");
338       put2.add(fam, qual, HConstants.LATEST_TIMESTAMP, value2);
339       put.setAttribute("visibility", Bytes.toBytes("ram"));
340       table.put(put2);
341       admin.flush(tableName.getName());
342       regions = TEST_UTIL.getHBaseCluster().getRegions(tableName.getName());
343       for(HRegion region : regions) {
344         Store store = region.getStore(fam);
345         while(!(store.getStorefilesCount() > 2)) {
346           Thread.sleep(10);
347         }
348       }
349       Scan s = new Scan(row);
350       ResultScanner scanner = table.getScanner(s);
351       try {
352         Result[] next = scanner.next(5);
353         for (Result result : next) {
354           CellScanner cellScanner = result.cellScanner();
355           boolean advance = cellScanner.advance();
356           KeyValue current = (KeyValue) cellScanner.current();
357           // System.out.println(current);
358           int tagsLength = current.getTagsLength();
359           if (tagsLength == 0) {
360             assertTrue(current.getValueOffset() + current.getValueLength() == current.getLength());
361           } else {
362             // even if taglength is going to be > 0 the byte array would be same
363             assertTrue(current.getValueOffset() + current.getValueLength() != current.getLength());
364           }
365         }
366       } finally {
367         if (scanner != null) {
368           scanner.close();
369         }
370       }
371       while(admin.getCompactionState(tableName.getName()) != CompactionState.NONE) {
372         Thread.sleep(10);
373       }
374       s = new Scan(row);
375       scanner = table.getScanner(s);
376       try {
377         Result[] next = scanner.next(5);
378         for (Result result : next) {
379           CellScanner cellScanner = result.cellScanner();
380           boolean advance = cellScanner.advance();
381           KeyValue current = (KeyValue) cellScanner.current();
382           // System.out.println(current);
383           if (current.getTagsLength() == 0) {
384             assertTrue(current.getValueOffset() + current.getValueLength() == current.getLength());
385           } else {
386             // even if taglength is going to be > 0 the byte array would be same
387             assertTrue(current.getValueOffset() + current.getValueLength() != current.getLength());
388           }
389         }
390       } finally {
391         if (scanner != null) {
392           scanner.close();
393         }
394       }
395     } finally {
396       if (table != null) {
397         table.close();
398       }
399     }
400   }
401 
402   @Test
403   public void testTagsWithAppendAndIncrement() throws Exception {
404     TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
405     byte[] f = Bytes.toBytes("f");
406     byte[] q = Bytes.toBytes("q");
407     byte[] row1 = Bytes.toBytes("r1");
408     byte[] row2 = Bytes.toBytes("r2");
409 
410     HTableDescriptor desc = new HTableDescriptor(tableName);
411     HColumnDescriptor colDesc = new HColumnDescriptor(f);
412     desc.addFamily(colDesc);
413     TEST_UTIL.getHBaseAdmin().createTable(desc);
414 
415     HTable table = null;
416     try {
417       table = new HTable(TEST_UTIL.getConfiguration(), tableName);
418       Put put = new Put(row1);
419       byte[] v = Bytes.toBytes(2L);
420       put.add(f, q, v);
421       put.setAttribute("visibility", Bytes.toBytes("tag1"));
422       table.put(put);
423       Increment increment = new Increment(row1);
424       increment.addColumn(f, q, 1L);
425       table.increment(increment);
426       TestCoprocessorForTags.checkTagPresence = true;
427       ResultScanner scanner = table.getScanner(new Scan());
428       Result result = scanner.next();
429       KeyValue kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
430       List<Tag> tags = TestCoprocessorForTags.tags;
431       assertEquals(3L, Bytes.toLong(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()));
432       assertEquals(1, tags.size());
433       assertEquals("tag1", Bytes.toString(tags.get(0).getValue()));
434       TestCoprocessorForTags.checkTagPresence = false;
435       TestCoprocessorForTags.tags = null;
436 
437       increment = new Increment(row1);
438       increment.add(new KeyValue(row1, f, q, 1234L, v));
439       increment.setAttribute("visibility", Bytes.toBytes("tag2"));
440       table.increment(increment);
441       TestCoprocessorForTags.checkTagPresence = true;
442       scanner = table.getScanner(new Scan());
443       result = scanner.next();
444       kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
445       tags = TestCoprocessorForTags.tags;
446       assertEquals(5L, Bytes.toLong(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()));
447       assertEquals(2, tags.size());
448       assertEquals("tag1", Bytes.toString(tags.get(0).getValue()));
449       assertEquals("tag2", Bytes.toString(tags.get(1).getValue()));
450       TestCoprocessorForTags.checkTagPresence = false;
451       TestCoprocessorForTags.tags = null;
452 
453       put = new Put(row2);
454       v = Bytes.toBytes(2L);
455       put.add(f, q, v);
456       table.put(put);
457       increment = new Increment(row2);
458       increment.add(new KeyValue(row2, f, q, 1234L, v));
459       increment.setAttribute("visibility", Bytes.toBytes("tag2"));
460       table.increment(increment);
461       Scan scan = new Scan();
462       scan.setStartRow(row2);
463       TestCoprocessorForTags.checkTagPresence = true;
464       scanner = table.getScanner(scan);
465       result = scanner.next();
466       kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
467       tags = TestCoprocessorForTags.tags;
468       assertEquals(4L, Bytes.toLong(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()));
469       assertEquals(1, tags.size());
470       assertEquals("tag2", Bytes.toString(tags.get(0).getValue()));
471       TestCoprocessorForTags.checkTagPresence = false;
472       TestCoprocessorForTags.tags = null;
473 
474       // Test Append
475       byte[] row3 = Bytes.toBytes("r3");
476       put = new Put(row3);
477       put.add(f, q, Bytes.toBytes("a"));
478       put.setAttribute("visibility", Bytes.toBytes("tag1"));
479       table.put(put);
480       Append append = new Append(row3);
481       append.add(f, q, Bytes.toBytes("b"));
482       table.append(append);
483       scan = new Scan();
484       scan.setStartRow(row3);
485       TestCoprocessorForTags.checkTagPresence = true;
486       scanner = table.getScanner(scan);
487       result = scanner.next();
488       kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
489       tags = TestCoprocessorForTags.tags;
490       assertEquals(1, tags.size());
491       assertEquals("tag1", Bytes.toString(tags.get(0).getValue()));
492       TestCoprocessorForTags.checkTagPresence = false;
493       TestCoprocessorForTags.tags = null;
494 
495       append = new Append(row3);
496       append.add(new KeyValue(row3, f, q, 1234L, v));
497       append.setAttribute("visibility", Bytes.toBytes("tag2"));
498       table.append(append);
499       TestCoprocessorForTags.checkTagPresence = true;
500       scanner = table.getScanner(scan);
501       result = scanner.next();
502       kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
503       tags = TestCoprocessorForTags.tags;
504       assertEquals(2, tags.size());
505       assertEquals("tag1", Bytes.toString(tags.get(0).getValue()));
506       assertEquals("tag2", Bytes.toString(tags.get(1).getValue()));
507       TestCoprocessorForTags.checkTagPresence = false;
508       TestCoprocessorForTags.tags = null;
509 
510       byte[] row4 = Bytes.toBytes("r4");
511       put = new Put(row4);
512       put.add(f, q, Bytes.toBytes("a"));
513       table.put(put);
514       append = new Append(row4);
515       append.add(new KeyValue(row4, f, q, 1234L, v));
516       append.setAttribute("visibility", Bytes.toBytes("tag2"));
517       table.append(append);
518       scan = new Scan();
519       scan.setStartRow(row4);
520       TestCoprocessorForTags.checkTagPresence = true;
521       scanner = table.getScanner(scan);
522       result = scanner.next();
523       kv = KeyValueUtil.ensureKeyValue(result.getColumnLatestCell(f, q));
524       tags = TestCoprocessorForTags.tags;
525       assertEquals(1, tags.size());
526       assertEquals("tag2", Bytes.toString(tags.get(0).getValue()));
527     } finally {
528       TestCoprocessorForTags.checkTagPresence = false;
529       TestCoprocessorForTags.tags = null;
530       if (table != null) {
531         table.close();
532       }
533     }
534   }
535 
536   private void result(byte[] fam, byte[] row, byte[] qual, byte[] row2, HTable table, byte[] value,
537       byte[] value2, byte[] row1, byte[] value1) throws IOException {
538     Scan s = new Scan(row);
539     // If filters are used this attribute can be specifically check for in
540     // filterKV method and
541     // kvs can be filtered out if the tags of interest is not found in that kv
542     s.setAttribute("visibility", Bytes.toBytes("myTag"));
543     ResultScanner scanner = null;
544     try {
545       scanner = table.getScanner(s);
546       Result next = scanner.next();
547       CellScanner cellScanner = next.cellScanner();
548       boolean advance = cellScanner.advance();
549       KeyValue current = (KeyValue) cellScanner.current();
550 
551       assertTrue(Bytes.equals(next.getRow(), row));
552       assertTrue(Bytes.equals(next.getValue(fam, qual), value));
553 
554       Result next2 = scanner.next();
555       assertTrue(next2 != null);
556       assertTrue(Bytes.equals(next2.getRow(), row1));
557       assertTrue(Bytes.equals(next2.getValue(fam, qual), value1));
558 
559       next2 = scanner.next();
560       assertTrue(next2 != null);
561       assertTrue(Bytes.equals(next2.getRow(), row2));
562       assertTrue(Bytes.equals(next2.getValue(fam, qual), value2));
563 
564     } finally {
565       if (scanner != null)
566         scanner.close();
567     }
568   }
569 
570   public static class TestCoprocessorForTags extends BaseRegionObserver {
571 
572     public static boolean checkTagPresence = false;
573     public static List<Tag> tags = null;
574 
575     @Override
576     public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e, final Put put,
577         final WALEdit edit, final Durability durability) throws IOException {
578       updateMutationAddingTags(put);
579     }
580 
581     private void updateMutationAddingTags(final Mutation m) {
582       byte[] attribute = m.getAttribute("visibility");
583       byte[] cf = null;
584       List<Cell> updatedCells = new ArrayList<Cell>();
585       if (attribute != null) {
586         for (List<? extends Cell> edits : m.getFamilyCellMap().values()) {
587           for (Cell cell : edits) {
588             KeyValue kv = KeyValueUtil.ensureKeyValue(cell);
589             if (cf == null) {
590               cf = kv.getFamily();
591             }
592             Tag tag = new Tag((byte) 1, attribute);
593             List<Tag> tagList = new ArrayList<Tag>();
594             tagList.add(tag);
595 
596             KeyValue newKV = new KeyValue(kv.getRow(), 0, kv.getRowLength(), kv.getFamily(), 0,
597                 kv.getFamilyLength(), kv.getQualifier(), 0, kv.getQualifierLength(),
598                 kv.getTimestamp(), KeyValue.Type.codeToType(kv.getType()), kv.getValue(), 0,
599                 kv.getValueLength(), tagList);
600             ((List<Cell>) updatedCells).add(newKV);
601           }
602         }
603         m.getFamilyCellMap().remove(cf);
604         // Update the family map
605         m.getFamilyCellMap().put(cf, updatedCells);
606       }
607     }
608 
609     @Override
610     public Result preIncrement(ObserverContext<RegionCoprocessorEnvironment> e, Increment increment)
611         throws IOException {
612       updateMutationAddingTags(increment);
613       return super.preIncrement(e, increment);
614     }
615 
616     @Override
617     public Result preAppend(ObserverContext<RegionCoprocessorEnvironment> e, Append append)
618         throws IOException {
619       updateMutationAddingTags(append);
620       return super.preAppend(e, append);
621     }
622 
623     @Override
624     public boolean postScannerNext(ObserverContext<RegionCoprocessorEnvironment> e,
625         InternalScanner s, List<Result> results, int limit, boolean hasMore) throws IOException {
626       if (checkTagPresence) {
627         if (results.size() > 0) {
628           // Check tag presence in the 1st cell in 1st Result
629           Result result = results.get(0);
630           CellScanner cellScanner = result.cellScanner();
631           if (cellScanner.advance()) {
632             Cell cell = cellScanner.current();
633             tags = Tag.asList(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
634           }
635         }
636       }
637       return hasMore;
638     }
639   }
640 }