1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase.coprocessor;
22  
23  import java.io.IOException;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.fs.Path;
29  import org.apache.hadoop.hbase.HBaseConfiguration;
30  import org.apache.hadoop.hbase.HColumnDescriptor;
31  import org.apache.hadoop.hbase.HRegionInfo;
32  import org.apache.hadoop.hbase.HTableDescriptor;
33  import org.apache.hadoop.hbase.Coprocessor;
34  import org.apache.hadoop.hbase.KeyValue;
35  import org.apache.hadoop.hbase.client.Put;
36  import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost;
37  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
38  import org.apache.hadoop.hbase.regionserver.HRegion;
39  import org.apache.hadoop.hbase.util.Bytes;
40  
41  import junit.framework.TestCase;
42  
43  public class TestRegionObserverStacking extends TestCase {
44    static final String DIR = "test/build/data/TestRegionObserverStacking/";
45  
46    public static class ObserverA extends BaseRegionObserver {
47      long id;
48      @Override
49      public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
50          final Put put, final WALEdit edit,
51          final boolean writeToWAL)
52          throws IOException {
53        id = System.currentTimeMillis();
54        try {
55          Thread.sleep(10);
56        } catch (InterruptedException ex) {
57        }
58      }
59    }
60  
61    public static class ObserverB extends BaseRegionObserver {
62      long id;
63      @Override
64      public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
65          final Put put, final WALEdit edit,
66          final boolean writeToWAL)
67          throws IOException {
68        id = System.currentTimeMillis();
69        try {
70          Thread.sleep(10);
71        } catch (InterruptedException ex) {
72        }
73      }
74    }
75  
76    public static class ObserverC extends BaseRegionObserver {
77      long id;
78  
79      @Override
80      public void postPut(final ObserverContext<RegionCoprocessorEnvironment> c,
81          final Put put, final WALEdit edit,
82          final boolean writeToWAL)
83          throws IOException {
84        id = System.currentTimeMillis();
85        try {
86          Thread.sleep(10);
87        } catch (InterruptedException ex) {
88        }
89      }
90    }
91  
92    HRegion initHRegion (byte [] tableName, String callingMethod,
93        Configuration conf, byte [] ... families) throws IOException {
94      HTableDescriptor htd = new HTableDescriptor(tableName);
95      for(byte [] family : families) {
96        htd.addFamily(new HColumnDescriptor(family));
97      }
98      HRegionInfo info = new HRegionInfo(htd.getName(), null, null, false);
99      Path path = new Path(DIR + callingMethod);
100     HRegion r = HRegion.createHRegion(info, path, conf, htd);
101     // this following piece is a hack. currently a coprocessorHost
102     // is secretly loaded at OpenRegionHandler. we don't really
103     // start a region server here, so just manually create cphost
104     // and set it to region.
105     RegionCoprocessorHost host = new RegionCoprocessorHost(r, null, conf);
106     r.setCoprocessorHost(host);
107     return r;
108   }
109 
110   public void testRegionObserverStacking() throws Exception {
111     byte[] ROW = Bytes.toBytes("testRow");
112     byte[] TABLE = Bytes.toBytes(getClass().getName());
113     byte[] A = Bytes.toBytes("A");
114     byte[][] FAMILIES = new byte[][] { A } ;
115 
116     Configuration conf = HBaseConfiguration.create();
117     HRegion region = initHRegion(TABLE, getClass().getName(),
118       conf, FAMILIES);
119     RegionCoprocessorHost h = region.getCoprocessorHost();
120     h.load(ObserverA.class, Coprocessor.PRIORITY_HIGHEST, conf);
121     h.load(ObserverB.class, Coprocessor.PRIORITY_USER, conf);
122     h.load(ObserverC.class, Coprocessor.PRIORITY_LOWEST, conf);
123 
124     Put put = new Put(ROW);
125     put.add(A, A, A);
126     int lockid = region.obtainRowLock(ROW);
127     region.put(put, lockid);
128     region.releaseRowLock(lockid);
129 
130     Coprocessor c = h.findCoprocessor(ObserverA.class.getName());
131     long idA = ((ObserverA)c).id;
132     c = h.findCoprocessor(ObserverB.class.getName());
133     long idB = ((ObserverB)c).id;
134     c = h.findCoprocessor(ObserverC.class.getName());
135     long idC = ((ObserverC)c).id;
136 
137     assertTrue(idA < idB);
138     assertTrue(idB < idC);
139   }
140 }