View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.replication.regionserver;
20  
21  import java.net.URLEncoder;
22  import java.util.ArrayList;
23  import java.util.List;
24  import org.apache.hadoop.hbase.KeyValue;
25  import org.apache.hadoop.hbase.Waiter;
26  import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl;
27  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
28  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
29  import org.apache.hadoop.hbase.replication.ReplicationSourceDummyWithNoTermination;
30  import org.apache.hadoop.hbase.testclassification.MediumTests;
31  import org.apache.hadoop.hbase.wal.WAL;
32  import org.apache.hadoop.hbase.wal.WALFactory;
33  import org.apache.hadoop.hbase.wal.WALKey;
34  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
35  import org.junit.Assert;
36  import org.junit.Before;
37  import org.junit.Test;
38  import org.junit.experimental.categories.Category;
39  
40  @Category(MediumTests.class)
41  public class TestReplicationSourceWithoutReplicationZnodes
42    extends TestReplicationSourceManagerBase {
43  
44    @Before
45    public void removeExistingSourcesFromSourceManager() {
46      manager.getSources().clear();
47      manager.getOldSources().clear();
48    }
49  
50    /**
51     * When the peer is removed, hbase remove the peer znodes and there is zk watcher
52     * which terminates the replication sources. In case of zk watcher not getting invoked
53     * or a race condition between source deleting the log znode and zk watcher
54     * terminating the source, we might get the NoNode exception. In that case, the right
55     * thing is to terminate the replication source.
56     *
57     * @throws Exception throws exception
58     */
59    @Test
60    public void testReplicationSourceRunningWithoutPeerZnodes() throws Exception {
61      String replicationSourceImplName = conf.get("replication.replicationsource.implementation");
62      MultiVersionConcurrencyControl mvcc = new MultiVersionConcurrencyControl();
63      KeyValue kv = new KeyValue(r1, f1, r1);
64      WALEdit edit = new WALEdit();
65      edit.add(kv);
66      try {
67        conf.set("replication.replicationsource.implementation",
68          ReplicationSourceDummyWithNoTermination.class.getCanonicalName());
69        List<WALActionsListener> listeners = new ArrayList<>();
70        listeners.add(replication);
71        final WALFactory wals = new WALFactory(utility.getConfiguration(), listeners,
72          URLEncoder.encode("regionserver:60020", "UTF8"));
73        final WAL wal = wals.getWAL(hri.getEncodedNameAsBytes(), hri.getTable().getNamespace());
74        manager.init();
75  
76        final long txid = wal.append(htd, hri,
77          new WALKey(hri.getEncodedNameAsBytes(), test, System.currentTimeMillis(), mvcc), edit,
78          true);
79        wal.sync(txid);
80  
81        wal.rollWriter();
82        Waiter.waitFor(conf, 20000, new Waiter.Predicate<Exception>() {
83          @Override public boolean evaluate() {
84            return !manager.getSources().isEmpty();
85          }
86        });
87        Assert.assertEquals("There should be exactly one source",
88          1, manager.getSources().size());
89        Assert.assertEquals("Replication source is not correct",
90          ReplicationSourceDummyWithNoTermination.class,
91          manager.getSources().get(0).getClass());
92        // delete the znodes for peer
93        ZKUtil.deleteNodeRecursively(zkw, "/hbase/replication/peers/1");
94        ZKUtil.deleteNodeRecursively(zkw, "/hbase/replication/rs/" + server.getServerName() + "/1");
95        manager
96          .logPositionAndCleanOldLogs(manager.getSources().get(0).getCurrentPath(), "1", 0, false,
97            false);
98        Waiter.waitFor(conf, 20000, new Waiter.Predicate<Exception>() {
99          @Override public boolean evaluate() {
100           return manager.getSources().isEmpty();
101         }
102       });
103     } finally {
104       conf.set("replication.replicationsource.implementation", replicationSourceImplName);
105     }
106   }
107 }