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
409 synchronized (replicationPeers) {
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(conf, replicationPeer.getConfiguration(),
520 fs, peerId, clusterId, replicationPeer, metrics, tableDescriptors, server));
521
522 return src;
523 }
524
525
526
527
528
529
530
531
532
533 private void transferQueues(String rsZnode) {
534 NodeFailoverWorker transfer =
535 new NodeFailoverWorker(rsZnode, this.replicationQueues, this.replicationPeers,
536 this.clusterId);
537 try {
538 this.executor.execute(transfer);
539 } catch (RejectedExecutionException ex) {
540 CompatibilitySingletonFactory.getInstance(MetricsReplicationSourceFactory.class)
541 .getGlobalSource().incrFailedRecoveryQueue();
542 LOG.info("Cancelling the transfer of " + rsZnode + " because of " + ex.getMessage());
543 }
544 }
545
546
547
548
549
550 public void closeRecoveredQueue(ReplicationSourceInterface src) {
551 LOG.info("Done with the recovered queue " + src.getPeerClusterZnode());
552 src.getSourceMetrics().clear();
553 this.oldsources.remove(src);
554 deleteSource(src.getPeerClusterZnode(), false);
555 this.walsByIdRecoveredQueues.remove(src.getPeerClusterZnode());
556 }
557
558
559
560
561
562 public void closeQueue(ReplicationSourceInterface src) {
563 LOG.info("Done with the queue " + src.getPeerClusterZnode());
564 src.getSourceMetrics().clear();
565 this.sources.remove(src);
566 deleteSource(src.getPeerClusterZnode(), true);
567 this.walsById.remove(src.getPeerClusterZnode());
568 }
569
570
571
572
573
574
575 public void removePeer(String id) {
576 LOG.info("Closing the following queue " + id + ", currently have "
577 + sources.size() + " and another "
578 + oldsources.size() + " that were recovered");
579 String terminateMessage = "Replication stream was removed by a user";
580 List<ReplicationSourceInterface> oldSourcesToDelete =
581 new ArrayList<ReplicationSourceInterface>();
582
583
584 synchronized (oldsources) {
585
586 for (ReplicationSourceInterface src : oldsources) {
587 if (id.equals(src.getPeerClusterId())) {
588 oldSourcesToDelete.add(src);
589 }
590 }
591 for (ReplicationSourceInterface src : oldSourcesToDelete) {
592 src.terminate(terminateMessage);
593 closeRecoveredQueue(src);
594 }
595 }
596 LOG.info("Number of deleted recovered sources for " + id + ": "
597 + oldSourcesToDelete.size());
598
599 List<ReplicationSourceInterface> srcToRemove = new ArrayList<ReplicationSourceInterface>();
600
601 synchronized (this.replicationPeers) {
602 for (ReplicationSourceInterface src : this.sources) {
603 if (id.equals(src.getPeerClusterId())) {
604 srcToRemove.add(src);
605 }
606 }
607 if (srcToRemove.isEmpty()) {
608 LOG.error("The peer we wanted to remove is missing a ReplicationSourceInterface. " +
609 "This could mean that ReplicationSourceInterface initialization failed for this peer " +
610 "and that replication on this peer may not be caught up. peerId=" + id);
611 }
612 for (ReplicationSourceInterface toRemove : srcToRemove) {
613 toRemove.terminate(terminateMessage);
614 closeQueue(toRemove);
615 }
616 deleteSource(id, true);
617 }
618 }
619
620 @Override
621 public void regionServerRemoved(String regionserver) {
622 transferQueues(regionserver);
623 }
624
625 @Override
626 public void peerRemoved(String peerId) {
627 removePeer(peerId);
628 this.replicationQueues.removePeerFromHFileRefs(peerId);
629 }
630
631 @Override
632 public void peerListChanged(List<String> peerIds) {
633 for (String id : peerIds) {
634 try {
635 boolean added = this.replicationPeers.peerAdded(id);
636 if (added) {
637 addSource(id);
638 if (replicationForBulkLoadDataEnabled) {
639 this.replicationQueues.addPeerToHFileRefs(id);
640 }
641 }
642 } catch (Exception e) {
643 LOG.error("Error while adding a new peer", e);
644 }
645 }
646 }
647
648
649
650
651
652 class NodeFailoverWorker extends Thread {
653
654 private String rsZnode;
655 private final ReplicationQueues rq;
656 private final ReplicationPeers rp;
657 private final UUID clusterId;
658
659
660
661
662 public NodeFailoverWorker(String rsZnode) {
663 this(rsZnode, replicationQueues, replicationPeers, ReplicationSourceManager.this.clusterId);
664 }
665
666 public NodeFailoverWorker(String rsZnode, final ReplicationQueues replicationQueues,
667 final ReplicationPeers replicationPeers, final UUID clusterId) {
668 super("Failover-for-"+rsZnode);
669 this.rsZnode = rsZnode;
670 this.rq = replicationQueues;
671 this.rp = replicationPeers;
672 this.clusterId = clusterId;
673 }
674
675 @Override
676 public void run() {
677 if (this.rq.isThisOurZnode(rsZnode)) {
678 return;
679 }
680
681
682 try {
683 Thread.sleep(sleepBeforeFailover + (long) (rand.nextFloat() * sleepBeforeFailover));
684 } catch (InterruptedException e) {
685 LOG.warn("Interrupted while waiting before transferring a queue.");
686 Thread.currentThread().interrupt();
687 }
688
689 if (server.isStopped()) {
690 LOG.info("Not transferring queue since we are shutting down");
691 return;
692 }
693
694 Map<String, SortedSet<String>> newQueues = new HashMap<>();
695 List<String> peers = rq.getUnClaimedQueueIds(rsZnode);
696 while (peers != null && !peers.isEmpty()) {
697 Pair<String, SortedSet<String>> peer = this.rq.claimQueue(rsZnode,
698 peers.get(rand.nextInt(peers.size())));
699 long sleep = sleepBeforeFailover/2;
700 if (peer != null) {
701 newQueues.put(peer.getFirst(), peer.getSecond());
702 sleep = sleepBeforeFailover;
703 }
704 try {
705 Thread.sleep(sleep);
706 } catch (InterruptedException e) {
707 LOG.warn("Interrupted while waiting before transferring a queue.");
708 Thread.currentThread().interrupt();
709 }
710 peers = rq.getUnClaimedQueueIds(rsZnode);
711 }
712 if (peers != null) {
713 rq.removeReplicatorIfQueueIsEmpty(rsZnode);
714 }
715
716
717 if (newQueues.isEmpty()) {
718
719
720 return;
721 }
722
723 for (Map.Entry<String, SortedSet<String>> entry : newQueues.entrySet()) {
724 String peerId = entry.getKey();
725 SortedSet<String> walsSet = entry.getValue();
726 try {
727
728 ReplicationQueueInfo replicationQueueInfo = new ReplicationQueueInfo(peerId);
729 String actualPeerId = replicationQueueInfo.getPeerId();
730 ReplicationPeer peer = replicationPeers.getPeer(actualPeerId);
731 ReplicationPeerConfig peerConfig = null;
732 try {
733 peerConfig = replicationPeers.getReplicationPeerConfig(actualPeerId);
734 } catch (ReplicationException ex) {
735 LOG.warn("Received exception while getting replication peer config, skipping replay"
736 + ex);
737 }
738 if (peer == null || peerConfig == null) {
739 LOG.warn("Skipping failover for peer:" + actualPeerId + " of node" + rsZnode);
740 replicationQueues.removeQueue(peerId);
741 continue;
742 }
743 if (server instanceof ReplicationSyncUp.DummyServer
744 && peer.getPeerState().equals(PeerState.DISABLED)) {
745 LOG.warn("Peer " + actualPeerId + " is disbaled. ReplicationSyncUp tool will skip "
746 + "replicating data to this peer.");
747 continue;
748 }
749
750 Map<String, SortedSet<String>> walsByGroup = new HashMap<String, SortedSet<String>>();
751 walsByIdRecoveredQueues.put(peerId, walsByGroup);
752 for (String wal : walsSet) {
753 String walPrefix = DefaultWALProvider.getWALPrefixFromWALName(wal);
754 SortedSet<String> wals = walsByGroup.get(walPrefix);
755 if (wals == null) {
756 wals = new TreeSet<String>();
757 walsByGroup.put(walPrefix, wals);
758 }
759 wals.add(wal);
760 }
761
762
763 ReplicationSourceInterface src =
764 getReplicationSource(conf, fs, ReplicationSourceManager.this, this.rq, this.rp,
765 server, peerId, this.clusterId, peerConfig, peer);
766
767
768 synchronized (oldsources) {
769 if (!this.rp.getPeerIds().contains(src.getPeerClusterId())) {
770 src.terminate("Recovered queue doesn't belong to any current peer");
771 closeRecoveredQueue(src);
772 continue;
773 }
774 oldsources.add(src);
775 for (String wal : walsSet) {
776 src.enqueueLog(new Path(oldLogDir, wal));
777 }
778 src.startup();
779 }
780 } catch (IOException e) {
781
782 LOG.error("Failed creating a source", e);
783 }
784 }
785 }
786 }
787
788
789
790
791
792 public Path getOldLogDir() {
793 return this.oldLogDir;
794 }
795
796
797
798
799
800 public Path getLogDir() {
801 return this.logDir;
802 }
803
804
805
806
807
808 public FileSystem getFs() {
809 return this.fs;
810 }
811
812
813
814
815
816 public ReplicationPeers getReplicationPeers() {return this.replicationPeers;}
817
818
819
820
821 public String getStats() {
822 StringBuffer stats = new StringBuffer();
823 for (ReplicationSourceInterface source : sources) {
824 stats.append("Normal source for cluster " + source.getPeerClusterId() + ": ");
825 stats.append(source.getStats() + "\n");
826 }
827 for (ReplicationSourceInterface oldSource : oldsources) {
828 stats.append("Recovered source for cluster/machine(s) " + oldSource.getPeerClusterId()+": ");
829 stats.append(oldSource.getStats()+ "\n");
830 }
831 return stats.toString();
832 }
833
834 public void addHFileRefs(TableName tableName, byte[] family, List<Pair<Path, Path>> pairs)
835 throws ReplicationException {
836 for (ReplicationSourceInterface source : this.sources) {
837 source.addHFileRefs(tableName, family, pairs);
838 }
839 }
840
841 public void cleanUpHFileRefs(String peerId, List<String> files) {
842 this.replicationQueues.removeHFileRefs(peerId, files);
843 }
844 }