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.regionserver;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.hadoop.conf.Configuration;
25 import org.apache.hadoop.hbase.HConstants;
26 import org.apache.hadoop.hbase.HRegionInfo;
27 import org.apache.hadoop.hbase.RemoteExceptionHandler;
28 import org.apache.hadoop.hbase.client.HTable;
29 import org.apache.hadoop.hbase.client.Put;
30 import org.apache.hadoop.hbase.util.Writables;
31 import org.apache.hadoop.util.StringUtils;
32
33 import java.io.IOException;
34 import java.util.HashSet;
35 import java.util.concurrent.BlockingQueue;
36 import java.util.concurrent.LinkedBlockingQueue;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.locks.ReentrantLock;
39
40
41
42
43 class CompactSplitThread extends Thread {
44 static final Log LOG = LogFactory.getLog(CompactSplitThread.class);
45
46 private HTable root = null;
47 private HTable meta = null;
48 private final long frequency;
49 private final ReentrantLock lock = new ReentrantLock();
50
51 private final HRegionServer server;
52 private final Configuration conf;
53
54 private final BlockingQueue<HRegion> compactionQueue =
55 new LinkedBlockingQueue<HRegion>();
56
57 private final HashSet<HRegion> regionsInQueue = new HashSet<HRegion>();
58
59
60 public CompactSplitThread(HRegionServer server) {
61 super();
62 this.server = server;
63 this.conf = server.conf;
64 this.frequency =
65 conf.getLong("hbase.regionserver.thread.splitcompactcheckfrequency",
66 20 * 1000);
67 }
68
69 @Override
70 public void run() {
71 int count = 0;
72 while (!this.server.isStopRequested()) {
73 HRegion r = null;
74 try {
75 r = compactionQueue.poll(this.frequency, TimeUnit.MILLISECONDS);
76 if (r != null && !this.server.isStopRequested()) {
77 synchronized (regionsInQueue) {
78 regionsInQueue.remove(r);
79 }
80 lock.lock();
81 try {
82
83 byte [] midKey = r.compactStores();
84 if (midKey != null && !this.server.isStopRequested()) {
85 split(r, midKey);
86 }
87 } finally {
88 lock.unlock();
89 }
90 }
91 } catch (InterruptedException ex) {
92 continue;
93 } catch (IOException ex) {
94 LOG.error("Compaction/Split failed for region " +
95 r.getRegionNameAsString(),
96 RemoteExceptionHandler.checkIOException(ex));
97 if (!server.checkFileSystem()) {
98 break;
99 }
100 } catch (Exception ex) {
101 LOG.error("Compaction failed" +
102 (r != null ? (" for region " + r.getRegionNameAsString()) : ""),
103 ex);
104 if (!server.checkFileSystem()) {
105 break;
106 }
107 }
108 }
109 regionsInQueue.clear();
110 compactionQueue.clear();
111 LOG.info(getName() + " exiting");
112 }
113
114
115
116
117
118 public synchronized void compactionRequested(final HRegion r,
119 final String why) {
120 compactionRequested(r, false, why);
121 }
122
123
124
125
126
127
128 public synchronized void compactionRequested(final HRegion r,
129 final boolean force, final String why) {
130 if (this.server.stopRequested.get()) {
131 return;
132 }
133 r.setForceMajorCompaction(force);
134 if (LOG.isDebugEnabled()) {
135 LOG.debug("Compaction " + (force? "(major) ": "") +
136 "requested for region " + r.getRegionNameAsString() +
137 (why != null && !why.isEmpty()? " because: " + why: ""));
138 }
139 synchronized (regionsInQueue) {
140 if (!regionsInQueue.contains(r)) {
141 compactionQueue.add(r);
142 regionsInQueue.add(r);
143 }
144 }
145 }
146
147 private void split(final HRegion region, final byte [] midKey)
148 throws IOException {
149 final HRegionInfo oldRegionInfo = region.getRegionInfo();
150 final long startTime = System.currentTimeMillis();
151 final HRegion[] newRegions = region.splitRegion(midKey);
152 if (newRegions == null) {
153
154 return;
155 }
156
157
158
159
160 HTable t = null;
161 if (region.getRegionInfo().isMetaTable()) {
162
163 if (this.root == null) {
164 this.root = new HTable(conf, HConstants.ROOT_TABLE_NAME);
165 }
166 t = root;
167 } else {
168
169 if (meta == null) {
170 meta = new HTable(conf, HConstants.META_TABLE_NAME);
171 }
172 t = meta;
173 }
174
175
176
177 oldRegionInfo.setOffline(true);
178 oldRegionInfo.setSplit(true);
179
180 this.server.removeFromOnlineRegions(oldRegionInfo);
181
182 Put put = new Put(oldRegionInfo.getRegionName());
183 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
184 Writables.getBytes(oldRegionInfo));
185 put.add(HConstants.CATALOG_FAMILY, HConstants.SERVER_QUALIFIER,
186 HConstants.EMPTY_BYTE_ARRAY);
187 put.add(HConstants.CATALOG_FAMILY, HConstants.STARTCODE_QUALIFIER,
188 HConstants.EMPTY_BYTE_ARRAY);
189 put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITA_QUALIFIER,
190 Writables.getBytes(newRegions[0].getRegionInfo()));
191 put.add(HConstants.CATALOG_FAMILY, HConstants.SPLITB_QUALIFIER,
192 Writables.getBytes(newRegions[1].getRegionInfo()));
193 t.put(put);
194
195
196
197
198
199
200 for (int i = 0; i < newRegions.length; i++) {
201 put = new Put(newRegions[i].getRegionName());
202 put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
203 Writables.getBytes(newRegions[i].getRegionInfo()));
204 t.put(put);
205 }
206
207
208
209
210
211
212 server.reportSplit(oldRegionInfo, newRegions[0].getRegionInfo(),
213 newRegions[1].getRegionInfo());
214
215 LOG.info("region split, META updated, and report to master all" +
216 " successful. Old region=" + oldRegionInfo.toString() +
217 ", new regions: " + newRegions[0].toString() + ", " +
218 newRegions[1].toString() + ". Split took " +
219 StringUtils.formatTimeDiff(System.currentTimeMillis(), startTime));
220 }
221
222
223
224
225 void interruptIfNecessary() {
226 if (lock.tryLock()) {
227 this.interrupt();
228 }
229 }
230
231
232
233
234
235
236
237 public int getCompactionQueueSize() {
238 return compactionQueue.size();
239 }
240 }