1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.quotas;
18
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.concurrent.TimeUnit;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hadoop.conf.Configuration;
29 import org.apache.hadoop.hbase.HRegionInfo;
30 import org.apache.hadoop.hbase.ScheduledChore;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.regionserver.HRegion;
33 import org.apache.hadoop.hbase.regionserver.HRegionServer;
34 import org.apache.hadoop.hbase.regionserver.Region;
35 import org.apache.hadoop.hbase.regionserver.Store;
36 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
37
38
39
40
41 @InterfaceAudience.Private
42 public class FileSystemUtilizationChore extends ScheduledChore {
43 private static final Log LOG = LogFactory.getLog(FileSystemUtilizationChore.class);
44 static final String FS_UTILIZATION_CHORE_PERIOD_KEY = "hbase.regionserver.quotas.fs.utilization.chore.period";
45 static final int FS_UTILIZATION_CHORE_PERIOD_DEFAULT = 1000 * 60 * 5;
46
47 static final String FS_UTILIZATION_CHORE_DELAY_KEY = "hbase.regionserver.quotas.fs.utilization.chore.delay";
48 static final long FS_UTILIZATION_CHORE_DELAY_DEFAULT = 1000L * 60L;
49
50 static final String FS_UTILIZATION_CHORE_TIMEUNIT_KEY = "hbase.regionserver.quotas.fs.utilization.chore.timeunit";
51 static final String FS_UTILIZATION_CHORE_TIMEUNIT_DEFAULT = TimeUnit.MILLISECONDS.name();
52
53 static final String FS_UTILIZATION_MAX_ITERATION_DURATION_KEY = "hbase.regionserver.quotas.fs.utilization.chore.max.iteration.millis";
54 static final long FS_UTILIZATION_MAX_ITERATION_DURATION_DEFAULT = 5000L;
55
56 private int numberOfCyclesToSkip = 0, prevNumberOfCyclesToSkip = 0;
57 private static final int CYCLE_UPPER_BOUND = 32;
58
59 private final HRegionServer rs;
60 private final long maxIterationMillis;
61 private Iterator<Region> leftoverRegions;
62
63 public FileSystemUtilizationChore(HRegionServer rs) {
64 super(FileSystemUtilizationChore.class.getSimpleName(), rs, getPeriod(rs.getConfiguration()),
65 getInitialDelay(rs.getConfiguration()), getTimeUnit(rs.getConfiguration()));
66 this.rs = rs;
67 this.maxIterationMillis = rs.getConfiguration().getLong(
68 FS_UTILIZATION_MAX_ITERATION_DURATION_KEY, FS_UTILIZATION_MAX_ITERATION_DURATION_DEFAULT);
69 }
70
71 @Override
72 protected void chore() {
73 if (numberOfCyclesToSkip > 0) {
74 numberOfCyclesToSkip--;
75 return;
76 }
77 final Map<HRegionInfo,Long> onlineRegionSizes = new HashMap<>();
78 final Set<Region> onlineRegions = new HashSet<>(rs.getOnlineRegions());
79
80
81 Iterator<Region> oldRegionsToProcess = getLeftoverRegions();
82 final Iterator<Region> iterator;
83 final boolean processingLeftovers;
84 if (oldRegionsToProcess == null) {
85 iterator = onlineRegions.iterator();
86 processingLeftovers = false;
87 } else {
88 iterator = oldRegionsToProcess;
89 processingLeftovers = true;
90 }
91
92 setLeftoverRegions(null);
93 long regionSizesCalculated = 0L;
94 long offlineRegionsSkipped = 0L;
95 long skippedSplitParents = 0L;
96 long skippedRegionReplicas = 0L;
97 final long start = EnvironmentEdgeManager.currentTime();
98 while (iterator.hasNext()) {
99
100 long timeRunning = EnvironmentEdgeManager.currentTime() - start;
101 if (timeRunning > maxIterationMillis) {
102 LOG.debug("Preempting execution of FileSystemUtilizationChore because it exceeds the"
103 + " maximum iteration configuration value. Will process remaining iterators"
104 + " on a subsequent invocation.");
105 setLeftoverRegions(iterator);
106 break;
107 }
108
109 final Region region = iterator.next();
110
111
112 if (processingLeftovers && !onlineRegions.contains(region)) {
113 offlineRegionsSkipped++;
114 continue;
115 }
116
117 if (region.getRegionInfo().isSplitParent()) {
118 skippedSplitParents++;
119 continue;
120 }
121
122 if (HRegionInfo.DEFAULT_REPLICA_ID != region.getRegionInfo().getReplicaId()) {
123 skippedRegionReplicas++;
124 continue;
125 }
126 final long sizeInBytes = computeSize(region);
127 onlineRegionSizes.put(region.getRegionInfo(), sizeInBytes);
128 regionSizesCalculated++;
129 }
130 if (LOG.isTraceEnabled()) {
131 LOG.trace("Computed the size of " + regionSizesCalculated + " Regions. Skipped computation"
132 + " of " + offlineRegionsSkipped + " regions due to not being online on this RS, "
133 + skippedSplitParents + " regions due to being the parent of a split, and"
134 + skippedRegionReplicas + " regions due to being region replicas.");
135 }
136 if (!reportRegionSizesToMaster(onlineRegionSizes)) {
137
138 numberOfCyclesToSkip = prevNumberOfCyclesToSkip > 0 ? 2 * prevNumberOfCyclesToSkip : 1;
139 if (numberOfCyclesToSkip > CYCLE_UPPER_BOUND) {
140 numberOfCyclesToSkip = CYCLE_UPPER_BOUND;
141 }
142 prevNumberOfCyclesToSkip = numberOfCyclesToSkip;
143 }
144 }
145
146
147
148
149
150
151 Iterator<Region> getLeftoverRegions() {
152 return leftoverRegions;
153 }
154
155
156
157
158 void setLeftoverRegions(Iterator<Region> newLeftovers) {
159 this.leftoverRegions = newLeftovers;
160 }
161
162
163
164
165
166
167
168 long computeSize(Region r) {
169 long regionSize = 0L;
170 for (Store store : r.getStores()) {
171
172
173 regionSize += store.getStorefilesSize();
174 }
175 return regionSize;
176 }
177
178
179
180
181
182
183
184
185 boolean reportRegionSizesToMaster(Map<HRegionInfo,Long> onlineRegionSizes) {
186 return this.rs.reportRegionSizesForQuotas(onlineRegionSizes);
187 }
188
189
190
191
192
193
194
195 static int getPeriod(Configuration conf) {
196 return conf.getInt(FS_UTILIZATION_CHORE_PERIOD_KEY, FS_UTILIZATION_CHORE_PERIOD_DEFAULT);
197 }
198
199
200
201
202
203
204
205 static long getInitialDelay(Configuration conf) {
206 return conf.getLong(FS_UTILIZATION_CHORE_DELAY_KEY, FS_UTILIZATION_CHORE_DELAY_DEFAULT);
207 }
208
209
210
211
212
213
214
215
216
217 static TimeUnit getTimeUnit(Configuration conf) {
218 return TimeUnit.valueOf(conf.get(FS_UTILIZATION_CHORE_TIMEUNIT_KEY,
219 FS_UTILIZATION_CHORE_TIMEUNIT_DEFAULT));
220 }
221 }