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  
19  package org.apache.hadoop.hbase.procedure2.store;
20  
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.util.Random;
24  import java.util.concurrent.atomic.AtomicLong;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.hbase.testclassification.SmallTests;
29  
30  import org.junit.Assert;
31  import org.junit.Test;
32  import org.junit.experimental.categories.Category;
33  
34  import static org.junit.Assert.assertEquals;
35  import static org.junit.Assert.assertFalse;
36  import static org.junit.Assert.assertTrue;
37  import static org.junit.Assert.fail;
38  
39  @Category(SmallTests.class)
40  public class TestProcedureStoreTracker {
41    private static final Log LOG = LogFactory.getLog(TestProcedureStoreTracker.class);
42  
43    @Test
44    public void testSeqInsertAndDelete() {
45      ProcedureStoreTracker tracker = new ProcedureStoreTracker();
46      assertTrue(tracker.isEmpty());
47  
48      final int MIN_PROC = 1;
49      final int MAX_PROC = 1 << 10;
50  
51      // sequential insert
52      for (int i = MIN_PROC; i < MAX_PROC; ++i) {
53        tracker.insert(i);
54  
55        // All the proc that we inserted should not be deleted
56        for (int j = MIN_PROC; j <= i; ++j) {
57          assertEquals(ProcedureStoreTracker.DeleteState.NO, tracker.isDeleted(j));
58        }
59        // All the proc that are not yet inserted should be result as deleted
60        for (int j = i + 1; j < MAX_PROC; ++j) {
61          assertTrue(tracker.isDeleted(j) != ProcedureStoreTracker.DeleteState.NO);
62        }
63      }
64  
65      // sequential delete
66      for (int i = MIN_PROC; i < MAX_PROC; ++i) {
67        tracker.delete(i);
68  
69        // All the proc that we deleted should be deleted
70        for (int j = MIN_PROC; j <= i; ++j) {
71          assertEquals(ProcedureStoreTracker.DeleteState.YES, tracker.isDeleted(j));
72        }
73        // All the proc that are not yet deleted should be result as not deleted
74        for (int j = i + 1; j < MAX_PROC; ++j) {
75          assertEquals(ProcedureStoreTracker.DeleteState.NO, tracker.isDeleted(j));
76        }
77      }
78      assertTrue(tracker.isEmpty());
79    }
80  
81    @Test
82    public void testPartialTracker() {
83      ProcedureStoreTracker tracker = new ProcedureStoreTracker();
84      tracker.setPartialFlag(true);
85  
86      // nothing in the tracker, the state is unknown
87      assertTrue(tracker.isEmpty());
88      assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(1));
89      assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(579));
90  
91      // Mark 1 as deleted, now that is a known state
92      tracker.setDeleted(1, true);
93      tracker.dump();
94      assertEquals(ProcedureStoreTracker.DeleteState.YES, tracker.isDeleted(1));
95      assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(2));
96      assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(579));
97  
98      // Mark 579 as non-deleted, now that is a known state
99      tracker.setDeleted(579, false);
100     assertEquals(ProcedureStoreTracker.DeleteState.YES, tracker.isDeleted(1));
101     assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(2));
102     assertEquals(ProcedureStoreTracker.DeleteState.NO, tracker.isDeleted(579));
103     assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(577));
104     assertEquals(ProcedureStoreTracker.DeleteState.MAYBE, tracker.isDeleted(580));
105 
106     tracker.setDeleted(579, true);
107     tracker.setPartialFlag(false);
108     assertTrue(tracker.isEmpty());
109   }
110 
111   @Test
112   public void testIsTracking() {
113     long[][] procIds = new long[][] {{4, 7}, {1024, 1027}, {8192, 8194}};
114     long[][] checkIds = new long[][] {{2, 8}, {1023, 1025}, {8193, 8191}};
115 
116     ProcedureStoreTracker tracker = new ProcedureStoreTracker();
117     for (int i = 0; i < procIds.length; ++i) {
118       long[] seq = procIds[i];
119       tracker.insert(seq[0]);
120       tracker.insert(seq[1]);
121     }
122 
123     for (int i = 0; i < procIds.length; ++i) {
124       long[] check = checkIds[i];
125       long[] seq = procIds[i];
126       assertTrue(tracker.isTracking(seq[0], seq[1]));
127       assertTrue(tracker.isTracking(check[0], check[1]));
128       tracker.delete(seq[0]);
129       tracker.delete(seq[1]);
130       assertFalse(tracker.isTracking(seq[0], seq[1]));
131       assertFalse(tracker.isTracking(check[0], check[1]));
132     }
133 
134     assertTrue(tracker.isEmpty());
135   }
136 
137   @Test
138   public void testBasicCRUD() {
139     ProcedureStoreTracker tracker = new ProcedureStoreTracker();
140     assertTrue(tracker.isEmpty());
141 
142     long[] procs = new long[] { 1, 2, 3, 4, 5, 6 };
143 
144     tracker.insert(procs[0]);
145     tracker.insert(procs[1], new long[] { procs[2], procs[3], procs[4] });
146     assertFalse(tracker.isEmpty());
147     assertTrue(tracker.isUpdated());
148 
149     tracker.resetUpdates();
150     assertFalse(tracker.isUpdated());
151 
152     for (int i = 0; i < 4; ++i) {
153       tracker.update(procs[i]);
154       assertFalse(tracker.isEmpty());
155       assertFalse(tracker.isUpdated());
156     }
157 
158     tracker.update(procs[4]);
159     assertFalse(tracker.isEmpty());
160     assertTrue(tracker.isUpdated());
161 
162     tracker.update(procs[5]);
163     assertFalse(tracker.isEmpty());
164     assertTrue(tracker.isUpdated());
165 
166     for (int i = 0; i < 5; ++i) {
167       tracker.delete(procs[i]);
168       assertFalse(tracker.isEmpty());
169       assertTrue(tracker.isUpdated());
170     }
171     tracker.delete(procs[5]);
172     assertTrue(tracker.isEmpty());
173   }
174 
175   @Test
176   public void testRandLoad() {
177     final int NPROCEDURES = 2500;
178     final int NRUNS = 5000;
179 
180     final ProcedureStoreTracker tracker = new ProcedureStoreTracker();
181 
182     Random rand = new Random(1);
183     for (int i = 0; i < NRUNS; ++i) {
184       assertTrue(tracker.isEmpty());
185 
186       int count = 0;
187       while (count < NPROCEDURES) {
188         long procId = rand.nextLong();
189         if (procId < 1) continue;
190 
191         tracker.setDeleted(procId, i % 2 == 0);
192         count++;
193       }
194 
195       tracker.reset();
196     }
197   }
198 
199   @Test
200   public void testLoad() {
201     final int MAX_PROCS = 1000;
202     final ProcedureStoreTracker tracker = new ProcedureStoreTracker();
203     for (int numProcs = 1; numProcs < MAX_PROCS; ++numProcs) {
204       for (int start = 1; start <= numProcs; ++start) {
205         assertTrue(tracker.isEmpty());
206 
207         LOG.debug("loading " + numProcs + " procs from start=" + start);
208         for (int i = start; i <= numProcs; ++i) {
209           tracker.setDeleted(i, false);
210         }
211         for (int i = 1; i < start; ++i) {
212           tracker.setDeleted(i, false);
213         }
214 
215         tracker.reset();
216       }
217     }
218   }
219 
220   @Test
221   public void testDelete() {
222     final ProcedureStoreTracker tracker = new ProcedureStoreTracker();
223 
224     long[] procIds = new long[] { 65, 1, 193 };
225     for (int i = 0; i < procIds.length; ++i) {
226       tracker.insert(procIds[i]);
227       tracker.dump();
228     }
229 
230     for (int i = 0; i < (64 * 4); ++i) {
231       boolean hasProc = false;
232       for (int j = 0; j < procIds.length; ++j) {
233         if (procIds[j] == i) {
234           hasProc = true;
235           break;
236         }
237       }
238       if (hasProc) {
239         assertEquals(ProcedureStoreTracker.DeleteState.NO, tracker.isDeleted(i));
240       } else {
241         assertEquals("procId=" + i, ProcedureStoreTracker.DeleteState.YES, tracker.isDeleted(i));
242       }
243     }
244   }
245 }