001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver; 019 020import java.io.IOException; 021import org.apache.hadoop.hbase.NotServingRegionException; 022import org.apache.hadoop.hbase.client.IsolationLevel; 023import org.apache.hadoop.hbase.client.RegionInfo; 024import org.apache.hadoop.hbase.errorhandling.ForeignExceptionDispatcher; 025import org.apache.hadoop.hbase.executor.EventType; 026import org.apache.hadoop.hbase.procedure2.BaseRSProcedureCallable; 027import org.apache.yetus.audience.InterfaceAudience; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 032import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.SnapshotRegionParameter; 033import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; 034 035@InterfaceAudience.Private 036public class SnapshotRegionCallable extends BaseRSProcedureCallable { 037 private static final Logger LOG = LoggerFactory.getLogger(SnapshotRegionCallable.class); 038 039 private SnapshotDescription snapshot; 040 private RegionInfo regionInfo; 041 private ForeignExceptionDispatcher monitor; 042 043 @Override 044 protected void doCall() throws Exception { 045 HRegion region = rs.getRegion(regionInfo.getEncodedName()); 046 if (region == null) { 047 throw new NotServingRegionException( 048 "snapshot=" + snapshot.getName() + ", region=" + regionInfo.getRegionNameAsString()); 049 } 050 LOG.debug("Starting snapshot operation on {}", region); 051 region.startRegionOperation(Region.Operation.SNAPSHOT); 052 try { 053 if (snapshot.getType() == SnapshotDescription.Type.FLUSH) { 054 boolean succeeded = false; 055 long readPt = region.getReadPoint(IsolationLevel.READ_COMMITTED); 056 int retryTimes = rs.getConfiguration().getInt("hbase.snapshot.flush.retryTimes", 3); 057 for (int i = 0; i < retryTimes; i++) { 058 HRegion.FlushResult res = region.flush(true); 059 if (res.getResult() == HRegion.FlushResult.Result.CANNOT_FLUSH) { 060 region.waitForFlushes(); 061 if (region.getMaxFlushedSeqId() >= readPt) { 062 succeeded = true; 063 break; 064 } 065 } else { 066 succeeded = true; 067 break; 068 } 069 } 070 if (!succeeded) { 071 throw new IOException("Unable to complete flush " + regionInfo.getRegionNameAsString() 072 + " after " + retryTimes + " attempts"); 073 } 074 } 075 LOG.debug("Snapshotting region {} for {} completed.", region, snapshot.getName()); 076 region.addRegionToSnapshot(snapshot, monitor); 077 } finally { 078 LOG.debug("Closing snapshot operation on {}", region); 079 region.closeRegionOperation(Region.Operation.SNAPSHOT); 080 } 081 } 082 083 @Override 084 protected void initParameter(byte[] parameter) throws Exception { 085 SnapshotRegionParameter param = SnapshotRegionParameter.parseFrom(parameter); 086 this.snapshot = param.getSnapshot(); 087 this.regionInfo = ProtobufUtil.toRegionInfo(param.getRegion()); 088 this.monitor = new ForeignExceptionDispatcher(snapshot.getName()); 089 } 090 091 @Override 092 public EventType getEventType() { 093 return EventType.RS_SNAPSHOT_REGIONS; 094 } 095}