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.wal;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Map;
27  import java.util.Set;
28  
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.testclassification.SmallTests;
31  import org.apache.hadoop.hbase.util.Bytes;
32  import org.junit.Test;
33  import org.junit.experimental.categories.Category;
34  
35  @Category(SmallTests.class)
36  public class TestSequenceIdAccounting {
37    private static final byte [] ENCODED_REGION_NAME = Bytes.toBytes("r");
38    private static final byte [] FAMILY_NAME = Bytes.toBytes("cf");
39    private static final Set<byte[]> FAMILIES;
40    static {
41      FAMILIES = new HashSet<byte[]>();
42      FAMILIES.add(FAMILY_NAME);
43    }
44  
45    @Test
46    public void testStartCacheFlush() {
47      SequenceIdAccounting sida = new SequenceIdAccounting();
48      sida.getOrCreateLowestSequenceIds(ENCODED_REGION_NAME);
49      Map<byte[], Long> m = new HashMap<byte[], Long>();
50      m.put(ENCODED_REGION_NAME, HConstants.NO_SEQNUM);
51      assertEquals(HConstants.NO_SEQNUM, (long)sida.startCacheFlush(ENCODED_REGION_NAME, FAMILIES));
52      sida.completeCacheFlush(ENCODED_REGION_NAME);
53      long sequenceid = 1;
54      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid, true);
55      // Only one family so should return NO_SEQNUM still.
56      assertEquals(HConstants.NO_SEQNUM, (long)sida.startCacheFlush(ENCODED_REGION_NAME, FAMILIES));
57      sida.completeCacheFlush(ENCODED_REGION_NAME);
58      long currentSequenceId = sequenceid;
59      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid, true);
60      final Set<byte[]> otherFamily = new HashSet<byte[]>(1);
61      otherFamily.add(Bytes.toBytes("otherCf"));
62      sida.update(ENCODED_REGION_NAME, FAMILIES, ++sequenceid, true);
63      // Should return oldest sequence id in the region.
64      assertEquals(currentSequenceId, (long)sida.startCacheFlush(ENCODED_REGION_NAME, otherFamily));
65      sida.completeCacheFlush(ENCODED_REGION_NAME);
66    }
67  
68    @Test
69    public void testAreAllLower() {
70      SequenceIdAccounting sida = new SequenceIdAccounting();
71      sida.getOrCreateLowestSequenceIds(ENCODED_REGION_NAME);
72      Map<byte[], Long> m = new HashMap<byte[], Long>();
73      m.put(ENCODED_REGION_NAME, HConstants.NO_SEQNUM);
74      assertTrue(sida.areAllLower(m));
75      long sequenceid = 1;
76      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid, true);
77      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
78      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
79      assertTrue(sida.areAllLower(m));
80      m.put(ENCODED_REGION_NAME, sequenceid);
81      assertFalse(sida.areAllLower(m));
82      long lowest = sida.getLowestSequenceId(ENCODED_REGION_NAME);
83      assertEquals("Lowest should be first sequence id inserted", 1, lowest);
84      m.put(ENCODED_REGION_NAME, lowest);
85      assertFalse(sida.areAllLower(m));
86      // Now make sure above works when flushing.
87      sida.startCacheFlush(ENCODED_REGION_NAME, FAMILIES);
88      assertFalse(sida.areAllLower(m));
89      m.put(ENCODED_REGION_NAME, HConstants.NO_SEQNUM);
90      assertTrue(sida.areAllLower(m));
91      // Let the flush complete and if we ask if the sequenceid is lower, should be yes since no edits
92      sida.completeCacheFlush(ENCODED_REGION_NAME);
93      m.put(ENCODED_REGION_NAME, sequenceid);
94      assertTrue(sida.areAllLower(m));
95      // Flush again but add sequenceids while we are flushing.
96      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
97      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
98      sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
99      lowest = sida.getLowestSequenceId(ENCODED_REGION_NAME);
100     m.put(ENCODED_REGION_NAME, lowest);
101     assertFalse(sida.areAllLower(m));
102     sida.startCacheFlush(ENCODED_REGION_NAME, FAMILIES);
103     // The cache flush will clear out all sequenceid accounting by region.
104     assertEquals(HConstants.NO_SEQNUM, sida.getLowestSequenceId(ENCODED_REGION_NAME));
105     sida.completeCacheFlush(ENCODED_REGION_NAME);
106     // No new edits have gone in so no sequenceid to work with.
107     assertEquals(HConstants.NO_SEQNUM, sida.getLowestSequenceId(ENCODED_REGION_NAME));
108     // Make an edit behind all we'll put now into sida.
109     m.put(ENCODED_REGION_NAME, sequenceid);
110     sida.update(ENCODED_REGION_NAME, FAMILIES, ++sequenceid, true);
111     sida.update(ENCODED_REGION_NAME, FAMILIES, ++sequenceid, true);
112     sida.update(ENCODED_REGION_NAME, FAMILIES, ++sequenceid, true);
113     assertTrue(sida.areAllLower(m));
114   }
115 
116   @Test
117   public void testFindLower() {
118     SequenceIdAccounting sida = new SequenceIdAccounting();
119     sida.getOrCreateLowestSequenceIds(ENCODED_REGION_NAME);
120     Map<byte[], Long> m = new HashMap<byte[], Long>();
121     m.put(ENCODED_REGION_NAME, HConstants.NO_SEQNUM);
122     long sequenceid = 1;
123     sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid, true);
124     sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
125     sida.update(ENCODED_REGION_NAME, FAMILIES, sequenceid++, true);
126     assertTrue(sida.findLower(m) == null);
127     m.put(ENCODED_REGION_NAME, sida.getLowestSequenceId(ENCODED_REGION_NAME));
128     assertTrue(sida.findLower(m).length == 1);
129     m.put(ENCODED_REGION_NAME, sida.getLowestSequenceId(ENCODED_REGION_NAME) - 1);
130     assertTrue(sida.findLower(m) == null);
131   }
132 }