1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.regionserver;
20
21 import com.google.common.annotations.VisibleForTesting;
22 import com.google.common.cache.Cache;
23 import com.google.common.cache.CacheBuilder;
24 import com.google.protobuf.ByteString;
25 import com.google.protobuf.Message;
26 import com.google.protobuf.RpcController;
27 import com.google.protobuf.ServiceException;
28 import com.google.protobuf.TextFormat;
29
30 import java.io.FileNotFoundException;
31 import java.io.IOException;
32 import java.io.InterruptedIOException;
33 import java.net.BindException;
34 import java.net.InetSocketAddress;
35 import java.net.UnknownHostException;
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Map.Entry;
44 import java.util.NavigableMap;
45 import java.util.Set;
46 import java.util.TreeSet;
47 import java.util.concurrent.ConcurrentHashMap;
48 import java.util.concurrent.ConcurrentMap;
49 import java.util.concurrent.TimeUnit;
50 import java.util.concurrent.atomic.AtomicLong;
51
52 import org.apache.commons.lang.mutable.MutableObject;
53 import org.apache.commons.logging.Log;
54 import org.apache.commons.logging.LogFactory;
55 import org.apache.hadoop.conf.Configuration;
56 import org.apache.hadoop.hbase.Cell;
57 import org.apache.hadoop.hbase.CellScannable;
58 import org.apache.hadoop.hbase.CellScanner;
59 import org.apache.hadoop.hbase.CellUtil;
60 import org.apache.hadoop.hbase.DoNotRetryIOException;
61 import org.apache.hadoop.hbase.DroppedSnapshotException;
62 import org.apache.hadoop.hbase.HBaseIOException;
63 import org.apache.hadoop.hbase.HConstants;
64 import org.apache.hadoop.hbase.HRegionInfo;
65 import org.apache.hadoop.hbase.HTableDescriptor;
66 import org.apache.hadoop.hbase.MetaTableAccessor;
67 import org.apache.hadoop.hbase.MultiActionResultTooLarge;
68 import org.apache.hadoop.hbase.NotServingRegionException;
69 import org.apache.hadoop.hbase.ServerName;
70 import org.apache.hadoop.hbase.TableName;
71 import org.apache.hadoop.hbase.UnknownScannerException;
72 import org.apache.hadoop.hbase.classification.InterfaceAudience;
73 import org.apache.hadoop.hbase.client.Append;
74 import org.apache.hadoop.hbase.client.ConnectionUtils;
75 import org.apache.hadoop.hbase.client.Delete;
76 import org.apache.hadoop.hbase.client.Durability;
77 import org.apache.hadoop.hbase.client.Get;
78 import org.apache.hadoop.hbase.client.Increment;
79 import org.apache.hadoop.hbase.client.Mutation;
80 import org.apache.hadoop.hbase.client.Put;
81 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
82 import org.apache.hadoop.hbase.client.Result;
83 import org.apache.hadoop.hbase.client.RowMutations;
84 import org.apache.hadoop.hbase.client.Scan;
85 import org.apache.hadoop.hbase.client.VersionInfoUtil;
86 import org.apache.hadoop.hbase.conf.ConfigurationObserver;
87 import org.apache.hadoop.hbase.coordination.CloseRegionCoordination;
88 import org.apache.hadoop.hbase.coordination.OpenRegionCoordination;
89 import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;
90 import org.apache.hadoop.hbase.exceptions.MergeRegionException;
91 import org.apache.hadoop.hbase.exceptions.OperationConflictException;
92 import org.apache.hadoop.hbase.exceptions.OutOfOrderScannerNextException;
93 import org.apache.hadoop.hbase.exceptions.ScannerResetException;
94 import org.apache.hadoop.hbase.filter.ByteArrayComparable;
95 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
96 import org.apache.hadoop.hbase.ipc.HBaseRPCErrorHandler;
97 import org.apache.hadoop.hbase.ipc.HBaseRpcController;
98 import org.apache.hadoop.hbase.ipc.PriorityFunction;
99 import org.apache.hadoop.hbase.ipc.QosPriority;
100 import org.apache.hadoop.hbase.ipc.RpcCallContext;
101 import org.apache.hadoop.hbase.ipc.RpcServer;
102 import org.apache.hadoop.hbase.ipc.RpcServer.BlockingServiceAndInterface;
103 import org.apache.hadoop.hbase.ipc.RpcServerInterface;
104 import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException;
105 import org.apache.hadoop.hbase.ipc.ServerRpcController;
106 import org.apache.hadoop.hbase.master.MasterRpcServices;
107 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
108 import org.apache.hadoop.hbase.protobuf.RequestConverter;
109 import org.apache.hadoop.hbase.protobuf.ResponseConverter;
110 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
111 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
112 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
113 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
114 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionResponse;
115 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
116 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionResponse;
117 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
118 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
119 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
120 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
121 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
122 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoResponse;
123 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
124 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileResponse;
125 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsRequest;
126 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsResponse;
127 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
128 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest.RegionOpenInfo;
129 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionResponse;
130 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionResponse.RegionOpeningState;
131 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ReplicateWALEntryRequest;
132 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ReplicateWALEntryResponse;
133 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
134 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
135 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
136 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionResponse;
137 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
138 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerResponse;
139 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateConfigurationRequest;
140 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateConfigurationResponse;
141 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest;
142 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesResponse;
143 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WALEntry;
144 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WarmupRegionRequest;
145 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WarmupRegionResponse;
146 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
147 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Action;
148 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
149 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest.FamilyPath;
150 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileResponse;
151 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
152 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition;
153 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceRequest;
154 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceResponse;
155 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
156 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetResponse;
157 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MultiRegionLoadStats;
158 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MultiRequest;
159 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MultiResponse;
160 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
161 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateResponse;
162 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
163 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
164 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
165 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
166 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ResultOrException;
167 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
168 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanResponse;
169 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameBytesPair;
170 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameInt64Pair;
171 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
172 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
173 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
174 import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos.ScanMetrics;
175 import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.RequestHeader;
176 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.BulkLoadDescriptor;
177 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.CompactionDescriptor;
178 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor;
179 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor;
180 import org.apache.hadoop.hbase.quotas.OperationQuota;
181 import org.apache.hadoop.hbase.quotas.RegionServerQuotaManager;
182 import org.apache.hadoop.hbase.regionserver.Leases.LeaseStillHeldException;
183 import org.apache.hadoop.hbase.regionserver.Region.Operation;
184 import org.apache.hadoop.hbase.regionserver.ScannerContext.LimitScope;
185 import org.apache.hadoop.hbase.regionserver.handler.OpenMetaHandler;
186 import org.apache.hadoop.hbase.regionserver.handler.OpenPriorityRegionHandler;
187 import org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler;
188 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
189 import org.apache.hadoop.hbase.security.User;
190 import org.apache.hadoop.hbase.util.Bytes;
191 import org.apache.hadoop.hbase.util.Counter;
192 import org.apache.hadoop.hbase.util.DNS;
193 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
194 import org.apache.hadoop.hbase.util.Pair;
195 import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
196 import org.apache.hadoop.hbase.util.Strings;
197 import org.apache.hadoop.hbase.wal.WAL;
198 import org.apache.hadoop.hbase.wal.WALKey;
199 import org.apache.hadoop.hbase.wal.WALSplitter;
200 import org.apache.hadoop.hbase.zookeeper.ZKSplitLog;
201 import org.apache.zookeeper.KeeperException;
202
203 import com.google.common.annotations.VisibleForTesting;
204
205
206
207
208 @InterfaceAudience.Private
209 @SuppressWarnings("deprecation")
210 public class RSRpcServices implements HBaseRPCErrorHandler,
211 AdminService.BlockingInterface, ClientService.BlockingInterface, PriorityFunction,
212 ConfigurationObserver {
213 protected static final Log LOG = LogFactory.getLog(RSRpcServices.class);
214
215
216 public static final String REGION_SERVER_RPC_SCHEDULER_FACTORY_CLASS =
217 "hbase.region.server.rpc.scheduler.factory.class";
218
219
220
221
222
223
224 private static final String REGION_SERVER_RPC_MINIMUM_SCAN_TIME_LIMIT_DELTA =
225 "hbase.region.server.rpc.minimum.scan.time.limit.delta";
226
227
228
229 private static final long DEFAULT_REGION_SERVER_RPC_MINIMUM_SCAN_TIME_LIMIT_DELTA = 10;
230
231
232
233
234 static final String BATCH_ROWS_THRESHOLD_NAME = "hbase.rpc.rows.warning.threshold";
235
236
237
238 static final int BATCH_ROWS_THRESHOLD_DEFAULT = 5000;
239
240
241 final Counter requestCount = new Counter();
242
243
244 final Counter rpcGetRequestCount = new Counter();
245
246
247 final Counter rpcScanRequestCount = new Counter();
248
249
250 final Counter rpcMultiRequestCount = new Counter();
251
252
253 final Counter rpcMutateRequestCount = new Counter();
254
255
256 final RpcServerInterface rpcServer;
257 final InetSocketAddress isa;
258
259 private final HRegionServer regionServer;
260 private final long maxScannerResultSize;
261
262
263 private final PriorityFunction priority;
264
265 private ScannerIdGenerator scannerIdGenerator;
266 private final ConcurrentMap<String, RegionScannerHolder> scanners = new ConcurrentHashMap<>();
267
268
269
270 private final Cache<String, String> closedScanners;
271
272
273
274 private final int scannerLeaseTimeoutPeriod;
275
276
277
278
279 private final int rpcTimeout;
280
281
282
283
284 private final long minimumScanTimeLimitDelta;
285
286
287
288
289 private final int rowSizeWarnThreshold;
290
291
292
293
294 private static final class RegionScannerHolder {
295
296 private final AtomicLong nextCallSeq = new AtomicLong(0);
297 private final String scannerName;
298 private final RegionScanner s;
299 private final Region r;
300 private byte[] rowOfLastPartialResult;
301 private boolean needCursor;
302
303 public RegionScannerHolder(String scannerName, RegionScanner s, Region r, boolean needCursor) {
304 this.scannerName = scannerName;
305 this.s = s;
306 this.r = r;
307 this.needCursor = needCursor;
308 }
309
310 public long getNextCallSeq() {
311 return nextCallSeq.get();
312 }
313
314 public boolean incNextCallSeq(long currentSeq) {
315
316 return nextCallSeq.compareAndSet(currentSeq, currentSeq + 1);
317 }
318 }
319
320
321
322
323
324 private class ScannerListener implements LeaseListener {
325 private final String scannerName;
326
327 ScannerListener(final String n) {
328 this.scannerName = n;
329 }
330
331 @Override
332 public void leaseExpired() {
333 RegionScannerHolder rsh = scanners.remove(this.scannerName);
334 if (rsh != null) {
335 RegionScanner s = rsh.s;
336 LOG.info("Scanner " + this.scannerName + " lease expired on region "
337 + s.getRegionInfo().getRegionNameAsString());
338 Region region = null;
339 try {
340 region = regionServer.getRegion(s.getRegionInfo().getRegionName());
341 if (region != null && region.getCoprocessorHost() != null) {
342 region.getCoprocessorHost().preScannerClose(s);
343 }
344 } catch (IOException e) {
345 LOG.error("Closing scanner for " + s.getRegionInfo().getRegionNameAsString(), e);
346 } finally {
347 try {
348 s.close();
349 if (region != null && region.getCoprocessorHost() != null) {
350 region.getCoprocessorHost().postScannerClose(s);
351 }
352 } catch (IOException e) {
353 LOG.error("Closing scanner for " + s.getRegionInfo().getRegionNameAsString(), e);
354 }
355 }
356 } else {
357 LOG.warn("Scanner " + this.scannerName + " lease expired, but no related" +
358 " scanner found, hence no chance to close that related scanner!");
359 }
360 }
361 }
362
363 private static ResultOrException getResultOrException(final ClientProtos.Result r,
364 final int index){
365 return getResultOrException(ResponseConverter.buildActionResult(r), index);
366 }
367
368 private static ResultOrException getResultOrException(final Exception e, final int index) {
369 return getResultOrException(ResponseConverter.buildActionResult(e), index);
370 }
371
372 private static ResultOrException getResultOrException(
373 final ResultOrException.Builder builder, final int index) {
374 return builder.setIndex(index).build();
375 }
376
377
378
379
380
381
382
383 private boolean startNonceOperation(final MutationProto mutation, long nonceGroup)
384 throws IOException, OperationConflictException {
385 if (regionServer.nonceManager == null || !mutation.hasNonce()) return true;
386 boolean canProceed = false;
387 try {
388 canProceed = regionServer.nonceManager.startOperation(
389 nonceGroup, mutation.getNonce(), regionServer);
390 } catch (InterruptedException ex) {
391 throw new InterruptedIOException("Nonce start operation interrupted");
392 }
393 return canProceed;
394 }
395
396
397
398
399
400
401
402 private void endNonceOperation(final MutationProto mutation,
403 long nonceGroup, boolean success) {
404 if (regionServer.nonceManager != null && mutation.hasNonce()) {
405 regionServer.nonceManager.endOperation(nonceGroup, mutation.getNonce(), success);
406 }
407 }
408
409
410
411
412 private boolean isClientCellBlockSupport() {
413 return isClientCellBlockSupport(RpcServer.getCurrentCall());
414 }
415
416 private boolean isClientCellBlockSupport(RpcCallContext context) {
417 return context != null && context.isClientCellBlockSupported();
418 }
419
420 private void addResult(final MutateResponse.Builder builder,
421 final Result result, final HBaseRpcController rpcc) {
422 if (result == null) return;
423 if (isClientCellBlockSupport()) {
424 builder.setResult(ProtobufUtil.toResultNoData(result));
425 rpcc.setCellScanner(result.cellScanner());
426 } else {
427 ClientProtos.Result pbr = ProtobufUtil.toResult(result);
428 builder.setResult(pbr);
429 }
430 }
431
432 private void addResults(final ScanResponse.Builder builder, final List<Result> results,
433 final HBaseRpcController controller, boolean isDefaultRegion) {
434 builder.setStale(!isDefaultRegion);
435 if (results.isEmpty()) {
436 return;
437 }
438 if (isClientCellBlockSupport()) {
439 for (Result res : results) {
440 builder.addCellsPerResult(res.size());
441 builder.addPartialFlagPerResult(res.mayHaveMoreCellsInRow());
442 }
443 controller.setCellScanner(CellUtil.createCellScanner(results));
444 } else {
445 for (Result res : results) {
446 ClientProtos.Result pbr = ProtobufUtil.toResult(res);
447 builder.addResults(pbr);
448 }
449 }
450 }
451
452
453
454
455
456
457
458
459
460 private void mutateRows(final Region region,
461 final List<ClientProtos.Action> actions,
462 final CellScanner cellScanner, RegionActionResult.Builder builder) throws IOException {
463 int countOfCompleteMutation = 0;
464 try {
465 if (!region.getRegionInfo().isMetaTable()) {
466 regionServer.cacheFlusher.reclaimMemStoreMemory();
467 }
468 RowMutations rm = null;
469 int i = 0;
470 ClientProtos.ResultOrException.Builder resultOrExceptionOrBuilder =
471 ClientProtos.ResultOrException.newBuilder();
472 for (ClientProtos.Action action: actions) {
473 if (action.hasGet()) {
474 throw new DoNotRetryIOException("Atomic put and/or delete only, not a Get=" +
475 action.getGet());
476 }
477 MutationType type = action.getMutation().getMutateType();
478 if (rm == null) {
479 rm = new RowMutations(action.getMutation().getRow().toByteArray());
480 }
481 switch (type) {
482 case PUT:
483 Put put = ProtobufUtil.toPut(action.getMutation(), cellScanner);
484 ++countOfCompleteMutation;
485 checkCellSizeLimit(region, put);
486 rm.add(put);
487 break;
488 case DELETE:
489 Delete delete = ProtobufUtil.toDelete(action.getMutation(), cellScanner);
490 ++countOfCompleteMutation;
491 rm.add(delete);
492 break;
493 default:
494 throw new DoNotRetryIOException("Atomic put and/or delete only, not " + type.name());
495 }
496
497
498 resultOrExceptionOrBuilder.clear();
499 resultOrExceptionOrBuilder.setIndex(i++);
500 builder.addResultOrException(
501 resultOrExceptionOrBuilder.build());
502 }
503 region.mutateRow(rm);
504 } finally {
505
506
507 for (int i = countOfCompleteMutation; i < actions.size(); ++i) {
508 skipCellsForMutation(actions.get(i), cellScanner);
509 }
510 }
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525 private boolean checkAndRowMutate(final Region region, final List<ClientProtos.Action> actions,
526 final CellScanner cellScanner, byte[] row, byte[] family, byte[] qualifier,
527 CompareOp compareOp, ByteArrayComparable comparator,
528 RegionActionResult.Builder builder) throws IOException {
529 int countOfCompleteMutation = 0;
530 try {
531 if (!region.getRegionInfo().isMetaTable()) {
532 regionServer.cacheFlusher.reclaimMemStoreMemory();
533 }
534 RowMutations rm = null;
535 int i = 0;
536 ClientProtos.ResultOrException.Builder resultOrExceptionOrBuilder =
537 ClientProtos.ResultOrException.newBuilder();
538 for (ClientProtos.Action action: actions) {
539 if (action.hasGet()) {
540 throw new DoNotRetryIOException("Atomic put and/or delete only, not a Get=" +
541 action.getGet());
542 }
543 MutationType type = action.getMutation().getMutateType();
544 if (rm == null) {
545 rm = new RowMutations(action.getMutation().getRow().toByteArray());
546 }
547 switch (type) {
548 case PUT:
549 Put put = ProtobufUtil.toPut(action.getMutation(), cellScanner);
550 ++countOfCompleteMutation;
551 checkCellSizeLimit(region, put);
552 rm.add(put);
553 break;
554 case DELETE:
555 Delete delete = ProtobufUtil.toDelete(action.getMutation(), cellScanner);
556 ++countOfCompleteMutation;
557 rm.add(delete);
558 break;
559 default:
560 throw new DoNotRetryIOException("Atomic put and/or delete only, not " + type.name());
561 }
562
563
564 resultOrExceptionOrBuilder.clear();
565 resultOrExceptionOrBuilder.setIndex(i++);
566 builder.addResultOrException(
567 resultOrExceptionOrBuilder.build());
568 }
569 return region.checkAndRowMutate(row, family, qualifier, compareOp,
570 comparator, rm, Boolean.TRUE);
571 } finally {
572
573
574 for (int i = countOfCompleteMutation; i < actions.size(); ++i) {
575 skipCellsForMutation(actions.get(i), cellScanner);
576 }
577 }
578 }
579
580
581
582
583
584
585
586
587
588
589
590
591 private Result append(final Region region, final OperationQuota quota,
592 final MutationProto mutation, final CellScanner cellScanner, long nonceGroup)
593 throws IOException {
594 long before = EnvironmentEdgeManager.currentTime();
595 Append append = ProtobufUtil.toAppend(mutation, cellScanner);
596 checkCellSizeLimit(region, append);
597 quota.addMutation(append);
598 Result r = null;
599 if (region.getCoprocessorHost() != null) {
600 r = region.getCoprocessorHost().preAppend(append);
601 }
602 if (r == null) {
603 boolean canProceed = startNonceOperation(mutation, nonceGroup);
604 boolean success = false;
605 try {
606 long nonce = mutation.hasNonce() ? mutation.getNonce() : HConstants.NO_NONCE;
607 if (canProceed) {
608 r = region.append(append, nonceGroup, nonce);
609 } else {
610
611 List<Cell> results = region.get(ProtobufUtil.toGet(mutation, cellScanner), false,
612 nonceGroup, nonce);
613 r = Result.create(results);
614 }
615 success = true;
616 } finally {
617 if (canProceed) {
618 endNonceOperation(mutation, nonceGroup, success);
619 }
620 }
621 if (region.getCoprocessorHost() != null) {
622 r = region.getCoprocessorHost().postAppend(append, r);
623 }
624 }
625 if (regionServer.metricsRegionServer != null) {
626 regionServer.metricsRegionServer.updateAppend(
627 region.getTableDesc().getTableName(),
628 EnvironmentEdgeManager.currentTime() - before);
629 }
630 return r;
631 }
632
633
634
635
636
637
638
639
640
641
642
643 private Result increment(final Region region, final OperationQuota quota,
644 final MutationProto mutation, final CellScanner cellScanner, long nonceGroup)
645 throws IOException {
646 long before = EnvironmentEdgeManager.currentTime();
647 Increment increment = ProtobufUtil.toIncrement(mutation, cellScanner);
648 checkCellSizeLimit(region, increment);
649 quota.addMutation(increment);
650 Result r = null;
651 if (region.getCoprocessorHost() != null) {
652 r = region.getCoprocessorHost().preIncrement(increment);
653 }
654 if (r == null) {
655 boolean canProceed = startNonceOperation(mutation, nonceGroup);
656 boolean success = false;
657 try {
658 long nonce = mutation.hasNonce() ? mutation.getNonce() : HConstants.NO_NONCE;
659 if (canProceed) {
660 r = region.increment(increment, nonceGroup, nonce);
661 } else {
662
663 List<Cell> results = region.get(ProtobufUtil.toGet(mutation, cellScanner), false,
664 nonceGroup, nonce);
665 r = Result.create(results);
666 }
667 success = true;
668 } finally {
669 if (canProceed) {
670 endNonceOperation(mutation, nonceGroup, success);
671 }
672 }
673 if (region.getCoprocessorHost() != null) {
674 r = region.getCoprocessorHost().postIncrement(increment, r);
675 }
676 }
677 if (regionServer.metricsRegionServer != null) {
678 regionServer.metricsRegionServer.updateIncrement(
679 region.getTableDesc().getTableName(),
680 EnvironmentEdgeManager.currentTime() - before);
681 }
682 return r;
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696 private List<CellScannable> doNonAtomicRegionMutation(final Region region,
697 final OperationQuota quota, final RegionAction actions, final CellScanner cellScanner,
698 final RegionActionResult.Builder builder, List<CellScannable> cellsToReturn, long nonceGroup) {
699
700
701
702
703 List<ClientProtos.Action> mutations = null;
704 long maxQuotaResultSize = Math.min(maxScannerResultSize, quota.getReadAvailable());
705 RpcCallContext context = RpcServer.getCurrentCall();
706 IOException sizeIOE = null;
707 Object lastBlock = null;
708 ClientProtos.ResultOrException.Builder resultOrExceptionBuilder = ResultOrException.newBuilder();
709 boolean hasResultOrException = false;
710 for (ClientProtos.Action action : actions.getActionList()) {
711 hasResultOrException = false;
712 resultOrExceptionBuilder.clear();
713 try {
714 Result r = null;
715
716 if (context != null
717 && context.isRetryImmediatelySupported()
718 && (context.getResponseCellSize() > maxQuotaResultSize
719 || context.getResponseBlockSize() + context.getResponseExceptionSize()
720 > maxQuotaResultSize)) {
721
722
723
724 if (sizeIOE == null ) {
725
726
727
728
729 sizeIOE = new MultiActionResultTooLarge("Max size exceeded"
730 + " CellSize: " + context.getResponseCellSize()
731 + " BlockSize: " + context.getResponseBlockSize());
732
733
734
735 rpcServer.getMetrics().exception(sizeIOE);
736 }
737
738
739
740
741
742 hasResultOrException = true;
743 NameBytesPair pair = ResponseConverter.buildException(sizeIOE);
744 resultOrExceptionBuilder.setException(pair);
745 context.incrementResponseExceptionSize(pair.getSerializedSize());
746 resultOrExceptionBuilder.setIndex(action.getIndex());
747 builder.addResultOrException(resultOrExceptionBuilder.build());
748 skipCellsForMutation(action, cellScanner);
749 continue;
750 }
751 if (action.hasGet()) {
752 long before = EnvironmentEdgeManager.currentTime();
753 try {
754 Get get = ProtobufUtil.toGet(action.getGet());
755 r = region.get(get);
756 } finally {
757 if (regionServer.metricsRegionServer != null) {
758 regionServer.metricsRegionServer.updateGet(
759 region.getTableDesc().getTableName(),
760 EnvironmentEdgeManager.currentTime() - before);
761 }
762 }
763 } else if (action.hasServiceCall()) {
764 hasResultOrException = true;
765 try {
766 Message result = execServiceOnRegion(region, action.getServiceCall());
767 ClientProtos.CoprocessorServiceResult.Builder serviceResultBuilder =
768 ClientProtos.CoprocessorServiceResult.newBuilder();
769 resultOrExceptionBuilder.setServiceResult(
770 serviceResultBuilder.setValue(
771 serviceResultBuilder.getValueBuilder()
772 .setName(result.getClass().getName())
773 .setValue(result.toByteString())));
774 } catch (IOException ioe) {
775 rpcServer.getMetrics().exception(ioe);
776 NameBytesPair pair = ResponseConverter.buildException(ioe);
777 resultOrExceptionBuilder.setException(pair);
778 context.incrementResponseExceptionSize(pair.getSerializedSize());
779 }
780 } else if (action.hasMutation()) {
781 MutationType type = action.getMutation().getMutateType();
782 if (type != MutationType.PUT && type != MutationType.DELETE && mutations != null &&
783 !mutations.isEmpty()) {
784
785 doBatchOp(builder, region, quota, mutations, cellScanner);
786 mutations.clear();
787 }
788 switch (type) {
789 case APPEND:
790 r = append(region, quota, action.getMutation(), cellScanner, nonceGroup);
791 break;
792 case INCREMENT:
793 r = increment(region, quota, action.getMutation(), cellScanner, nonceGroup);
794 break;
795 case PUT:
796 case DELETE:
797
798 if (mutations == null) {
799 mutations = new ArrayList<ClientProtos.Action>(actions.getActionCount());
800 }
801 mutations.add(action);
802 break;
803 default:
804 throw new DoNotRetryIOException("Unsupported mutate type: " + type.name());
805 }
806 } else {
807 throw new HBaseIOException("Unexpected Action type");
808 }
809 if (r != null) {
810 ClientProtos.Result pbResult = null;
811 if (isClientCellBlockSupport()) {
812 pbResult = ProtobufUtil.toResultNoData(r);
813
814 if (cellsToReturn == null) {
815 cellsToReturn = new ArrayList<CellScannable>();
816 }
817 cellsToReturn.add(r);
818 } else {
819 pbResult = ProtobufUtil.toResult(r);
820 }
821 lastBlock = addSize(context, r, lastBlock);
822 hasResultOrException = true;
823 resultOrExceptionBuilder.setResult(pbResult);
824 }
825
826
827
828
829 } catch (IOException ie) {
830 rpcServer.getMetrics().exception(ie);
831 hasResultOrException = true;
832 NameBytesPair pair = ResponseConverter.buildException(ie);
833 resultOrExceptionBuilder.setException(pair);
834 context.incrementResponseExceptionSize(pair.getSerializedSize());
835 }
836 if (hasResultOrException) {
837
838 resultOrExceptionBuilder.setIndex(action.getIndex());
839 builder.addResultOrException(resultOrExceptionBuilder.build());
840 }
841 }
842
843 if (mutations != null && !mutations.isEmpty()) {
844 doBatchOp(builder, region, quota, mutations, cellScanner);
845 }
846 return cellsToReturn;
847 }
848
849 private void checkCellSizeLimit(final Region region, final Mutation m) throws IOException {
850 if (!(region instanceof HRegion)) {
851 return;
852 }
853 HRegion r = (HRegion)region;
854 if (r.maxCellSize > 0) {
855 CellScanner cells = m.cellScanner();
856 while (cells.advance()) {
857 int size = CellUtil.estimatedSerializedSizeOf(cells.current());
858 if (size > r.maxCellSize) {
859 String msg = "Cell with size " + size + " exceeds limit of " + r.maxCellSize + " bytes";
860 if (LOG.isDebugEnabled()) {
861 LOG.debug(msg);
862 }
863 throw new DoNotRetryIOException(msg);
864 }
865 }
866 }
867 }
868
869
870
871
872
873
874
875
876 private void doBatchOp(final RegionActionResult.Builder builder, final Region region,
877 final OperationQuota quota,
878 final List<ClientProtos.Action> mutations, final CellScanner cells) {
879 Mutation[] mArray = new Mutation[mutations.size()];
880 long before = EnvironmentEdgeManager.currentTime();
881 boolean batchContainsPuts = false, batchContainsDelete = false;
882 try {
883
884
885
886
887
888
889
890 Map<Mutation, ClientProtos.Action> mutationActionMap = new HashMap<Mutation, ClientProtos.Action>();
891 int i = 0;
892 for (ClientProtos.Action action: mutations) {
893 MutationProto m = action.getMutation();
894 Mutation mutation;
895 if (m.getMutateType() == MutationType.PUT) {
896 mutation = ProtobufUtil.toPut(m, cells);
897 batchContainsPuts = true;
898 } else {
899 mutation = ProtobufUtil.toDelete(m, cells);
900 batchContainsDelete = true;
901 }
902 mutationActionMap.put(mutation, action);
903 mArray[i++] = mutation;
904 checkCellSizeLimit(region, mutation);
905 quota.addMutation(mutation);
906 }
907
908 if (!region.getRegionInfo().isMetaTable()) {
909 regionServer.cacheFlusher.reclaimMemStoreMemory();
910 }
911
912
913
914 Arrays.sort(mArray);
915
916 OperationStatus[] codes = region.batchMutate(mArray, HConstants.NO_NONCE,
917 HConstants.NO_NONCE);
918 for (i = 0; i < codes.length; i++) {
919 Mutation currentMutation = mArray[i];
920 ClientProtos.Action currentAction = mutationActionMap.get(currentMutation);
921 int index = currentAction.getIndex();
922 Exception e = null;
923 switch (codes[i].getOperationStatusCode()) {
924 case BAD_FAMILY:
925 e = new NoSuchColumnFamilyException(codes[i].getExceptionMsg());
926 builder.addResultOrException(getResultOrException(e, index));
927 break;
928
929 case SANITY_CHECK_FAILURE:
930 e = new FailedSanityCheckException(codes[i].getExceptionMsg());
931 builder.addResultOrException(getResultOrException(e, index));
932 break;
933
934 default:
935 e = new DoNotRetryIOException(codes[i].getExceptionMsg());
936 builder.addResultOrException(getResultOrException(e, index));
937 break;
938
939 case SUCCESS:
940 builder.addResultOrException(getResultOrException(
941 ClientProtos.Result.getDefaultInstance(), index));
942 break;
943 }
944 }
945 } catch (IOException ie) {
946 int processedMutationIndex = 0;
947 for (Action mutation : mutations) {
948
949 if (mArray[processedMutationIndex++] == null) {
950 skipCellsForMutation(mutation, cells);
951 }
952 builder.addResultOrException(getResultOrException(ie, mutation.getIndex()));
953 }
954 }
955 if (regionServer.metricsRegionServer != null) {
956 long after = EnvironmentEdgeManager.currentTime();
957 if (batchContainsPuts) {
958 regionServer.metricsRegionServer.updatePutBatch(
959 region.getTableDesc().getTableName(), after - before);
960 }
961 if (batchContainsDelete) {
962 regionServer.metricsRegionServer.updateDeleteBatch(
963 region.getTableDesc().getTableName(), after - before);
964 }
965 }
966 }
967
968
969
970
971
972
973
974
975
976
977
978 private OperationStatus [] doReplayBatchOp(final Region region,
979 final List<WALSplitter.MutationReplay> mutations, long replaySeqId) throws IOException {
980 long before = EnvironmentEdgeManager.currentTime();
981 boolean batchContainsPuts = false, batchContainsDelete = false;
982 try {
983 for (Iterator<WALSplitter.MutationReplay> it = mutations.iterator(); it.hasNext();) {
984 WALSplitter.MutationReplay m = it.next();
985
986 if (m.type == MutationType.PUT) {
987 batchContainsPuts = true;
988 } else {
989 batchContainsDelete = true;
990 }
991
992 NavigableMap<byte[], List<Cell>> map = m.mutation.getFamilyCellMap();
993 List<Cell> metaCells = map.get(WALEdit.METAFAMILY);
994 if (metaCells != null && !metaCells.isEmpty()) {
995 for (Cell metaCell : metaCells) {
996 CompactionDescriptor compactionDesc = WALEdit.getCompaction(metaCell);
997 boolean isDefaultReplica = RegionReplicaUtil.isDefaultReplica(region.getRegionInfo());
998 HRegion hRegion = (HRegion)region;
999 if (compactionDesc != null) {
1000
1001
1002 hRegion.replayWALCompactionMarker(compactionDesc, !isDefaultReplica, isDefaultReplica,
1003 replaySeqId);
1004 continue;
1005 }
1006 FlushDescriptor flushDesc = WALEdit.getFlushDescriptor(metaCell);
1007 if (flushDesc != null && !isDefaultReplica) {
1008 hRegion.replayWALFlushMarker(flushDesc, replaySeqId);
1009 continue;
1010 }
1011 RegionEventDescriptor regionEvent = WALEdit.getRegionEventDescriptor(metaCell);
1012 if (regionEvent != null && !isDefaultReplica) {
1013 hRegion.replayWALRegionEventMarker(regionEvent);
1014 continue;
1015 }
1016 BulkLoadDescriptor bulkLoadEvent = WALEdit.getBulkLoadDescriptor(metaCell);
1017 if (bulkLoadEvent != null) {
1018 hRegion.replayWALBulkLoadEventMarker(bulkLoadEvent);
1019 continue;
1020 }
1021 }
1022 it.remove();
1023 }
1024 }
1025 requestCount.increment();
1026 if (!region.getRegionInfo().isMetaTable()) {
1027 regionServer.cacheFlusher.reclaimMemStoreMemory();
1028 }
1029 return region.batchReplay(mutations.toArray(
1030 new WALSplitter.MutationReplay[mutations.size()]), replaySeqId);
1031 } finally {
1032 if (regionServer.metricsRegionServer != null) {
1033 long after = EnvironmentEdgeManager.currentTime();
1034 if (batchContainsPuts) {
1035 regionServer.metricsRegionServer.updatePutBatch(
1036 region.getTableDesc().getTableName(), after - before);
1037 }
1038 if (batchContainsDelete) {
1039 regionServer.metricsRegionServer.updateDeleteBatch(
1040 region.getTableDesc().getTableName(), after - before);
1041 }
1042 }
1043 }
1044 }
1045
1046 private void closeAllScanners() {
1047
1048
1049 for (Map.Entry<String, RegionScannerHolder> e : scanners.entrySet()) {
1050 try {
1051 e.getValue().s.close();
1052 } catch (IOException ioe) {
1053 LOG.warn("Closing scanner " + e.getKey(), ioe);
1054 }
1055 }
1056 }
1057
1058
1059 static interface LogDelegate {
1060 void logBatchWarning(String firstRegionName, int sum, int rowSizeWarnThreshold);
1061 }
1062
1063 private static LogDelegate DEFAULT_LOG_DELEGATE = new LogDelegate() {
1064 @Override
1065 public void logBatchWarning(String firstRegionName, int sum, int rowSizeWarnThreshold) {
1066 if (LOG.isWarnEnabled()) {
1067 LOG.warn("Large batch operation detected (greater than " + rowSizeWarnThreshold
1068 + ") (HBASE-18023)." + " Requested Number of Rows: " + sum + " Client: "
1069 + RpcServer.getRequestUserName() + "/" + RpcServer.getRemoteAddress()
1070 + " first region in multi=" + firstRegionName);
1071 }
1072 }
1073 };
1074
1075 private final LogDelegate ld;
1076
1077 public RSRpcServices(HRegionServer rs) throws IOException {
1078 this(rs, DEFAULT_LOG_DELEGATE);
1079 }
1080
1081
1082 RSRpcServices(HRegionServer rs, LogDelegate ld) throws IOException {
1083 this.ld = ld;
1084 regionServer = rs;
1085 rowSizeWarnThreshold = rs.conf.getInt(BATCH_ROWS_THRESHOLD_NAME, BATCH_ROWS_THRESHOLD_DEFAULT);
1086 RpcSchedulerFactory rpcSchedulerFactory;
1087 try {
1088 Class<?> rpcSchedulerFactoryClass = rs.conf.getClass(
1089 REGION_SERVER_RPC_SCHEDULER_FACTORY_CLASS,
1090 SimpleRpcSchedulerFactory.class);
1091 rpcSchedulerFactory = (RpcSchedulerFactory)
1092 rpcSchedulerFactoryClass.getDeclaredConstructor().newInstance();
1093 } catch (Exception e) {
1094 throw new IllegalArgumentException(e);
1095 }
1096
1097 InetSocketAddress initialIsa;
1098 InetSocketAddress bindAddress;
1099 if(this instanceof MasterRpcServices) {
1100 String hostname = getHostname(rs.conf, true);
1101 int port = rs.conf.getInt(HConstants.MASTER_PORT, HConstants.DEFAULT_MASTER_PORT);
1102
1103 initialIsa = new InetSocketAddress(hostname, port);
1104 bindAddress = new InetSocketAddress(rs.conf.get("hbase.master.ipc.address", hostname), port);
1105 } else {
1106 String hostname = getHostname(rs.conf, false);
1107 int port = rs.conf.getInt(HConstants.REGIONSERVER_PORT,
1108 HConstants.DEFAULT_REGIONSERVER_PORT);
1109
1110 initialIsa = new InetSocketAddress(hostname, port);
1111 bindAddress = new InetSocketAddress(
1112 rs.conf.get("hbase.regionserver.ipc.address", hostname), port);
1113 }
1114 if (initialIsa.getAddress() == null) {
1115 throw new IllegalArgumentException("Failed resolve of " + initialIsa);
1116 }
1117 priority = createPriority();
1118 String name = rs.getProcessName() + "/" + initialIsa.toString();
1119
1120 ConnectionUtils.setServerSideHConnectionRetriesConfig(rs.conf, name, LOG);
1121 try {
1122 rpcServer = new RpcServer(rs, name, getServices(),
1123 bindAddress,
1124 rs.conf,
1125 rpcSchedulerFactory.create(rs.conf, this, rs));
1126 rpcServer.setRsRpcServices(this);
1127 } catch (BindException be) {
1128 String configName = (this instanceof MasterRpcServices) ? HConstants.MASTER_PORT :
1129 HConstants.REGIONSERVER_PORT;
1130 throw new IOException(be.getMessage() + ". To switch ports use the '" + configName +
1131 "' configuration property.", be.getCause() != null ? be.getCause() : be);
1132 }
1133
1134 scannerLeaseTimeoutPeriod = rs.conf.getInt(
1135 HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD,
1136 HConstants.DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD);
1137 maxScannerResultSize = rs.conf.getLong(
1138 HConstants.HBASE_SERVER_SCANNER_MAX_RESULT_SIZE_KEY,
1139 HConstants.DEFAULT_HBASE_SERVER_SCANNER_MAX_RESULT_SIZE);
1140 rpcTimeout = rs.conf.getInt(
1141 HConstants.HBASE_RPC_TIMEOUT_KEY,
1142 HConstants.DEFAULT_HBASE_RPC_TIMEOUT);
1143 minimumScanTimeLimitDelta = rs.conf.getLong(
1144 REGION_SERVER_RPC_MINIMUM_SCAN_TIME_LIMIT_DELTA,
1145 DEFAULT_REGION_SERVER_RPC_MINIMUM_SCAN_TIME_LIMIT_DELTA);
1146
1147 InetSocketAddress address = rpcServer.getListenerAddress();
1148 if (address == null) {
1149 throw new IOException("Listener channel is closed");
1150 }
1151
1152 isa = new InetSocketAddress(initialIsa.getHostName(), address.getPort());
1153 rpcServer.setErrorHandler(this);
1154 rs.setName(name);
1155
1156 closedScanners = CacheBuilder.newBuilder()
1157 .expireAfterAccess(scannerLeaseTimeoutPeriod, TimeUnit.MILLISECONDS).build();
1158 }
1159
1160 @Override
1161 public void onConfigurationChange(Configuration newConf) {
1162 if (rpcServer instanceof ConfigurationObserver) {
1163 ((ConfigurationObserver)rpcServer).onConfigurationChange(newConf);
1164 }
1165 }
1166
1167 protected PriorityFunction createPriority() {
1168 return new AnnotationReadingPriorityFunction(this);
1169 }
1170
1171 public static String getHostname(Configuration conf, boolean isMaster)
1172 throws UnknownHostException {
1173 String hostname = conf.get(isMaster? HRegionServer.MASTER_HOSTNAME_KEY :
1174 HRegionServer.RS_HOSTNAME_KEY);
1175 if (hostname == null || hostname.isEmpty()) {
1176 String masterOrRS = isMaster ? "master" : "regionserver";
1177 return Strings.domainNamePointerToHostName(DNS.getDefaultHost(
1178 conf.get("hbase." + masterOrRS + ".dns.interface", "default"),
1179 conf.get("hbase." + masterOrRS + ".dns.nameserver", "default")));
1180 } else {
1181 LOG.info("hostname is configured to be " + hostname);
1182 return hostname;
1183 }
1184 }
1185
1186 public
1187 RegionScanner getScanner(long scannerId) {
1188 String scannerIdString = Long.toString(scannerId);
1189 RegionScannerHolder scannerHolder = scanners.get(scannerIdString);
1190 if (scannerHolder != null) {
1191 return scannerHolder.s;
1192 }
1193 return null;
1194 }
1195
1196 public String getScanDetailsWithId(long scannerId) {
1197 RegionScanner scanner = getScanner(scannerId);
1198 if (scanner == null) {
1199 return null;
1200 }
1201 StringBuilder builder = new StringBuilder();
1202 builder.append("table: ").append(scanner.getRegionInfo().getTable().getNameAsString());
1203 builder.append(" region: ").append(scanner.getRegionInfo().getRegionNameAsString());
1204 return builder.toString();
1205 }
1206
1207
1208
1209
1210
1211 long getScannerVirtualTime(long scannerId) {
1212 String scannerIdString = Long.toString(scannerId);
1213 RegionScannerHolder scannerHolder = scanners.get(scannerIdString);
1214 if (scannerHolder != null) {
1215 return scannerHolder.getNextCallSeq();
1216 }
1217 return 0L;
1218 }
1219
1220
1221
1222
1223
1224 Object addSize(RpcCallContext context, Result r, Object lastBlock) {
1225 if (context != null && r != null && !r.isEmpty()) {
1226 for (Cell c : r.rawCells()) {
1227 context.incrementResponseCellSize(CellUtil.estimatedHeapSizeOf(c));
1228
1229
1230
1231
1232
1233
1234 byte[] valueArray = c.getValueArray();
1235 if (valueArray != lastBlock) {
1236 context.incrementResponseBlockSize(valueArray.length);
1237 lastBlock = valueArray;
1238 }
1239 }
1240 }
1241 return lastBlock;
1242 }
1243
1244 private RegionScannerHolder addScanner(String scannerName, RegionScanner s, Region r,
1245 boolean needCursor) throws LeaseStillHeldException {
1246 regionServer.leases.createLease(scannerName, this.scannerLeaseTimeoutPeriod,
1247 new ScannerListener(scannerName));
1248 RegionScannerHolder rsh = new RegionScannerHolder(scannerName, s, r, needCursor);
1249 RegionScannerHolder existing = scanners.putIfAbsent(scannerName, rsh);
1250 assert existing == null : "scannerId must be unique within regionserver's whole lifecycle!";
1251 return rsh;
1252 }
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262 @VisibleForTesting
1263 public Region getRegion(
1264 final RegionSpecifier regionSpecifier) throws IOException {
1265 ByteString value = regionSpecifier.getValue();
1266 RegionSpecifierType type = regionSpecifier.getType();
1267 switch (type) {
1268 case REGION_NAME:
1269 byte[] regionName = value.toByteArray();
1270 String encodedRegionName = HRegionInfo.encodeRegionName(regionName);
1271 return regionServer.getRegionByEncodedName(regionName, encodedRegionName);
1272 case ENCODED_REGION_NAME:
1273 return regionServer.getRegionByEncodedName(value.toStringUtf8());
1274 default:
1275 throw new DoNotRetryIOException(
1276 "Unsupported region specifier type: " + type);
1277 }
1278 }
1279
1280 @VisibleForTesting
1281 public PriorityFunction getPriority() {
1282 return priority;
1283 }
1284
1285 @VisibleForTesting
1286 public Configuration getConfiguration() {
1287 return regionServer.getConfiguration();
1288 }
1289
1290 private RegionServerQuotaManager getQuotaManager() {
1291 return regionServer.getRegionServerQuotaManager();
1292 }
1293
1294 void start() {
1295 this.scannerIdGenerator = new ScannerIdGenerator(this.regionServer.serverName);
1296 rpcServer.start();
1297 }
1298
1299 void stop() {
1300 closeAllScanners();
1301 rpcServer.stop();
1302 }
1303
1304
1305
1306
1307
1308
1309 protected void checkOpen() throws IOException {
1310 if (regionServer.isAborted()) {
1311 throw new RegionServerAbortedException("Server " + regionServer.serverName + " aborting");
1312 }
1313 if (regionServer.isStopped()) {
1314 throw new RegionServerStoppedException("Server " + regionServer.serverName + " stopping");
1315 }
1316 if (!regionServer.fsOk) {
1317 throw new RegionServerStoppedException("File system not available");
1318 }
1319 if (!regionServer.isOnline()) {
1320 throw new ServerNotRunningYetException("Server " + regionServer.serverName
1321 + " is not running yet");
1322 }
1323 }
1324
1325
1326
1327
1328 protected List<BlockingServiceAndInterface> getServices() {
1329 List<BlockingServiceAndInterface> bssi = new ArrayList<BlockingServiceAndInterface>(2);
1330 bssi.add(new BlockingServiceAndInterface(
1331 ClientService.newReflectiveBlockingService(this),
1332 ClientService.BlockingInterface.class));
1333 bssi.add(new BlockingServiceAndInterface(
1334 AdminService.newReflectiveBlockingService(this),
1335 AdminService.BlockingInterface.class));
1336 return bssi;
1337 }
1338
1339 public InetSocketAddress getSocketAddress() {
1340 return isa;
1341 }
1342
1343 @Override
1344 public int getPriority(RequestHeader header, Message param, User user) {
1345 return priority.getPriority(header, param, user);
1346 }
1347
1348 @Override
1349 public long getDeadline(RequestHeader header, Message param) {
1350 return priority.getDeadline(header, param);
1351 }
1352
1353
1354
1355
1356
1357
1358
1359
1360 @Override
1361 public boolean checkOOME(final Throwable e) {
1362 return exitIfOOME(e);
1363 }
1364
1365 public static boolean exitIfOOME(final Throwable e ){
1366 boolean stop = false;
1367 try {
1368 if (e instanceof OutOfMemoryError
1369 || (e.getCause() != null && e.getCause() instanceof OutOfMemoryError)
1370 || (e.getMessage() != null && e.getMessage().contains(
1371 "java.lang.OutOfMemoryError"))) {
1372 stop = true;
1373 LOG.fatal("Run out of memory; " + RSRpcServices.class.getSimpleName()
1374 + " will abort itself immediately", e);
1375 }
1376 } finally {
1377 if (stop) {
1378 Runtime.getRuntime().halt(1);
1379 }
1380 }
1381 return stop;
1382 }
1383
1384
1385
1386
1387
1388
1389
1390
1391 @Override
1392 @QosPriority(priority=HConstants.ADMIN_QOS)
1393 public CloseRegionResponse closeRegion(final RpcController controller,
1394 final CloseRegionRequest request) throws ServiceException {
1395 final ServerName sn = (request.hasDestinationServer() ?
1396 ProtobufUtil.toServerName(request.getDestinationServer()) : null);
1397
1398 try {
1399 checkOpen();
1400 if (request.hasServerStartCode()) {
1401
1402 long serverStartCode = request.getServerStartCode();
1403 if (regionServer.serverName.getStartcode() != serverStartCode) {
1404 throw new ServiceException(new DoNotRetryIOException("This RPC was intended for a " +
1405 "different server with startCode: " + serverStartCode + ", this server is: "
1406 + regionServer.serverName));
1407 }
1408 }
1409 final String encodedRegionName = ProtobufUtil.getRegionEncodedName(request.getRegion());
1410
1411 requestCount.increment();
1412 LOG.info("Close " + encodedRegionName + ", moving to " + sn);
1413 CloseRegionCoordination.CloseRegionDetails crd = regionServer.getCoordinatedStateManager()
1414 .getCloseRegionCoordination().parseFromProtoRequest(request);
1415
1416 boolean closed = regionServer.closeRegion(encodedRegionName, false, crd, sn);
1417 CloseRegionResponse.Builder builder = CloseRegionResponse.newBuilder().setClosed(closed);
1418 return builder.build();
1419 } catch (IOException ie) {
1420 throw new ServiceException(ie);
1421 }
1422 }
1423
1424
1425
1426
1427
1428
1429
1430
1431 @Override
1432 @QosPriority(priority=HConstants.ADMIN_QOS)
1433 public CompactRegionResponse compactRegion(final RpcController controller,
1434 final CompactRegionRequest request) throws ServiceException {
1435 try {
1436 checkOpen();
1437 requestCount.increment();
1438 Region region = getRegion(request.getRegion());
1439 region.startRegionOperation(Operation.COMPACT_REGION);
1440 LOG.info("Compacting " + region.getRegionInfo().getRegionNameAsString());
1441 boolean major = false;
1442 byte [] family = null;
1443 Store store = null;
1444 if (request.hasFamily()) {
1445 family = request.getFamily().toByteArray();
1446 store = region.getStore(family);
1447 if (store == null) {
1448 throw new ServiceException(new IOException("column family " + Bytes.toString(family)
1449 + " does not exist in region " + region.getRegionInfo().getRegionNameAsString()));
1450 }
1451 }
1452 if (request.hasMajor()) {
1453 major = request.getMajor();
1454 }
1455 if (major) {
1456 if (family != null) {
1457 store.triggerMajorCompaction();
1458 } else {
1459 region.triggerMajorCompaction();
1460 }
1461 }
1462
1463 String familyLogMsg = (family != null)?" for column family: " + Bytes.toString(family):"";
1464 if (LOG.isTraceEnabled()) {
1465 LOG.trace("User-triggered compaction requested for region "
1466 + region.getRegionInfo().getRegionNameAsString() + familyLogMsg);
1467 }
1468 String log = "User-triggered " + (major ? "major " : "") + "compaction" + familyLogMsg;
1469 if(family != null) {
1470 regionServer.compactSplitThread.requestCompaction(region, store, log,
1471 Store.PRIORITY_USER, null, RpcServer.getRequestUser());
1472 } else {
1473 regionServer.compactSplitThread.requestCompaction(region, log,
1474 Store.PRIORITY_USER, null, RpcServer.getRequestUser());
1475 }
1476 return CompactRegionResponse.newBuilder().build();
1477 } catch (IOException ie) {
1478 throw new ServiceException(ie);
1479 }
1480 }
1481
1482
1483
1484
1485
1486
1487
1488
1489 @Override
1490 @QosPriority(priority=HConstants.ADMIN_QOS)
1491 public FlushRegionResponse flushRegion(final RpcController controller,
1492 final FlushRegionRequest request) throws ServiceException {
1493 try {
1494 checkOpen();
1495 requestCount.increment();
1496 Region region = getRegion(request.getRegion());
1497 LOG.info("Flushing " + region.getRegionInfo().getRegionNameAsString());
1498 boolean shouldFlush = true;
1499 if (request.hasIfOlderThanTs()) {
1500 shouldFlush = region.getEarliestFlushTimeForAllStores() < request.getIfOlderThanTs();
1501 }
1502 FlushRegionResponse.Builder builder = FlushRegionResponse.newBuilder();
1503 if (shouldFlush) {
1504 boolean writeFlushWalMarker = request.hasWriteFlushWalMarker() ?
1505 request.getWriteFlushWalMarker() : false;
1506
1507 HRegion.FlushResultImpl flushResult = (HRegion.FlushResultImpl)
1508 ((HRegion)region).flushcache(true, writeFlushWalMarker);
1509 boolean compactionNeeded = flushResult.isCompactionNeeded();
1510 if (compactionNeeded) {
1511 regionServer.compactSplitThread.requestSystemCompaction(region,
1512 "Compaction through user triggered flush");
1513 }
1514 builder.setFlushed(flushResult.isFlushSucceeded());
1515 builder.setWroteFlushWalMarker(flushResult.wroteFlushWalMarker);
1516 }
1517 builder.setLastFlushTime(region.getEarliestFlushTimeForAllStores());
1518 return builder.build();
1519 } catch (DroppedSnapshotException ex) {
1520
1521
1522
1523
1524 regionServer.abort("Replay of WAL required. Forcing server shutdown", ex);
1525 throw new ServiceException(ex);
1526 } catch (IOException ie) {
1527 throw new ServiceException(ie);
1528 }
1529 }
1530
1531 @Override
1532 @QosPriority(priority=HConstants.ADMIN_QOS)
1533 public GetOnlineRegionResponse getOnlineRegion(final RpcController controller,
1534 final GetOnlineRegionRequest request) throws ServiceException {
1535 try {
1536 checkOpen();
1537 requestCount.increment();
1538 Map<String, Region> onlineRegions = regionServer.onlineRegions;
1539 List<HRegionInfo> list = new ArrayList<HRegionInfo>(onlineRegions.size());
1540 for (Region region: onlineRegions.values()) {
1541 list.add(region.getRegionInfo());
1542 }
1543 Collections.sort(list);
1544 return ResponseConverter.buildGetOnlineRegionResponse(list);
1545 } catch (IOException ie) {
1546 throw new ServiceException(ie);
1547 }
1548 }
1549
1550 @Override
1551 @QosPriority(priority=HConstants.ADMIN_QOS)
1552 public GetRegionInfoResponse getRegionInfo(final RpcController controller,
1553 final GetRegionInfoRequest request) throws ServiceException {
1554 try {
1555 checkOpen();
1556 requestCount.increment();
1557 Region region = getRegion(request.getRegion());
1558 HRegionInfo info = region.getRegionInfo();
1559 GetRegionInfoResponse.Builder builder = GetRegionInfoResponse.newBuilder();
1560 builder.setRegionInfo(HRegionInfo.convert(info));
1561 if (request.hasCompactionState() && request.getCompactionState()) {
1562 builder.setCompactionState(region.getCompactionState());
1563 }
1564 builder.setIsRecovering(region.isRecovering());
1565 return builder.build();
1566 } catch (IOException ie) {
1567 throw new ServiceException(ie);
1568 }
1569 }
1570
1571
1572
1573
1574
1575
1576
1577
1578 @Override
1579 @QosPriority(priority=HConstants.ADMIN_QOS)
1580 public GetServerInfoResponse getServerInfo(final RpcController controller,
1581 final GetServerInfoRequest request) throws ServiceException {
1582 try {
1583 checkOpen();
1584 } catch (IOException ie) {
1585 throw new ServiceException(ie);
1586 }
1587 requestCount.increment();
1588 int infoPort = regionServer.infoServer != null ? regionServer.infoServer.getPort() : -1;
1589 return ResponseConverter.buildGetServerInfoResponse(regionServer.serverName, infoPort);
1590 }
1591
1592 @Override
1593 @QosPriority(priority=HConstants.ADMIN_QOS)
1594 public GetStoreFileResponse getStoreFile(final RpcController controller,
1595 final GetStoreFileRequest request) throws ServiceException {
1596 try {
1597 checkOpen();
1598 Region region = getRegion(request.getRegion());
1599 requestCount.increment();
1600 Set<byte[]> columnFamilies;
1601 if (request.getFamilyCount() == 0) {
1602 columnFamilies = region.getTableDesc().getFamiliesKeys();
1603 } else {
1604 columnFamilies = new TreeSet<byte[]>(Bytes.BYTES_RAWCOMPARATOR);
1605 for (ByteString cf: request.getFamilyList()) {
1606 columnFamilies.add(cf.toByteArray());
1607 }
1608 }
1609 int nCF = columnFamilies.size();
1610 List<String> fileList = region.getStoreFileList(
1611 columnFamilies.toArray(new byte[nCF][]));
1612 GetStoreFileResponse.Builder builder = GetStoreFileResponse.newBuilder();
1613 builder.addAllStoreFile(fileList);
1614 return builder.build();
1615 } catch (IOException ie) {
1616 throw new ServiceException(ie);
1617 }
1618 }
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628 @Override
1629 @QosPriority(priority = HConstants.ADMIN_QOS)
1630 public MergeRegionsResponse mergeRegions(final RpcController controller,
1631 final MergeRegionsRequest request) throws ServiceException {
1632 try {
1633 checkOpen();
1634 requestCount.increment();
1635 Region regionA = getRegion(request.getRegionA());
1636 Region regionB = getRegion(request.getRegionB());
1637 boolean forcible = request.getForcible();
1638 long masterSystemTime = request.hasMasterSystemTime() ? request.getMasterSystemTime() : -1;
1639 regionA.startRegionOperation(Operation.MERGE_REGION);
1640 regionB.startRegionOperation(Operation.MERGE_REGION);
1641 if (regionA.getRegionInfo().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID ||
1642 regionB.getRegionInfo().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) {
1643 throw new ServiceException(new MergeRegionException("Can't merge non-default replicas"));
1644 }
1645 LOG.info("Receiving merging request for " + regionA + ", " + regionB
1646 + ",forcible=" + forcible);
1647 regionA.flush(true);
1648 regionB.flush(true);
1649 regionServer.compactSplitThread.requestRegionsMerge(regionA, regionB, forcible,
1650 masterSystemTime, RpcServer.getRequestUser());
1651 return MergeRegionsResponse.newBuilder().build();
1652 } catch (DroppedSnapshotException ex) {
1653 regionServer.abort("Replay of WAL required. Forcing server shutdown", ex);
1654 throw new ServiceException(ex);
1655 } catch (IOException ie) {
1656 throw new ServiceException(ie);
1657 }
1658 }
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683 @Override
1684 @QosPriority(priority=HConstants.ADMIN_QOS)
1685 @edu.umd.cs.findbugs.annotations.SuppressWarnings(
1686 value="JLM_JSR166_UTILCONCURRENT_MONITORENTER",
1687 justification="We double up use of an atomic both as monitor and condition variable")
1688 public OpenRegionResponse openRegion(final RpcController controller,
1689 final OpenRegionRequest request) throws ServiceException {
1690 requestCount.increment();
1691 if (request.hasServerStartCode()) {
1692
1693 long serverStartCode = request.getServerStartCode();
1694 if (regionServer.serverName.getStartcode() != serverStartCode) {
1695 throw new ServiceException(new DoNotRetryIOException("This RPC was intended for a " +
1696 "different server with startCode: " + serverStartCode + ", this server is: "
1697 + regionServer.serverName));
1698 }
1699 }
1700
1701 OpenRegionResponse.Builder builder = OpenRegionResponse.newBuilder();
1702 final int regionCount = request.getOpenInfoCount();
1703 final Map<TableName, HTableDescriptor> htds =
1704 new HashMap<TableName, HTableDescriptor>(regionCount);
1705 final boolean isBulkAssign = regionCount > 1;
1706 try {
1707 checkOpen();
1708 } catch (IOException ie) {
1709 TableName tableName = null;
1710 if (regionCount == 1) {
1711 RegionInfo ri = request.getOpenInfo(0).getRegion();
1712 if (ri != null) {
1713 tableName = ProtobufUtil.toTableName(ri.getTableName());
1714 }
1715 }
1716 if (!TableName.META_TABLE_NAME.equals(tableName)) {
1717 throw new ServiceException(ie);
1718 }
1719
1720 int timeout = regionServer.conf.getInt(HConstants.HBASE_RPC_TIMEOUT_KEY,
1721 HConstants.DEFAULT_HBASE_RPC_TIMEOUT) >> 2;
1722 long endTime = System.currentTimeMillis() + timeout;
1723 synchronized (regionServer.online) {
1724 try {
1725 while (System.currentTimeMillis() <= endTime
1726 && !regionServer.isStopped() && !regionServer.isOnline()) {
1727 regionServer.online.wait(regionServer.msgInterval);
1728 }
1729 checkOpen();
1730 } catch (InterruptedException t) {
1731 Thread.currentThread().interrupt();
1732 throw new ServiceException(t);
1733 } catch (IOException e) {
1734 throw new ServiceException(e);
1735 }
1736 }
1737 }
1738
1739 long masterSystemTime = request.hasMasterSystemTime() ? request.getMasterSystemTime() : -1;
1740
1741 for (RegionOpenInfo regionOpenInfo : request.getOpenInfoList()) {
1742 final HRegionInfo region = HRegionInfo.convert(regionOpenInfo.getRegion());
1743 OpenRegionCoordination coordination = regionServer.getCoordinatedStateManager().
1744 getOpenRegionCoordination();
1745 OpenRegionCoordination.OpenRegionDetails ord =
1746 coordination.parseFromProtoRequest(regionOpenInfo);
1747
1748 HTableDescriptor htd;
1749 try {
1750 final Region onlineRegion = regionServer.getFromOnlineRegions(region.getEncodedName());
1751 if (onlineRegion != null) {
1752
1753 if (onlineRegion.getCoprocessorHost() != null) {
1754 onlineRegion.getCoprocessorHost().preOpen();
1755 }
1756
1757
1758 Pair<HRegionInfo, ServerName> p = MetaTableAccessor.getRegion(
1759 regionServer.getConnection(), region.getRegionName());
1760 if (regionServer.serverName.equals(p.getSecond())) {
1761 Boolean closing = regionServer.regionsInTransitionInRS.get(region.getEncodedNameAsBytes());
1762
1763
1764
1765
1766
1767 if (!Boolean.FALSE.equals(closing)
1768 && regionServer.getFromOnlineRegions(region.getEncodedName()) != null) {
1769 LOG.warn("Attempted open of " + region.getEncodedName()
1770 + " but already online on this server");
1771 builder.addOpeningState(RegionOpeningState.ALREADY_OPENED);
1772 continue;
1773 }
1774 } else {
1775 LOG.warn("The region " + region.getEncodedName() + " is online on this server"
1776 + " but hbase:meta does not have this server - continue opening.");
1777 regionServer.removeFromOnlineRegions(onlineRegion, null);
1778 }
1779 }
1780 LOG.info("Open " + region.getRegionNameAsString());
1781 htd = htds.get(region.getTable());
1782 if (htd == null) {
1783 htd = regionServer.tableDescriptors.get(region.getTable());
1784 htds.put(region.getTable(), htd);
1785 }
1786
1787 final Boolean previous = regionServer.regionsInTransitionInRS.putIfAbsent(
1788 region.getEncodedNameAsBytes(), Boolean.TRUE);
1789
1790 if (Boolean.FALSE.equals(previous)) {
1791
1792
1793 coordination.tryTransitionFromOfflineToFailedOpen(regionServer, region, ord);
1794
1795 throw new RegionAlreadyInTransitionException("Received OPEN for the region:"
1796 + region.getRegionNameAsString() + " , which we are already trying to CLOSE ");
1797 }
1798
1799 if (Boolean.TRUE.equals(previous)) {
1800
1801 LOG.info("Receiving OPEN for the region:" +
1802 region.getRegionNameAsString() + " , which we are already trying to OPEN"
1803 + " - ignoring this new request for this region.");
1804 }
1805
1806
1807
1808 regionServer.removeFromMovedRegions(region.getEncodedName());
1809
1810 if (previous == null) {
1811
1812 if (ZKSplitLog.isRegionMarkedRecoveringInZK(regionServer.getZooKeeper(),
1813 region.getEncodedName())) {
1814
1815
1816 if (!regionOpenInfo.hasOpenForDistributedLogReplay()
1817 || regionOpenInfo.getOpenForDistributedLogReplay()) {
1818 regionServer.recoveringRegions.put(region.getEncodedName(), null);
1819 } else {
1820
1821
1822 List<String> tmpRegions = new ArrayList<String>();
1823 tmpRegions.add(region.getEncodedName());
1824 ZKSplitLog.deleteRecoveringRegionZNodes(regionServer.getZooKeeper(),
1825 tmpRegions);
1826 }
1827 }
1828 if (htd == null) {
1829 throw new IOException("Missing table descriptor for " + region.getEncodedName());
1830 }
1831
1832
1833 if (region.isMetaRegion()) {
1834 regionServer.service.submit(new OpenMetaHandler(
1835 regionServer, regionServer, region, htd, masterSystemTime, coordination, ord));
1836 } else {
1837 regionServer.updateRegionFavoredNodesMapping(region.getEncodedName(),
1838 regionOpenInfo.getFavoredNodesList());
1839 if (htd.getPriority() >= HConstants.ADMIN_QOS || region.getTable().isSystemTable()) {
1840 regionServer.service.submit(new OpenPriorityRegionHandler(
1841 regionServer, regionServer, region, htd, masterSystemTime, coordination, ord));
1842 } else {
1843 regionServer.service.submit(new OpenRegionHandler(
1844 regionServer, regionServer, region, htd, masterSystemTime, coordination, ord));
1845 }
1846 }
1847 }
1848
1849 builder.addOpeningState(RegionOpeningState.OPENED);
1850
1851 } catch (KeeperException zooKeeperEx) {
1852 LOG.error("Can't retrieve recovering state from zookeeper", zooKeeperEx);
1853 throw new ServiceException(zooKeeperEx);
1854 } catch (IOException ie) {
1855 LOG.warn("Failed opening region " + region.getRegionNameAsString(), ie);
1856 if (isBulkAssign) {
1857 builder.addOpeningState(RegionOpeningState.FAILED_OPENING);
1858 } else {
1859 throw new ServiceException(ie);
1860 }
1861 }
1862 }
1863 return builder.build();
1864 }
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 @Override
1878 public WarmupRegionResponse warmupRegion(final RpcController controller,
1879 final WarmupRegionRequest request) throws ServiceException {
1880
1881 RegionInfo regionInfo = request.getRegionInfo();
1882 final HRegionInfo region = HRegionInfo.convert(regionInfo);
1883 HTableDescriptor htd;
1884 WarmupRegionResponse response = WarmupRegionResponse.getDefaultInstance();
1885
1886 try {
1887 checkOpen();
1888 String encodedName = region.getEncodedName();
1889 byte[] encodedNameBytes = region.getEncodedNameAsBytes();
1890 final Region onlineRegion = regionServer.getFromOnlineRegions(encodedName);
1891
1892 if (onlineRegion != null) {
1893 LOG.info("Region already online. Skipping warming up " + region);
1894 return response;
1895 }
1896
1897 if (LOG.isDebugEnabled()) {
1898 LOG.debug("Warming up Region " + region.getRegionNameAsString());
1899 }
1900
1901 htd = regionServer.tableDescriptors.get(region.getTable());
1902
1903 if (regionServer.getRegionsInTransitionInRS().containsKey(encodedNameBytes)) {
1904 LOG.info("Region is in transition. Skipping warmup " + region);
1905 return response;
1906 }
1907
1908 HRegion.warmupHRegion(region, htd, regionServer.getWAL(region),
1909 regionServer.getConfiguration(), regionServer, null);
1910
1911 } catch (IOException ie) {
1912 LOG.error("Failed warming up region " + region.getRegionNameAsString(), ie);
1913 throw new ServiceException(ie);
1914 }
1915
1916 return response;
1917 }
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927 @Override
1928 @QosPriority(priority = HConstants.REPLAY_QOS)
1929 public ReplicateWALEntryResponse replay(final RpcController controller,
1930 final ReplicateWALEntryRequest request) throws ServiceException {
1931 long before = EnvironmentEdgeManager.currentTime();
1932 CellScanner cells = ((HBaseRpcController) controller).cellScanner();
1933 try {
1934 checkOpen();
1935 List<WALEntry> entries = request.getEntryList();
1936 if (entries == null || entries.isEmpty()) {
1937
1938 return ReplicateWALEntryResponse.newBuilder().build();
1939 }
1940 ByteString regionName = entries.get(0).getKey().getEncodedRegionName();
1941 Region region = regionServer.getRegionByEncodedName(regionName.toStringUtf8());
1942 RegionCoprocessorHost coprocessorHost =
1943 ServerRegionReplicaUtil.isDefaultReplica(region.getRegionInfo())
1944 ? region.getCoprocessorHost()
1945 : null;
1946 List<Pair<WALKey, WALEdit>> walEntries = new ArrayList<Pair<WALKey, WALEdit>>();
1947
1948
1949 boolean isPrimary = RegionReplicaUtil.isDefaultReplica(region.getRegionInfo());
1950 Durability durability = isPrimary ? Durability.USE_DEFAULT : Durability.SKIP_WAL;
1951
1952 for (WALEntry entry : entries) {
1953 if (!regionName.equals(entry.getKey().getEncodedRegionName())) {
1954 throw new NotServingRegionException("Replay request contains entries from multiple " +
1955 "regions. First region:" + regionName.toStringUtf8() + " , other region:"
1956 + entry.getKey().getEncodedRegionName());
1957 }
1958 if (regionServer.nonceManager != null && isPrimary) {
1959 long nonceGroup = entry.getKey().hasNonceGroup()
1960 ? entry.getKey().getNonceGroup() : HConstants.NO_NONCE;
1961 long nonce = entry.getKey().hasNonce() ? entry.getKey().getNonce() : HConstants.NO_NONCE;
1962 regionServer.nonceManager.reportOperationFromWal(
1963 nonceGroup,
1964 nonce,
1965 entry.getKey().getWriteTime());
1966 }
1967 Pair<WALKey, WALEdit> walEntry = (coprocessorHost == null) ? null :
1968 new Pair<WALKey, WALEdit>();
1969 List<WALSplitter.MutationReplay> edits = WALSplitter.getMutationsFromWALEntry(entry,
1970 cells, walEntry, durability);
1971 if (coprocessorHost != null) {
1972
1973
1974 if (coprocessorHost.preWALRestore(region.getRegionInfo(), walEntry.getFirst(),
1975 walEntry.getSecond())) {
1976
1977 continue;
1978 }
1979 walEntries.add(walEntry);
1980 }
1981 if(edits!=null && !edits.isEmpty()) {
1982
1983
1984 Collections.sort(edits);
1985 long replaySeqId = (entry.getKey().hasOrigSequenceNumber()) ?
1986 entry.getKey().getOrigSequenceNumber() : entry.getKey().getLogSequenceNumber();
1987 OperationStatus[] result = doReplayBatchOp(region, edits, replaySeqId);
1988
1989 for (int i = 0; result != null && i < result.length; i++) {
1990 if (result[i] != OperationStatus.SUCCESS) {
1991 throw new IOException(result[i].getExceptionMsg());
1992 }
1993 }
1994 }
1995 }
1996
1997
1998 WAL wal = getWAL(region);
1999 if (wal != null) {
2000 wal.sync();
2001 }
2002
2003 if (coprocessorHost != null) {
2004 for (Pair<WALKey, WALEdit> entry : walEntries) {
2005 coprocessorHost.postWALRestore(region.getRegionInfo(), entry.getFirst(),
2006 entry.getSecond());
2007 }
2008 }
2009 return ReplicateWALEntryResponse.newBuilder().build();
2010 } catch (IOException ie) {
2011 throw new ServiceException(ie);
2012 } finally {
2013 if (regionServer.metricsRegionServer != null) {
2014 regionServer.metricsRegionServer.updateReplay(
2015 EnvironmentEdgeManager.currentTime() - before);
2016 }
2017 }
2018 }
2019
2020 WAL getWAL(Region region) {
2021 return ((HRegion)region).getWAL();
2022 }
2023
2024
2025
2026
2027
2028
2029
2030
2031 @Override
2032 @QosPriority(priority=HConstants.REPLICATION_QOS)
2033 public ReplicateWALEntryResponse replicateWALEntry(final RpcController controller,
2034 final ReplicateWALEntryRequest request) throws ServiceException {
2035 try {
2036 checkOpen();
2037 if (regionServer.replicationSinkHandler != null) {
2038 requestCount.increment();
2039 List<WALEntry> entries = request.getEntryList();
2040 CellScanner cellScanner = ((HBaseRpcController)controller).cellScanner();
2041 regionServer.getRegionServerCoprocessorHost().preReplicateLogEntries(entries, cellScanner);
2042 regionServer.replicationSinkHandler.replicateLogEntries(entries, cellScanner,
2043 request.getReplicationClusterId(), request.getSourceBaseNamespaceDirPath(),
2044 request.getSourceHFileArchiveDirPath());
2045 regionServer.getRegionServerCoprocessorHost().postReplicateLogEntries(entries, cellScanner);
2046 return ReplicateWALEntryResponse.newBuilder().build();
2047 } else {
2048 throw new ServiceException("Replication services are not initialized yet");
2049 }
2050 } catch (IOException ie) {
2051 throw new ServiceException(ie);
2052 }
2053 }
2054
2055
2056
2057
2058
2059
2060
2061 @Override
2062 public RollWALWriterResponse rollWALWriter(final RpcController controller,
2063 final RollWALWriterRequest request) throws ServiceException {
2064 try {
2065 checkOpen();
2066 requestCount.increment();
2067 regionServer.getRegionServerCoprocessorHost().preRollWALWriterRequest();
2068 regionServer.walRoller.requestRollAll();
2069 regionServer.getRegionServerCoprocessorHost().postRollWALWriterRequest();
2070 RollWALWriterResponse.Builder builder = RollWALWriterResponse.newBuilder();
2071 return builder.build();
2072 } catch (IOException ie) {
2073 throw new ServiceException(ie);
2074 }
2075 }
2076
2077
2078
2079
2080
2081
2082
2083
2084 @Override
2085 @QosPriority(priority=HConstants.ADMIN_QOS)
2086 public SplitRegionResponse splitRegion(final RpcController controller,
2087 final SplitRegionRequest request) throws ServiceException {
2088 try {
2089 checkOpen();
2090 requestCount.increment();
2091 Region region = getRegion(request.getRegion());
2092 region.startRegionOperation(Operation.SPLIT_REGION);
2093 if (region.getRegionInfo().getReplicaId() != HRegionInfo.DEFAULT_REPLICA_ID) {
2094 throw new IOException("Can't split replicas directly. "
2095 + "Replicas are auto-split when their primary is split.");
2096 }
2097 LOG.info("Splitting " + region.getRegionInfo().getRegionNameAsString());
2098 region.flush(true);
2099 byte[] splitPoint = null;
2100 if (request.hasSplitPoint()) {
2101 splitPoint = request.getSplitPoint().toByteArray();
2102 }
2103 ((HRegion)region).forceSplit(splitPoint);
2104 regionServer.compactSplitThread.requestSplit(region, ((HRegion)region).checkSplit(),
2105 RpcServer.getRequestUser());
2106 return SplitRegionResponse.newBuilder().build();
2107 } catch (DroppedSnapshotException ex) {
2108 regionServer.abort("Replay of WAL required. Forcing server shutdown", ex);
2109 throw new ServiceException(ex);
2110 } catch (IOException ie) {
2111 throw new ServiceException(ie);
2112 }
2113 }
2114
2115
2116
2117
2118
2119
2120
2121
2122 @Override
2123 @QosPriority(priority=HConstants.ADMIN_QOS)
2124 public StopServerResponse stopServer(final RpcController controller,
2125 final StopServerRequest request) throws ServiceException {
2126 requestCount.increment();
2127 String reason = request.getReason();
2128 regionServer.stop(reason);
2129 return StopServerResponse.newBuilder().build();
2130 }
2131
2132 @Override
2133 public UpdateFavoredNodesResponse updateFavoredNodes(RpcController controller,
2134 UpdateFavoredNodesRequest request) throws ServiceException {
2135 List<UpdateFavoredNodesRequest.RegionUpdateInfo> openInfoList = request.getUpdateInfoList();
2136 UpdateFavoredNodesResponse.Builder respBuilder = UpdateFavoredNodesResponse.newBuilder();
2137 for (UpdateFavoredNodesRequest.RegionUpdateInfo regionUpdateInfo : openInfoList) {
2138 HRegionInfo hri = HRegionInfo.convert(regionUpdateInfo.getRegion());
2139 regionServer.updateRegionFavoredNodesMapping(hri.getEncodedName(),
2140 regionUpdateInfo.getFavoredNodesList());
2141 }
2142 respBuilder.setResponse(openInfoList.size());
2143 return respBuilder.build();
2144 }
2145
2146
2147
2148
2149
2150
2151 @Override
2152 public BulkLoadHFileResponse bulkLoadHFile(final RpcController controller,
2153 final BulkLoadHFileRequest request) throws ServiceException {
2154 long start = EnvironmentEdgeManager.currentTime();
2155 try {
2156 checkOpen();
2157 requestCount.increment();
2158 Region region = getRegion(request.getRegion());
2159 List<Pair<byte[], String>> familyPaths = new ArrayList<Pair<byte[], String>>();
2160 for (FamilyPath familyPath: request.getFamilyPathList()) {
2161 familyPaths.add(new Pair<byte[], String>(familyPath.getFamily().toByteArray(),
2162 familyPath.getPath()));
2163 }
2164 boolean bypass = false;
2165 if (region.getCoprocessorHost() != null) {
2166 bypass = region.getCoprocessorHost().preBulkLoadHFile(familyPaths);
2167 }
2168 boolean loaded = false;
2169 try {
2170 if (!bypass) {
2171 loaded = region.bulkLoadHFiles(familyPaths, request.getAssignSeqNum(), null);
2172 }
2173 } finally {
2174 if (region.getCoprocessorHost() != null) {
2175 loaded = region.getCoprocessorHost().postBulkLoadHFile(familyPaths, loaded);
2176 }
2177 }
2178 BulkLoadHFileResponse.Builder builder = BulkLoadHFileResponse.newBuilder();
2179 builder.setLoaded(loaded);
2180 return builder.build();
2181 } catch (IOException ie) {
2182 throw new ServiceException(ie);
2183 } finally {
2184 if (regionServer.metricsRegionServer != null) {
2185 regionServer.metricsRegionServer.updateBulkLoad(
2186 EnvironmentEdgeManager.currentTime() - start);
2187 }
2188 }
2189 }
2190
2191 @Override
2192 public CoprocessorServiceResponse execService(final RpcController controller,
2193 final CoprocessorServiceRequest request) throws ServiceException {
2194 try {
2195 checkOpen();
2196 requestCount.increment();
2197 Region region = getRegion(request.getRegion());
2198 Message result = execServiceOnRegion(region, request.getCall());
2199 CoprocessorServiceResponse.Builder builder =
2200 CoprocessorServiceResponse.newBuilder();
2201 builder.setRegion(RequestConverter.buildRegionSpecifier(
2202 RegionSpecifierType.REGION_NAME, region.getRegionInfo().getRegionName()));
2203 builder.setValue(
2204 builder.getValueBuilder().setName(result.getClass().getName())
2205 .setValue(result.toByteString()));
2206 return builder.build();
2207 } catch (IOException ie) {
2208 throw new ServiceException(ie);
2209 }
2210 }
2211
2212 private Message execServiceOnRegion(Region region,
2213 final ClientProtos.CoprocessorServiceCall serviceCall) throws IOException {
2214
2215 ServerRpcController execController = new ServerRpcController();
2216 return region.execService(execController, serviceCall);
2217 }
2218
2219
2220
2221
2222
2223
2224
2225
2226 @Override
2227 public GetResponse get(final RpcController controller,
2228 final GetRequest request) throws ServiceException {
2229 long before = EnvironmentEdgeManager.currentTime();
2230 OperationQuota quota = null;
2231 Region region = null;
2232 try {
2233 checkOpen();
2234 requestCount.increment();
2235 rpcGetRequestCount.increment();
2236 region = getRegion(request.getRegion());
2237
2238 GetResponse.Builder builder = GetResponse.newBuilder();
2239 ClientProtos.Get get = request.getGet();
2240 Boolean existence = null;
2241 Result r = null;
2242 quota = getQuotaManager().checkQuota(region, OperationQuota.OperationType.GET);
2243
2244 if (get.hasClosestRowBefore() && get.getClosestRowBefore()) {
2245 if (get.getColumnCount() != 1) {
2246 throw new DoNotRetryIOException(
2247 "get ClosestRowBefore supports one and only one family now, not "
2248 + get.getColumnCount() + " families");
2249 }
2250 byte[] row = get.getRow().toByteArray();
2251 byte[] family = get.getColumn(0).getFamily().toByteArray();
2252 r = region.getClosestRowBefore(row, family);
2253 } else {
2254 Get clientGet = ProtobufUtil.toGet(get);
2255 if (get.getExistenceOnly() && region.getCoprocessorHost() != null) {
2256 existence = region.getCoprocessorHost().preExists(clientGet);
2257 }
2258 if (existence == null) {
2259 r = region.get(clientGet);
2260 if (get.getExistenceOnly()) {
2261 boolean exists = r.getExists();
2262 if (region.getCoprocessorHost() != null) {
2263 exists = region.getCoprocessorHost().postExists(clientGet, exists);
2264 }
2265 existence = exists;
2266 }
2267 }
2268 }
2269 if (existence != null){
2270 ClientProtos.Result pbr =
2271 ProtobufUtil.toResult(existence, region.getRegionInfo().getReplicaId() != 0);
2272 builder.setResult(pbr);
2273 } else if (r != null) {
2274 ClientProtos.Result pbr;
2275 RpcCallContext call = RpcServer.getCurrentCall();
2276 if (isClientCellBlockSupport(call) && controller instanceof HBaseRpcController
2277 && VersionInfoUtil.hasMinimumVersion(call.getClientVersionInfo(), 1, 3)) {
2278 pbr = ProtobufUtil.toResultNoData(r);
2279 ((HBaseRpcController) controller)
2280 .setCellScanner(CellUtil.createCellScanner(r.rawCells()));
2281 addSize(call, r, null);
2282 } else {
2283 pbr = ProtobufUtil.toResult(r);
2284 }
2285 builder.setResult(pbr);
2286 }
2287 if (r != null) {
2288 quota.addGetResult(r);
2289 }
2290 return builder.build();
2291 } catch (IOException ie) {
2292 throw new ServiceException(ie);
2293 } finally {
2294 MetricsRegionServer mrs = regionServer.metricsRegionServer;
2295 if (mrs != null) {
2296 HTableDescriptor td = region != null ? region.getTableDesc() : null;
2297 if (td != null) {
2298 mrs.updateGet(td.getTableName(), EnvironmentEdgeManager.currentTime() - before);
2299 }
2300 }
2301 if (quota != null) {
2302 quota.close();
2303 }
2304 }
2305 }
2306
2307 private void checkBatchSizeAndLogLargeSize(MultiRequest request) {
2308 int sum = 0;
2309 String firstRegionName = null;
2310 for (RegionAction regionAction : request.getRegionActionList()) {
2311 if (sum == 0) {
2312 firstRegionName = Bytes.toStringBinary(regionAction.getRegion().getValue().toByteArray());
2313 }
2314 sum += regionAction.getActionCount();
2315 }
2316 if (sum > rowSizeWarnThreshold) {
2317 ld.logBatchWarning(firstRegionName, sum, rowSizeWarnThreshold);
2318 }
2319 }
2320
2321
2322
2323
2324
2325
2326
2327
2328 @Override
2329 public MultiResponse multi(final RpcController rpcc, final MultiRequest request)
2330 throws ServiceException {
2331 try {
2332 checkOpen();
2333 } catch (IOException ie) {
2334 throw new ServiceException(ie);
2335 }
2336
2337 checkBatchSizeAndLogLargeSize(request);
2338
2339
2340
2341 HBaseRpcController controller = (HBaseRpcController)rpcc;
2342 CellScanner cellScanner = controller != null ? controller.cellScanner(): null;
2343 if (controller != null) {
2344 controller.setCellScanner(null);
2345 }
2346
2347 long nonceGroup = request.hasNonceGroup() ? request.getNonceGroup() : HConstants.NO_NONCE;
2348
2349
2350 List<CellScannable> cellsToReturn = null;
2351 MultiResponse.Builder responseBuilder = MultiResponse.newBuilder();
2352 RegionActionResult.Builder regionActionResultBuilder = RegionActionResult.newBuilder();
2353 Boolean processed = null;
2354
2355 this.rpcMultiRequestCount.increment();
2356 this.requestCount.increment();
2357 Map<RegionSpecifier, ClientProtos.RegionLoadStats> regionStats = new HashMap<>(request
2358 .getRegionActionCount());
2359 for (RegionAction regionAction : request.getRegionActionList()) {
2360 OperationQuota quota;
2361 Region region;
2362 regionActionResultBuilder.clear();
2363 RegionSpecifier regionSpecifier = regionAction.getRegion();
2364 try {
2365 region = getRegion(regionSpecifier);
2366 quota = getQuotaManager().checkQuota(region, regionAction.getActionList());
2367 } catch (IOException e) {
2368 rpcServer.getMetrics().exception(e);
2369 regionActionResultBuilder.setException(ResponseConverter.buildException(e));
2370 responseBuilder.addRegionActionResult(regionActionResultBuilder.build());
2371
2372
2373
2374 skipCellsForMutations(regionAction.getActionList(), cellScanner);
2375 continue;
2376 }
2377
2378 if (regionAction.hasAtomic() && regionAction.getAtomic()) {
2379
2380
2381 try {
2382 if (request.hasCondition()) {
2383 Condition condition = request.getCondition();
2384 byte[] row = condition.getRow().toByteArray();
2385 byte[] family = condition.getFamily().toByteArray();
2386 byte[] qualifier = condition.getQualifier().toByteArray();
2387 CompareOp compareOp = CompareOp.valueOf(condition.getCompareType().name());
2388 ByteArrayComparable comparator =
2389 ProtobufUtil.toComparator(condition.getComparator());
2390 processed = checkAndRowMutate(region, regionAction.getActionList(),
2391 cellScanner, row, family, qualifier, compareOp,
2392 comparator, regionActionResultBuilder);
2393 } else {
2394 mutateRows(region, regionAction.getActionList(), cellScanner,
2395 regionActionResultBuilder);
2396 processed = Boolean.TRUE;
2397 }
2398 } catch (IOException e) {
2399 rpcServer.getMetrics().exception(e);
2400
2401 regionActionResultBuilder.setException(ResponseConverter.buildException(e));
2402 }
2403 } else {
2404
2405 cellsToReturn = doNonAtomicRegionMutation(region, quota, regionAction, cellScanner,
2406 regionActionResultBuilder, cellsToReturn, nonceGroup);
2407 }
2408 responseBuilder.addRegionActionResult(regionActionResultBuilder.build());
2409 quota.close();
2410 ClientProtos.RegionLoadStats regionLoadStats = ((HRegion)region).getLoadStatistics();
2411 if(regionLoadStats != null) {
2412 regionStats.put(regionSpecifier, regionLoadStats);
2413 }
2414 }
2415
2416 if (cellsToReturn != null && !cellsToReturn.isEmpty() && controller != null) {
2417 controller.setCellScanner(CellUtil.createCellScanner(cellsToReturn));
2418 }
2419
2420 if (processed != null) {
2421 responseBuilder.setProcessed(processed);
2422 }
2423
2424 MultiRegionLoadStats.Builder builder = MultiRegionLoadStats.newBuilder();
2425 for(Entry<RegionSpecifier, ClientProtos.RegionLoadStats> stat: regionStats.entrySet()){
2426 builder.addRegion(stat.getKey());
2427 builder.addStat(stat.getValue());
2428 }
2429 responseBuilder.setRegionStatistics(builder);
2430 return responseBuilder.build();
2431 }
2432
2433 private void skipCellsForMutations(List<Action> actions, CellScanner cellScanner) {
2434 if (cellScanner == null) {
2435 return;
2436 }
2437 for (Action action : actions) {
2438 skipCellsForMutation(action, cellScanner);
2439 }
2440 }
2441
2442 private void skipCellsForMutation(Action action, CellScanner cellScanner) {
2443 if (cellScanner == null) {
2444 return;
2445 }
2446 try {
2447 if (action.hasMutation()) {
2448 MutationProto m = action.getMutation();
2449 if (m.hasAssociatedCellCount()) {
2450 for (int i = 0; i < m.getAssociatedCellCount(); i++) {
2451 cellScanner.advance();
2452 }
2453 }
2454 }
2455 } catch (IOException e) {
2456
2457
2458
2459 LOG.error("Error while skipping Cells in CellScanner for invalid Region Mutations", e);
2460 }
2461 }
2462
2463
2464
2465
2466
2467
2468
2469
2470 @Override
2471 public MutateResponse mutate(final RpcController rpcc,
2472 final MutateRequest request) throws ServiceException {
2473
2474
2475 HBaseRpcController controller = (HBaseRpcController)rpcc;
2476 CellScanner cellScanner = controller != null ? controller.cellScanner() : null;
2477 OperationQuota quota = null;
2478 RpcCallContext context = RpcServer.getCurrentCall();
2479 MutationType type = null;
2480 Region region = null;
2481 long before = EnvironmentEdgeManager.currentTime();
2482
2483 if (controller != null) {
2484 controller.setCellScanner(null);
2485 }
2486 try {
2487 checkOpen();
2488 requestCount.increment();
2489 rpcMutateRequestCount.increment();
2490 region = getRegion(request.getRegion());
2491 MutateResponse.Builder builder = MutateResponse.newBuilder();
2492 MutationProto mutation = request.getMutation();
2493 if (!region.getRegionInfo().isMetaTable()) {
2494 regionServer.cacheFlusher.reclaimMemStoreMemory();
2495 }
2496 long nonceGroup = request.hasNonceGroup() ? request.getNonceGroup() : HConstants.NO_NONCE;
2497 Result r = null;
2498 Boolean processed = null;
2499 type = mutation.getMutateType();
2500 long mutationSize = 0;
2501 quota = getQuotaManager().checkQuota(region, OperationQuota.OperationType.MUTATE);
2502 switch (type) {
2503 case APPEND:
2504
2505 r = append(region, quota, mutation, cellScanner, nonceGroup);
2506 break;
2507 case INCREMENT:
2508
2509 r = increment(region, quota, mutation, cellScanner, nonceGroup);
2510 break;
2511 case PUT:
2512 Put put = ProtobufUtil.toPut(mutation, cellScanner);
2513 checkCellSizeLimit(region, put);
2514 quota.addMutation(put);
2515 if (request.hasCondition()) {
2516 Condition condition = request.getCondition();
2517 byte[] row = condition.getRow().toByteArray();
2518 byte[] family = condition.getFamily().toByteArray();
2519 byte[] qualifier = condition.getQualifier().toByteArray();
2520 CompareOp compareOp = CompareOp.valueOf(condition.getCompareType().name());
2521 ByteArrayComparable comparator =
2522 ProtobufUtil.toComparator(condition.getComparator());
2523 if (region.getCoprocessorHost() != null) {
2524 processed = region.getCoprocessorHost().preCheckAndPut(
2525 row, family, qualifier, compareOp, comparator, put);
2526 }
2527 if (processed == null) {
2528 boolean result = region.checkAndMutate(row, family,
2529 qualifier, compareOp, comparator, put, true);
2530 if (region.getCoprocessorHost() != null) {
2531 result = region.getCoprocessorHost().postCheckAndPut(row, family,
2532 qualifier, compareOp, comparator, put, result);
2533 }
2534 processed = result;
2535 }
2536 } else {
2537 region.put(put);
2538 processed = Boolean.TRUE;
2539 }
2540 break;
2541 case DELETE:
2542 Delete delete = ProtobufUtil.toDelete(mutation, cellScanner);
2543 checkCellSizeLimit(region, delete);
2544 quota.addMutation(delete);
2545 if (request.hasCondition()) {
2546 Condition condition = request.getCondition();
2547 byte[] row = condition.getRow().toByteArray();
2548 byte[] family = condition.getFamily().toByteArray();
2549 byte[] qualifier = condition.getQualifier().toByteArray();
2550 CompareOp compareOp = CompareOp.valueOf(condition.getCompareType().name());
2551 ByteArrayComparable comparator =
2552 ProtobufUtil.toComparator(condition.getComparator());
2553 if (region.getCoprocessorHost() != null) {
2554 processed = region.getCoprocessorHost().preCheckAndDelete(
2555 row, family, qualifier, compareOp, comparator, delete);
2556 }
2557 if (processed == null) {
2558 boolean result = region.checkAndMutate(row, family,
2559 qualifier, compareOp, comparator, delete, true);
2560 if (region.getCoprocessorHost() != null) {
2561 result = region.getCoprocessorHost().postCheckAndDelete(row, family,
2562 qualifier, compareOp, comparator, delete, result);
2563 }
2564 processed = result;
2565 }
2566 } else {
2567 region.delete(delete);
2568 processed = Boolean.TRUE;
2569 }
2570 break;
2571 default:
2572 throw new DoNotRetryIOException(
2573 "Unsupported mutate type: " + type.name());
2574 }
2575 if (processed != null) builder.setProcessed(processed.booleanValue());
2576 addResult(builder, r, controller);
2577 boolean clientCellBlockSupported = isClientCellBlockSupport(context);
2578 if (clientCellBlockSupported) {
2579 addSize(context, r, null);
2580 }
2581 return builder.build();
2582 } catch (IOException ie) {
2583 regionServer.checkFileSystem();
2584 throw new ServiceException(ie);
2585 } finally {
2586 if (quota != null) {
2587 quota.close();
2588 }
2589
2590 if (regionServer.metricsRegionServer != null && type != null) {
2591 long after = EnvironmentEdgeManager.currentTime();
2592 switch (type) {
2593 case DELETE:
2594 if (request.hasCondition()) {
2595 regionServer.metricsRegionServer.updateCheckAndDelete(after - before);
2596 } else {
2597 regionServer.metricsRegionServer.updateDelete(
2598 region == null ? null : region.getRegionInfo().getTable(), after - before);
2599 }
2600 break;
2601 case PUT:
2602 if (request.hasCondition()) {
2603 regionServer.metricsRegionServer.updateCheckAndPut(after - before);
2604 } else {
2605 regionServer.metricsRegionServer.updatePut(
2606 region == null ? null : region.getRegionInfo().getTable(),after - before);
2607 }
2608 break;
2609 default:
2610 break;
2611
2612 }
2613 }
2614 }
2615 }
2616
2617
2618
2619
2620 @Deprecated
2621 private static final IOException SCANNER_ALREADY_CLOSED = new IOException() {
2622
2623 private static final long serialVersionUID = -4305297078988180130L;
2624
2625 @Override
2626 public synchronized Throwable fillInStackTrace() {
2627 return this;
2628 }
2629 };
2630
2631 private RegionScannerHolder getRegionScanner(ScanRequest request) throws IOException {
2632 String scannerName = Long.toString(request.getScannerId());
2633 RegionScannerHolder rsh = scanners.get(scannerName);
2634 if (rsh == null) {
2635
2636 if (closedScanners.getIfPresent(scannerName) != null) {
2637 throw SCANNER_ALREADY_CLOSED;
2638 } else {
2639 LOG.warn("Client tried to access missing scanner " + scannerName);
2640 throw new UnknownScannerException(
2641 "Unknown scanner '" + scannerName + "'. This can happen due to any of the following " +
2642 "reasons: a) Scanner id given is wrong, b) Scanner lease expired because of " +
2643 "long wait between consecutive client checkins, c) Server may be closing down, " +
2644 "d) RegionServer restart during upgrade.\nIf the issue is due to reason (b), a " +
2645 "possible fix would be increasing the value of" +
2646 "'hbase.client.scanner.timeout.period' configuration.");
2647 }
2648 }
2649 HRegionInfo hri = rsh.s.getRegionInfo();
2650
2651 if (regionServer.getOnlineRegion(hri.getRegionName()) != rsh.r) {
2652 String msg = "Region was re-opened after the scanner" + scannerName + " was created: "
2653 + hri.getRegionNameAsString();
2654 LOG.warn(msg + ", closing...");
2655 scanners.remove(scannerName);
2656 try {
2657 rsh.s.close();
2658 } catch (IOException e) {
2659 LOG.warn("Getting exception closing " + scannerName, e);
2660 } finally {
2661 try {
2662 regionServer.leases.cancelLease(scannerName);
2663 } catch (LeaseException e) {
2664 LOG.warn("Getting exception closing " + scannerName, e);
2665 }
2666 }
2667 throw new NotServingRegionException(msg);
2668 }
2669 return rsh;
2670 }
2671
2672 private RegionScannerHolder newRegionScanner(ScanRequest request, ScanResponse.Builder builder)
2673 throws IOException {
2674 Region region = getRegion(request.getRegion());
2675 ClientProtos.Scan protoScan = request.getScan();
2676 boolean isLoadingCfsOnDemandSet = protoScan.hasLoadColumnFamiliesOnDemand();
2677 Scan scan = ProtobufUtil.toScan(protoScan);
2678
2679 if (!isLoadingCfsOnDemandSet) {
2680 scan.setLoadColumnFamiliesOnDemand(region.isLoadingCfsOnDemandDefault());
2681 }
2682 if (!scan.hasFamilies()) {
2683
2684 for (byte[] family : region.getTableDesc().getFamiliesKeys()) {
2685 scan.addFamily(family);
2686 }
2687 }
2688 RegionScanner scanner = null;
2689 if (region.getCoprocessorHost() != null) {
2690 scanner = region.getCoprocessorHost().preScannerOpen(scan);
2691 }
2692 if (scanner == null) {
2693 scanner = region.getScanner(scan);
2694 }
2695 if (region.getCoprocessorHost() != null) {
2696 scanner = region.getCoprocessorHost().postScannerOpen(scan, scanner);
2697 }
2698 long scannerId = scannerIdGenerator.generateNewScannerId();
2699 builder.setScannerId(scannerId);
2700 builder.setMvccReadPoint(scanner.getMvccReadPoint());
2701 builder.setTtl(scannerLeaseTimeoutPeriod);
2702 String scannerName = String.valueOf(scannerId);
2703 return addScanner(scannerName, scanner, region, scan.isNeedCursorResult());
2704 }
2705
2706 private void checkScanNextCallSeq(ScanRequest request, RegionScannerHolder rsh)
2707 throws OutOfOrderScannerNextException {
2708
2709
2710
2711 if (request.hasNextCallSeq()) {
2712 long callSeq = request.getNextCallSeq();
2713 if (!rsh.incNextCallSeq(callSeq)) {
2714 throw new OutOfOrderScannerNextException("Expected nextCallSeq: " + rsh.getNextCallSeq()
2715 + " But the nextCallSeq got from client: " + request.getNextCallSeq() + "; request="
2716 + TextFormat.shortDebugString(request));
2717 }
2718 }
2719 }
2720
2721 private void addScannerLeaseBack(Leases.Lease lease) {
2722 try {
2723 regionServer.leases.addLease(lease);
2724 } catch (LeaseStillHeldException e) {
2725
2726 throw new AssertionError(e);
2727 }
2728 }
2729
2730 private long getTimeLimit(HBaseRpcController controller,
2731 boolean allowHeartbeatMessages) {
2732
2733
2734
2735 if (allowHeartbeatMessages && (scannerLeaseTimeoutPeriod > 0 || rpcTimeout > 0)) {
2736 long timeLimitDelta;
2737 if (scannerLeaseTimeoutPeriod > 0 && rpcTimeout > 0) {
2738 timeLimitDelta = Math.min(scannerLeaseTimeoutPeriod, rpcTimeout);
2739 } else {
2740 timeLimitDelta = scannerLeaseTimeoutPeriod > 0 ? scannerLeaseTimeoutPeriod : rpcTimeout;
2741 }
2742 if (controller != null && controller.getCallTimeout() > 0) {
2743 timeLimitDelta = Math.min(timeLimitDelta, controller.getCallTimeout());
2744 }
2745
2746
2747
2748 timeLimitDelta = Math.max(timeLimitDelta / 2, minimumScanTimeLimitDelta);
2749
2750
2751 return System.currentTimeMillis() + timeLimitDelta;
2752 }
2753
2754
2755 return -1L;
2756 }
2757
2758 private void checkLimitOfRows(int numOfCompleteRows, int limitOfRows, boolean moreRows,
2759 ScannerContext scannerContext, ScanResponse.Builder builder) {
2760 if (numOfCompleteRows >= limitOfRows) {
2761 if (LOG.isTraceEnabled()) {
2762 LOG.trace("Done scanning, limit of rows reached, moreRows: " + moreRows +
2763 " scannerContext: " + scannerContext);
2764 }
2765 builder.setMoreResults(false);
2766 }
2767 }
2768
2769
2770 private void scan(HBaseRpcController controller, ScanRequest request, RegionScannerHolder rsh,
2771 long maxQuotaResultSize, int maxResults, int limitOfRows, List<Result> results,
2772 ScanResponse.Builder builder, MutableObject lastBlock, RpcCallContext context)
2773 throws IOException {
2774 Region region = rsh.r;
2775 RegionScanner scanner = rsh.s;
2776 long maxResultSize;
2777 if (scanner.getMaxResultSize() > 0) {
2778 maxResultSize = Math.min(scanner.getMaxResultSize(), maxQuotaResultSize);
2779 } else {
2780 maxResultSize = maxQuotaResultSize;
2781 }
2782
2783
2784
2785 List<Cell> values = new ArrayList<Cell>(32);
2786 region.startRegionOperation(Operation.SCAN);
2787 try {
2788 int numOfResults = 0;
2789 int numOfCompleteRows = 0;
2790 long before = EnvironmentEdgeManager.currentTime();
2791 synchronized (scanner) {
2792 boolean stale = (region.getRegionInfo().getReplicaId() != 0);
2793 boolean clientHandlesPartials =
2794 request.hasClientHandlesPartials() && request.getClientHandlesPartials();
2795 boolean clientHandlesHeartbeats =
2796 request.hasClientHandlesHeartbeats() && request.getClientHandlesHeartbeats();
2797
2798
2799
2800
2801
2802
2803 boolean serverGuaranteesOrderOfPartials = results.isEmpty();
2804 boolean allowPartialResults = clientHandlesPartials && serverGuaranteesOrderOfPartials;
2805 boolean moreRows = false;
2806
2807
2808
2809
2810
2811
2812
2813
2814 boolean allowHeartbeatMessages = clientHandlesHeartbeats && allowPartialResults;
2815
2816 long timeLimit = getTimeLimit(controller, allowHeartbeatMessages);
2817
2818 final LimitScope sizeScope =
2819 allowPartialResults ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;
2820 final LimitScope timeScope =
2821 allowHeartbeatMessages ? LimitScope.BETWEEN_CELLS : LimitScope.BETWEEN_ROWS;
2822
2823 boolean trackMetrics = request.hasTrackScanMetrics() && request.getTrackScanMetrics();
2824
2825
2826
2827 ScannerContext.Builder contextBuilder = ScannerContext.newBuilder(true);
2828 contextBuilder.setSizeLimit(sizeScope, maxResultSize);
2829 contextBuilder.setBatchLimit(scanner.getBatch());
2830 contextBuilder.setTimeLimit(timeScope, timeLimit);
2831 contextBuilder.setTrackMetrics(trackMetrics);
2832 ScannerContext scannerContext = contextBuilder.build();
2833 boolean limitReached = false;
2834 while (numOfResults < maxResults) {
2835
2836
2837
2838
2839
2840 scannerContext.setBatchProgress(0);
2841
2842
2843 moreRows = scanner.nextRaw(values, scannerContext);
2844
2845 if (!values.isEmpty()) {
2846 if (limitOfRows > 0) {
2847
2848
2849 if (results.isEmpty()) {
2850 if (rsh.rowOfLastPartialResult != null &&
2851 !CellUtil.matchingRow(values.get(0), rsh.rowOfLastPartialResult)) {
2852 numOfCompleteRows++;
2853 checkLimitOfRows(numOfCompleteRows, limitOfRows, moreRows, scannerContext,
2854 builder);
2855 }
2856 } else {
2857 Result lastResult = results.get(results.size() - 1);
2858 if (lastResult.mayHaveMoreCellsInRow() &&
2859 !CellUtil.matchingRow(values.get(0), lastResult.getRow())) {
2860 numOfCompleteRows++;
2861 checkLimitOfRows(numOfCompleteRows, limitOfRows, moreRows, scannerContext,
2862 builder);
2863 }
2864 }
2865 if (builder.hasMoreResults() && !builder.getMoreResults()) {
2866 break;
2867 }
2868 }
2869 boolean mayHaveMoreCellsInRow = scannerContext.mayHaveMoreCellsInRow();
2870 Result r = Result.create(values, null, stale, mayHaveMoreCellsInRow);
2871 lastBlock.setValue(addSize(context, r, lastBlock.getValue()));
2872 results.add(r);
2873 numOfResults++;
2874 if (!mayHaveMoreCellsInRow && limitOfRows > 0) {
2875 numOfCompleteRows++;
2876 checkLimitOfRows(numOfCompleteRows, limitOfRows, moreRows, scannerContext, builder);
2877 if (builder.hasMoreResults() && !builder.getMoreResults()) {
2878 break;
2879 }
2880 }
2881 } else if (!moreRows && !results.isEmpty()) {
2882
2883
2884
2885
2886
2887
2888 int lastIdx = results.size() - 1;
2889 Result r = results.get(lastIdx);
2890 if (r.mayHaveMoreCellsInRow()) {
2891 results.set(lastIdx, Result.create(r.rawCells(), r.getExists(), r.isStale(), false));
2892 }
2893 }
2894 boolean sizeLimitReached = scannerContext.checkSizeLimit(LimitScope.BETWEEN_ROWS);
2895 boolean timeLimitReached = scannerContext.checkTimeLimit(LimitScope.BETWEEN_ROWS);
2896 boolean resultsLimitReached = numOfResults >= maxResults;
2897 limitReached = sizeLimitReached || timeLimitReached || resultsLimitReached;
2898
2899 if (limitReached || !moreRows) {
2900 if (LOG.isTraceEnabled()) {
2901 LOG.trace("Done scanning. limitReached: " + limitReached + " moreRows: " + moreRows
2902 + " scannerContext: " + scannerContext);
2903 }
2904
2905
2906
2907
2908 if (moreRows && timeLimitReached) {
2909
2910 builder.setHeartbeatMessage(true);
2911 if (rsh.needCursor) {
2912 Cell cursorCell = scannerContext.getLastPeekedCell();
2913 if (cursorCell != null) {
2914 builder.setCursor(ProtobufUtil.toCursor(cursorCell));
2915 }
2916 }
2917 }
2918 break;
2919 }
2920 values.clear();
2921 }
2922 builder.setMoreResultsInRegion(moreRows);
2923
2924
2925 if (trackMetrics) {
2926 Map<String, Long> metrics = scannerContext.getMetrics().getMetricsMap();
2927 ScanMetrics.Builder metricBuilder = ScanMetrics.newBuilder();
2928 NameInt64Pair.Builder pairBuilder = NameInt64Pair.newBuilder();
2929
2930 for (Entry<String, Long> entry : metrics.entrySet()) {
2931 pairBuilder.setName(entry.getKey());
2932 pairBuilder.setValue(entry.getValue());
2933 metricBuilder.addMetrics(pairBuilder.build());
2934 }
2935
2936 builder.setScanMetrics(metricBuilder.build());
2937 }
2938 }
2939 long end = EnvironmentEdgeManager.currentTime();
2940 long responseCellSize = context != null ? context.getResponseCellSize() : 0;
2941 region.getMetrics().updateScanTime(end - before);
2942 if (regionServer.metricsRegionServer != null) {
2943 regionServer.metricsRegionServer.updateScanSize(
2944 region.getTableDesc().getTableName(), responseCellSize);
2945 regionServer.metricsRegionServer.updateScanTime(
2946 region.getTableDesc().getTableName(), end - before);
2947 }
2948 } finally {
2949 region.closeRegionOperation();
2950 }
2951
2952 if (region.getCoprocessorHost() != null) {
2953 region.getCoprocessorHost().postScannerNext(scanner, results, maxResults, true);
2954 }
2955 }
2956
2957
2958
2959
2960
2961
2962
2963
2964 @Override
2965 public ScanResponse scan(final RpcController controller, final ScanRequest request)
2966 throws ServiceException {
2967 if (controller != null && !(controller instanceof HBaseRpcController)) {
2968 throw new UnsupportedOperationException(
2969 "We only do HBaseRpcController! FIX IF A PROBLEM: " + controller);
2970 }
2971 if (!request.hasScannerId() && !request.hasScan()) {
2972 throw new ServiceException(
2973 new DoNotRetryIOException("Missing required input: scannerId or scan"));
2974 }
2975 try {
2976 checkOpen();
2977 } catch (IOException e) {
2978 if (request.hasScannerId()) {
2979 String scannerName = Long.toString(request.getScannerId());
2980 if (LOG.isDebugEnabled()) {
2981 LOG.debug(
2982 "Server shutting down and client tried to access missing scanner " + scannerName);
2983 }
2984 if (regionServer.leases != null) {
2985 try {
2986 regionServer.leases.cancelLease(scannerName);
2987 } catch (LeaseException le) {
2988
2989 if (LOG.isTraceEnabled()) {
2990 LOG.trace("Un-able to cancel lease of scanner. It could already be closed.");
2991 }
2992 }
2993 }
2994 }
2995 throw new ServiceException(e);
2996 }
2997 requestCount.increment();
2998 rpcScanRequestCount.increment();
2999 RegionScannerHolder rsh;
3000 ScanResponse.Builder builder = ScanResponse.newBuilder();
3001 try {
3002 if (request.hasScannerId()) {
3003
3004
3005 builder.setScannerId(request.getScannerId());
3006 rsh = getRegionScanner(request);
3007 } else {
3008 rsh = newRegionScanner(request, builder);
3009 }
3010 } catch (IOException e) {
3011 if (e == SCANNER_ALREADY_CLOSED) {
3012
3013
3014 return builder.build();
3015 }
3016 throw new ServiceException(e);
3017 }
3018 Region region = rsh.r;
3019 String scannerName = rsh.scannerName;
3020 Leases.Lease lease;
3021 try {
3022
3023
3024 lease = regionServer.leases.removeLease(scannerName);
3025 } catch (LeaseException e) {
3026 throw new ServiceException(e);
3027 }
3028 if (request.hasRenew() && request.getRenew()) {
3029
3030 addScannerLeaseBack(lease);
3031 try {
3032 checkScanNextCallSeq(request, rsh);
3033 } catch (OutOfOrderScannerNextException e) {
3034 throw new ServiceException(e);
3035 }
3036 return builder.build();
3037 }
3038 OperationQuota quota;
3039 try {
3040 quota = getQuotaManager().checkQuota(region, OperationQuota.OperationType.SCAN);
3041 } catch (IOException e) {
3042 addScannerLeaseBack(lease);
3043 throw new ServiceException(e);
3044 };
3045 try {
3046 checkScanNextCallSeq(request, rsh);
3047 } catch (OutOfOrderScannerNextException e) {
3048 addScannerLeaseBack(lease);
3049 throw new ServiceException(e);
3050 }
3051
3052
3053
3054 boolean closeScanner = request.hasCloseScanner() ? request.getCloseScanner() : false;
3055 int rows;
3056 if (request.hasNumberOfRows()) {
3057 rows = request.getNumberOfRows();
3058 } else {
3059 rows = closeScanner ? 0 : 1;
3060 }
3061 RpcCallContext context = RpcServer.getCurrentCall();
3062
3063 long maxQuotaResultSize = Math.min(maxScannerResultSize, quota.getReadAvailable());
3064 RegionScanner scanner = rsh.s;
3065
3066
3067 int limitOfRows;
3068 if (request.hasLimitOfRows()) {
3069 limitOfRows = request.getLimitOfRows();
3070 } else {
3071 limitOfRows = -1;
3072 }
3073 MutableObject lastBlock = new MutableObject();
3074 boolean scannerClosed = false;
3075 try {
3076 List<Result> results = new ArrayList<>();
3077 if (rows > 0) {
3078 boolean done = false;
3079
3080 if (region.getCoprocessorHost() != null) {
3081 Boolean bypass = region.getCoprocessorHost().preScannerNext(scanner, results, rows);
3082 if (!results.isEmpty()) {
3083 for (Result r : results) {
3084 lastBlock.setValue(addSize(context, r, lastBlock.getValue()));
3085 }
3086 }
3087 if (bypass != null && bypass.booleanValue()) {
3088 done = true;
3089 }
3090 }
3091 if (!done) {
3092 scan((HBaseRpcController) controller, request, rsh, maxQuotaResultSize, rows, limitOfRows,
3093 results, builder, lastBlock, context);
3094 } else {
3095 builder.setMoreResultsInRegion(!results.isEmpty());
3096 }
3097 } else {
3098
3099 builder.setMoreResultsInRegion(true);
3100 }
3101
3102 quota.addScanResult(results);
3103 addResults(builder, results, (HBaseRpcController) controller,
3104 RegionReplicaUtil.isDefaultReplica(region.getRegionInfo()));
3105 if (scanner.isFilterDone() && results.isEmpty()) {
3106
3107
3108
3109
3110 builder.setMoreResults(false);
3111 }
3112
3113
3114 assert builder.hasMoreResultsInRegion();
3115
3116
3117 if (!builder.hasMoreResults()) {
3118 builder.setMoreResults(true);
3119 }
3120 if (builder.getMoreResults() && builder.getMoreResultsInRegion() && !results.isEmpty()) {
3121
3122
3123
3124
3125
3126
3127 Result lastResult = results.get(results.size() - 1);
3128 if (lastResult.mayHaveMoreCellsInRow()) {
3129 rsh.rowOfLastPartialResult = lastResult.getRow();
3130 } else {
3131 rsh.rowOfLastPartialResult = null;
3132 }
3133 }
3134 if (!builder.getMoreResults() || !builder.getMoreResultsInRegion() || closeScanner) {
3135 scannerClosed = true;
3136 closeScanner(region, scanner, scannerName, context);
3137 }
3138 return builder.build();
3139 } catch (IOException e) {
3140 try {
3141
3142 scannerClosed = true;
3143
3144
3145
3146 closeScanner(region, scanner, scannerName, context);
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159 if (e instanceof DoNotRetryIOException) {
3160 throw e;
3161 }
3162
3163
3164
3165 if (e instanceof FileNotFoundException) {
3166 throw new DoNotRetryIOException(e);
3167 }
3168
3169
3170
3171
3172 if (VersionInfoUtil.hasMinimumVersion(context.getClientVersionInfo(), 1, 4)) {
3173
3174 throw new ScannerResetException("Scanner is closed on the server-side", e);
3175 } else {
3176
3177 throw new UnknownScannerException("Throwing UnknownScannerException to reset the client"
3178 + " scanner state for clients older than 1.4.", e);
3179 }
3180 } catch (IOException ioe) {
3181 throw new ServiceException(ioe);
3182 }
3183 } finally {
3184 if (!scannerClosed) {
3185
3186 addScannerLeaseBack(lease);
3187 }
3188 quota.close();
3189 }
3190 }
3191
3192 private void closeScanner(Region region, RegionScanner scanner, String scannerName,
3193 RpcCallContext context) throws IOException {
3194 if (region.getCoprocessorHost() != null) {
3195 if (region.getCoprocessorHost().preScannerClose(scanner)) {
3196
3197 return;
3198 }
3199 }
3200 RegionScannerHolder rsh = scanners.remove(scannerName);
3201 if (rsh != null) {
3202 rsh.s.close();
3203 if (region.getCoprocessorHost() != null) {
3204 region.getCoprocessorHost().postScannerClose(scanner);
3205 }
3206 closedScanners.put(scannerName, scannerName);
3207 }
3208 }
3209
3210 @Override
3211 public CoprocessorServiceResponse execRegionServerService(RpcController controller,
3212 CoprocessorServiceRequest request) throws ServiceException {
3213 return regionServer.execRegionServerService(controller, request);
3214 }
3215
3216 @Override
3217 public UpdateConfigurationResponse updateConfiguration(
3218 RpcController controller, UpdateConfigurationRequest request)
3219 throws ServiceException {
3220 try {
3221 this.regionServer.updateConfiguration();
3222 } catch (Exception e) {
3223 throw new ServiceException(e);
3224 }
3225 return UpdateConfigurationResponse.getDefaultInstance();
3226 }
3227 }