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 junit.framework.TestCase;
21  import org.apache.hadoop.hbase.testclassification.SmallTests;
22  import org.junit.experimental.categories.Category;
23  
24  import java.util.Random;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  import java.util.concurrent.atomic.AtomicLong;
27  
28  /**
29   * This is a hammer test that verifies MultiVersionConsistencyControl in a
30   * multiple writer single reader scenario.
31   */
32  @Category(SmallTests.class)
33  public class TestMultiVersionConsistencyControl extends TestCase {
34    static class Writer implements Runnable {
35      final AtomicBoolean finished;
36      final MultiVersionConsistencyControl mvcc;
37      final AtomicBoolean status;
38  
39      Writer(AtomicBoolean finished, MultiVersionConsistencyControl mvcc, AtomicBoolean status) {
40        this.finished = finished;
41        this.mvcc = mvcc;
42        this.status = status;
43      }
44  
45      private Random rnd = new Random();
46      public boolean failed = false;
47  
48      public void run() {
49        while (!finished.get()) {
50          MultiVersionConsistencyControl.WriteEntry e = mvcc.beginMemstoreInsert();
51          // System.out.println("Begin write: " + e.getWriteNumber());
52          // 10 usec - 500usec (including 0)
53          int sleepTime = rnd.nextInt(500);
54          // 500 * 1000 = 500,000ns = 500 usec
55          // 1 * 100 = 100ns = 1usec
56          try {
57            if (sleepTime > 0) Thread.sleep(0, sleepTime * 1000);
58          } catch (InterruptedException e1) {
59          }
60          try {
61            mvcc.completeMemstoreInsert(e);
62          } catch (RuntimeException ex) {
63            // got failure
64            System.out.println(ex.toString());
65            ex.printStackTrace();
66            status.set(false);
67            return;
68            // Report failure if possible.
69          }
70        }
71      }
72    }
73  
74    public void testParallelism() throws Exception {
75      final MultiVersionConsistencyControl mvcc = new MultiVersionConsistencyControl();
76  
77      final AtomicBoolean finished = new AtomicBoolean(false);
78  
79      // fail flag for the reader thread
80      final AtomicBoolean readerFailed = new AtomicBoolean(false);
81      final AtomicLong failedAt = new AtomicLong();
82      Runnable reader = new Runnable() {
83        public void run() {
84          long prev = mvcc.memstoreReadPoint();
85          while (!finished.get()) {
86            long newPrev = mvcc.memstoreReadPoint();
87            if (newPrev < prev) {
88              // serious problem.
89              System.out.println("Reader got out of order, prev: " + prev + " next was: " + newPrev);
90              readerFailed.set(true);
91              // might as well give up
92              failedAt.set(newPrev);
93              return;
94            }
95          }
96        }
97      };
98  
99      // writer thread parallelism.
100     int n = 20;
101     Thread[] writers = new Thread[n];
102     AtomicBoolean[] statuses = new AtomicBoolean[n];
103     Thread readThread = new Thread(reader);
104 
105     for (int i = 0; i < n; ++i) {
106       statuses[i] = new AtomicBoolean(true);
107       writers[i] = new Thread(new Writer(finished, mvcc, statuses[i]));
108       writers[i].start();
109     }
110     readThread.start();
111 
112     try {
113       Thread.sleep(10 * 1000);
114     } catch (InterruptedException ex) {
115     }
116 
117     finished.set(true);
118 
119     readThread.join();
120     for (int i = 0; i < n; ++i) {
121       writers[i].join();
122     }
123 
124     // check failure.
125     assertFalse(readerFailed.get());
126     for (int i = 0; i < n; ++i) {
127       assertTrue(statuses[i].get());
128     }
129 
130   }
131 
132 }