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.conf;
20  
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.testclassification.SmallTests;
28  import org.junit.Test;
29  import org.junit.experimental.categories.Category;
30  
31  @Category(SmallTests.class)
32  public class TestConfigurationManager {
33    public static final Log LOG = LogFactory.getLog(TestConfigurationManager.class);
34  
35    class DummyConfigurationObserver implements ConfigurationObserver {
36      private boolean notifiedOnChange = false;
37      private ConfigurationManager cm;
38  
39      public DummyConfigurationObserver(ConfigurationManager cm) {
40        this.cm = cm;
41        register();
42      }
43  
44      public void onConfigurationChange(Configuration conf) {
45        notifiedOnChange = true;
46      }
47  
48      // Was the observer notified on Configuration change?
49      public boolean wasNotifiedOnChange() {
50        return notifiedOnChange;
51      }
52  
53      public void resetNotifiedOnChange() {
54        notifiedOnChange = false;
55      }
56  
57      public void register() {
58        this.cm.registerObserver(this);
59      }
60  
61      public void deregister() {
62        this.cm.deregisterObserver(this);
63      }
64    }
65  
66    /**
67     * Test if observers get notified by the <code>ConfigurationManager</code>
68     * when the Configuration is reloaded.
69     */
70    @Test
71    public void testCheckIfObserversNotified() {
72      Configuration conf = new Configuration();
73      ConfigurationManager cm = new ConfigurationManager();
74      DummyConfigurationObserver d1 = new DummyConfigurationObserver(cm);
75  
76      // Check if we get notified.
77      cm.notifyAllObservers(conf);
78      assertTrue(d1.wasNotifiedOnChange());
79      d1.resetNotifiedOnChange();
80  
81      // Now check if we get notified on change with more than one observers.
82      DummyConfigurationObserver d2 = new DummyConfigurationObserver(cm);
83      cm.notifyAllObservers(conf);
84      assertTrue(d1.wasNotifiedOnChange());
85      d1.resetNotifiedOnChange();
86      assertTrue(d2.wasNotifiedOnChange());
87      d2.resetNotifiedOnChange();
88  
89      // Now try deregistering an observer and verify that it was not notified
90      d2.deregister();
91      cm.notifyAllObservers(conf);
92      assertTrue(d1.wasNotifiedOnChange());
93      d1.resetNotifiedOnChange();
94      assertFalse(d2.wasNotifiedOnChange());
95    }
96  
97    // Register an observer that will go out of scope immediately, allowing
98    // us to test that out of scope observers are deregistered.
99    private void registerLocalObserver(ConfigurationManager cm) {
100     new DummyConfigurationObserver(cm);
101   }
102 
103   /**
104    * Test if out-of-scope observers are deregistered on GC.
105    */
106   @Test
107   public void testDeregisterOnOutOfScope() {
108     Configuration conf = new Configuration();
109     ConfigurationManager cm = new ConfigurationManager();
110 
111     boolean outOfScopeObserversDeregistered = false;
112 
113     // On my machine, I was able to cause a GC after around 5 iterations.
114     // If we do not cause a GC in 100k iterations, which is very unlikely,
115     // there might be something wrong with the GC.
116     for (int i = 0; i < 100000; i++) {
117       registerLocalObserver(cm);
118       cm.notifyAllObservers(conf);
119 
120       // 'Suggest' the system to do a GC. We should be able to cause GC
121       // atleast once in the 2000 iterations.
122       System.gc();
123 
124       // If GC indeed happened, all the observers (which are all out of scope),
125       // should have been deregistered.
126       if (cm.getNumObservers() <= i) {
127         outOfScopeObserversDeregistered = true;
128         break;
129       }
130     }
131     if (!outOfScopeObserversDeregistered) {
132       LOG.warn("Observers were not GC-ed! Something seems to be wrong.");
133     }
134     assertTrue(outOfScopeObserversDeregistered);
135   }
136 }