1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.replication.regionserver;
21
22 import com.google.common.annotations.VisibleForTesting;
23 import com.google.common.util.concurrent.ThreadFactoryBuilder;
24
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Random;
34 import java.util.Set;
35 import java.util.SortedSet;
36 import java.util.TreeSet;
37 import java.util.UUID;
38 import java.util.concurrent.ConcurrentHashMap;
39 import java.util.concurrent.CopyOnWriteArrayList;
40 import java.util.concurrent.LinkedBlockingQueue;
41 import java.util.concurrent.RejectedExecutionException;
42 import java.util.concurrent.ThreadPoolExecutor;
43 import java.util.concurrent.TimeUnit;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
47 import org.apache.hadoop.conf.Configuration;
48 import org.apache.hadoop.fs.FileSystem;
49 import org.apache.hadoop.fs.Path;
50 import org.apache.hadoop.hbase.CompatibilitySingletonFactory;
51 import org.apache.hadoop.hbase.HConstants;
52 import org.apache.hadoop.hbase.Server;
53 import org.apache.hadoop.hbase.TableDescriptors;
54 import org.apache.hadoop.hbase.TableName;
55 import org.apache.hadoop.hbase.classification.InterfaceAudience;
56 import org.apache.hadoop.hbase.regionserver.HRegionServer;
57 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
58 import org.apache.hadoop.hbase.replication.ReplicationEndpoint;
59 import org.apache.hadoop.hbase.replication.ReplicationException;
60 import org.apache.hadoop.hbase.replication.ReplicationListener;
61 import org.apache.hadoop.hbase.replication.ReplicationPeer;
62 import org.apache.hadoop.hbase.replication.ReplicationPeer.PeerState;
63 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
64 import org.apache.hadoop.hbase.replication.ReplicationPeers;
65 import org.apache.hadoop.hbase.replication.ReplicationQueueInfo;
66 import org.apache.hadoop.hbase.replication.ReplicationQueues;
67 import org.apache.hadoop.hbase.replication.ReplicationTracker;
68 import org.apache.hadoop.hbase.util.Pair;
69 import org.apache.hadoop.hbase.wal.DefaultWALProvider;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @InterfaceAudience.Private
88 public class ReplicationSourceManager implements ReplicationListener {
89 private static final Log LOG =
90 LogFactory.getLog(ReplicationSourceManager.class);
91
92 private final List<ReplicationSourceInterface> sources;
93
94 private final List<ReplicationSourceInterface> oldsources;
95 private final ReplicationQueues replicationQueues;
96 private final ReplicationTracker replicationTracker;
97 private final ReplicationPeers replicationPeers;
98
99 private final UUID clusterId;
100
101 private final Server server;
102
103
104 private final Map<String, Map<String, SortedSet<String>>> walsById;
105
106 private final Map<String, Map<String, SortedSet<String>>> walsByIdRecoveredQueues;
107 private final Configuration conf;
108 private final FileSystem fs;
109
110 private Set<Path> latestPaths;
111
112 private final Path logDir;
113
114 private final Path oldLogDir;
115
116 private final long sleepBeforeFailover;
117
118 private final ThreadPoolExecutor executor;
119
120 private final Random rand;
121 private final boolean replicationForBulkLoadDataEnabled;
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public ReplicationSourceManager(final ReplicationQueues replicationQueues,
137 final ReplicationPeers replicationPeers, final ReplicationTracker replicationTracker,
138 final Configuration conf, final Server server, final FileSystem fs, final Path logDir,
139 final Path oldLogDir, final UUID clusterId) {
140
141
142 this.sources = new CopyOnWriteArrayList<ReplicationSourceInterface>();
143 this.replicationQueues = replicationQueues;
144 this.replicationPeers = replicationPeers;
145 this.replicationTracker = replicationTracker;
146 this.server = server;
147 this.walsById = new HashMap<String, Map<String, SortedSet<String>>>();
148 this.walsByIdRecoveredQueues = new ConcurrentHashMap<String, Map<String, SortedSet<String>>>();
149 this.oldsources = new CopyOnWriteArrayList<ReplicationSourceInterface>();
150 this.conf = conf;
151 this.fs = fs;
152 this.logDir = logDir;
153 this.oldLogDir = oldLogDir;
154 this.sleepBeforeFailover =
155 conf.getLong("replication.sleep.before.failover", 30000);
156 this.clusterId = clusterId;
157 this.replicationTracker.registerListener(this);
158 this.replicationPeers.getAllPeerIds();
159
160
161 int nbWorkers = conf.getInt("replication.executor.workers", 1);
162
163
164 this.executor = new ThreadPoolExecutor(nbWorkers, nbWorkers,
165 100, TimeUnit.MILLISECONDS,
166 new LinkedBlockingQueue<Runnable>());
167 ThreadFactoryBuilder tfb = new ThreadFactoryBuilder();
168 tfb.setNameFormat("ReplicationExecutor-%d");
169 tfb.setDaemon(true);
170 this.executor.setThreadFactory(tfb.build());
171 this.rand = new Random();
172 this.latestPaths = Collections.synchronizedSet(new HashSet<Path>());
173 replicationForBulkLoadDataEnabled =
174 conf.getBoolean(HConstants.REPLICATION_BULKLOAD_ENABLE_KEY,
175 HConstants.REPLICATION_BULKLOAD_ENABLE_DEFAULT);
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189 public void logPositionAndCleanOldLogs(Path log, String id, long position,
190 boolean queueRecovered, boolean holdLogInZK) {
191 String fileName = log.getName();
192 this.replicationQueues.setLogPosition(id, fileName, position);
193 if (holdLogInZK) {
194 return;
195 }
196 cleanOldLogs(fileName, id, queueRecovered);
197 }
198
199
200
201
202
203
204
205
206 public void cleanOldLogs(String key, String id, boolean queueRecovered) {
207 String logPrefix = DefaultWALProvider.getWALPrefixFromWALName(key);
208 if (queueRecovered) {
209 SortedSet<String> wals = walsByIdRecoveredQueues.get(id).get(logPrefix);
210 if (wals != null && !wals.first().equals(key)) {
211 cleanOldLogs(wals, key, id);
212 }
213 } else {
214 synchronized (this.walsById) {
215 SortedSet<String> wals = walsById.get(id).get(logPrefix);
216 if (wals != null && !wals.first().equals(key)) {
217 cleanOldLogs(wals, key, id);
218 }
219 }
220 }
221 }
222
223 private void cleanOldLogs(SortedSet<String> wals, String key, String id) {
224 SortedSet<String> walSet = wals.headSet(key);
225 LOG.debug("Removing " + walSet.size() + " logs in the list: " + walSet);
226 for (String wal : walSet) {
227 this.replicationQueues.removeLog(id, wal);
228 }
229 walSet.clear();
230 }
231
232
233
234
235
236 protected void init() throws IOException, ReplicationException {
237 for (String id : this.replicationPeers.getPeerIds()) {
238 addSource(id);
239 if (replicationForBulkLoadDataEnabled) {
240
241
242 this.replicationQueues.addPeerToHFileRefs(id);
243 }
244 }
245 List<String> currentReplicators = this.replicationQueues.getListOfReplicators();
246 if (currentReplicators == null || currentReplicators.isEmpty()) {
247 return;
248 }
249 List<String> otherRegionServers = replicationTracker.getListOfRegionServers();
250 LOG.info("Current list of replicators: " + currentReplicators + " other RSs: "
251 + otherRegionServers);
252
253
254 for (String rs : currentReplicators) {
255 if (!otherRegionServers.contains(rs)) {
256 transferQueues(rs);
257 }
258 }
259 }
260
261
262
263
264
265
266
267
268 protected ReplicationSourceInterface addSource(String id) throws IOException,
269 ReplicationException {
270 ReplicationPeerConfig peerConfig = replicationPeers.getReplicationPeerConfig(id);
271 ReplicationPeer peer = replicationPeers.getPeer(id);
272 ReplicationSourceInterface src =
273 getReplicationSource(this.conf, this.fs, this, this.replicationQueues,
274 this.replicationPeers, server, id, this.clusterId, peerConfig, peer);
275 synchronized (this.walsById) {
276 this.sources.add(src);
277 Map<String, SortedSet<String>> walsByGroup = new HashMap<String, SortedSet<String>>();
278 this.walsById.put(id, walsByGroup);
279
280 synchronized (latestPaths) {
281 if (this.latestPaths.size() > 0) {
282 for (Path logPath : latestPaths) {
283 String name = logPath.getName();
284 String walPrefix = DefaultWALProvider.getWALPrefixFromWALName(name);
285 SortedSet<String> logs = new TreeSet<String>();
286 logs.add(name);
287 walsByGroup.put(walPrefix, logs);
288 try {
289 this.replicationQueues.addLog(id, name);
290 } catch (ReplicationException e) {
291 String message =
292 "Cannot add log to queue when creating a new source, queueId=" + id
293 + ", filename=" + name;
294 server.stop(message);
295 throw e;
296 }
297 src.enqueueLog(logPath);
298 }
299 }
300 }
301 }
302 src.startup();
303 return src;
304 }
305
306
307
308
309
310 public void deleteSource(String peerId, boolean closeConnection) {
311 this.replicationQueues.removeQueue(peerId);
312 if (closeConnection) {
313 this.replicationPeers.peerRemoved(peerId);
314 }
315 }
316
317
318
319
320 public void join() {
321 this.executor.shutdown();
322 if (this.sources.size() == 0) {
323 this.replicationQueues.removeAllQueues();
324 }
325 for (ReplicationSourceInterface source : this.sources) {
326 source.terminate("Region server is closing");
327 }
328 }
329
330
331
332
333
334 protected Map<String, Map<String, SortedSet<String>>> getWALs() {
335 return Collections.unmodifiableMap(walsById);
336 }
337
338
339
340
341
342 protected Map<String, Map<String, SortedSet<String>>> getWalsByIdRecoveredQueues() {
343 return Collections.unmodifiableMap(walsByIdRecoveredQueues);
344 }
345
346
347
348
349
350 public List<ReplicationSourceInterface> getSources() {
351 return this.sources;
352 }
353
354
355
356
357
358 public List<ReplicationSourceInterface> getOldSources() {
359 return this.oldsources;
360 }
361
362
363
364
365
366
367 public ReplicationSourceInterface getSource(String peerId) {
368 for (ReplicationSourceInterface source: getSources()) {
369 if (source.getPeerClusterId().equals(peerId)) {
370 return source;
371 }
372 }
373 return null;
374 }
375
376 @VisibleForTesting
377 List<String> getAllQueues() {
378 return replicationQueues.getAllQueues();
379 }
380
381 void preLogRoll(Path newLog) throws IOException {
382 recordLog(newLog);
383 String logName = newLog.getName();
384 String logPrefix = DefaultWALProvider.getWALPrefixFromWALName(logName);
385 synchronized (latestPaths) {
386 Iterator<Path> iterator = latestPaths.iterator();
387 while (iterator.hasNext()) {
388 Path path = iterator.next();
389 if (path.getName().contains(logPrefix)) {
390 iterator.remove();
391 break;
392 }
393 }
394 this.latestPaths.add(newLog);
395 }
396 }
397
398
399
400
401
402
403
404 private void recordLog(Path logPath) throws IOException {
405 String logName = logPath.getName();
406 String logPrefix = DefaultWALProvider.getWALPrefixFromWALName(logName);
407
408 synchronized (replicationPeers) {
409
410 for (String id : replicationPeers.getPeerIds()) {
411 try {
412 this.replicationQueues.addLog(id, logName);
413 } catch (ReplicationException e) {
414 throw new IOException("Cannot add log to replication queue"
415 + " when creating a new source, queueId=" + id + ", filename=" + logName, e);
416 }
417 }
418 }
419
420 synchronized (walsById) {
421 for (Map.Entry<String, Map<String, SortedSet<String>>> entry : this.walsById.entrySet()) {
422 String peerId = entry.getKey();
423 Map<String, SortedSet<String>> walsByPrefix = entry.getValue();
424 boolean existingPrefix = false;
425 for (Map.Entry<String, SortedSet<String>> walsEntry : walsByPrefix.entrySet()) {
426 SortedSet<String> wals = walsEntry.getValue();
427 if (this.sources.isEmpty()) {
428
429
430 wals.clear();
431 }
432 if (logPrefix.equals(walsEntry.getKey())) {
433 wals.add(logName);
434 existingPrefix = true;
435 }
436 }
437 if (!existingPrefix) {
438
439 LOG.debug("Start tracking logs for wal group " + logPrefix + " for peer " + peerId);
440 SortedSet<String> wals = new TreeSet<String>();
441 wals.add(logName);
442 walsByPrefix.put(logPrefix, wals);
443 }
444 }
445 }
446 }
447
448 void postLogRoll(Path newLog) throws IOException {
449
450 for (ReplicationSourceInterface source : this.sources) {
451 source.enqueueLog(newLog);
452 }
453 }
454
455
456
457
458
459
460
461
462
463
464
465 protected ReplicationSourceInterface getReplicationSource(final Configuration conf,
466 final FileSystem fs, final ReplicationSourceManager manager,
467 final ReplicationQueues replicationQueues, final ReplicationPeers replicationPeers,
468 final Server server, final String peerId, final UUID clusterId,
469 final ReplicationPeerConfig peerConfig, final ReplicationPeer replicationPeer)
470 throws IOException {
471 RegionServerCoprocessorHost rsServerHost = null;
472 TableDescriptors tableDescriptors = null;
473 if (server instanceof HRegionServer) {
474 rsServerHost = ((HRegionServer) server).getRegionServerCoprocessorHost();
475 tableDescriptors = ((HRegionServer) server).getTableDescriptors();
476 }
477 ReplicationSourceInterface src;
478 try {
479 @SuppressWarnings("rawtypes")
480 Class c = Class.forName(conf.get("replication.replicationsource.implementation",
481 ReplicationSource.class.getCanonicalName()));
482 src = (ReplicationSourceInterface) c.newInstance();
483 } catch (Exception e) {
484 LOG.warn("Passed replication source implementation throws errors, " +
485 "defaulting to ReplicationSource", e);
486 src = new ReplicationSource();
487 }
488
489 ReplicationEndpoint replicationEndpoint = null;
490 try {
491 String replicationEndpointImpl = peerConfig.getReplicationEndpointImpl();
492 if (replicationEndpointImpl == null) {
493
494 replicationEndpointImpl = HBaseInterClusterReplicationEndpoint.class.getName();
495 }
496 @SuppressWarnings("rawtypes")
497 Class c = Class.forName(replicationEndpointImpl);
498 replicationEndpoint = (ReplicationEndpoint) c.newInstance();
499 if(rsServerHost != null) {
500 ReplicationEndpoint newReplicationEndPoint = rsServerHost
501 .postCreateReplicationEndPoint(replicationEndpoint);
502 if(newReplicationEndPoint != null) {
503
504 replicationEndpoint = newReplicationEndPoint;
505 }
506 }
507 } catch (Exception e) {
508 LOG.warn("Passed replication endpoint implementation throws errors"
509 + " while initializing ReplicationSource for peer: " + peerId, e);
510 throw new IOException(e);
511 }
512
513 MetricsSource metrics = new MetricsSource(peerId);
514
515 src.init(conf, fs, manager, replicationQueues, replicationPeers, server, peerId,
516 clusterId, replicationEndpoint, metrics);
517
518
519 replicationEndpoint.init(new ReplicationEndpoint.Context(replicationPeer.getConfiguration(),
520 fs, peerConfig, peerId, clusterId, replicationPeer, metrics, tableDescriptors, server));
521 return src;
522 }
523
524
525
526
527
528
529
530
531
532 private void transferQueues(String rsZnode) {
533 NodeFailoverWorker transfer =
534 new NodeFailoverWorker(rsZnode, this.replicationQueues, this.replicationPeers,
535 this.clusterId);
536 try {
537 this.executor.execute(transfer);
538 } catch (RejectedExecutionException ex) {
539 CompatibilitySingletonFactory.getInstance(MetricsReplicationSourceFactory.class)
540 .getGlobalSource().incrFailedRecoveryQueue();
541 LOG.info("Cancelling the transfer of " + rsZnode + " because of " + ex.getMessage());
542 }
543 }
544
545
546
547
548
549 public void closeRecoveredQueue(ReplicationSourceInterface src) {
550 LOG.info("Done with the recovered queue " + src.getPeerClusterZnode());
551 src.getSourceMetrics().clear();
552 this.oldsources.remove(src);
553 deleteSource(src.getPeerClusterZnode(), false);
554 this.walsByIdRecoveredQueues.remove(src.getPeerClusterZnode());
555 }
556
557
558
559
560
561 public void closeQueue(ReplicationSourceInterface src) {
562 LOG.info("Done with the queue " + src.getPeerClusterZnode());
563 src.getSourceMetrics().clear();
564 this.sources.remove(src);
565 deleteSource(src.getPeerClusterZnode(), true);
566 this.walsById.remove(src.getPeerClusterZnode());
567 }
568
569
570
571
572
573
574 public void removePeer(String id) {
575 LOG.info("Closing the following queue " + id + ", currently have "
576 + sources.size() + " and another "
577 + oldsources.size() + " that were recovered");
578 String terminateMessage = "Replication stream was removed by a user";
579 List<ReplicationSourceInterface> oldSourcesToDelete =
580 new ArrayList<ReplicationSourceInterface>();
581
582
583 synchronized (oldsources) {
584
585 for (ReplicationSourceInterface src : oldsources) {
586 if (id.equals(src.getPeerClusterId())) {
587 oldSourcesToDelete.add(src);
588 }
589 }
590 for (ReplicationSourceInterface src : oldSourcesToDelete) {
591 src.terminate(terminateMessage);
592 closeRecoveredQueue(src);
593 }
594 }
595 LOG.info("Number of deleted recovered sources for " + id + ": "
596 + oldSourcesToDelete.size());
597
598 List<ReplicationSourceInterface> srcToRemove = new ArrayList<ReplicationSourceInterface>();
599
600 synchronized (this.replicationPeers) {
601 for (ReplicationSourceInterface src : this.sources) {
602 if (id.equals(src.getPeerClusterId())) {
603 srcToRemove.add(src);
604 }
605 }
606 if (srcToRemove.isEmpty()) {
607 LOG.error("The peer we wanted to remove is missing a ReplicationSourceInterface. " +
608 "This could mean that ReplicationSourceInterface initialization failed for this peer " +
609 "and that replication on this peer may not be caught up. peerId=" + id);
610 }
611 for (ReplicationSourceInterface toRemove : srcToRemove) {
612 toRemove.terminate(terminateMessage);
613 closeQueue(toRemove);
614 }
615 deleteSource(id, true);
616 }
617 }
618
619 @Override
620 public void regionServerRemoved(String regionserver) {
621 transferQueues(regionserver);
622 }
623
624 @Override
625 public void peerRemoved(String peerId) {
626 removePeer(peerId);
627 this.replicationQueues.removePeerFromHFileRefs(peerId);
628 }
629
630 @Override
631 public void peerListChanged(List<String> peerIds) {
632 for (String id : peerIds) {
633 try {
634 boolean added = this.replicationPeers.peerAdded(id);
635 if (added) {
636 addSource(id);
637 if (replicationForBulkLoadDataEnabled) {
638 this.replicationQueues.addPeerToHFileRefs(id);
639 }
640 }
641 } catch (Exception e) {
642 LOG.error("Error while adding a new peer", e);
643 }
644 }
645 }
646
647
648
649
650
651 class NodeFailoverWorker extends Thread {
652
653 private String rsZnode;
654 private final ReplicationQueues rq;
655 private final ReplicationPeers rp;
656 private final UUID clusterId;
657
658
659
660
661 public NodeFailoverWorker(String rsZnode) {
662 this(rsZnode, replicationQueues, replicationPeers, ReplicationSourceManager.this.clusterId);
663 }
664
665 public NodeFailoverWorker(String rsZnode, final ReplicationQueues replicationQueues,
666 final ReplicationPeers replicationPeers, final UUID clusterId) {
667 super("Failover-for-"+rsZnode);
668 this.rsZnode = rsZnode;
669 this.rq = replicationQueues;
670 this.rp = replicationPeers;
671 this.clusterId = clusterId;
672 }
673
674 @Override
675 public void run() {
676 if (this.rq.isThisOurZnode(rsZnode)) {
677 return;
678 }
679
680
681 try {
682 Thread.sleep(sleepBeforeFailover + (long) (rand.nextFloat() * sleepBeforeFailover));
683 } catch (InterruptedException e) {
684 LOG.warn("Interrupted while waiting before transferring a queue.");
685 Thread.currentThread().interrupt();
686 }
687
688 if (server.isStopped()) {
689 LOG.info("Not transferring queue since we are shutting down");
690 return;
691 }
692
693 Map<String, SortedSet<String>> newQueues = new HashMap<>();
694 List<String> peers = rq.getUnClaimedQueueIds(rsZnode);
695 while (peers != null && !peers.isEmpty()) {
696 Pair<String, SortedSet<String>> peer = this.rq.claimQueue(rsZnode,
697 peers.get(rand.nextInt(peers.size())));
698 long sleep = sleepBeforeFailover/2;
699 if (peer != null) {
700 newQueues.put(peer.getFirst(), peer.getSecond());
701 sleep = sleepBeforeFailover;
702 }
703 try {
704 Thread.sleep(sleep);
705 } catch (InterruptedException e) {
706 LOG.warn("Interrupted while waiting before transferring a queue.");
707 Thread.currentThread().interrupt();
708 }
709 peers = rq.getUnClaimedQueueIds(rsZnode);
710 }
711 if (peers != null) {
712 rq.removeReplicatorIfQueueIsEmpty(rsZnode);
713 }
714
715
716 if (newQueues.isEmpty()) {
717
718
719 return;
720 }
721
722 for (Map.Entry<String, SortedSet<String>> entry : newQueues.entrySet()) {
723 String peerId = entry.getKey();
724 SortedSet<String> walsSet = entry.getValue();
725 try {
726
727 ReplicationQueueInfo replicationQueueInfo = new ReplicationQueueInfo(peerId);
728 String actualPeerId = replicationQueueInfo.getPeerId();
729 ReplicationPeer peer = replicationPeers.getPeer(actualPeerId);
730 ReplicationPeerConfig peerConfig = null;
731 try {
732 peerConfig = replicationPeers.getReplicationPeerConfig(actualPeerId);
733 } catch (ReplicationException ex) {
734 LOG.warn("Received exception while getting replication peer config, skipping replay"
735 + ex);
736 }
737 if (peer == null || peerConfig == null) {
738 LOG.warn("Skipping failover for peer:" + actualPeerId + " of node" + rsZnode);
739 replicationQueues.removeQueue(peerId);
740 continue;
741 }
742 if (server instanceof ReplicationSyncUp.DummyServer
743 && peer.getPeerState().equals(PeerState.DISABLED)) {
744 LOG.warn("Peer " + actualPeerId + " is disbaled. ReplicationSyncUp tool will skip "
745 + "replicating data to this peer.");
746 continue;
747 }
748
749 Map<String, SortedSet<String>> walsByGroup = new HashMap<String, SortedSet<String>>();
750 walsByIdRecoveredQueues.put(peerId, walsByGroup);
751 for (String wal : walsSet) {
752 String walPrefix = DefaultWALProvider.getWALPrefixFromWALName(wal);
753 SortedSet<String> wals = walsByGroup.get(walPrefix);
754 if (wals == null) {
755 wals = new TreeSet<String>();
756 walsByGroup.put(walPrefix, wals);
757 }
758 wals.add(wal);
759 }
760
761
762 ReplicationSourceInterface src =
763 getReplicationSource(conf, fs, ReplicationSourceManager.this, this.rq, this.rp,
764 server, peerId, this.clusterId, peerConfig, peer);
765
766
767 synchronized (oldsources) {
768 if (!this.rp.getPeerIds().contains(src.getPeerClusterId())) {
769 src.terminate("Recovered queue doesn't belong to any current peer");
770 closeRecoveredQueue(src);
771 continue;
772 }
773 oldsources.add(src);
774 for (String wal : walsSet) {
775 src.enqueueLog(new Path(oldLogDir, wal));
776 }
777 src.startup();
778 }
779 } catch (IOException e) {
780
781 LOG.error("Failed creating a source", e);
782 }
783 }
784 }
785 }
786
787
788
789
790
791 public Path getOldLogDir() {
792 return this.oldLogDir;
793 }
794
795
796
797
798
799 public Path getLogDir() {
800 return this.logDir;
801 }
802
803
804
805
806
807 public FileSystem getFs() {
808 return this.fs;
809 }
810
811
812
813
814
815 public ReplicationPeers getReplicationPeers() {return this.replicationPeers;}
816
817
818
819
820 public String getStats() {
821 StringBuffer stats = new StringBuffer();
822 for (ReplicationSourceInterface source : sources) {
823 stats.append("Normal source for cluster " + source.getPeerClusterId() + ": ");
824 stats.append(source.getStats() + "\n");
825 }
826 for (ReplicationSourceInterface oldSource : oldsources) {
827 stats.append("Recovered source for cluster/machine(s) " + oldSource.getPeerClusterId()+": ");
828 stats.append(oldSource.getStats()+ "\n");
829 }
830 return stats.toString();
831 }
832
833 public void addHFileRefs(TableName tableName, byte[] family, List<String> files)
834 throws ReplicationException {
835 for (ReplicationSourceInterface source : this.sources) {
836 source.addHFileRefs(tableName, family, files);
837 }
838 }
839
840 public void cleanUpHFileRefs(String peerId, List<String> files) {
841 this.replicationQueues.removeHFileRefs(peerId, files);
842 }
843 }