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.omid.transaction;
19  
20  import org.apache.hadoop.hbase.client.Delete;
21  import org.apache.hadoop.hbase.client.Get;
22  import org.apache.hadoop.hbase.client.HTable;
23  import org.apache.hadoop.hbase.client.Put;
24  import org.apache.hadoop.hbase.client.Result;
25  import org.apache.hadoop.hbase.client.ResultScanner;
26  import org.apache.hadoop.hbase.client.Scan;
27  import org.apache.hadoop.hbase.util.Bytes;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  import org.testng.ITestContext;
31  import org.testng.annotations.Test;
32  
33  import java.io.IOException;
34  import java.util.HashMap;
35  import java.util.Map;
36  
37  import static org.testng.Assert.assertEquals;
38  import static org.testng.Assert.assertTrue;
39  
40  @Test(groups = "sharedHBase")
41  public class TestDeletion extends OmidTestBase {
42  
43      private static final Logger LOG = LoggerFactory.getLogger(TestDeletion.class);
44  
45      private byte[] famA = Bytes.toBytes(TEST_FAMILY);
46      private byte[] famB = Bytes.toBytes(TEST_FAMILY2);
47      private byte[] colA = Bytes.toBytes("testdataA");
48      private byte[] colB = Bytes.toBytes("testdataB");
49      private byte[] data1 = Bytes.toBytes("testWrite-1");
50      private byte[] modrow = Bytes.toBytes("test-del" + 3);
51  
52      private static class FamCol {
53  
54          final byte[] fam;
55          final byte[] col;
56  
57          FamCol(byte[] fam, byte[] col) {
58              this.fam = fam;
59              this.col = col;
60          }
61  
62      }
63  
64      @Test
65      public void runTestDeleteFamily(ITestContext context) throws Exception {
66  
67          TransactionManager tm = newTransactionManager(context);
68          TTable tt = new TTable(hbaseConf, TEST_TABLE);
69  
70          Transaction t1 = tm.begin();
71          LOG.info("Transaction created " + t1);
72  
73          int rowsWritten = 10;
74          FamCol famColA = new FamCol(famA, colA);
75          FamCol famColB = new FamCol(famB, colB);
76          writeRows(tt, t1, rowsWritten, famColA, famColB);
77          tm.commit(t1);
78  
79          Transaction t2 = tm.begin();
80          Delete d = new Delete(modrow);
81          d.deleteFamily(famA);
82          tt.delete(t2, d);
83  
84          Transaction tscan = tm.begin();
85          ResultScanner rs = tt.getScanner(tscan, new Scan());
86  
87          Map<FamCol, Integer> count = countColsInRows(rs, famColA, famColB);
88          assertEquals((int) count.get(famColA), rowsWritten, "ColA count should be equal to rowsWritten");
89          assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
90          tm.commit(t2);
91  
92          tscan = tm.begin();
93          rs = tt.getScanner(tscan, new Scan());
94  
95          count = countColsInRows(rs, famColA, famColB);
96          assertEquals((int) count.get(famColA), (rowsWritten - 1), "ColA count should be equal to rowsWritten - 1");
97          assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
98  
99      }
100 
101     @Test
102     public void runTestDeleteColumn(ITestContext context) throws Exception {
103 
104         TransactionManager tm = newTransactionManager(context);
105         TTable tt = new TTable(hbaseConf, TEST_TABLE);
106 
107         Transaction t1 = tm.begin();
108         LOG.info("Transaction created " + t1);
109 
110         int rowsWritten = 10;
111 
112         FamCol famColA = new FamCol(famA, colA);
113         FamCol famColB = new FamCol(famA, colB);
114         writeRows(tt, t1, rowsWritten, famColA, famColB);
115         tm.commit(t1);
116 
117         Transaction t2 = tm.begin();
118         Delete d = new Delete(modrow);
119         d.deleteColumn(famA, colA);
120         tt.delete(t2, d);
121 
122         Transaction tscan = tm.begin();
123         ResultScanner rs = tt.getScanner(tscan, new Scan());
124 
125         Map<FamCol, Integer> count = countColsInRows(rs, famColA, famColB);
126         assertEquals((int) count.get(famColA), rowsWritten, "ColA count should be equal to rowsWritten");
127         assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
128         tm.commit(t2);
129 
130         tscan = tm.begin();
131         rs = tt.getScanner(tscan, new Scan());
132 
133         count = countColsInRows(rs, famColA, famColB);
134         assertEquals((int) count.get(famColA), (rowsWritten - 1), "ColA count should be equal to rowsWritten - 1");
135         assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
136 
137     }
138 
139     /**
140      * This test is very similar to #runTestDeleteColumn() but exercises Delete#deleteColumns()
141      */
142     @Test
143     public void runTestDeleteColumns(ITestContext context) throws Exception {
144 
145         TransactionManager tm = newTransactionManager(context);
146         TTable tt = new TTable(hbaseConf, TEST_TABLE);
147 
148         Transaction t1 = tm.begin();
149         LOG.info("Transaction created " + t1);
150 
151         int rowsWritten = 10;
152 
153         FamCol famColA = new FamCol(famA, colA);
154         FamCol famColB = new FamCol(famA, colB);
155         writeRows(tt, t1, rowsWritten, famColA, famColB);
156         tm.commit(t1);
157 
158         Transaction t2 = tm.begin();
159         Delete d = new Delete(modrow);
160         d.deleteColumns(famA, colA);
161         tt.delete(t2, d);
162 
163         Transaction tscan = tm.begin();
164         ResultScanner rs = tt.getScanner(tscan, new Scan());
165 
166         Map<FamCol, Integer> count = countColsInRows(rs, famColA, famColB);
167         assertEquals((int) count.get(famColA), rowsWritten, "ColA count should be equal to rowsWritten");
168         assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
169         tm.commit(t2);
170 
171         tscan = tm.begin();
172         rs = tt.getScanner(tscan, new Scan());
173 
174         count = countColsInRows(rs, famColA, famColB);
175 
176         assertEquals((int) count.get(famColA), (rowsWritten - 1), "ColA count should be equal to rowsWritten - 1");
177         assertEquals((int) count.get(famColB), rowsWritten, "ColB count should be equal to rowsWritten");
178 
179     }
180 
181     @Test
182     public void runTestDeleteRow(ITestContext context) throws Exception {
183         TransactionManager tm = newTransactionManager(context);
184         TTable tt = new TTable(hbaseConf, TEST_TABLE);
185 
186         Transaction t1 = tm.begin();
187         LOG.info("Transaction created " + t1);
188 
189         int rowsWritten = 10;
190 
191         FamCol famColA = new FamCol(famA, colA);
192         writeRows(tt, t1, rowsWritten, famColA);
193 
194         tm.commit(t1);
195 
196         Transaction t2 = tm.begin();
197         Delete d = new Delete(modrow);
198         tt.delete(t2, d);
199 
200         Transaction tscan = tm.begin();
201         ResultScanner rs = tt.getScanner(tscan, new Scan());
202 
203         int rowsRead = countRows(rs);
204         assertTrue(rowsRead == rowsWritten, "Expected " + rowsWritten + " rows but " + rowsRead + " found");
205 
206         tm.commit(t2);
207 
208         tscan = tm.begin();
209         rs = tt.getScanner(tscan, new Scan());
210 
211         rowsRead = countRows(rs);
212         assertTrue(rowsRead == (rowsWritten - 1), "Expected " + (rowsWritten - 1) + " rows but " + rowsRead + " found");
213 
214     }
215 
216     @Test
217     public void testDeletionOfNonExistingColumnFamilyDoesNotWriteToHBase(ITestContext context) throws Exception {
218 
219         // --------------------------------------------------------------------
220         // Setup initial environment for the test
221         // --------------------------------------------------------------------
222         TransactionManager tm = newTransactionManager(context);
223         TTable txTable = new TTable(hbaseConf, TEST_TABLE);
224 
225         Transaction tx1 = tm.begin();
226         LOG.info("{} writing initial data created ", tx1);
227         Put p = new Put(Bytes.toBytes("row1"));
228         p.add(famA, colA, data1);
229         txTable.put(tx1, p);
230         tm.commit(tx1);
231 
232         // --------------------------------------------------------------------
233         // Try to delete a non existing CF
234         // --------------------------------------------------------------------
235         Transaction deleteTx = tm.begin();
236         LOG.info("{} trying to delete a non-existing family created ", deleteTx);
237         Delete del = new Delete(Bytes.toBytes("row1"));
238         del.deleteFamily(famB);
239         // This delete should not put data on HBase
240         txTable.delete(deleteTx, del);
241 
242         // --------------------------------------------------------------------
243         // Check data has not been written to HBase
244         // --------------------------------------------------------------------
245         HTable table = new HTable(hbaseConf, TEST_TABLE);
246         Get get = new Get(Bytes.toBytes("row1"));
247         get.setTimeStamp(deleteTx.getTransactionId());
248         Result result = table.get(get);
249         assertTrue(result.isEmpty());
250 
251     }
252 
253     private int countRows(ResultScanner rs) throws IOException {
254         int count;
255         Result r = rs.next();
256         count = 0;
257         while (r != null) {
258             count++;
259             LOG.trace("row: " + Bytes.toString(r.getRow()) + " count: " + count);
260             r = rs.next();
261         }
262         return count;
263     }
264 
265     private void writeRows(TTable tt, Transaction t1, int rowcount, FamCol... famCols) throws IOException {
266         for (int i = 0; i < rowcount; i++) {
267             byte[] row = Bytes.toBytes("test-del" + i);
268 
269             Put p = new Put(row);
270             for (FamCol col : famCols) {
271                 p.add(col.fam, col.col, data1);
272             }
273             tt.put(t1, p);
274         }
275     }
276 
277     private Map<FamCol, Integer> countColsInRows(ResultScanner rs, FamCol... famCols) throws IOException {
278         Map<FamCol, Integer> colCount = new HashMap<>();
279         Result r = rs.next();
280         while (r != null) {
281             for (FamCol col : famCols) {
282                 if (r.containsColumn(col.fam, col.col)) {
283                     Integer c = colCount.get(col);
284 
285                     if (c == null) {
286                         colCount.put(col, 1);
287                     } else {
288                         colCount.put(col, c + 1);
289                     }
290                 }
291             }
292             r = rs.next();
293         }
294         return colCount;
295     }
296 
297 }