View Javadoc

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  package org.apache.hadoop.hbase.replication.regionserver;
21  
22  import java.io.IOException;
23  import java.util.NavigableMap;
24  import java.util.TreeMap;
25  import java.util.concurrent.atomic.AtomicBoolean;
26  
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.fs.FileSystem;
29  import org.apache.hadoop.fs.Path;
30  import org.apache.hadoop.hbase.HRegionInfo;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.KeyValue;
33  import org.apache.hadoop.hbase.Server;
34  import org.apache.hadoop.hbase.regionserver.ReplicationSourceService;
35  import org.apache.hadoop.hbase.regionserver.ReplicationSinkService;
36  import org.apache.hadoop.hbase.regionserver.wal.HLog;
37  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
38  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
39  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
40  import org.apache.hadoop.hbase.replication.ReplicationZookeeper;
41  import org.apache.hadoop.hbase.replication.master.ReplicationLogCleaner;
42  import org.apache.hadoop.hbase.util.Bytes;
43  import org.apache.zookeeper.KeeperException;
44  
45  import static org.apache.hadoop.hbase.HConstants.HBASE_MASTER_LOGCLEANER_PLUGINS;
46  import static org.apache.hadoop.hbase.HConstants.REPLICATION_ENABLE_KEY;
47  import static org.apache.hadoop.hbase.HConstants.REPLICATION_SCOPE_LOCAL;
48  
49  /**
50   * Gateway to Replication.  Used by {@link org.apache.hadoop.hbase.regionserver.HRegionServer}.
51   */
52  public class Replication implements WALActionsListener, 
53    ReplicationSourceService, ReplicationSinkService {
54    private boolean replication;
55    private ReplicationSourceManager replicationManager;
56    private final AtomicBoolean replicating = new AtomicBoolean(true);
57    private ReplicationZookeeper zkHelper;
58    private Configuration conf;
59    private ReplicationSink replicationSink;
60    // Hosting server
61    private Server server;
62  
63    /**
64     * Instantiate the replication management (if rep is enabled).
65     * @param server Hosting server
66     * @param fs handle to the filesystem
67     * @param logDir
68     * @param oldLogDir directory where logs are archived
69     * @throws IOException
70     */
71    public Replication(final Server server, final FileSystem fs,
72        final Path logDir, final Path oldLogDir) throws IOException{
73      initialize(server, fs, logDir, oldLogDir);
74    }
75  
76    /**
77     * Empty constructor
78     */
79    public Replication() {
80    }
81  
82    public void initialize(final Server server, final FileSystem fs,
83        final Path logDir, final Path oldLogDir) throws IOException {
84      this.server = server;
85      this.conf = this.server.getConfiguration();
86      this.replication = isReplication(this.conf);
87      if (replication) {
88        try {
89          this.zkHelper = new ReplicationZookeeper(server, this.replicating);
90        } catch (KeeperException ke) {
91          throw new IOException("Failed replication handler create " +
92             "(replicating=" + this.replicating, ke);
93        }
94        this.replicationManager = new ReplicationSourceManager(zkHelper, conf,
95            this.server, fs, this.replicating, logDir, oldLogDir) ;
96      } else {
97        this.replicationManager = null;
98        this.zkHelper = null;
99      }
100   }
101 
102    /**
103     * @param c Configuration to look at
104     * @return True if replication is enabled.
105     */
106   public static boolean isReplication(final Configuration c) {
107     return c.getBoolean(REPLICATION_ENABLE_KEY, false);
108   }
109 
110    /*
111     * Returns an object to listen to new hlog changes
112     **/
113   public WALActionsListener getWALActionsListener() {
114     return this;
115   }
116   /**
117    * Stops replication service.
118    */
119   public void stopReplicationService() {
120     join();
121   }
122 
123   /**
124    * Join with the replication threads
125    */
126   public void join() {
127     if (this.replication) {
128       this.replicationManager.join();
129       this.replicationSink.stopReplicationSinkServices();
130     }
131   }
132 
133   /**
134    * Carry on the list of log entries down to the sink
135    * @param entries list of entries to replicate
136    * @throws IOException
137    */
138   public void replicateLogEntries(HLog.Entry[] entries) throws IOException {
139     if (this.replication) {
140       this.replicationSink.replicateEntries(entries);
141     }
142   }
143 
144   /**
145    * If replication is enabled and this cluster is a master,
146    * it starts
147    * @throws IOException
148    */
149   public void startReplicationService() throws IOException {
150     if (this.replication) {
151       this.replicationManager.init();
152       this.replicationSink = new ReplicationSink(this.conf, this.server);
153     }
154   }
155 
156   /**
157    * Get the replication sources manager
158    * @return the manager if replication is enabled, else returns false
159    */
160   public ReplicationSourceManager getReplicationManager() {
161     return this.replicationManager;
162   }
163 
164   @Override
165   public void visitLogEntryBeforeWrite(HRegionInfo info, HLogKey logKey,
166       WALEdit logEdit) {
167     // Not interested
168   }
169 
170   @Override
171   public void visitLogEntryBeforeWrite(HTableDescriptor htd, HLogKey logKey,
172                                        WALEdit logEdit) {
173     NavigableMap<byte[], Integer> scopes =
174         new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR);
175     byte[] family;
176     for (KeyValue kv : logEdit.getKeyValues()) {
177       family = kv.getFamily();
178       int scope = htd.getFamily(family).getScope();
179       if (scope != REPLICATION_SCOPE_LOCAL &&
180           !scopes.containsKey(family)) {
181         scopes.put(family, scope);
182       }
183     }
184     if (!scopes.isEmpty()) {
185       logEdit.setScopes(scopes);
186     }
187   }
188 
189   @Override
190   public void preLogRoll(Path oldPath, Path newPath) throws IOException {
191     getReplicationManager().preLogRoll(newPath);
192   }
193 
194   @Override
195   public void postLogRoll(Path oldPath, Path newPath) throws IOException {
196     getReplicationManager().postLogRoll(newPath);
197   }
198 
199   @Override
200   public void preLogArchive(Path oldPath, Path newPath) throws IOException {
201     // Not interested
202   }
203 
204   @Override
205   public void postLogArchive(Path oldPath, Path newPath) throws IOException {
206     // Not interested
207   }
208 
209   /**
210    * This method modifies the master's configuration in order to inject
211    * replication-related features
212    * @param conf
213    */
214   public static void decorateMasterConfiguration(Configuration conf) {
215     if (!isReplication(conf)) {
216       return;
217     }
218     String plugins = conf.get(HBASE_MASTER_LOGCLEANER_PLUGINS);
219     if (!plugins.contains(ReplicationLogCleaner.class.toString())) {
220       conf.set(HBASE_MASTER_LOGCLEANER_PLUGINS,
221           plugins + "," + ReplicationLogCleaner.class.getCanonicalName());
222     }
223   }
224 
225   @Override
226   public void logRollRequested() {
227     // Not interested
228   }
229 
230   @Override
231   public void logCloseRequested() {
232     // not interested
233   }
234 }