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.namequeues.impl;
21
22 import com.google.common.collect.Lists;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.classification.InterfaceAudience;
28 import org.apache.hadoop.hbase.client.BalancerDecision;
29 import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer;
30 import org.apache.hadoop.hbase.namequeues.BalancerDecisionDetails;
31 import org.apache.hadoop.hbase.namequeues.NamedQueuePayload;
32 import org.apache.hadoop.hbase.namequeues.NamedQueueService;
33 import org.apache.hadoop.hbase.namequeues.queue.EvictingQueue;
34 import org.apache.hadoop.hbase.namequeues.request.NamedQueueGetRequest;
35 import org.apache.hadoop.hbase.namequeues.response.NamedQueueGetResponse;
36 import org.apache.hadoop.hbase.protobuf.generated.RecentLogs;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43 @InterfaceAudience.Private
44 public class BalancerDecisionQueueService implements NamedQueueService {
45
46 private static final Logger LOG = LoggerFactory.getLogger(BalancerDecisionQueueService.class);
47
48 private final boolean isBalancerDecisionRecording;
49
50 private static final String BALANCER_DECISION_QUEUE_SIZE =
51 "hbase.master.balancer.decision.queue.size";
52 private static final int DEFAULT_BALANCER_DECISION_QUEUE_SIZE = 250;
53
54 private static final int REGION_PLANS_THRESHOLD_PER_BALANCER = 15;
55
56 private final EvictingQueue<RecentLogs.BalancerDecision> balancerDecisionQueue;
57
58 public BalancerDecisionQueueService(Configuration conf) {
59 isBalancerDecisionRecording = conf.getBoolean(BaseLoadBalancer.BALANCER_DECISION_BUFFER_ENABLED,
60 BaseLoadBalancer.DEFAULT_BALANCER_DECISION_BUFFER_ENABLED);
61 if (!isBalancerDecisionRecording) {
62 balancerDecisionQueue = null;
63 return;
64 }
65 final int queueSize =
66 conf.getInt(BALANCER_DECISION_QUEUE_SIZE, DEFAULT_BALANCER_DECISION_QUEUE_SIZE);
67 balancerDecisionQueue = EvictingQueue.create(queueSize);
68 }
69
70 @Override
71 public NamedQueuePayload.NamedQueueEvent getEvent() {
72 return NamedQueuePayload.NamedQueueEvent.BALANCE_DECISION;
73 }
74
75 @Override
76 public void consumeEventFromDisruptor(NamedQueuePayload namedQueuePayload) {
77 if (!isBalancerDecisionRecording) {
78 return;
79 }
80 if (!(namedQueuePayload instanceof BalancerDecisionDetails)) {
81 LOG.warn(
82 "BalancerDecisionQueueService: NamedQueuePayload is not of type BalancerDecisionDetails.");
83 return;
84 }
85 BalancerDecisionDetails balancerDecisionDetails = (BalancerDecisionDetails) namedQueuePayload;
86 BalancerDecision balancerDecisionRecords =
87 balancerDecisionDetails.getBalancerDecision();
88 List<String> regionPlans = balancerDecisionRecords.getRegionPlans();
89 List<List<String>> regionPlansList;
90 if (regionPlans.size() > REGION_PLANS_THRESHOLD_PER_BALANCER) {
91 regionPlansList = Lists.partition(regionPlans, REGION_PLANS_THRESHOLD_PER_BALANCER);
92 } else {
93 regionPlansList = Collections.singletonList(regionPlans);
94 }
95 for (List<String> regionPlansPerBalancer : regionPlansList) {
96 RecentLogs.BalancerDecision balancerDecision = RecentLogs.BalancerDecision.newBuilder()
97 .setInitTotalCost(balancerDecisionRecords.getInitTotalCost())
98 .setInitialFunctionCosts(balancerDecisionRecords.getInitialFunctionCosts())
99 .setComputedTotalCost(balancerDecisionRecords.getComputedTotalCost())
100 .setFinalFunctionCosts(balancerDecisionRecords.getFinalFunctionCosts())
101 .setComputedSteps(balancerDecisionRecords.getComputedSteps())
102 .addAllRegionPlans(regionPlansPerBalancer)
103 .build();
104 balancerDecisionQueue.add(balancerDecision);
105 }
106 }
107
108 @Override
109 public boolean clearNamedQueue() {
110 if (!isBalancerDecisionRecording) {
111 return false;
112 }
113 LOG.debug("Received request to clean up balancer decision queue.");
114 balancerDecisionQueue.clear();
115 return true;
116 }
117
118 @Override
119 public NamedQueueGetResponse getNamedQueueRecords(NamedQueueGetRequest request) {
120 if (!isBalancerDecisionRecording) {
121 return null;
122 }
123 List<RecentLogs.BalancerDecision> balancerDecisions =
124 Arrays.asList(balancerDecisionQueue.toArray(new RecentLogs.BalancerDecision[0]));
125
126 Collections.reverse(balancerDecisions);
127 int limit = balancerDecisions.size();
128 if (request.getBalancerDecisionsRequest().hasLimit()) {
129 limit = Math.min(request.getBalancerDecisionsRequest().getLimit(), balancerDecisions.size());
130 }
131
132 balancerDecisions = balancerDecisions.subList(0, limit);
133 final NamedQueueGetResponse namedQueueGetResponse = new NamedQueueGetResponse();
134 namedQueueGetResponse.setNamedQueueEvent(BalancerDecisionDetails.BALANCER_DECISION_EVENT);
135 namedQueueGetResponse.setBalancerDecisions(balancerDecisions);
136 return namedQueueGetResponse;
137 }
138
139 @Override
140 public void persistAll() {
141
142 }
143
144 }