Java tutorial
// @@@ START COPYRIGHT @@@ // // (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // @@@ END COPYRIGHT @@@ package org.apache.hadoop.hbase.coprocessor.transactional; import java.io.IOException; import org.apache.commons.codec.binary.Hex; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hbase.Coprocessor; import org.apache.hadoop.hbase.CoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.ColumnInterpreter; import org.apache.hadoop.hbase.coprocessor.CoprocessorException; import org.apache.hadoop.hbase.coprocessor.CoprocessorService; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import java.io.*; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.lang.management.MemoryMXBean; import java.lang.reflect.InvocationTargetException; import java.lang.StringBuilder; import java.lang.StringBuilder; import java.lang.Thread.UncaughtExceptionHandler; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.ListIterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NavigableSet; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.codec.binary.Hex; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Durability; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Increment; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.ScannerTimeoutException; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.transactional.MemoryUsageException; import org.apache.hadoop.hbase.client.transactional.OutOfOrderProtocolException; import org.apache.hadoop.hbase.client.transactional.UnknownTransactionException; import org.apache.hadoop.hbase.client.transactional.BatchException; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; import org.apache.hadoop.hbase.filter.FilterBase; import org.apache.hadoop.hbase.filter.FilterList; import org.apache.hadoop.hbase.KeyValueUtil; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.KeyValue.Type; import org.apache.hadoop.hbase.Coprocessor; import org.apache.hadoop.hbase.CoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.CoprocessorException; import org.apache.hadoop.hbase.coprocessor.CoprocessorService; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.RegionObserver; import org.apache.hadoop.hbase.exceptions.OutOfOrderScannerNextException; import org.apache.hadoop.hbase.filter.FilterBase; import org.apache.hadoop.hbase.coprocessor.CoprocessorService; import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; import org.apache.hadoop.hbase.coprocessor.RegionObserver; import org.apache.hadoop.hbase.filter.FilterList; import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.Tag; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.regionserver.RegionServerServices; import org.apache.hadoop.hbase.Stoppable; import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.UnknownScannerException; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.KeyValueScanner; import org.apache.hadoop.hbase.regionserver.LeaseException; import org.apache.hadoop.hbase.regionserver.LeaseListener; import org.apache.hadoop.hbase.regionserver.Leases; import org.apache.hadoop.hbase.regionserver.Leases.LeaseStillHeldException; import org.apache.hadoop.hbase.regionserver.MultiVersionConsistencyControl; import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; import org.apache.hadoop.hbase.regionserver.RegionScanner; import org.apache.hadoop.hbase.regionserver.WrongRegionException; import org.apache.hadoop.hbase.regionserver.wal.HLog; import org.apache.hadoop.hbase.regionserver.wal.HLogKey; import org.apache.hadoop.hbase.regionserver.wal.HLogUtil; import org.apache.hadoop.hbase.regionserver.wal.WALEdit; import org.apache.hadoop.hbase.regionserver.transactional.CleanOldTransactionsChore; import org.apache.hadoop.hbase.regionserver.transactional.MemoryUsageChore; import org.apache.hadoop.hbase.regionserver.transactional.TransactionalRegion; import org.apache.hadoop.hbase.regionserver.transactional.TransactionalRegionScannerHolder; import org.apache.hadoop.hbase.regionserver.transactional.TransactionState; import org.apache.hadoop.hbase.regionserver.transactional.TrxTransactionState; import org.apache.hadoop.hbase.regionserver.transactional.TrxTransactionState.TransactionScanner; import org.apache.hadoop.hbase.regionserver.transactional.TrxTransactionState.WriteAction; import org.apache.hadoop.hbase.regionserver.transactional.TransactionState.CommitProgress; import org.apache.hadoop.hbase.regionserver.transactional.TransactionState.Status; import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.FSUtils; import org.apache.hadoop.hbase.util.Threads; import org.apache.hadoop.hbase.protobuf.ProtobufUtil; import org.apache.hadoop.hbase.protobuf.ResponseConverter; import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto; import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType; import org.apache.hadoop.hbase.coprocessor.transactional.TrxRegionObserver; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.BeginTransactionRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.BeginTransactionResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CloseScannerRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CloseScannerResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitIfPossibleRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitIfPossibleResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndDeleteRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndDeleteResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndPutRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndPutResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteMultipleTransactionalRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteMultipleTransactionalResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteTransactionalRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteTransactionalResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.GetTransactionalRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.GetTransactionalResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PerformScanRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PerformScanResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.OpenScannerRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.OpenScannerResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutTransactionalRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutTransactionalResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutMultipleTransactionalRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutMultipleTransactionalResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.RecoveryRequestRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.RecoveryRequestResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.TransactionalAggregateRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.TransactionalAggregateResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.TrxRegionService; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.apache.hadoop.hbase.zookeeper.ZKUtil; import org.apache.zookeeper.KeeperException; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionMultipleRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionMultipleResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitMultipleRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitMultipleResponse; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestMultipleRequest; import org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestMultipleResponse; import com.google.protobuf.ByteString; import com.google.protobuf.Message; import com.google.protobuf.RpcCallback; import com.google.protobuf.RpcController; import com.google.protobuf.Service; import com.google.protobuf.ServiceException; @InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.COPROC) @InterfaceStability.Evolving public class TrxRegionEndpoint<T, S, P extends Message, Q extends Message, R extends Message> extends TrxRegionService implements CoprocessorService, Coprocessor { private static final Log LOG = LogFactory.getLog(TrxRegionEndpoint.class); private RegionCoprocessorEnvironment env; protected Map<Long, Long> transactionsByIdTest = null; ConcurrentHashMap<String, Object> transactionsByIdTestz = null; // Collection of active transactions (PENDING) keyed by id. protected ConcurrentHashMap<String, TrxTransactionState> transactionsById = new ConcurrentHashMap<String, TrxTransactionState>(); // Map of recent transactions that are COMMIT_PENDING or COMMITED keyed // by their sequence number private SortedMap<Long, TrxTransactionState> commitedTransactionsBySequenceNumber = Collections .synchronizedSortedMap(new TreeMap<Long, TrxTransactionState>()); // Collection of transactions that are COMMIT_PENDING private Set<TrxTransactionState> commitPendingTransactions = Collections .synchronizedSet(new HashSet<TrxTransactionState>()); // an in-doubt transaction list during recovery WALEdit replay private Map<Long, List<WALEdit>> indoubtTransactionsById = new TreeMap<Long, List<WALEdit>>(); // list of transactions to check for stale scanners private List<Long> cleanScannersForTransactions = Collections.synchronizedList(new LinkedList<Long>()); // an in-doubt transaction list count by TM id private Map<Integer, Integer> indoubtTransactionsCountByTmid = new TreeMap<Integer, Integer>(); // Concurrent map for transactional region scanner holders // Protected by synchronized methods final ConcurrentHashMap<Long, TransactionalRegionScannerHolder> scanners = new ConcurrentHashMap<Long, TransactionalRegionScannerHolder>(); // Atomic values to manage region scanners private AtomicLong performScannerId = new AtomicLong(0); private AtomicLong nextSequenceId = new AtomicLong(0); private Object commitCheckLock = new Object(); private Object recoveryCheckLock = new Object(); private Object editReplay = new Object(); private static Object stoppableLock = new Object(); private int reconstructIndoubts = 0; //temporary THLog getSequenceNumber() replacement private AtomicLong nextLogSequenceId = new AtomicLong(0); public AtomicLong controlPointEpoch = new AtomicLong(1); private final int oldTransactionFlushTrigger = 0; private final Boolean splitDelayEnabled = false; private final Boolean doWALHlog = false; static Leases transactionLeases = null; // Joanie: commenting out scanner leases for now //static Leases scannerLeases = null; CleanOldTransactionsChore cleanOldTransactionsThread; static MemoryUsageChore memoryUsageThread = null; Stoppable stoppable = new StoppableImplementation(); static Stoppable stoppable2 = new StoppableImplementation(); private int cleanTimer = 5000; // Five minutes private int memoryUsageTimer = 60000; // One minute private int regionState = 0; private Path recoveryTrxPath = null; private int cleanAT = 0; private long[] commitCheckTimes = new long[50]; private long[] hasConflictTimes = new long[50]; private long[] putBySequenceTimes = new long[50]; private long[] writeToLogTimes = new long[50]; private AtomicInteger timeIndex = new AtomicInteger(0); private AtomicInteger totalCommits = new AtomicInteger(0); private AtomicInteger writeToLogOperations = new AtomicInteger(0); private AtomicInteger putBySequenceOperations = new AtomicInteger(0); private long totalCommitCheckTime = 0; private long totalConflictTime = 0; private long totalPutTime = 0; private long totalWriteToLogTime = 0; private long minCommitCheckTime = 1000000000; private long maxCommitCheckTime = 0; private double avgCommitCheckTime = 0; private long minConflictTime = 1000000000; private long maxConflictTime = 0; private double avgConflictTime = 0; private long minPutTime = 1000000000; private long maxPutTime = 0; private double avgPutTime = 0; private long minWriteToLogTime = 1000000000; private long maxWriteToLogTime = 0; private double avgWriteToLogTime = 0; private HRegionInfo regionInfo = null; private HRegion m_Region = null; private TransactionalRegion t_Region = null; private FileSystem fs = null; private RegionCoprocessorHost rch = null; private HLog tHLog = null; private AtomicBoolean closing = new AtomicBoolean(false); private boolean fullEditInCommit = true; private boolean configuredEarlyLogging = false; private boolean configuredConflictReinstate = false; private static Object zkRecoveryCheckLock = new Object(); private static ZooKeeperWatcher zkw1 = null; String lv_hostName; int lv_port; private static String zNodePath = "/hbase/Trafodion/recovery/"; private static final int MINIMUM_LEASE_TIME = 7200 * 1000; private static final int LEASE_CHECK_FREQUENCY = 1000; private static final int DEFAULT_SLEEP = 60 * 1000; private static final int DEFAULT_MEMORY_THRESHOLD = 100; // 100% memory used private static final int DEFAULT_MEMORY_SLEEP = 15 * 1000; private static final boolean DEFAULT_MEMORY_WARN_ONLY = true; private static final boolean DEFAULT_MEMORY_PERFORM_GC = false; private static final boolean DEFAULT_SUPPRESS_OOP = false; private static final String SLEEP_CONF = "hbase.transaction.clean.sleep"; private static final String LEASE_CONF = "hbase.transaction.lease.timeout"; private static final String MEMORY_THRESHOLD = "hbase.transaction.memory.threshold"; private static final String MEMORY_WARN_ONLY = "hbase.transaction.memory.warn.only"; private static final String MEMORY_CONF = "hbase.transaction.memory.sleep"; private static final String MEMORY_PERFORM_GC = "hbase.transaction.memory.perform.GC"; private static final String SUPPRESS_OOP = "hbase.transaction.suppress.OOP.exception"; protected static int transactionLeaseTimeout = 0; private static int scannerLeaseTimeoutPeriod = 0; private static int scannerThreadWakeFrequency = 0; private static int memoryUsageThreshold = DEFAULT_MEMORY_THRESHOLD; private static boolean memoryUsagePerformGC = DEFAULT_MEMORY_PERFORM_GC; private static boolean memoryUsageWarnOnly = DEFAULT_MEMORY_WARN_ONLY; private static MemoryMXBean memoryBean = null; private static float memoryPercentage = 0; private static boolean memoryThrottle = false; private static boolean suppressOutOfOrderProtocolException = DEFAULT_SUPPRESS_OOP; // Transaction state defines private static final int COMMIT_OK = 1; private static final int COMMIT_OK_READ_ONLY = 2; private static final int COMMIT_UNSUCCESSFUL_FROM_COPROCESSOR = 3; private static final int COMMIT_CONFLICT = 5; private static final int CLOSE_WAIT_ON_COMMIT_PENDING = 1000; private static final int MAX_COMMIT_PENDING_WAITS = 10; private Thread ChoreThread = null; private static Thread ChoreThread2 = null; //private static Thread ScannerLeasesThread = null; private static Thread TransactionalLeasesThread = null; public static final int TS_ACTIVE = 0; public static final int TS_COMMIT_REQUEST = 1; public static final int TS_COMMIT = 2; public static final int TS_ABORT = 3; public static final int TS_CONTROL_POINT_COMMIT = 4; public static final int REGION_STATE_RECOVERING = 0; public static final int REGION_STATE_START = 2; public static final String trxkeyEPCPinstance = "EPCPinstance"; // TBD Maybe we should just use HashMap to improve the performance, ConcurrentHashMap could be too strict static ConcurrentHashMap<String, Object> transactionsEPCPMap = new ConcurrentHashMap<String, Object>(); // TrxRegionService methods @Override public void abortTransaction(RpcController controller, AbortTransactionRequest request, RpcCallback<AbortTransactionResponse> done) { AbortTransactionResponse response = AbortTransactionResponse.getDefaultInstance(); long transactionId = request.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString()); IOException ioe = null; UnknownTransactionException ute = null; WrongRegionException wre = null; Throwable t = null; /* commenting out for the time being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:abortTransaction threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { // Process in local memory try { abortTransaction(transactionId); } catch (UnknownTransactionException u) { if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor:abort - txId " + transactionId + ", Caught UnknownTransactionException after internal abortTransaction call - " + u.getMessage() + " " + stackTraceToString(u)); ute = u; } catch (IOException e) { if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor:abort - txId " + transactionId + ", Caught IOException after internal abortTransaction call - " + e.getMessage() + " " + stackTraceToString(e)); ioe = e; } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionResponse.Builder abortTransactionResponseBuilder = AbortTransactionResponse .newBuilder(); abortTransactionResponseBuilder.setHasException(false); if (t != null) { abortTransactionResponseBuilder.setHasException(true); abortTransactionResponseBuilder.setException(t.toString()); } if (wre != null) { abortTransactionResponseBuilder.setHasException(true); abortTransactionResponseBuilder.setException(wre.toString()); } if (ioe != null) { abortTransactionResponseBuilder.setHasException(true); abortTransactionResponseBuilder.setException(ioe.toString()); } if (ute != null) { abortTransactionResponseBuilder.setHasException(true); abortTransactionResponseBuilder.setException(ute.toString()); } AbortTransactionResponse aresponse = abortTransactionResponseBuilder.build(); done.run(aresponse); } @Override public void abortTransactionMultiple(RpcController controller, AbortTransactionMultipleRequest request, RpcCallback<AbortTransactionMultipleResponse> done) { AbortTransactionMultipleResponse response = AbortTransactionMultipleResponse.getDefaultInstance(); long transactionId = request.getTransactionId(); int i = 0; int numOfRegion = request.getRegionNameCount(); String requestRegionName; IOException ioe = null; UnknownTransactionException ute = null; WrongRegionException wre = null; Throwable t = null; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortMultiple - txId " + transactionId + ", master regionName " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortMultiple - txId " + transactionId + " number of region is commitMultiple " + numOfRegion); org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.AbortTransactionMultipleResponse.Builder abortTransactionMultipleResponseBuilder = AbortTransactionMultipleResponse .newBuilder(); abortTransactionMultipleResponseBuilder.setHasException(false); while (i < numOfRegion) { requestRegionName = request.getRegionName(i).toStringUtf8(); abortTransactionMultipleResponseBuilder.addException(BatchException.EXCEPTION_OK.toString()); try { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint abortMultiple begins for region " + requestRegionName); TrxRegionEndpoint regionEPCP = (TrxRegionEndpoint) transactionsEPCPMap .get(requestRegionName + trxkeyEPCPinstance); if (regionEPCP == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint abortMultiple region NOT FOUND in EPCP map " + requestRegionName); abortTransactionMultipleResponseBuilder.setHasException(true); abortTransactionMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_REGIONNOTFOUND_ERR.toString()); } else { regionEPCP.abortTransaction(transactionId); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint abortMultiple ends"); // abortTransaction(transactionId); } catch (UnknownTransactionException u) { if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor:abort - txId " + transactionId + ", Caught UnknownTransactionException after internal abortTransaction call - " + u.getMessage() + " " + stackTraceToString(u)); ute = u; } catch (IOException e) { if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor:abort - txId " + transactionId + ", Caught IOException after internal abortTransaction call - " + e.getMessage() + " " + stackTraceToString(e)); ioe = e; } if (t != null) { abortTransactionMultipleResponseBuilder.setHasException(true); abortTransactionMultipleResponseBuilder.setException(i, t.toString()); } if (wre != null) { abortTransactionMultipleResponseBuilder.setHasException(true); abortTransactionMultipleResponseBuilder.setException(i, wre.toString()); } if (ioe != null) { abortTransactionMultipleResponseBuilder.setHasException(true); abortTransactionMultipleResponseBuilder.setException(i, ioe.toString()); } if (ute != null) { abortTransactionMultipleResponseBuilder.setHasException(true); abortTransactionMultipleResponseBuilder.setException(i, ute.toString()); } i++; // move to next region } // end of while-loop on all the regions in thecommitMultiple request AbortTransactionMultipleResponse aresponse = abortTransactionMultipleResponseBuilder.build(); done.run(aresponse); } @Override public void beginTransaction(RpcController controller, BeginTransactionRequest request, RpcCallback<BeginTransactionResponse> done) { BeginTransactionResponse response = BeginTransactionResponse.getDefaultInstance(); Throwable t = null; java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); WrongRegionException wre = null; MemoryUsageException mue = null; long transactionId = request.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString()); // First test if this region matches our region name /* commenting it out for the time-being if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:beginTransaction threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); }else */ { if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: beginTransaction - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); mue = new MemoryUsageException("beginTransaction memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } else { try { beginTransaction(transactionId); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction - txId " + transactionId + ", Caught exception after internal beginTransaction call " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.BeginTransactionResponse.Builder beginTransactionResponseBuilder = BeginTransactionResponse .newBuilder(); beginTransactionResponseBuilder.setHasException(false); if (t != null) { beginTransactionResponseBuilder.setHasException(true); beginTransactionResponseBuilder.setException(t.toString()); } if (wre != null) { beginTransactionResponseBuilder.setHasException(true); beginTransactionResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); beginTransactionResponseBuilder.setHasException(true); beginTransactionResponseBuilder.setException(mue.toString()); } BeginTransactionResponse bresponse = beginTransactionResponseBuilder.build(); done.run(bresponse); } @Override public void commit(RpcController controller, CommitRequest request, RpcCallback<CommitResponse> done) { CommitResponse response = CommitResponse.getDefaultInstance(); Throwable t = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString()); /* commenting out for the time being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commit threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { // Process local memory try { commit(transactionId, request.getIgnoreUnknownTransactionException()); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Caught exception after internal commit call " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitResponse.Builder commitResponseBuilder = CommitResponse .newBuilder(); commitResponseBuilder.setHasException(false); if (t != null) { commitResponseBuilder.setHasException(true); commitResponseBuilder.setException(t.toString()); } if (wre != null) { commitResponseBuilder.setHasException(true); commitResponseBuilder.setException(wre.toString()); } CommitResponse cresponse = commitResponseBuilder.build(); done.run(cresponse); } @Override public void commitMultiple(RpcController controller, CommitMultipleRequest request, RpcCallback<CommitMultipleResponse> done) { CommitMultipleResponse response = CommitMultipleResponse.getDefaultInstance(); Throwable t = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); int i = 0; int numOfRegion = request.getRegionNameCount(); String requestRegionName; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitMultiple - txId " + transactionId + " master regionName " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitMultiple - txId " + transactionId + " number of region is commitMultiple " + numOfRegion); org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitMultipleResponse.Builder commitMultipleResponseBuilder = CommitMultipleResponse .newBuilder(); commitMultipleResponseBuilder.setHasException(false); while (i < numOfRegion) { requestRegionName = request.getRegionName(i).toStringUtf8(); commitMultipleResponseBuilder.addException(BatchException.EXCEPTION_OK.toString()); try { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitMultiple begins for region " + requestRegionName); TrxRegionEndpoint regionEPCP = (TrxRegionEndpoint) transactionsEPCPMap .get(requestRegionName + trxkeyEPCPinstance); if (regionEPCP == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitMultiple region NOT FOUND in EPCP map " + requestRegionName); commitMultipleResponseBuilder.setHasException(true); commitMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_REGIONNOTFOUND_ERR.toString()); } else { regionEPCP.commit(transactionId, request.getIgnoreUnknownTransactionException()); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitMultiple ends"); //commit(transactionId, request.getIgnoreUnknownTransactionException()); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitMultiple - txId " + transactionId + ", Caught exception after internal commit call " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (t != null) { commitMultipleResponseBuilder.setHasException(true); commitMultipleResponseBuilder.setException(i, t.toString()); } if (wre != null) { commitMultipleResponseBuilder.setHasException(true); commitMultipleResponseBuilder.setException(i, wre.toString()); } i++; // move to next region } // end of while-loop on all the regions in thecommitMultiple request CommitMultipleResponse cresponse = commitMultipleResponseBuilder.build(); done.run(cresponse); } @Override public void commitIfPossible(RpcController controller, CommitIfPossibleRequest request, RpcCallback<CommitIfPossibleResponse> done) { CommitIfPossibleResponse response = CommitIfPossibleResponse.getDefaultInstance(); boolean reply = false; long transactionId = request.getTransactionId(); Throwable t = null; WrongRegionException wre = null; /* commenting out for the time being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commitIfPossible threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { // Process local memory try { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible - txId " + transactionId + ", regionName, " + regionInfo.getRegionNameAsString() + "calling internal commitIfPossible"); reply = commitIfPossible(transactionId); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible - txId " + transactionId + ", Caught exception after internal commitIfPossible call " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitIfPossibleResponse.Builder commitIfPossibleResponseBuilder = CommitIfPossibleResponse .newBuilder(); commitIfPossibleResponseBuilder.setHasException(false); if (t != null) { commitIfPossibleResponseBuilder.setHasException(true); commitIfPossibleResponseBuilder.setException(t.toString()); } if (wre != null) { commitIfPossibleResponseBuilder.setHasException(true); commitIfPossibleResponseBuilder.setException(wre.toString()); } CommitIfPossibleResponse cresponse = commitIfPossibleResponseBuilder.build(); done.run(cresponse); } @Override public void commitRequest(RpcController controller, CommitRequestRequest request, RpcCallback<CommitRequestResponse> done) { CommitRequestResponse response = CommitRequestResponse.getDefaultInstance(); int status = 0; IOException ioe = null; UnknownTransactionException ute = null; Throwable t = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString()); /* commenting out for the time being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commitRequest threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { // Process local memory try { status = commitRequest(transactionId); } catch (UnknownTransactionException u) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest - txId " + transactionId + ", Caught UnknownTransactionException after internal commitRequest call - " + u.toString()); ute = u; } catch (IOException e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest - txId " + transactionId + ", Caught IOException after internal commitRequest call - " + e.toString()); ioe = e; } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestResponse.Builder commitRequestResponseBuilder = CommitRequestResponse .newBuilder(); commitRequestResponseBuilder.setHasException(false); if (t != null) { commitRequestResponseBuilder.setHasException(true); commitRequestResponseBuilder.setException(t.toString()); } if (wre != null) { commitRequestResponseBuilder.setHasException(true); commitRequestResponseBuilder.setException(wre.toString()); } if (ioe != null) { commitRequestResponseBuilder.setHasException(true); commitRequestResponseBuilder.setException(ioe.toString()); } if (ute != null) { commitRequestResponseBuilder.setHasException(true); commitRequestResponseBuilder.setException(ute.toString()); } commitRequestResponseBuilder.setResult(status); CommitRequestResponse cresponse = commitRequestResponseBuilder.build(); done.run(cresponse); } @Override public void commitRequestMultiple(RpcController controller, CommitRequestMultipleRequest request, RpcCallback<CommitRequestMultipleResponse> done) { CommitRequestMultipleResponse response = CommitRequestMultipleResponse.getDefaultInstance(); int status = 0; IOException ioe = null; UnknownTransactionException ute = null; Throwable t = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); int i = 0; int numOfRegion = request.getRegionNameCount(); String requestRegionName; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequestMultiple - txId " + transactionId + ", master regionName " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequestMultiple - txId " + transactionId + " number of region is commitMultiple " + numOfRegion); org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CommitRequestMultipleResponse.Builder commitRequestMultipleResponseBuilder = CommitRequestMultipleResponse .newBuilder(); commitRequestMultipleResponseBuilder.setHasException(false); while (i < numOfRegion) { requestRegionName = request.getRegionName(i).toStringUtf8(); /* if (LOG.isTraceEnabled()) LOG.trace("EPCP AA0 Region Key " + Hex.encodeHexString(request.getRegionName(i).toStringUtf8().getBytes())); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA0 Region Key " + this.m_Region.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA0 Region Key " + this.m_Region.getRegionName().toString()); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA0 Region Key " + Hex.encodeHexString(ByteString.copyFrom(this.m_Region.getRegionName()).toString().getBytes())); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA1 Region Key " + Hex.encodeHexString(requestRegionName.getBytes())); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA2 Region Key " + Hex.encodeHexString(this.m_Region.getRegionNameAsString().getBytes())); if (LOG.isTraceEnabled()) LOG.trace("EPCP AA2 Region Key " + Hex.encodeHexString(this.m_Region.getRegionName())); if (requestRegionName.equals(ByteString.copyFrom(this.m_Region.getRegionName()).toString())) { if (LOG.isTraceEnabled()) { LOG.trace("EPCP BB0 Region Key matches !! " + request.getRegionName(i).toString()); } } if (Arrays.equals(request.getRegionName(i).toStringUtf8().getBytes(), this.m_Region.getRegionNameAsString().getBytes())) { if (LOG.isTraceEnabled()) { LOG.trace("EPCP BB1 Region Key matches !! " + request.getRegionName(i).toString()); } } if (request.getRegionName(i).toStringUtf8().equals(this.m_Region.getRegionNameAsString())) { if (LOG.isTraceEnabled()) { LOG.trace("EPCP BB2 Region Key matches !! " + request.getRegionName(i).toString()); } } */ commitRequestMultipleResponseBuilder.addException(BatchException.EXCEPTION_OK.toString()); try { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitRequestMultiple begins for region " + requestRegionName); TrxRegionEndpoint regionEPCP = (TrxRegionEndpoint) transactionsEPCPMap .get(requestRegionName + trxkeyEPCPinstance); if (regionEPCP == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitRequestMultiple region NOT FOUND in EPCP map " + requestRegionName); commitRequestMultipleResponseBuilder.setHasException(true); commitRequestMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_REGIONNOTFOUND_ERR.toString()); } else { if (i == (numOfRegion - 1)) { status = regionEPCP.commitRequest(transactionId, true); } // only the last region flush else { status = regionEPCP.commitRequest(transactionId, false); } } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint commitRequestMultiple ends"); //status = commitRequest(transactionId); } catch (UnknownTransactionException u) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequestMultiple - txId " + transactionId + ", Caught UnknownTransactionException after internal commitRequest call - " + u.toString()); ute = u; } catch (IOException e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequestMultiple - txId " + transactionId + ", Caught IOException after internal commitRequest call - " + e.toString()); ioe = e; } if (t != null) { commitRequestMultipleResponseBuilder.setHasException(true); commitRequestMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_SKIPREMAININGREGIONS_OK.toString()); } if (wre != null) { commitRequestMultipleResponseBuilder.setHasException(true); commitRequestMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_SKIPREMAININGREGIONS_OK.toString()); } if (ioe != null) { commitRequestMultipleResponseBuilder.setHasException(true); commitRequestMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_SKIPREMAININGREGIONS_OK.toString()); } if (ute != null) { commitRequestMultipleResponseBuilder.setHasException(true); commitRequestMultipleResponseBuilder.setException(i, BatchException.EXCEPTION_SKIPREMAININGREGIONS_OK.toString()); } commitRequestMultipleResponseBuilder.addResult(status); i++; // move to next region } // end of while-loop on all the regions in thecommitMultiple request CommitRequestMultipleResponse cresponse = commitRequestMultipleResponseBuilder.build(); done.run(cresponse); } @Override public void checkAndDelete(RpcController controller, CheckAndDeleteRequest request, RpcCallback<CheckAndDeleteResponse> done) { CheckAndDeleteResponse response = CheckAndDeleteResponse.getDefaultInstance(); byte[] rowArray = null; MutationProto proto = request.getDelete(); MutationType type = proto.getMutateType(); Delete delete = null; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; boolean result = false; long transactionId = request.getTransactionId(); java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name /* commenting it out for the time-being if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:checkAndDelete threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } */ org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndDeleteResponse.Builder checkAndDeleteResponseBuilder = CheckAndDeleteResponse .newBuilder(); if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: checkAndDelete - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndDelete - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); mue = new MemoryUsageException("checkAndDelete memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } if (mue == null && wre == null && type == MutationType.DELETE && proto.hasRow()) { try { delete = ProtobufUtil.toDelete(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndDelete - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } // Process in local memory if (delete != null && t == null) { if (request.hasRow()) { if (!Bytes.equals(proto.getRow().toByteArray(), request.getRow().toByteArray())) t = new org.apache.hadoop.hbase.DoNotRetryIOException( "Action's " + "Delete row must match the passed row"); } if (t == null) { try { result = checkAndDelete(transactionId, request.getRow().toByteArray(), request.getFamily().toByteArray(), request.getQualifier().toByteArray(), request.getValue().toByteArray(), delete); } catch (Throwable e) { if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: checkAndDelete - txId " + transactionId + ", Caught exception after internal checkAndDelete call - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } checkAndDeleteResponseBuilder.setResult(result); } } else { result = false; checkAndDeleteResponseBuilder.setResult(result); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndDelete - txId " + transactionId + ", result is " + result); checkAndDeleteResponseBuilder.setHasException(false); if (t != null) { checkAndDeleteResponseBuilder.setHasException(true); checkAndDeleteResponseBuilder.setException(t.toString()); } if (wre != null) { checkAndDeleteResponseBuilder.setHasException(true); checkAndDeleteResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndDelete - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); checkAndDeleteResponseBuilder.setHasException(true); checkAndDeleteResponseBuilder.setException(mue.toString()); } CheckAndDeleteResponse checkAndDeleteResponse = checkAndDeleteResponseBuilder.build(); done.run(checkAndDeleteResponse); } @Override public void checkAndPut(RpcController controller, CheckAndPutRequest request, RpcCallback<CheckAndPutResponse> done) { CheckAndPutResponse response = CheckAndPutResponse.getDefaultInstance(); byte[] rowArray = null; com.google.protobuf.ByteString row = null; com.google.protobuf.ByteString family = null; com.google.protobuf.ByteString qualifier = null; com.google.protobuf.ByteString value = null; MutationProto proto = request.getPut(); MutationType type = proto.getMutateType(); Put put = null; MemoryUsageException mue = null; WrongRegionException wre = null; Throwable t = null; boolean result = false; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:checkAndPut threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } */ org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CheckAndPutResponse.Builder checkAndPutResponseBuilder = CheckAndPutResponse .newBuilder(); if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: checkAndPut - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { mue = new MemoryUsageException("checkAndPut memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage exception"); } } if (mue == null && wre == null && type == MutationType.PUT && proto.hasRow()) { rowArray = proto.getRow().toByteArray(); try { put = ProtobufUtil.toPut(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } // Process in local memory if (put != null) { if (request.hasRow()) { row = request.getRow(); if (!Bytes.equals(rowArray, request.getRow().toByteArray())) t = new org.apache.hadoop.hbase.DoNotRetryIOException( "Action's " + "Put row must match the passed row"); } if (t == null) { if (request.hasRow()) row = request.getRow(); if (request.hasFamily()) family = request.getFamily(); if (request.hasQualifier()) qualifier = request.getQualifier(); if (request.hasValue()) value = request.getValue(); try { result = checkAndPut(transactionId, request.getRow().toByteArray(), request.getFamily().toByteArray(), request.getQualifier().toByteArray(), request.getValue().toByteArray(), put); } catch (Throwable e) { if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: checkAndPut - txId " + transactionId + ", Caught exception after internal checkAndPut call - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } checkAndPutResponseBuilder.setResult(result); } } else { result = false; checkAndPutResponseBuilder.setResult(result); } if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: checkAndPut - txId " + transactionId + ", result is " + result); checkAndPutResponseBuilder.setHasException(false); if (wre != null) { checkAndPutResponseBuilder.setHasException(true); checkAndPutResponseBuilder.setException(wre.toString()); } if (t != null) { checkAndPutResponseBuilder.setHasException(true); checkAndPutResponseBuilder.setException(t.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage exception"); checkAndPutResponseBuilder.setHasException(true); checkAndPutResponseBuilder.setException(mue.toString()); } CheckAndPutResponse checkAndPutResponse = checkAndPutResponseBuilder.build(); done.run(checkAndPutResponse); } @Override public void closeScanner(RpcController controller, CloseScannerRequest request, RpcCallback<CloseScannerResponse> done) { RegionScanner scanner = null; Throwable t = null; OutOfOrderProtocolException oop = null; WrongRegionException wre = null; Exception ce = null; long transId = request.getTransactionId(); long scannerId = request.getScannerId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner - txId " + transId + ", scanner id " + scannerId + ", regionName " + regionInfo.getRegionNameAsString()); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else { */ // There should be a matching key in the transactionsById map // associated with this transaction id. If there is not // one, then the initial openScanner call for the transaction // id was not called. This is a protocol error requiring // openScanner, performScan followed by a closeScanner. String key = getTransactionalUniqueId(transId); boolean keyFound = transactionsById.containsKey(key); if (keyFound != true) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner - Unknown transaction [" + transId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "], will create an OutOfOrderProtocol exception "); oop = new OutOfOrderProtocolException( "closeScanner does not have an active transaction with an open scanner, txId: " + transId); } if (oop == null) { try { scanner = removeScanner(scannerId); if (scanner != null) { scanner.close(); } else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner - txId " + transId + ", scanner was null for scanner id " + scannerId); /* try { scannerLeases.cancelLease(getScannerLeaseId(scannerId)); } catch (LeaseException le) { // ignore if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner failed to get a lease " + scannerId); } */ } catch (Exception e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner - txId " + transId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); ce = e; } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: closeScanner - txId " + transId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.CloseScannerResponse.Builder closeResponseBuilder = CloseScannerResponse .newBuilder(); closeResponseBuilder.setHasException(false); if (t != null) { closeResponseBuilder.setHasException(true); closeResponseBuilder.setException(t.toString()); } if (wre != null) { closeResponseBuilder.setHasException(true); closeResponseBuilder.setException(wre.toString()); } if (ce != null) { closeResponseBuilder.setHasException(true); closeResponseBuilder.setException(ce.toString()); } if (oop != null) { if (this.suppressOutOfOrderProtocolException == false) { closeResponseBuilder.setHasException(true); closeResponseBuilder.setException(oop.toString()); LOG.warn( "TrxRegionEndpoint coprocessor: closeScanner - OutOfOrderProtocolException, transaction was not found, txId: " + transId + ",returned exception" + ", regionName " + regionInfo.getRegionNameAsString()); } else LOG.warn( "TrxRegionEndpoint coprocessor: closeScanner - suppressing OutOfOrderProtocolException, transaction was not found, txId: " + transId + ", regionName " + regionInfo.getRegionNameAsString()); } CloseScannerResponse cresponse = closeResponseBuilder.build(); done.run(cresponse); } @Override public void deleteMultiple(RpcController controller, DeleteMultipleTransactionalRequest request, RpcCallback<DeleteMultipleTransactionalResponse> done) { DeleteMultipleTransactionalResponse response = DeleteMultipleTransactionalResponse.getDefaultInstance(); java.util.List<org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto> results; results = request.getDeleteList(); int resultCount = request.getDeleteCount(); byte[] row = null; Delete delete = null; MutationType type; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:deleteMultiple threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } */ if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: deleteMultiple - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: deleteMultiple - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage exception"); mue = new MemoryUsageException("deleteMultiple memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } if (mue == null && wre == null) { for (org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto proto : results) { delete = null; if (proto != null) { type = proto.getMutateType(); if (type == MutationType.DELETE && proto.hasRow()) { try { delete = ProtobufUtil.toDelete(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:deleteMultiple - txId " + transactionId + ", Caught exception after protobuf conversion delete" + e.getMessage() + " " + stackTraceToString(e)); t = e; } // Process in local memory if (delete != null) { try { delete(transactionId, delete); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:deleteMultiple - txId " + transactionId + ", Caught exception after internal delete - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: deleteMultiple - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", type " + type + ", row " + Bytes.toStringBinary(proto.getRow().toByteArray()) + ", row in hex " + Hex.encodeHexString(proto.getRow().toByteArray())); } } } else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: deleteMultiple - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", delete proto was null"); } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteMultipleTransactionalResponse.Builder deleteMultipleTransactionalResponseBuilder = DeleteMultipleTransactionalResponse .newBuilder(); deleteMultipleTransactionalResponseBuilder.setHasException(false); if (t != null) { deleteMultipleTransactionalResponseBuilder.setHasException(true); deleteMultipleTransactionalResponseBuilder.setException(t.toString()); } if (wre != null) { deleteMultipleTransactionalResponseBuilder.setHasException(true); deleteMultipleTransactionalResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: deleteMultiple - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); deleteMultipleTransactionalResponseBuilder.setHasException(true); deleteMultipleTransactionalResponseBuilder.setException(mue.toString()); } DeleteMultipleTransactionalResponse dresponse = deleteMultipleTransactionalResponseBuilder.build(); done.run(dresponse); } @Override public void delete(RpcController controller, DeleteTransactionalRequest request, RpcCallback<DeleteTransactionalResponse> done) { DeleteTransactionalResponse response = DeleteTransactionalResponse.getDefaultInstance(); byte[] row = null; MutationProto proto = request.getDelete(); MutationType type = proto.getMutateType(); Delete delete = null; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:delete threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } */ if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: delete - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: delete - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); mue = new MemoryUsageException("delete memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } else { try { delete = ProtobufUtil.toDelete(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:delete - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } // Process in local memory try { delete(transactionId, delete); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:delete - txId " + transactionId + ", Caught exception after internal delete - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: delete - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", type " + type + ", row " + Bytes.toStringBinary(proto.getRow().toByteArray()) + ", row in hex " + Hex.encodeHexString(proto.getRow().toByteArray())); } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.DeleteTransactionalResponse.Builder deleteTransactionalResponseBuilder = DeleteTransactionalResponse .newBuilder(); deleteTransactionalResponseBuilder.setHasException(false); if (t != null) { deleteTransactionalResponseBuilder.setHasException(true); deleteTransactionalResponseBuilder.setException(t.toString()); } if (wre != null) { deleteTransactionalResponseBuilder.setHasException(true); deleteTransactionalResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: delete - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); deleteTransactionalResponseBuilder.setHasException(true); deleteTransactionalResponseBuilder.setException(mue.toString()); } DeleteTransactionalResponse dresponse = deleteTransactionalResponseBuilder.build(); done.run(dresponse); } @Override public void get(RpcController controller, GetTransactionalRequest request, RpcCallback<GetTransactionalResponse> done) { GetTransactionalResponse response = GetTransactionalResponse.getDefaultInstance(); org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Get proto = request.getGet(); Get get = null; RegionScanner scanner = null; Throwable t = null; Exception ge = null; IOException gioe = null; MemoryUsageException mue = null; WrongRegionException wre = null; org.apache.hadoop.hbase.client.Result result2 = null; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:get threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else { */ if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) LOG.warn("TrxRegionEndpoint coprocessor: get - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage exception"); mue = new MemoryUsageException( "get memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } else { try { get = ProtobufUtil.toGet(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:get - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } Scan scan = new Scan(get); List<Cell> results = new ArrayList<Cell>(); try { if (LOG.isTraceEnabled()) { byte[] row = proto.getRow().toByteArray(); byte[] getrow = get.getRow(); String rowKey = Bytes.toString(row); String getRowKey = Bytes.toString(getrow); LOG.trace("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", Calling getScanner for regionName " + regionInfo.getRegionNameAsString() + ", row = " + Bytes.toStringBinary(row) + ", row in hex " + Hex.encodeHexString(row) + ", getrow = " + Bytes.toStringBinary(getrow) + ", getrow in hex " + Hex.encodeHexString(getrow)); } scanner = getScanner(transactionId, scan); if (scanner != null) scanner.next(results); result2 = Result.create(results); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", getScanner result2 isEmpty is " + result2.isEmpty() + ", row " + Bytes.toStringBinary(result2.getRow()) + " result length: " + result2.size()); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } finally { if (scanner != null) { try { scanner.close(); } catch (Exception e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); ge = e; } } } } // End of MemoryUsageCheck //} // End of WrongRegionCheck org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.GetTransactionalResponse.Builder getResponseBuilder = GetTransactionalResponse .newBuilder(); if (result2 != null) { getResponseBuilder.setResult(ProtobufUtil.toResult(result2)); } else { if (t == null && wre == null && ge == null) gioe = new IOException("TrxRegionEndpoint coprocessor: get - result2 was null"); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", result2 was null "); } getResponseBuilder.setHasException(false); if (t != null) { getResponseBuilder.setHasException(true); getResponseBuilder.setException(t.toString()); } if (wre != null) { getResponseBuilder.setHasException(true); getResponseBuilder.setException(wre.toString()); } if (ge != null) { getResponseBuilder.setHasException(true); getResponseBuilder.setException(ge.toString()); } if (gioe != null) { getResponseBuilder.setHasException(true); getResponseBuilder.setException(gioe.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage exception"); getResponseBuilder.setHasException(true); getResponseBuilder.setException(mue.toString()); } GetTransactionalResponse gresponse = getResponseBuilder.build(); done.run(gresponse); } @Override public void openScanner(RpcController controller, OpenScannerRequest request, RpcCallback<OpenScannerResponse> done) { boolean hasMore = true; RegionScanner scanner = null; RegionScanner scannert = null; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; boolean exceptionThrown = false; NullPointerException npe = null; Exception ge = null; IOException ioe = null; LeaseStillHeldException lse = null; Scan scan = null; long scannerId = 0L; boolean isLoadingCfsOnDemandSet = false; long transId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:openScanner threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); exceptionThrown = true; } else */ { if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: openScanner - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); exceptionThrown = true; mue = new MemoryUsageException("openScanner memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transId); } } else { try { scan = ProtobufUtil.toScan(request.getScan()); if (scan == null) if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", scan was null"); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; exceptionThrown = true; } if (!exceptionThrown) { if (scan == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", scan is null"); npe = new NullPointerException( "TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", scan is null "); ioe = new IOException("Invalid arguments to openScanner", npe); exceptionThrown = true; } else { try { scan.getAttribute(Scan.SCAN_ATTRIBUTES_METRICS_ENABLE); prepareScanner(scan); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", scan Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; exceptionThrown = true; } } } List<Cell> results = new ArrayList<Cell>(); if (!exceptionThrown) { try { scanner = getScanner(transId, scan); if (scanner != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", called getScanner, scanner is " + scanner); // Add the scanner to the map scannerId = addScanner(transId, scanner, this.m_Region); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", called addScanner, scanner id " + scannerId + ", regionName " + regionInfo.getRegionNameAsString()); } else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", getScanner returned null, scanner id " + scannerId + ", regionName " + regionInfo.getRegionNameAsString()); } catch (LeaseStillHeldException llse) { /* try { scannerLeases.cancelLease(getScannerLeaseId(scannerId)); } catch (LeaseException le) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScanner failed to get a lease " + scannerId); } */ LOG.error("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", getScanner Error opening scanner, " + llse.toString()); exceptionThrown = true; lse = llse; } catch (IOException e) { LOG.error("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", getScanner Error opening scanner, " + e.toString()); exceptionThrown = true; } } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - txId " + transId + ", scanner id " + scannerId + ", regionName " + regionInfo.getRegionNameAsString()); } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.OpenScannerResponse.Builder openResponseBuilder = OpenScannerResponse .newBuilder(); openResponseBuilder.setScannerId(scannerId); openResponseBuilder.setHasException(false); if (t != null) { openResponseBuilder.setHasException(true); openResponseBuilder.setException(t.toString()); } if (wre != null) { openResponseBuilder.setHasException(true); openResponseBuilder.setException(wre.toString()); } if (ioe != null) { openResponseBuilder.setHasException(true); openResponseBuilder.setException(ioe.toString()); } if (lse != null) { openResponseBuilder.setHasException(true); openResponseBuilder.setException(lse.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: openScanner - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); openResponseBuilder.setHasException(true); openResponseBuilder.setException(mue.toString()); } OpenScannerResponse oresponse = openResponseBuilder.build(); done.run(oresponse); } @Override public void performScan(RpcController controller, PerformScanRequest request, RpcCallback<PerformScanResponse> done) { boolean hasMore = true; RegionScanner scanner = null; Throwable t = null; ScannerTimeoutException ste = null; OutOfOrderProtocolException oop = null; OutOfOrderScannerNextException ooo = null; UnknownScannerException use = null; MemoryUsageException mue = null; WrongRegionException wre = null; Exception ne = null; Scan scan = null; List<Cell> cellResults = new ArrayList<Cell>(); List<Result> results = new ArrayList<Result>(); org.apache.hadoop.hbase.client.Result result = null; long scannerId = request.getScannerId(); long transId = request.getTransactionId(); int numberOfRows = request.getNumberOfRows(); boolean closeScanner = request.getCloseScanner(); long nextCallSeq = request.getNextCallSeq(); long count = 0L; boolean shouldContinue = true; TransactionalRegionScannerHolder rsh = null; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + ", numberOfRows " + numberOfRows + ", nextCallSeq " + nextCallSeq + ", closeScanner is " + closeScanner + ", region is " + regionInfo.getRegionNameAsString()); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:performScan threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: performScan - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); mue = new MemoryUsageException("performScan memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transId); } } else { // There should be a matching key in the transactionsById map // associated with this transaction id. If there is not // one, then the initial openScanner call for the transaction // id was not called. This is a protocol error requiring // openScanner, performScan followed by a closeScanner. String key = getTransactionalUniqueId(transId); boolean keyFound = transactionsById.containsKey(key); if (keyFound != true) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - Unknown transaction [" + transId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "], will create an OutOfOrderProtocol exception "); oop = new OutOfOrderProtocolException( "performScan does not have an active transaction with an open scanner, txId: " + transId); } if (oop == null) { try { scanner = getScanner(scannerId, nextCallSeq); if (scanner != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + ", scanner is not null"); while (shouldContinue) { hasMore = scanner.next(cellResults); result = Result.create(cellResults); cellResults.clear(); if (!result.isEmpty()) { results.add(result); count++; } if (count == numberOfRows || !hasMore) shouldContinue = false; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + ", count is " + count + ", hasMore is " + hasMore + ", result " + result.isEmpty()); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + transId + ", scanner is null"); } } catch (OutOfOrderScannerNextException ooone) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + " Caught OutOfOrderScannerNextException " + ooone.getMessage() + " " + stackTraceToString(ooone)); ooo = ooone; } catch (ScannerTimeoutException cste) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + " Caught ScannerTimeoutException " + cste.getMessage() + " " + stackTraceToString(cste)); ste = cste; } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + " Caught throwable exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } finally { if (scanner != null) { try { if (closeScanner) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + ", close scanner was true, closing the scanner" + ", closeScanner is " + closeScanner + ", region is " + regionInfo.getRegionNameAsString()); removeScanner(scannerId); scanner.close(); /* try { scannerLeases.cancelLease(getScannerLeaseId(scannerId)); } catch (LeaseException le) { // ignore if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan failed to get a lease " + scannerId); } */ } } catch (Exception e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - transaction id " + transId + ", Caught general exception " + e.getMessage() + " " + stackTraceToString(e)); ne = e; } } } rsh = scanners.get(scannerId); nextCallSeq++; if (rsh == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan rsh is null"); use = new UnknownScannerException("ScannerId: " + scannerId + ", already closed?"); } else { rsh.nextCallSeq = nextCallSeq; if (rsh == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", performScan rsh is null, UnknownScannerException for scannerId: " + scannerId + ", nextCallSeq was " + nextCallSeq + ", for region " + regionInfo.getRegionNameAsString()); use = new UnknownScannerException( "ScannerId: " + scannerId + ", was scanner already closed?, transaction id " + transId + ", nextCallSeq was " + nextCallSeq + ", for region " + regionInfo.getRegionNameAsString()); } else { rsh.nextCallSeq = nextCallSeq; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - txId " + transId + ", scanner id " + scannerId + ", regionName " + regionInfo.getRegionNameAsString() + ", nextCallSeq " + nextCallSeq + ", rsh.nextCallSeq " + rsh.nextCallSeq + ", close scanner is " + closeScanner); } } } } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PerformScanResponse.Builder performResponseBuilder = PerformScanResponse .newBuilder(); performResponseBuilder.setHasMore(hasMore); performResponseBuilder.setNextCallSeq(nextCallSeq); performResponseBuilder.setCount(count); performResponseBuilder.setHasException(false); if (results != null) { if (!results.isEmpty()) { for (Result r : results) { performResponseBuilder.addResult(ProtobufUtil.toResult(r)); } } } if (t != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(t.toString()); } if (ste != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(ste.toString()); } if (wre != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(wre.toString()); } if (ne != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(ne.toString()); } if (ooo != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(ooo.toString()); } if (use != null) { performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(use.toString()); } if (oop != null) { performResponseBuilder.setHasMore(false); if (this.suppressOutOfOrderProtocolException == false) { performResponseBuilder.setHasException(true); performResponseBuilder.setException(oop.toString()); LOG.warn( "TrxRegionEndpoint coprocessor: performScan - OutOfOrderProtocolException, transaction was not found, txId: " + transId + ", return exception" + ", regionName " + regionInfo.getRegionNameAsString()); } else LOG.warn( "TrxRegionEndpoint coprocessor: performScan - suppressing OutOfOrderProtocolException, transaction was not found, txId: " + transId + ", regionName " + regionInfo.getRegionNameAsString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: performScan - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); performResponseBuilder.setHasMore(false); performResponseBuilder.setHasException(true); performResponseBuilder.setException(mue.toString()); } PerformScanResponse presponse = performResponseBuilder.build(); done.run(presponse); } @Override public void put(RpcController controller, PutTransactionalRequest request, RpcCallback<PutTransactionalResponse> done) { PutTransactionalResponse response = PutTransactionalResponse.getDefaultInstance(); byte[] row = null; MutationProto proto = request.getPut(); MutationType type = proto.getMutateType(); Put put = null; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:put threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: put - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: put - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage exception"); mue = new MemoryUsageException( "put memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } else { try { put = ProtobufUtil.toPut(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:put - txId " + transactionId + ", Caught exception " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (mue == null && type == MutationType.PUT && proto.hasRow()) { // Process in local memory try { put(transactionId, put); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:put - txId " + transactionId + ", Caught exception after internal put - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: put - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", type " + type + ", row " + Bytes.toStringBinary(proto.getRow().toByteArray()) + ", row in hex " + Hex.encodeHexString(proto.getRow().toByteArray())); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: put - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + "- no valid PUT type or does not contain a row"); } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutTransactionalResponse.Builder putTransactionalResponseBuilder = PutTransactionalResponse .newBuilder(); putTransactionalResponseBuilder.setHasException(false); if (t != null) { putTransactionalResponseBuilder.setHasException(true); putTransactionalResponseBuilder.setException(t.toString()); } if (wre != null) { putTransactionalResponseBuilder.setHasException(true); putTransactionalResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: put - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage exception"); putTransactionalResponseBuilder.setHasException(true); putTransactionalResponseBuilder.setException(mue.toString()); } PutTransactionalResponse presponse = putTransactionalResponseBuilder.build(); done.run(presponse); } @Override public void putMultiple(RpcController controller, PutMultipleTransactionalRequest request, RpcCallback<PutMultipleTransactionalResponse> done) { PutMultipleTransactionalResponse response = PutMultipleTransactionalResponse.getDefaultInstance(); java.util.List<org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto> results; results = request.getPutList(); int resultCount = request.getPutCount(); byte[] row = null; Put put = null; MutationType type; Throwable t = null; MemoryUsageException mue = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:putMultiple threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } else */ { if (memoryThrottle == true) { if (memoryUsageWarnOnly == true) { LOG.warn("TrxRegionEndpoint coprocessor: putMultiple - performing memoryPercentage " + memoryPercentage + ", warning memory usage exceeds indicated percentage"); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: putMultiple - performing memoryPercentage " + memoryPercentage + ", generating memory usage exceeds indicated percentage"); mue = new MemoryUsageException("putMultiple memory usage exceeds " + memoryUsageThreshold + " percent, trxId is " + transactionId); } } else { for (org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto proto : results) { put = null; if (proto != null) { type = proto.getMutateType(); if (type == MutationType.PUT && proto.hasRow()) { try { put = ProtobufUtil.toPut(proto); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:putMultiple - txId " + transactionId + ", Caught exception after protobuf conversion put" + e.getMessage() + " " + stackTraceToString(e)); t = e; } // Process in local memory if (put != null) { try { put(transactionId, put); } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:putMultiple - txId " + transactionId + ", Caught exception after internal put - " + e.getMessage() + " " + stackTraceToString(e)); t = e; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: putMultiple - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", type " + type + ", row " + Bytes.toStringBinary(proto.getRow().toByteArray()) + ", row in hex " + Hex.encodeHexString(proto.getRow().toByteArray())); } } } else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: putMultiple - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", put proto was null"); } } } org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.PutMultipleTransactionalResponse.Builder putMultipleTransactionalResponseBuilder = PutMultipleTransactionalResponse .newBuilder(); putMultipleTransactionalResponseBuilder.setHasException(false); if (t != null) { putMultipleTransactionalResponseBuilder.setHasException(true); putMultipleTransactionalResponseBuilder.setException(t.toString()); } if (wre != null) { putMultipleTransactionalResponseBuilder.setHasException(true); putMultipleTransactionalResponseBuilder.setException(wre.toString()); } if (mue != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: putMultiple - performing memoryPercentage " + memoryPercentage + ", posting memory usage exceeds indicated percentage"); putMultipleTransactionalResponseBuilder.setHasException(true); putMultipleTransactionalResponseBuilder.setException(mue.toString()); } PutMultipleTransactionalResponse pmresponse = putMultipleTransactionalResponseBuilder.build(); done.run(pmresponse); } @Override public void recoveryRequest(RpcController controller, RecoveryRequestRequest request, RpcCallback<RecoveryRequestResponse> done) { int tmId = request.getTmId(); Throwable t = null; WrongRegionException wre = null; long transactionId = request.getTransactionId(); if (reconstructIndoubts == 0) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: recoveryRequest - txId " + transactionId + ", RECOV"); constructIndoubtTransactions(); } // Placeholder for real work when recovery is added if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: recoveryRequest - txId " + transactionId + ", regionName " + regionInfo.getRegionNameAsString() + ", tmId" + tmId); /* commenting it out for the time-being java.lang.String name = ((com.google.protobuf.ByteString) request.getRegionName()).toStringUtf8(); // First test if this region matches our region name if (!name.equals(regionInfo.getRegionNameAsString())) { wre = new WrongRegionException("Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:recoveryResponse threw WrongRegionException" + "Request Region Name, " + name + ", does not match this region, " + regionInfo.getRegionNameAsString()); } */ org.apache.hadoop.hbase.coprocessor.transactional.generated.TrxRegionProtos.RecoveryRequestResponse.Builder recoveryResponseBuilder = RecoveryRequestResponse .newBuilder(); List<Long> indoubtTransactions = new ArrayList<Long>(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: recoveryRequest Trafodion Recovery: region " + regionInfo.getEncodedName() + " receives recovery request from TM " + tmId + " with region state " + regionState); switch (regionState) { case REGION_STATE_RECOVERING: // RECOVERING, already create a list of in-doubt txn, but still in the state of resolving them, // retrieve all in-doubt txn from rmid and return them into a long a if (LOG.isInfoEnabled()) LOG.info("TRAF RCOV:recoveryRequest in region starting" + regionInfo.getEncodedName() + " has in-doubt transaction " + indoubtTransactionsById.size()); for (Entry<Long, List<WALEdit>> entry : indoubtTransactionsById.entrySet()) { long tid = entry.getKey(); if ((int) (tid >> 32) == tmId) { indoubtTransactions.add(tid); if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: recoveryRequest - txId " + transactionId + ", Trafodion Recovery: region " + regionInfo.getEncodedName() + " in-doubt transaction " + tid + " has been added into the recovery reply to TM " + tmId + " during recovery "); } } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: recoveryRequest " + indoubtTransactions.size()); if (indoubtTransactions.size() == 0) { String lv_encoded = m_Region.getRegionInfo().getEncodedName(); try { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: recoveryRequest - Trafodion Recovery: delete recovery zNode TM " + tmId + " region encoded name " + lv_encoded + " for 0 in-doubt transaction"); deleteRecoveryzNode(tmId, lv_encoded); } catch (IOException e) { LOG.error( "TrxRegionEndpoint coprocessor: recoveryRequest - Trafodion Recovery: delete recovery zNode failed"); } } break; case REGION_STATE_START: // START List<TrxTransactionState> commitPendingCopy = new ArrayList<TrxTransactionState>( commitPendingTransactions); if (LOG.isInfoEnabled()) LOG.info("TRAF RCOV:recoveryRequest in region started" + regionInfo.getEncodedName() + " has in-doubt transaction " + commitPendingCopy.size()); for (TrxTransactionState commitPendingTS : commitPendingCopy) { long tid = commitPendingTS.getTransactionId(); if ((int) (tid >> 32) == tmId) { indoubtTransactions.add(tid); if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: recoveryRequest - Trafodion Recovery: region " + regionInfo.getEncodedName() + " in-doubt transaction " + tid + " has been added into the recovery reply to TM " + tmId + " during start "); } } // now remove the ZK node after TM has initiated the ecovery request String lv_encoded = m_Region.getRegionInfo().getEncodedName(); try { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: recoveryRequest - Trafodion Recovery: delete recovery zNode TM " + tmId + " region encoded name " + lv_encoded + " for 0 in-doubt transaction"); deleteRecoveryzNode(tmId, lv_encoded); } catch (IOException e) { LOG.error( "TrxRegionEndpoint coprocessor: recoveryRequest - Trafodion Recovery: delete recovery zNode failed"); } break; default: LOG.error("Trafodion Recovery: encounter incorrect region state " + regionState); break; } // Placeholder response forced to zero for now for (Long transactionInDoubtId : indoubtTransactions) { recoveryResponseBuilder.addResult(transactionInDoubtId); } // Placeholder response forced to zero for now recoveryResponseBuilder.setHasException(false); if (t != null) { recoveryResponseBuilder.setHasException(true); recoveryResponseBuilder.setException(t.toString()); } if (wre != null) { recoveryResponseBuilder.setHasException(true); recoveryResponseBuilder.setException(wre.toString()); } RecoveryRequestResponse rresponse = recoveryResponseBuilder.build(); done.run(rresponse); } /** * Gives the maximum for a given combination of column qualifier and column * family, in the given row range as defined in the Scan object. In its * current implementation, it takes one column family and one column qualifier * (if provided). In case of null column qualifier, maximum value for the * entire column family will be returned. */ @Override public void getMax(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { RegionScanner scanner = null; TransactionalAggregateResponse response = null; long transactionId = request.getTransactionId(); T max = null; try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); T temp; Scan scan = ProtobufUtil.toScan(request.getScan()); scanner = getScanner(transactionId, scan); List<Cell> results = new ArrayList<Cell>(); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } // qualifier can be null. boolean hasMoreRows = false; do { hasMoreRows = scanner.next(results); for (Cell kv : results) { temp = ci.getValue(colFamily, qualifier, kv); max = (max == null || (temp != null && ci.compare(temp, max) > 0)) ? temp : max; } results.clear(); } while (hasMoreRows); if (max != null) { TransactionalAggregateResponse.Builder builder = TransactionalAggregateResponse.newBuilder(); builder.addFirstPart(ci.getProtoForCellType(max).toByteString()); response = builder.build(); } } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: getMax - txId " + transactionId + ", Maximum from this region is " + env.getRegion().getRegionNameAsString() + ": " + max); done.run(response); } /** * Gives the minimum for a given combination of column qualifier and column * family, in the given row range as defined in the Scan object. In its * current implementation, it takes one column family and one column qualifier * (if provided). In case of null column qualifier, minimum value for the * entire column family will be returned. */ @Override public void getMin(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { TransactionalAggregateResponse response = null; RegionScanner scanner = null; long transactionId = request.getTransactionId(); T min = null; try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); T temp; Scan scan = ProtobufUtil.toScan(request.getScan()); scanner = getScanner(transactionId, scan); List<Cell> results = new ArrayList<Cell>(); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } boolean hasMoreRows = false; do { hasMoreRows = scanner.next(results); for (Cell kv : results) { temp = ci.getValue(colFamily, qualifier, kv); min = (min == null || (temp != null && ci.compare(temp, min) < 0)) ? temp : min; } results.clear(); } while (hasMoreRows); if (min != null) { response = TransactionalAggregateResponse.newBuilder() .addFirstPart(ci.getProtoForCellType(min).toByteString()).build(); } } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } if (LOG.isInfoEnabled()) LOG.info("TrxRegionEndpoint coprocessor: getMin - txId " + transactionId + ", Minimum from this region is " + env.getRegion().getRegionNameAsString() + ": " + min); done.run(response); } /** * Gives the sum for a given combination of column qualifier and column * family, in the given row range as defined in the Scan object. In its * current implementation, it takes one column family and one column qualifier * (if provided). In case of null column qualifier, sum for the entire column * family will be returned. */ @Override public void getSum(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { TransactionalAggregateResponse response = null; RegionScanner scanner = null; long sum = 0l; long transactionId = request.getTransactionId(); try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); S sumVal = null; T temp; Scan scan = ProtobufUtil.toScan(request.getScan()); scanner = getScanner(transactionId, scan); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } List<Cell> results = new ArrayList<Cell>(); boolean hasMoreRows = false; do { hasMoreRows = scanner.next(results); for (Cell kv : results) { temp = ci.getValue(colFamily, qualifier, kv); if (temp != null) sumVal = ci.add(sumVal, ci.castToReturnType(temp)); } results.clear(); } while (hasMoreRows); if (sumVal != null) { response = TransactionalAggregateResponse.newBuilder() .addFirstPart(ci.getProtoForPromotedType(sumVal).toByteString()).build(); } } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getSum - txId " + transactionId + ", Sum from this region is " + env.getRegion().getRegionNameAsString() + ": " + sum); done.run(response); } /** * Gives the row count for the given column family and column qualifier, in * the given row range as defined in the Scan object. * @throws IOException */ @Override public void getRowNum(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { TransactionalAggregateResponse response = null; long counter = 0L; List<Cell> results = new ArrayList<Cell>(); RegionScanner scanner = null; long transactionId = 0L; try { Scan scan = ProtobufUtil.toScan(request.getScan()); byte[][] colFamilies = scan.getFamilies(); byte[] colFamily = colFamilies != null ? colFamilies[0] : null; NavigableSet<byte[]> qualifiers = colFamilies != null ? scan.getFamilyMap().get(colFamily) : null; byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } if (scan.getFilter() == null && qualifier == null) scan.setFilter(new FirstKeyOnlyFilter()); transactionId = request.getTransactionId(); scanner = getScanner(transactionId, scan); boolean hasMoreRows = false; do { hasMoreRows = scanner.next(results); if (results.size() > 0) { counter++; } results.clear(); } while (hasMoreRows); ByteBuffer bb = ByteBuffer.allocate(8).putLong(counter); bb.rewind(); response = TransactionalAggregateResponse.newBuilder().addFirstPart(ByteString.copyFrom(bb)).build(); } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } if (LOG.isInfoEnabled()) LOG.info(String.format( "Row counter for txId %d from this region: %s is %d, startKey is [%s], endKey is [%s]", transactionId, env.getRegion().getRegionNameAsString(), counter, env.getRegion().getStartKey() == null ? "null" : Bytes.toStringBinary(env.getRegion().getStartKey()), env.getRegion().getEndKey() == null ? "null" : Bytes.toStringBinary(env.getRegion().getEndKey()))); done.run(response); } /** * Gives a Pair with first object as Sum and second object as row count, * computed for a given combination of column qualifier and column family in * the given row range as defined in the Scan object. In its current * implementation, it takes one column family and one column qualifier (if * provided). In case of null column qualifier, an aggregate sum over all the * entire column family will be returned. * <p> * The average is computed in * AggregationClient#avg(byte[], ColumnInterpreter, Scan) by * processing results from all regions, so its "ok" to pass sum and a Long * type. */ @Override public void getAvg(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { TransactionalAggregateResponse response = null; RegionScanner scanner = null; try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); S sumVal = null; Long rowCountVal = 0l; Scan scan = ProtobufUtil.toScan(request.getScan()); long transactionId = request.getTransactionId(); scanner = getScanner(transactionId, scan); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } List<Cell> results = new ArrayList<Cell>(); boolean hasMoreRows = false; do { results.clear(); hasMoreRows = scanner.next(results); for (Cell kv : results) { sumVal = ci.add(sumVal, ci.castToReturnType(ci.getValue(colFamily, qualifier, kv))); } rowCountVal++; } while (hasMoreRows); if (sumVal != null) { ByteString first = ci.getProtoForPromotedType(sumVal).toByteString(); TransactionalAggregateResponse.Builder pair = TransactionalAggregateResponse.newBuilder(); pair.addFirstPart(first); ByteBuffer bb = ByteBuffer.allocate(8).putLong(rowCountVal); bb.rewind(); pair.setSecondPart(ByteString.copyFrom(bb)); response = pair.build(); } } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } done.run(response); } /** * Gives a Pair with first object a List containing Sum and sum of squares, * and the second object as row count. It is computed for a given combination of * column qualifier and column family in the given row range as defined in the * Scan object. In its current implementation, it takes one column family and * one column qualifier (if provided). The idea is get the value of variance first: * the average of the squares less the square of the average a standard * deviation is square root of variance. */ @Override public void getStd(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { RegionScanner scanner = null; TransactionalAggregateResponse response = null; try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); S sumVal = null, sumSqVal = null, tempVal = null; long rowCountVal = 0l; Scan scan = ProtobufUtil.toScan(request.getScan()); long transactionId = request.getTransactionId(); scanner = getScanner(transactionId, scan); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] qualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { qualifier = qualifiers.pollFirst(); } List<Cell> results = new ArrayList<Cell>(); boolean hasMoreRows = false; do { tempVal = null; hasMoreRows = scanner.next(results); for (Cell kv : results) { tempVal = ci.add(tempVal, ci.castToReturnType(ci.getValue(colFamily, qualifier, kv))); } results.clear(); sumVal = ci.add(sumVal, tempVal); sumSqVal = ci.add(sumSqVal, ci.multiply(tempVal, tempVal)); rowCountVal++; } while (hasMoreRows); if (sumVal != null) { ByteString first_sumVal = ci.getProtoForPromotedType(sumVal).toByteString(); ByteString first_sumSqVal = ci.getProtoForPromotedType(sumSqVal).toByteString(); TransactionalAggregateResponse.Builder pair = TransactionalAggregateResponse.newBuilder(); pair.addFirstPart(first_sumVal); pair.addFirstPart(first_sumSqVal); ByteBuffer bb = ByteBuffer.allocate(8).putLong(rowCountVal); bb.rewind(); pair.setSecondPart(ByteString.copyFrom(bb)); response = pair.build(); } } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } done.run(response); } /** * Gives a List containing sum of values and sum of weights. * It is computed for the combination of column * family and column qualifier(s) in the given row range as defined in the * Scan object. In its current implementation, it takes one column family and * two column qualifiers. The first qualifier is for values column and * the second qualifier (optional) is for weight column. */ @Override public void getMedian(RpcController controller, TransactionalAggregateRequest request, RpcCallback<TransactionalAggregateResponse> done) { TransactionalAggregateResponse response = null; RegionScanner scanner = null; try { ColumnInterpreter<T, S, P, Q, R> ci = constructColumnInterpreterFromRequest(request); S sumVal = null, sumWeights = null, tempVal = null, tempWeight = null; Scan scan = ProtobufUtil.toScan(request.getScan()); long transactionId = request.getTransactionId(); scanner = getScanner(transactionId, scan); byte[] colFamily = scan.getFamilies()[0]; NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(colFamily); byte[] valQualifier = null, weightQualifier = null; if (qualifiers != null && !qualifiers.isEmpty()) { valQualifier = qualifiers.pollFirst(); // if weighted median is requested, get qualifier for the weight column weightQualifier = qualifiers.pollLast(); } List<Cell> results = new ArrayList<Cell>(); boolean hasMoreRows = false; do { tempVal = null; tempWeight = null; hasMoreRows = scanner.next(results); for (Cell kv : results) { tempVal = ci.add(tempVal, ci.castToReturnType(ci.getValue(colFamily, valQualifier, kv))); if (weightQualifier != null) { tempWeight = ci.add(tempWeight, ci.castToReturnType(ci.getValue(colFamily, weightQualifier, kv))); } } results.clear(); sumVal = ci.add(sumVal, tempVal); sumWeights = ci.add(sumWeights, tempWeight); } while (hasMoreRows); ByteString first_sumVal = ci.getProtoForPromotedType(sumVal).toByteString(); S s = sumWeights == null ? ci.castToReturnType(ci.getMinValue()) : sumWeights; ByteString first_sumWeights = ci.getProtoForPromotedType(s).toByteString(); TransactionalAggregateResponse.Builder pair = TransactionalAggregateResponse.newBuilder(); pair.addFirstPart(first_sumVal); pair.addFirstPart(first_sumWeights); response = pair.build(); } catch (IOException e) { ResponseConverter.setControllerException(controller, e); } finally { if (scanner != null) { try { scanner.close(); } catch (IOException ignored) { } } } done.run(response); } @SuppressWarnings("unchecked") ColumnInterpreter<T, S, P, Q, R> constructColumnInterpreterFromRequest(TransactionalAggregateRequest request) throws IOException { String className = request.getInterpreterClassName(); Class<?> cls; try { cls = Class.forName(className); ColumnInterpreter<T, S, P, Q, R> ci = (ColumnInterpreter<T, S, P, Q, R>) cls.newInstance(); if (request.hasInterpreterSpecificBytes()) { ByteString b = request.getInterpreterSpecificBytes(); P initMsg = ProtobufUtil.getParsedGenericInstance(ci.getClass(), 2, b); ci.initialize(initMsg); } return ci; } catch (ClassNotFoundException e) { throw new IOException(e); } catch (InstantiationException e) { throw new IOException(e); } catch (IllegalAccessException e) { throw new IOException(e); } } @Override public Service getService() { return this; } /** * Stores a reference to the coprocessor environment provided by the * {@link org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost} * from the region where this coprocessor is loaded. * Since this is a coprocessor endpoint, it always expects to be loaded * on a table region, so always expects this to be an instance of * {@link RegionCoprocessorEnvironment}. * @param env the environment provided by the coprocessor host * @throws IOException if the provided environment is not an instance of * {@code RegionCoprocessorEnvironment} */ @Override public void start(CoprocessorEnvironment env) throws IOException { if (env instanceof RegionCoprocessorEnvironment) { this.env = (RegionCoprocessorEnvironment) env; } else { throw new CoprocessorException( "TrxRegionEndpoint coprocessor: start - Must be loaded on a table region!"); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: start"); RegionCoprocessorEnvironment tmp_env = (RegionCoprocessorEnvironment) env; this.m_Region = tmp_env.getRegion(); this.regionInfo = this.m_Region.getRegionInfo(); this.t_Region = (TransactionalRegion) tmp_env.getRegion(); this.fs = this.m_Region.getFilesystem(); org.apache.hadoop.conf.Configuration conf = tmp_env.getConfiguration(); synchronized (stoppableLock) { try { this.transactionLeaseTimeout = conf.getInt(LEASE_CONF, MINIMUM_LEASE_TIME); if (this.transactionLeaseTimeout < MINIMUM_LEASE_TIME) { if (LOG.isWarnEnabled()) LOG.warn("Transaction lease time: " + this.transactionLeaseTimeout + ", was less than the minimum lease time. Now setting the timeout to the minimum default value: " + MINIMUM_LEASE_TIME); this.transactionLeaseTimeout = MINIMUM_LEASE_TIME; } this.scannerLeaseTimeoutPeriod = HBaseConfiguration.getInt(conf, HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, HConstants.DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD); this.scannerThreadWakeFrequency = conf.getInt(HConstants.THREAD_WAKE_FREQUENCY, 10 * 1000); this.cleanTimer = conf.getInt(SLEEP_CONF, DEFAULT_SLEEP); this.memoryUsageThreshold = conf.getInt(MEMORY_THRESHOLD, DEFAULT_MEMORY_THRESHOLD); this.memoryUsagePerformGC = conf.getBoolean(MEMORY_PERFORM_GC, DEFAULT_MEMORY_PERFORM_GC); this.memoryUsageWarnOnly = conf.getBoolean(MEMORY_WARN_ONLY, DEFAULT_MEMORY_WARN_ONLY); this.memoryUsageTimer = conf.getInt(MEMORY_CONF, DEFAULT_MEMORY_SLEEP); this.memoryUsageTimer = conf.getInt(MEMORY_CONF, DEFAULT_MEMORY_SLEEP); this.suppressOutOfOrderProtocolException = conf.getBoolean(SUPPRESS_OOP, DEFAULT_SUPPRESS_OOP); if (this.transactionLeases == null) this.transactionLeases = new Leases(LEASE_CHECK_FREQUENCY); //if (this.scannerLeases == null) // this.scannerLeases = new Leases(scannerThreadWakeFrequency); if (LOG.isTraceEnabled()) LOG.trace("Transaction lease time: " + this.transactionLeaseTimeout + " Scanner lease time: " + this.scannerThreadWakeFrequency + ", Scanner lease timeout period: " + this.scannerLeaseTimeoutPeriod + ", Clean timer: " + this.cleanTimer + ", MemoryUsage timer: " + this.memoryUsageTimer + ", MemoryUsageThreshold: " + this.memoryUsageThreshold + ", MemoryUsagePerformGC: " + this.memoryUsagePerformGC + ", MemoryUsageWarnOnly: " + this.memoryUsageWarnOnly + ", Suppress OutOfOrderProtocolException: " + this.suppressOutOfOrderProtocolException); // Start the clean core thread this.cleanOldTransactionsThread = new CleanOldTransactionsChore(this, cleanTimer, stoppable); UncaughtExceptionHandler handler = new UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { LOG.fatal("CleanOldTransactionChore uncaughtException: " + t.getName(), e); } }; String n = Thread.currentThread().getName(); ChoreThread = new Thread(this.cleanOldTransactionsThread); Threads.setDaemonThreadRunning(ChoreThread, n + ".oldTransactionCleaner", handler); // Start the memory usage chore thread if the threshold // selected is greater than the default of 100%. if (memoryUsageThreshold < DEFAULT_MEMORY_THRESHOLD && memoryUsageThread == null) { LOG.warn("TrxRegionEndpoint coprocessor: start - starting memoryUsageThread"); memoryUsageThread = new MemoryUsageChore(this, memoryUsageTimer, stoppable2); UncaughtExceptionHandler handler2 = new UncaughtExceptionHandler() { public void uncaughtException(final Thread t, final Throwable e) { LOG.fatal("MemoryUsageChore uncaughtException: " + t.getName(), e); } }; String n2 = Thread.currentThread().getName(); ChoreThread2 = new Thread(memoryUsageThread); Threads.setDaemonThreadRunning(ChoreThread2, n2 + ".memoryUsage", handler2); } if (TransactionalLeasesThread == null) { TransactionalLeasesThread = new Thread(this.transactionLeases); if (TransactionalLeasesThread != null) { Threads.setDaemonThreadRunning(TransactionalLeasesThread, "Transactional leases"); } } /* if (ScannerLeasesThread == null) { ScannerLeasesThread = new Thread(this.scannerLeases); if (ScannerLeasesThread != null) { Threads.setDaemonThreadRunning(ScannerLeasesThread, "Scanner leases"); } } */ } catch (Exception e) { throw new CoprocessorException("TrxRegionEndpoint coprocessor: start - Caught exception " + e); } } this.t_Region = (TransactionalRegion) tmp_env.getRegion(); this.fs = this.m_Region.getFilesystem(); tHLog = this.m_Region.getLog(); RegionServerServices rss = tmp_env.getRegionServerServices(); ServerName sn = rss.getServerName(); lv_hostName = sn.getHostname(); lv_port = sn.getPort(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: hostname " + lv_hostName + " port " + lv_port); this.regionInfo = this.m_Region.getRegionInfo(); this.nextLogSequenceId = this.m_Region.getSequenceId(); this.t_Region = (TransactionalRegion) tmp_env.getRegion(); zkw1 = rss.getZooKeeper(); this.configuredEarlyLogging = tmp_env.getConfiguration() .getBoolean("hbase.regionserver.region.transactional.earlylogging", false); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: early logging setting is " + this.configuredEarlyLogging + "\nTrxRegionEndpoint coprocessor: get the reference from Region CoprocessorEnvironment "); this.configuredConflictReinstate = tmp_env.getConfiguration() .getBoolean("hbase.regionserver.region.transactional.conflictreinstate", false); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: conflict reinstate setting is " + this.configuredConflictReinstate + "\nTrxRegionEndpoint coprocessor: get the reference from Region CoprocessorEnvironment "); if (tmp_env.getSharedData().isEmpty()) if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: shared map is empty "); else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: shared map is NOT empty"); transactionsEPCPMap.put(this.m_Region.getRegionNameAsString() + trxkeyEPCPinstance, this); transactionsByIdTestz = TrxRegionObserver.getRefMap(); if (transactionsByIdTestz.isEmpty()) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: reference map is empty "); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: reference map is NOT empty "); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Region " + this.m_Region.getRegionNameAsString() + " check indoubt list from reference map "); Map<Long, List<WALEdit>> indoubtTransactionsByIdCheck = (TreeMap<Long, List<WALEdit>>) transactionsByIdTestz .get(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeypendingTransactionsById); if (indoubtTransactionsByIdCheck != null) { this.indoubtTransactionsById = indoubtTransactionsByIdCheck; } else { transactionsByIdTestz.put( this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeypendingTransactionsById, this.indoubtTransactionsById); } Map<Integer, Integer> indoubtTransactionsCountByTmidCheck = (TreeMap<Integer, Integer>) transactionsByIdTestz .get(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeyindoubtTransactionsCountByTmid); if (indoubtTransactionsCountByTmidCheck != null) { this.indoubtTransactionsCountByTmid = indoubtTransactionsCountByTmidCheck; } else { transactionsByIdTestz.put( this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeyindoubtTransactionsCountByTmid, this.indoubtTransactionsCountByTmid); } Set<TrxTransactionState> commitPendingTransactionsCheck = (Set<TrxTransactionState>) transactionsByIdTestz .get(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeycommitPendingTransactions); if (commitPendingTransactionsCheck != null) { this.commitPendingTransactions = commitPendingTransactionsCheck; } else { transactionsByIdTestz.put( this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeycommitPendingTransactions, this.commitPendingTransactions); } ConcurrentHashMap<String, TrxTransactionState> transactionsByIdCheck = (ConcurrentHashMap<String, TrxTransactionState>) transactionsByIdTestz .get(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeytransactionsById); if (transactionsByIdCheck != null) { this.transactionsById = transactionsByIdCheck; } else { transactionsByIdTestz.put( this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeytransactionsById, this.transactionsById); } AtomicBoolean closingCheck = (AtomicBoolean) transactionsByIdTestz .get(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeyClosingVar); if (closingCheck != null) { this.closing = closingCheck; } else { transactionsByIdTestz.put(this.m_Region.getRegionNameAsString() + TrxRegionObserver.trxkeyClosingVar, this.closing); } // Set up the memoryBean from the ManagementFactory if (memoryUsageThreshold < DEFAULT_MEMORY_THRESHOLD) memoryBean = ManagementFactory.getMemoryMXBean(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: start"); } @Override public void stop(CoprocessorEnvironment env) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: stop "); stoppable.stop("stop() TrxRegionEndpoint"); transactionsEPCPMap.remove(this.m_Region.getRegionNameAsString() + trxkeyEPCPinstance); } // Internal support methods /** * Checks if the region is closing * @param long transactionId * @return String * @throws IOException */ private void checkClosing(final long transactionId) throws IOException { if (closing.get()) { if (LOG.isWarnEnabled()) LOG.warn("TrxRegionEndpoint coprocessor: checkClosing - txId " + transactionId + ", Trafodion Recovery: Raising exception. no more new transactions allowed."); throw new IOException("closing region, no more new transactions allowed. Region: " + regionInfo.getRegionNameAsString()); } } /** * Gets the transaction state * @param long transactionId * @return TrxTransactionState * @throws UnknownTransactionException */ protected TrxTransactionState getTransactionState(final long transactionId) throws UnknownTransactionException { TrxTransactionState state = null; boolean throwUTE = false; String key = getTransactionalUniqueId(transactionId); state = transactionsById.get(key); if (state == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getTransactionState Unknown transaction: [" + transactionId + "], throwing UnknownTransactionException"); throwUTE = true; } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getTransactionState Found transaction: [" + transactionId + "]"); try { transactionLeases.renewLease(key); } catch (LeaseException e) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: getTransactionState renewLease failed will try to createLease for transaction: [" + transactionId + "]"); try { transactionLeases.createLease(key, transactionLeaseTimeout, new TransactionLeaseListener(transactionId)); } catch (LeaseStillHeldException lshe) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: getTransactionState renewLeasefollowed by createLease failed throwing original LeaseException for transaction: [" + transactionId + "]"); throw new RuntimeException(e); } } } if (throwUTE) throw new UnknownTransactionException(); return state; } /** * Retires the transaction * @param TrxTransactionState state */ private void retireTransaction(final TrxTransactionState state, final boolean clear) { String key = getTransactionalUniqueId(state.getTransactionId()); long transId = state.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction: [" + transId + "]"); try { transactionLeases.cancelLease(key); } catch (LeaseException le) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction: [" + transId + "] LeaseException"); // Ignore } catch (Exception e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction: [" + transId + "] General Lease exception" + e.getMessage() + " " + stackTraceToString(e)); // Ignore } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction clearTransactionsToCheck for: " + key + " from all its TrxTransactionState lists"); // Clear out transaction state if (clear == true) { state.clearState(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction clearState for: " + key + " from all its TrxTransactionState lists"); } else { state.clearTransactionsToCheck(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction clearTransactionsToCheck for: " + key); } synchronized (cleanScannersForTransactions) { cleanScannersForTransactions.add(transId); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: retireTransaction calling remove entry for: " + key + " , from transactionById map "); transactionsById.remove(key); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:retireTransaction " + key + ", looking for retire transaction id " + transId + ", transactionsById " + transactionsById.size() + ", commitedTransactionsBySequenceNumber " + commitedTransactionsBySequenceNumber.size() + ", commitPendingTransactions " + commitPendingTransactions.size()); } public void choreThreadDetectStaleTransactionBranch() { List<Integer> staleBranchforTMId = new ArrayList<Integer>(); List<TrxTransactionState> commitPendingCopy = new ArrayList<TrxTransactionState>(commitPendingTransactions); Map<Long, List<WALEdit>> indoubtTransactionsMap = new TreeMap<Long, List<WALEdit>>(indoubtTransactionsById); int tmid, tm; // selected printout for CP long currentEpoch = controlPointEpoch.get(); if ((currentEpoch < 10) || ((currentEpoch % 10) == 1)) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:choreThreadDetectStaleTransactionBranch: Region " + regionInfo.getRegionNameAsString() + " ChoreThread CP Epoch " + controlPointEpoch.get()); } byte[] lv_byte_region_info = regionInfo.toByteArray(); String lv_encoded = regionInfo.getEncodedName(); long transactionId; if ((indoubtTransactionsById != null) && (indoubtTransactionsById.size() > 0) && (this.regionState != REGION_STATE_START)) { for (Entry<Long, List<WALEdit>> entry : indoubtTransactionsMap.entrySet()) { transactionId = entry.getKey(); if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor:choreThreadDetectStaleTransactionBranch: indoubt branch Txn id " + transactionId + " region info bytes " + new String(lv_byte_region_info)); tmid = (int) (transactionId >> 32); if (!staleBranchforTMId.contains(tmid)) { staleBranchforTMId.add(tmid); } } } else { // region has started for (TrxTransactionState commitPendingTS : commitPendingCopy) { if (commitPendingTS.getCPEpoch() < (controlPointEpoch.get() - 1)) { transactionId = commitPendingTS.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor:choreThreadDetectStaleTransactionBranch: stale branch Txn id " + transactionId + " region info bytes " + new String(lv_byte_region_info)); tmid = (int) (transactionId >> 32); if (!staleBranchforTMId.contains(tmid)) { staleBranchforTMId.add(tmid); } } } } if (!staleBranchforTMId.isEmpty()) { for (int i = 0; i < staleBranchforTMId.size(); i++) { try { tm = staleBranchforTMId.get(i); if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor:choreThreadDetectStaleTransactionBranch: ZKW Create Recovery zNode TM " + tm + " region encoded name " + lv_encoded + " region info bytes " + new String(lv_byte_region_info)); createRecoveryzNode(tm, lv_encoded, lv_byte_region_info); } catch (IOException exp) { LOG.error( "TrxRegionEndpoint coprocessor:choreThreadDetectStaleTransactionBranch: ZKW Create recovery zNode failed " + exp); } } // for } // if block controlPointEpoch.getAndIncrement(); commitPendingCopy.clear(); indoubtTransactionsMap.clear(); staleBranchforTMId.clear(); } public void createRecoveryzNode(int node, String encodedName, byte[] data) throws IOException { synchronized (zkRecoveryCheckLock) { // default zNodePath for recovery String zNodeKey = lv_hostName + "," + lv_port + "," + encodedName; StringBuilder sb = new StringBuilder(); sb.append("TM"); sb.append(node); String str = sb.toString(); String zNodePathTM = zNodePath + str; String zNodePathTMKey = zNodePathTM + "/" + zNodeKey; if (LOG.isTraceEnabled()) LOG.trace("Trafodion Recovery Region Observer CP: ZKW Post region recovery znode" + node + " zNode Path " + zNodePathTMKey); // create zookeeper recovery zNode, call ZK ... try { if (ZKUtil.checkExists(zkw1, zNodePathTM) == -1) { // create parent nodename if (LOG.isTraceEnabled()) LOG.trace("Trafodion Recovery Region Observer CP: ZKW create parent zNodes " + zNodePathTM); ZKUtil.createWithParents(zkw1, zNodePathTM); } ZKUtil.createAndFailSilent(zkw1, zNodePathTMKey, data); } catch (KeeperException e) { throw new IOException( "Trafodion Recovery Region Observer CP: ZKW Unable to create recovery zNode to TM, throw IOException " + node, e); } } } // end ogf createRecoveryzNode public void deleteRecoveryzNode(int node, String encodedName) throws IOException { synchronized (zkRecoveryCheckLock) { // default zNodePath String zNodeKey = lv_hostName + "," + lv_port + "," + encodedName; StringBuilder sb = new StringBuilder(); sb.append("TM"); sb.append(node); String str = sb.toString(); String zNodePathTM = zNodePath + str; String zNodePathTMKey = zNodePathTM + "/" + zNodeKey; if (LOG.isTraceEnabled()) LOG.trace("Trafodion Recovery Region Observer CP: ZKW Delete region recovery znode" + node + " zNode Path " + zNodePathTMKey); // delete zookeeper recovery zNode, call ZK ... try { ZKUtil.deleteNodeFailSilent(zkw1, zNodePathTMKey); } catch (KeeperException e) { throw new IOException( "Trafodion Recovery Region Observer CP: ZKW Unable to delete recovery zNode to TM " + node, e); } } } // end of deleteRecoveryzNode /** * Starts the region after a recovery */ public void startRegionAfterRecovery() throws IOException { boolean isFlush = false; try { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Trafodion Recovery: Flushing cache in startRegionAfterRecovery " + m_Region.getRegionInfo().getRegionNameAsString()); m_Region.flushcache(); //if (!m_Region.flushcache().isFlushSucceeded()) { // LOG.trace("TrxRegionEndpoint coprocessor: Trafodion Recovery: Flushcache returns false !!! " + m_Region.getRegionInfo().getRegionNameAsString()); //} } catch (IOException e) { LOG.error("TrxRegionEndpoint coprocessor: Trafodion Recovery: Flush failed after replay edits" + m_Region.getRegionInfo().getRegionNameAsString() + ", Caught exception " + e.toString()); return; } //FileSystem fileSystem = m_Region.getFilesystem(); //Path archiveTHLog = new Path (recoveryTrxPath.getParent(),"archivethlogfile.log"); //if (fileSystem.exists(archiveTHLog)) fileSystem.delete(archiveTHLog, true); //if (fileSystem.exists(recoveryTrxPath))fileSystem.rename(recoveryTrxPath,archiveTHLog); if (indoubtTransactionsById != null) if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Trafodion Recovery: region " + recoveryTrxPath + " has " + indoubtTransactionsById.size() + " in-doubt transactions and edits are archived."); else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Trafodion Recovery: region " + recoveryTrxPath + " has 0 in-doubt transactions and edits are archived."); regionState = REGION_STATE_START; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Trafodion Recovery: region " + m_Region.getRegionInfo().getEncodedName() + " is STARTED."); } /** * Commits the transaction * @param TrxTransactionState state * @throws IOException */ private void commit(final TrxTransactionState state) throws IOException { long txid = 0; WALEdit b = null; int num = 0; Tag commitTag; ArrayList<WALEdit> editList; long transactionId = state.getTransactionId(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commit - txId " + transactionId + ", region " + m_Region.getRegionInfo().getRegionNameAsString() + ", transactionsById " + transactionsById.size() + ", commitedTransactionsBySequenceNumber " + commitedTransactionsBySequenceNumber.size() + ", commitPendingTransactions " + commitPendingTransactions.size()); if (state.isReinstated() && !this.configuredConflictReinstate) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: commit Trafodion Recovery: commit reinstated indoubt transactions " + transactionId + " in region " + m_Region.getRegionInfo().getRegionNameAsString()); synchronized (indoubtTransactionsById) { editList = (ArrayList<WALEdit>) indoubtTransactionsById.get(transactionId); } num = editList.size(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", region " + regionInfo.getRegionNameAsString() + ", Redrive commit with number of edit kvs list size " + num); for (int i = 0; i < num; i++) { b = editList.get(i); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Writing " + b.size() + " updates for reinstated transaction"); for (KeyValue kv : b.getKeyValues()) { synchronized (editReplay) { Put put; Delete del; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commit - txId " + transactionId + ", Trafodion Recovery: region " + m_Region.getRegionInfo().getRegionNameAsString() + ", Replay commit for transaction with Op " + kv.getType()); if (kv.getTypeByte() == KeyValue.Type.Put.getCode()) { put = new Put(CellUtil.cloneRow(kv)); // kv.getRow() put.add(CellUtil.cloneFamily(kv), CellUtil.cloneQualifier(kv), kv.getTimestamp(), CellUtil.cloneValue(kv)); //state.addWrite(put); // no need to add since add has been done in constructInDoubtTransactions try { m_Region.put(put); } catch (Exception e) { LOG.warn("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: Executing put caught an exception " + e.toString()); throw new IOException(e.toString()); } } else if (CellUtil.isDelete(kv)) { del = new Delete(CellUtil.cloneRow(kv)); if (CellUtil.isDeleteFamily(kv)) { del.deleteFamily(CellUtil.cloneFamily(kv)); } else if (kv.isDeleteType()) { del.deleteColumn(CellUtil.cloneFamily(kv), CellUtil.cloneQualifier(kv)); } //state.addDelete(del); // no need to add since add has been done in constructInDoubtTransactions try { m_Region.delete(del); } catch (Exception e) { LOG.warn("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: Executing delete caught an exception " + e.toString()); throw new IOException(e.toString()); } } } // synchronized reply edits } // for WALEdit } // for ediList } // reinstated transactions else { // either non-reinstated transaction, or reinstate transaction with conflict reinstate TRUE (write from TS write ordering) // Perform write operations timestamped to right now // maybe we can turn off WAL here for HLOG since THLOG has contained required edits in phase 1 ListIterator<WriteAction> writeOrderIter = null; for (writeOrderIter = state.getWriteOrderingIter(); writeOrderIter.hasNext();) { WriteAction action = (WriteAction) writeOrderIter.next(); // Process Put Put put = action.getPut(); if (null != put) { put.setDurability(Durability.SKIP_WAL); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Executing put directly to m_Region"); try { m_Region.put(put); } catch (Exception e) { LOG.warn("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Executing put caught an exception " + e.toString()); throw new IOException(e.toString()); } } // Process Delete Delete delete = action.getDelete(); if (null != delete) { delete.setDurability(Durability.SKIP_WAL); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Executing delete directly to m_Region"); try { m_Region.delete(delete); } catch (Exception e) { LOG.warn("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Executing delete caught an exception " + e.toString()); throw new IOException(e.toString()); } } } } // normal transactions // Now write a commit edit to HLOG List<Tag> tagList = new ArrayList<Tag>(); if (state.hasWrite() || state.isReinstated()) { if (!state.getFullEditInCommit()) { commitTag = state.formTransactionalContextTag(TS_COMMIT); tagList.add(commitTag); WALEdit e1 = state.getEdit(); WALEdit e = new WALEdit(); if (e1.isEmpty() || e1.getKeyValues().size() <= 0) { if (LOG.isInfoEnabled()) LOG.info("TRAF RCOV endpoint CP: commit - txId " + transactionId + ", Encountered empty TS WAL Edit list during commit, HLog txid " + txid); } else { Cell c = e1.getKeyValues().get(0); KeyValue kv = new KeyValue(c.getRowArray(), c.getRowOffset(), (int) c.getRowLength(), c.getFamilyArray(), c.getFamilyOffset(), (int) c.getFamilyLength(), c.getQualifierArray(), c.getQualifierOffset(), (int) c.getQualifierLength(), c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(), c.getValueLength(), tagList); e.add(kv); try { txid = this.tHLog.appendNoSync(this.regionInfo, this.regionInfo.getTable(), e, new ArrayList<UUID>(), EnvironmentEdgeManager.currentTimeMillis(), this.m_Region.getTableDesc(), nextLogSequenceId, false, HConstants.NO_NONCE, HConstants.NO_NONCE); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Write commit HLOG seq " + txid); } catch (IOException exp1) { if (LOG.isTraceEnabled()) LOG.trace("TRAF RCOV endpoint CP: commit - txId " + transactionId + ", Writing to HLOG : Threw an exception " + exp1.toString()); throw exp1; } } // e1 is not empty } // not full edit write in commit record during phase 2 else { //do this for rollover case if (LOG.isTraceEnabled()) LOG.trace("TRAF RCOV endpoint CP:commit -- HLOG rollover txId: " + transactionId); commitTag = state.formTransactionalContextTag(TS_CONTROL_POINT_COMMIT); tagList.add(commitTag); WALEdit e1 = state.getEdit(); WALEdit e = new WALEdit(); for (Cell c : e1.getKeyValues()) { KeyValue kv = new KeyValue(c.getRowArray(), c.getRowOffset(), (int) c.getRowLength(), c.getFamilyArray(), c.getFamilyOffset(), (int) c.getFamilyLength(), c.getQualifierArray(), c.getQualifierOffset(), (int) c.getQualifierLength(), c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(), c.getValueLength(), tagList); e.add(kv); } try { txid = this.tHLog.appendNoSync(this.regionInfo, this.regionInfo.getTable(), e, new ArrayList<UUID>(), EnvironmentEdgeManager.currentTimeMillis(), this.m_Region.getTableDesc(), nextLogSequenceId, false, HConstants.NO_NONCE, HConstants.NO_NONCE); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Y11 write commit HLOG seq " + txid); } catch (IOException exp1) { if (LOG.isTraceEnabled()) LOG.trace("TRAF RCOV endpoint CP: commit - txId " + transactionId + ", Writing to HLOG : Threw an exception " + exp1.toString()); throw exp1; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commit -- EXIT txId: " + transactionId + " HLog seq " + txid); if (this.fullEditInCommit) this.fullEditInCommit = false; } // else -- full edit write in commit record during phase 2 } // write or reinstated state.setStatus(Status.COMMITED); if (state.hasWrite() || state.isReinstated()) { synchronized (commitPendingTransactions) { if (!commitPendingTransactions.remove(state)) { LOG.fatal("TrxRegionEndpoint coprocessor: commit - txid: " + transactionId + ", Commiting a non-query transaction that is not in commitPendingTransactions"); // synchronized statements are cleared for a throw throw new IOException("commit failure"); } } } if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: commit(tstate) -- EXIT TrxTransactionState: " + state.toString()); if (state.isReinstated()) { synchronized (indoubtTransactionsById) { indoubtTransactionsById.remove(state.getTransactionId()); int tmid = (int) (transactionId >> 32); int count = 0; if (indoubtTransactionsCountByTmid.containsKey(tmid)) { count = (int) indoubtTransactionsCountByTmid.get(tmid) - 1; if (count > 0) indoubtTransactionsCountByTmid.put(tmid, count); } if (count == 0) { indoubtTransactionsCountByTmid.remove(tmid); String lv_encoded = m_Region.getRegionInfo().getEncodedName(); try { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: delete in commit recovery zNode TM " + tmid + " region encoded name " + lv_encoded + " for 0 in-doubt transaction"); deleteRecoveryzNode(tmid, lv_encoded); } catch (IOException e) { LOG.error("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: delete recovery zNode failed. Caught exception " + e.toString()); } } if ((indoubtTransactionsById == null) || (indoubtTransactionsById.size() == 0)) { if (indoubtTransactionsById == null) if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: start region in commit with indoubtTransactionsById null"); else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit - txId " + transactionId + ", Trafodion Recovery: start region in commit with indoubtTransactionsById size " + indoubtTransactionsById.size()); startRegionAfterRecovery(); } } } state.setCommitProgress(CommitProgress.COMMITED); retireTransaction(state, false); } /** * Rssolves the transaction from the log * @param TrxTransactionState transactionState * @throws IOException */ private void resolveTransactionFromLog(final TrxTransactionState transactionState) throws IOException { LOG.error( "TrxRegionEndpoint coprocessor: Global transaction log is not Implemented. (Optimisticly) assuming transaction commit!"); commit(transactionState); } /** * TransactionLeaseListener */ private class TransactionLeaseListener implements LeaseListener { //private final long transactionName; private final String transactionName; TransactionLeaseListener(final long n) { this.transactionName = getTransactionalUniqueId(n); } public void leaseExpired() { long transactionId = 0L; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: leaseExpired Transaction [" + this.transactionName + "] expired in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "]"); TrxTransactionState s = null; synchronized (transactionsById) { s = transactionsById.remove(transactionName); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: leaseExpired Removing transaction: " + this.transactionName + " from list"); } if (s == null) { LOG.warn("leaseExpired Unknown transaction expired " + this.transactionName); return; } transactionId = s.getTransactionId(); switch (s.getStatus()) { case PENDING: if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: leaseExpired transaction " + transactionId + " was PENDING, calling retireTransaction"); s.setStatus(Status.ABORTED); retireTransaction(s, true); break; case COMMIT_PENDING: if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: leaseExpired Transaction " + transactionId + " expired in COMMIT_PENDING state"); String key = getTransactionalUniqueId(transactionId); try { if (s.getCommitPendingWaits() > MAX_COMMIT_PENDING_WAITS) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: leaseExpired Checking transaction status in transaction log"); resolveTransactionFromLog(s); break; } if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: leaseExpired renewing lease and hoping for commit"); s.incrementCommitPendingWaits(); synchronized (transactionsById) { transactionsById.put(key, s); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: leaseExpired Adding transaction: " + transactionId + " to list"); } try { transactionLeases.createLease(key, transactionLeaseTimeout, this); } catch (LeaseStillHeldException e) { transactionLeases.renewLease(key); } } catch (IOException e) { throw new RuntimeException(e); } break; default: LOG.warn("TrxRegionEndpoint coprocessor: leaseExpired Unexpected status on expired lease"); } } } /** * Processes a transactional delete * @param long transactionId * @param Delete delete * @throws IOException */ public void delete(final long transactionId, final Delete delete) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: delete -- ENTRY txId: " + transactionId); TrxTransactionState state = this.beginTransIfNotExist(transactionId); state.addDelete(delete); } /** * Processes multiple transactional deletes * @param long transactionId * @param Delete[] deletes * @throws IOException */ public synchronized void delete(final long transactionId, Delete[] deletes) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("Enter TrxRegionEndpoint coprocessor: deletes[], txid: " + transactionId); TrxTransactionState state = this.beginTransIfNotExist(transactionId); for (Delete del : deletes) { state.addDelete(del); } } /** * Processes a transactional checkAndDelete * @param long transactionId * @param byte[] row * @param byte[] family * @param byte[] qualifier * @param byte[] value * @param Delete delete * @return boolean * @throws IOException */ public boolean checkAndDelete(final long transactionId, byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("Enter TrxRegionEndpoint coprocessor: checkAndDelete, txid: " + transactionId + ", on HRegion " + this); TrxTransactionState state = this.beginTransIfNotExist(transactionId); boolean result = false; byte[] rsValue = null; byte[] startKey = null; byte[] endKey = null; if (!this.m_Region.rowIsInRange(this.regionInfo, row)) { startKey = this.regionInfo.getStartKey(); endKey = this.regionInfo.getEndKey(); LOG.error("Requested row out of range for " + "checkAndDelete for txid " + transactionId + ", on HRegion " + this + ", startKey=[" + Bytes.toStringBinary(startKey) + "], startKey in hex[" + Hex.encodeHexString(startKey) + "], endKey [" + Bytes.toStringBinary(endKey) + "], endKey in hex[" + Hex.encodeHexString(endKey) + "]" + "], row=[" + Bytes.toStringBinary(row) + "]"); } try { Get get = new Get(row); get.addColumn(family, qualifier); Result rs = this.get(transactionId, get); boolean valueIsNull = value == null || value.length == 0; if (rs.isEmpty() && valueIsNull) { this.delete(transactionId, delete); result = true; } else if (!rs.isEmpty() && valueIsNull) { rsValue = rs.getValue(family, qualifier); if (rsValue != null && rsValue.length == 0) { this.delete(transactionId, delete); result = true; } else result = false; } else if ((!rs.isEmpty()) && !valueIsNull && (Bytes.equals(rs.getValue(family, qualifier), value))) { this.delete(transactionId, delete); result = true; } else { result = false; } } catch (Exception e) { if (LOG.isWarnEnabled()) LOG.warn("TrxRegionEndpoint coprocessor: checkAndDelete - txid " + transactionId + ", Caught internal exception " + e.toString() + ", returning false"); throw new IOException("TrxRegionEndpoint coprocessor: checkAndDelete - " + e.toString()); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndDelete EXIT - returns " + result + ", transId " + transactionId + ", row " + Bytes.toStringBinary(row) + ", row in hex " + Hex.encodeHexString(row)); return result; } /** * Processes a transactional checkAndPut * @param long transactionId * @param byte[] row * @param byte[] family * @param byte[] qualifier * @param byte[] value * @param Put put * @return boolean * @throws IOException */ public boolean checkAndPut(final long transactionId, byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("Enter TrxRegionEndpoint coprocessor: checkAndPut, txid: " + transactionId + ", on HRegion " + this); TrxTransactionState state = this.beginTransIfNotExist(transactionId); boolean result = false; byte[] rsValue = null; byte[] startKey = null; byte[] endKey = null; if (!this.m_Region.rowIsInRange(this.regionInfo, row)) { startKey = this.regionInfo.getStartKey(); endKey = this.regionInfo.getEndKey(); LOG.error("Requested row out of range for " + "checkAndPut for txid " + transactionId + ", on HRegion " + this + ", startKey=[" + Bytes.toStringBinary(startKey) + "], startKey in hex[" + Hex.encodeHexString(startKey) + "], endKey [" + Bytes.toStringBinary(endKey) + "], endKey in hex[" + Hex.encodeHexString(endKey) + "]" + "], row=[" + Bytes.toStringBinary(row) + "]"); } try { Get get = new Get(row); get.addColumn(family, qualifier); Result rs = this.get(transactionId, get); boolean valueIsNull = value == null || value.length == 0; if (rs.isEmpty() && valueIsNull) { this.put(transactionId, put); result = true; } else if (!rs.isEmpty() && valueIsNull) { rsValue = rs.getValue(family, qualifier); if (rsValue != null && rsValue.length == 0) { this.put(transactionId, put); result = true; } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut - txid " + transactionId + ", row " + Bytes.toStringBinary(row) + ", row in hex " + Hex.encodeHexString(row) + ", first check setting result to false"); result = false; } } else if ((!rs.isEmpty()) && !valueIsNull && (Bytes.equals(rs.getValue(family, qualifier), value))) { this.put(transactionId, put); result = true; } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut - txid " + transactionId + ", row " + Bytes.toStringBinary(row) + ", row in hex " + Hex.encodeHexString(row) + ", second check setting result to false"); result = false; } } catch (Exception e) { if (LOG.isWarnEnabled()) LOG.warn("TrxRegionEndpoint coprocessor: checkAndPut - txid " + transactionId + ", Caught internal exception " + e.toString() + ", returning false"); throw new IOException("TrxRegionEndpoint coprocessor: checkAndPut - " + e.toString()); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkAndPut EXIT - returns " + result + ", transId " + transactionId + ", row " + Bytes.toStringBinary(row) + ", row in hex " + Hex.encodeHexString(row)); return result; } /** * Obtains a transactional Result for Get * @param long transactionId * @param Get get * @return Result * @throws IOException */ public Result get(final long transactionId, final Get get) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get -- ENTRY txId: " + transactionId); /* if (LOG.isTraceEnabled()) { Map<byte[],NavigableSet<byte[]>> lv_fm = get.getFamilyMap(); byte [][] lv_fms = lv_fm.keySet().toArray(new byte[0][0]); byte[] lv_f = lv_fms[0]; if (LOG.isTraceEnabled()) LOG.trace("family: " + new String(lv_f)); NavigableSet<byte []> lv_set = lv_fm.get(lv_f); if (LOG.isTraceEnabled()) LOG.trace("lv_set size: " + lv_set.size()); } */ Scan scan = new Scan(get); List<Cell> results = new ArrayList<Cell>(); RegionScanner scanner = null; try { scanner = getScanner(transactionId, scan); if (scanner != null) scanner.next(results); } catch (Exception e) { LOG.warn("TrxRegionEndpoint coprocessor: get - txId " + transactionId + ", Caught internal exception " + e.getMessage() + " " + stackTraceToString(e)); } finally { if (scanner != null) { scanner.close(); } } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: get -- EXIT txId: " + transactionId); return Result.create(results); } /** * Obtain a RegionScanner * @param long transactionId * @param Scan scan * @return RegionScanner * @throws IOException */ public RegionScanner getScanner(final long transactionId, final Scan scan) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: RegionScanner getScanner -- ENTRY txId: " + transactionId); TrxTransactionState state = this.beginTransIfNotExist(transactionId); state.addScan(scan); List<KeyValueScanner> scanners = new ArrayList<KeyValueScanner>(1); scanners.add(state.getScanner(scan)); Scan deleteWrapScan = wrapWithDeleteFilter(scan, state); if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: RegionScanner getScanner -- Calling t_Region.getScanner txId: " + transactionId); RegionScanner gotScanner = this.t_Region.getScanner(deleteWrapScan, scanners); if (gotScanner != null) if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: RegionScanner getScanner -- obtained scanner was not null, txId: " + transactionId); else if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: RegionScanner getScanner -- obtained scanner was null, txId: " + transactionId); return gotScanner; } /** * Wraps the transactional scan with a delete filter * @param Scan scan * @param TrxTransactionState state * @return Scan */ private Scan wrapWithDeleteFilter(final Scan scan, final TrxTransactionState state) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: wrapWithDeleteFilter -- ENTRY"); FilterBase deleteFilter = new FilterBase() { private boolean rowFiltered = false; @Override public void reset() { rowFiltered = false; } @Override public boolean hasFilterRow() { return true; } @Override public void filterRowCells(final List<Cell> kvs) { state.applyDeletes(kvs, scan.getTimeRange().getMin(), scan.getTimeRange().getMax()); rowFiltered = kvs.isEmpty(); } public boolean filterRow() { return rowFiltered; } }; if (scan.getFilter() == null) { scan.setFilter(deleteFilter); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: no previous filter, wrapWithDeleteFilter -- EXIT"); return scan; } FilterList wrappedFilter = new FilterList(Arrays.asList(deleteFilter, scan.getFilter())); scan.setFilter(wrappedFilter); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: new filter array, wrapWithDeleteFilter -- EXIT"); return scan; } /** * Add a write to the transaction. Does not get applied until commit * process. * @param long transactionId * @param Put put * @throws IOException */ public void put(final long transactionId, final Put put) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("Enter TrxRegionEndpoint coprocessor: put, txid: " + transactionId); TrxTransactionState state = this.beginTransIfNotExist(transactionId); state.addWrite(put); } public void constructIndoubtTransactions() { synchronized (recoveryCheckLock) { if ((indoubtTransactionsById == null) || (indoubtTransactionsById.size() == 0)) { if (LOG.isInfoEnabled()) LOG.info("TRAF RCOV endpoint CP: Region " + regionInfo.getRegionNameAsString() + " has no in-doubt transaction, set region START "); regionState = REGION_STATE_START; // region is started for transactional access reconstructIndoubts = 1; try { startRegionAfterRecovery(); } catch (IOException exp1) { if (LOG.isDebugEnabled()) LOG.debug("Trafodion Recovery: flush error during region start"); } return; } if (LOG.isTraceEnabled()) LOG.trace( "Trafodion Recovery Endpoint Coprocessor: Trafodion Recovery RegionObserver to Endpoint coprocessor " + "data exchange test try to access indoubt transaction list with size " + indoubtTransactionsById.size()); if (reconstructIndoubts == 0) { //Retrieve (tid,Edits) from indoubt Transaction and construct/add into desired transaction data list for (Entry<Long, List<WALEdit>> entry : indoubtTransactionsById.entrySet()) { long txid = 0; long transactionId = entry.getKey(); String key = String.valueOf(transactionId); ArrayList<WALEdit> editList = (ArrayList<WALEdit>) entry.getValue(); //editList = (ArrayList<WALEdit>) indoubtTransactionsById.get(transactionId); if (LOG.isTraceEnabled()) LOG.trace("Trafodion endpoint CP: reconstruct transaction in Region " + regionInfo.getRegionNameAsString() + " process in-doubt transaction " + transactionId); TrxTransactionState state = new TrxTransactionState( transactionId, /* 1L my_Region.getLog().getSequenceNumber()*/ nextLogSequenceId.getAndIncrement(), nextLogSequenceId, regionInfo, m_Region.getTableDesc(), tHLog, false); if (LOG.isTraceEnabled()) LOG.trace("Trafodion endpointCP: reconstruct transaction in Region " + regionInfo.getRegionNameAsString() + " create transaction state for " + transactionId); state.setFullEditInCommit(true); state.setStartSequenceNumber(nextSequenceId.get()); transactionsById.put(getTransactionalUniqueId(transactionId), state); // Re-establish write ordering (put and get) for in-doubt transactional int num = editList.size(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegion endpoint CP: reconstruct transaction " + transactionId + ", region " + regionInfo.getRegionNameAsString() + " with number of edit list kvs size " + num); for (int i = 0; i < num; i++) { WALEdit b = editList.get(i); if (LOG.isTraceEnabled()) LOG.trace("TrxRegion endpoint CP: reconstruction transaction " + transactionId + ", region " + regionInfo.getRegionNameAsString() + " with " + b.size() + " kv in WALEdit " + i); for (KeyValue kv : b.getKeyValues()) { Put put; Delete del; synchronized (editReplay) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegion endpoint CP:reconstruction transaction " + transactionId + ", region " + regionInfo.getRegionNameAsString() + " re-establish write ordering Op Code " + kv.getType()); if (kv.getTypeByte() == KeyValue.Type.Put.getCode()) { put = new Put(CellUtil.cloneRow(kv)); // kv.getRow() put.add(CellUtil.cloneFamily(kv), CellUtil.cloneQualifier(kv), kv.getTimestamp(), CellUtil.cloneValue(kv)); state.addWrite(put); } else if (CellUtil.isDelete(kv)) { del = new Delete(CellUtil.cloneRow(kv)); if (CellUtil.isDeleteFamily(kv)) { del.deleteFamily(CellUtil.cloneFamily(kv)); } else if (kv.isDeleteType()) { del.deleteColumn(CellUtil.cloneFamily(kv), CellUtil.cloneQualifier(kv)); } state.addDelete(del); } // handle put/delete op code } // sync editReplay } // for all kv in edit b } // for all edit b in ediList state.setReinstated(); state.setStatus(Status.COMMIT_PENDING); commitPendingTransactions.add(state); state.setSequenceNumber(nextSequenceId.getAndIncrement()); commitedTransactionsBySequenceNumber.put(state.getSequenceNumber(), state); if (LOG.isTraceEnabled()) LOG.trace("TrxRegion endpoint CP: reconstruct transaction " + transactionId + ", region " + regionInfo.getRegionNameAsString() + " complete in prepared state"); // Rewrite HLOG for prepared edit (this method should be invoked in postOpen Observer ?? try { txid = this.tHLog.appendNoSync(this.regionInfo, this.regionInfo.getTable(), state.getEdit(), new ArrayList<UUID>(), EnvironmentEdgeManager.currentTimeMillis(), this.m_Region.getTableDesc(), nextLogSequenceId, false, HConstants.NO_NONCE, HConstants.NO_NONCE); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest COMMIT_OK -- EXIT txId: " + transactionId + " HLog seq " + txid); this.tHLog.sync(txid); } catch (IOException exp) { LOG.warn( "TrxRegion endpoint CP: reconstruct transaction - Caught IOException in HLOG appendNoSync -- EXIT txId: " + transactionId + " HLog seq " + txid); //throw exp; } if (LOG.isTraceEnabled()) LOG.trace( "TrxRegion endpoint CP: reconstruct transaction: rewrite to HLOG CR edit for transaction " + transactionId); int tmid = (int) (transactionId >> 32); if (LOG.isTraceEnabled()) LOG.trace("TrxRegion endpoint CP " + regionInfo.getRegionNameAsString() + " reconstruct transaction " + transactionId + " for TM " + tmid); } // for all txns in indoubt transcation list } // not reconstruct indoubtes yet reconstructIndoubts = 1; if (this.configuredConflictReinstate) { regionState = REGION_STATE_START; // set region state START , so new transaction can start with conflict re-established } } // synchronized } /** * Begin a transaction * @param longtransactionId * @throws IOException */ public void beginTransaction(final long transactionId) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction -- ENTRY txId: " + transactionId); checkClosing(transactionId); // TBD until integration with recovery if (reconstructIndoubts == 0) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: RECOV beginTransaction -- ENTRY txId: " + transactionId); constructIndoubtTransactions(); } if (regionState != REGION_STATE_START) { //print out all the in-doubt transaction at this moment if ((indoubtTransactionsById == null) || (indoubtTransactionsById.size() == 0)) regionState = REGION_STATE_START; else { LOG.warn( "TRAF RCOV coprocessor: RECOVERY WARN beginTransaction while the region is still in recovering state " + regionState + " indoubt tx size " + indoubtTransactionsById.size()); for (Entry<Long, List<WALEdit>> entry : indoubtTransactionsById.entrySet()) { long tid = entry.getKey(); if (LOG.isTraceEnabled()) LOG.trace("Trafodion Recovery: region " + regionInfo.getEncodedName() + " still has in-doubt transaction " + tid + " when new transaction arrives "); } throw new IOException("NewTransactionStartedBeforeRecoveryCompleted"); } } TrxTransactionState state; synchronized (transactionsById) { // if (transactionsById.get(getTransactionalUniqueId(transactionId)) != null) { // TrxTransactionState alias = getTransactionState(transactionId); // LOG.error("TrxRegionEndpoint coprocessor: beginTransaction - Ignoring - Existing transaction with id [" // + transactionId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "]"); // if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: beginTransaction -- EXIT txId: " + transactionId); // return; // } if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: beginTransaction -- creating new TrxTransactionState without coprocessorHost txId: " + transactionId); state = new TrxTransactionState(transactionId, //this.m_Region.getLog().getSequenceNumber(), nextLogSequenceId.getAndIncrement(), nextLogSequenceId, m_Region.getRegionInfo(), m_Region.getTableDesc(), tHLog, configuredEarlyLogging); state.setFullEditInCommit(this.fullEditInCommit); state.setStartSequenceNumber(nextSequenceId.get()); } List<TrxTransactionState> commitPendingCopy = new ArrayList<TrxTransactionState>(commitPendingTransactions); for (TrxTransactionState commitPending : commitPendingCopy) { state.addTransactionToCheck(commitPending); } String key = getTransactionalUniqueId(transactionId); synchronized (transactionsById) { transactionsById.put(key, state); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: beginTransaction - Adding transaction: [" + transactionId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "]" + " to list"); try { transactionLeases.createLease(key, transactionLeaseTimeout, new TransactionLeaseListener(transactionId)); } catch (LeaseStillHeldException e) { LOG.error("TrxRegionEndpoint coprocessor: beginTransaction - Lease still held for [" + transactionId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "]"); throw new RuntimeException(e); } if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: beginTransaction -- EXIT txId: " + transactionId + " transactionsById size: " + transactionsById.size() + " region ID: " + this.regionInfo.getRegionId()); } /** * Obtains a scanner lease id * @param long scannerId * @return String */ private String getScannerLeaseId(final long scannerId) { String lstring = m_Region.getRegionInfo().getRegionNameAsString() + scannerId; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScannerLeaseId -- EXIT txId: " + scannerId + " lease string " + lstring); return m_Region.getRegionInfo().getRegionNameAsString() + scannerId; } /** * Obtains a transactional lease id * @param long transactionId * @return String */ private String getTransactionalUniqueId(final long transactionId) { if (LOG.isTraceEnabled()) { String lstring = m_Region.getRegionInfo().getRegionNameAsString() + transactionId; LOG.trace("TrxRegionEndpoint coprocessor: getTransactionalUniqueId -- EXIT txId: " + transactionId + " transactionsById size: " + transactionsById.size() + " name " + lstring); } return m_Region.getRegionInfo().getRegionNameAsString() + transactionId; } /**begin transaction if not yet * @param transactionId * @return true: begin; false: not necessary to begin * @throws IOException */ private TrxTransactionState beginTransIfNotExist(final long transactionId) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("Enter TrxRegionEndpoint coprocessor: beginTransIfNotExist, txid: " + transactionId + " transactionsById size: " + transactionsById.size()); String key = getTransactionalUniqueId(transactionId); synchronized (transactionsById) { TrxTransactionState state = transactionsById.get(key); if (state == null) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Begin transaction in beginTransIfNotExist beginning the transaction internally as state was null"); this.beginTransaction(transactionId); state = transactionsById.get(key); } return state; } } /** * Commits the transaction * @param long TransactionId * @throws IOException */ public void commit(final long transactionId) throws IOException { commit(transactionId, false /* IgnoreUnknownTransactionException */); } /** * Commits the transaction * @param long TransactionId * @param boolean ignoreUnknownTransactionException * @throws IOException */ public void commit(final long transactionId, final boolean ignoreUnknownTransactionException) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit(txId) -- ENTRY txId: " + transactionId + " ignoreUnknownTransactionException: " + ignoreUnknownTransactionException); CommitProgress commitStatus = CommitProgress.NONE; TrxTransactionState state; try { state = getTransactionState(transactionId); } catch (UnknownTransactionException e) { if (ignoreUnknownTransactionException == true) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: ignoring UnknownTransactionException in commit : " + transactionId + " in region " + m_Region.getRegionInfo().getRegionNameAsString()); return; } LOG.fatal("TrxRegionEndpoint coprocessor: Asked to commit unknown transaction: " + transactionId + " in region " + m_Region.getRegionInfo().getRegionNameAsString()); throw new IOException("UnknownTransactionException"); } if (!state.getStatus().equals(Status.COMMIT_PENDING)) { LOG.fatal("TrxRegionEndpoint coprocessor: commit - Asked to commit a non pending transaction "); throw new IOException("Asked to commit a non-pending transaction"); } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit(txId) -- EXIT txId: " + transactionId); // manage concurrent duplicate commit requests through TS.xaOperation object synchronized (state.getXaOperationObject()) { commitStatus = state.getCommitProgress(); //if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit HHH " + commitStatus); if (commitStatus == CommitProgress.COMMITED) { // already committed, this is likely unnecessary due to Status check above if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: commit - duplicate commit for committed transaction "); } else if (commitStatus == CommitProgress.COMMITTING) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: commit - duplicate commit during committing transaction "); try { Thread.sleep(1000); ///1000 milliseconds is one second. } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } else if (commitStatus == CommitProgress.NONE) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit " + commitStatus); state.setCommitProgress(CommitProgress.COMMITTING); commit(state); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commit(txId) -- EXIT txId: " + transactionId); } } } /** * @param transactionId * @return TransactionRegionInterface commit code * @throws IOException */ public int commitRequest(final long transactionId) throws IOException { return commitRequest(transactionId, true); } public int commitRequest(final long transactionId, boolean flushHLOG) throws IOException { long txid = 0; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest -- ENTRY txId: " + transactionId); TrxTransactionState state; int lv_totalCommits = 0; int lv_timeIndex = 0; if (LOG.isInfoEnabled()) { synchronized (totalCommits) { lv_totalCommits = totalCommits.incrementAndGet(); lv_timeIndex = (timeIndex.getAndIncrement() % 50); } } boolean returnPending = false; long commitCheckEndTime = 0; long hasConflictStartTime = 0; long hasConflictEndTime = 0; long putBySequenceStartTime = 0; long putBySequenceEndTime = 0; long writeToLogEndTime = 0; long commitCheckStartTime = System.nanoTime(); try { state = getTransactionState(transactionId); } catch (UnknownTransactionException e) { if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: commitRequest Unknown transaction [" + transactionId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "], ignoring"); state = null; } // may change to indicate a NOTFOUND case then depends on the TM ts state, if reinstated tx, ignore the exception if (state == null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest encountered unknown transactionID txId: " + transactionId + " returning COMMIT_UNSUCCESSFUL_FROM_COPROCESSOR"); return COMMIT_UNSUCCESSFUL_FROM_COPROCESSOR; } if (LOG.isInfoEnabled()) hasConflictStartTime = System.nanoTime(); synchronized (commitCheckLock) { if (hasConflict(state)) { if (LOG.isInfoEnabled()) { hasConflictEndTime = System.nanoTime(); hasConflictTimes[lv_timeIndex] = hasConflictEndTime - hasConflictStartTime; totalConflictTime += hasConflictTimes[lv_timeIndex]; } state.setStatus(Status.ABORTED); retireTransaction(state, true); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest encountered conflict txId: " + transactionId + "returning COMMIT_CONFLICT"); return COMMIT_CONFLICT; } if (LOG.isInfoEnabled()) hasConflictEndTime = System.nanoTime(); // No conflicts, we can commit. if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: No conflicts for transaction " + transactionId + " found in region " + m_Region.getRegionInfo().getRegionNameAsString() + ". Votes to commit"); // If there are writes we must keep record of the transaction putBySequenceStartTime = System.nanoTime(); if (state.hasWrite()) { if (LOG.isInfoEnabled()) putBySequenceOperations.getAndIncrement(); // Order is important state.setStatus(Status.COMMIT_PENDING); state.setCPEpoch(controlPointEpoch.get()); commitPendingTransactions.add(state); state.setSequenceNumber(nextSequenceId.getAndIncrement()); commitedTransactionsBySequenceNumber.put(state.getSequenceNumber(), state); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Transaction " + transactionId + " found in region " + m_Region.getRegionInfo().getRegionNameAsString() + ". Adding to commitedTransactionsBySequenceNumber for sequence number " + state.getSequenceNumber()); } commitCheckEndTime = putBySequenceEndTime = System.nanoTime(); } // exit sync block of commitCheckLock if (state.hasWrite()) { if (LOG.isTraceEnabled()) LOG.trace("write commitRequest edit to HLOG"); //call HLog by passing tagged WALEdits and associated fields try { // Once we append edit into HLOG during DML operation, there is no need to do any HLOG write in phase 1. // Likely all the edits have been synced, so just do a sync(state.getLargestFlushTxId()) --> most likely, it is an no-op // This is to leverage the time between last DML and phase 1, so there is no need to do any logging (and waited) in phase 1. // And there is no need to write "prepared" record since we try to optimize normal running mode (99.99% commit) // We can append "commit" or "abort" into HLOG in phase 2 in a no-sync mode, but it can also be eliminated if necessary. // All the transaction reinstated during recovery will be treated as "in-doubt" and need to use TLOG to resolve. // So TLOG must be kept for a while (likely a few CP), besides, HRegion chore thread can perform ~ CP action by writing // the smallest sequenceId (not logSeqid), so we don't need to deal with commite case (but we did write abort edit since // the number of abort is < 0.1% -- we can set this as a configurable property). if (!state.getEarlyLogging()) { txid = this.tHLog.appendNoSync(this.regionInfo, this.regionInfo.getTable(), state.getEdit(), new ArrayList<UUID>(), EnvironmentEdgeManager.currentTimeMillis(), this.m_Region.getTableDesc(), nextLogSequenceId, false, HConstants.NO_NONCE, HConstants.NO_NONCE); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitRequest COMMIT_OK -- EXIT txId: " + transactionId + " HLog seq " + txid); if (flushHLOG) this.tHLog.sync(txid); } else { //if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: YYY0 commitRequest just SYNC -- EXIT txId: " + transactionId + " MAX HLog seq " + state.getFlushTxId()); if (flushHLOG) this.tHLog.sync(state.getFlushTxId()); } if (LOG.isInfoEnabled()) { writeToLogEndTime = System.nanoTime(); writeToLogTimes[lv_timeIndex] = writeToLogEndTime - commitCheckEndTime; writeToLogOperations.getAndIncrement(); } //if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor:commitRequest COMMIT_OK -- EXIT txId: " + transactionId + " HLog seq " + txid); } catch (IOException exp) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: commitRequest - Caught IOException in HLOG appendNoSync -- EXIT txId: " + transactionId + " HLog seq " + txid); throw exp; } if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: commitRequest COMMIT_OK -- EXIT txId: " + transactionId); returnPending = true; } // No write pending else { if (LOG.isInfoEnabled()) writeToLogTimes[lv_timeIndex] = 0; } if (LOG.isInfoEnabled()) { commitCheckTimes[lv_timeIndex] = commitCheckEndTime - commitCheckStartTime; hasConflictTimes[lv_timeIndex] = hasConflictEndTime - hasConflictStartTime; putBySequenceTimes[lv_timeIndex] = putBySequenceEndTime - putBySequenceStartTime; totalCommitCheckTime += commitCheckTimes[lv_timeIndex]; totalConflictTime += hasConflictTimes[lv_timeIndex]; totalPutTime += putBySequenceTimes[lv_timeIndex]; totalWriteToLogTime += writeToLogTimes[lv_timeIndex]; if (commitCheckTimes[lv_timeIndex] > maxCommitCheckTime) { maxCommitCheckTime = commitCheckTimes[lv_timeIndex]; } if (commitCheckTimes[lv_timeIndex] < minCommitCheckTime) { minCommitCheckTime = commitCheckTimes[lv_timeIndex]; } if (hasConflictTimes[lv_timeIndex] > maxConflictTime) { maxConflictTime = hasConflictTimes[lv_timeIndex]; } if (hasConflictTimes[lv_timeIndex] < minConflictTime) { minConflictTime = hasConflictTimes[lv_timeIndex]; } if (putBySequenceTimes[lv_timeIndex] > maxPutTime) { maxPutTime = putBySequenceTimes[lv_timeIndex]; } if (putBySequenceTimes[lv_timeIndex] < minPutTime) { minPutTime = putBySequenceTimes[lv_timeIndex]; } if (writeToLogTimes[lv_timeIndex] > maxWriteToLogTime) { maxWriteToLogTime = writeToLogTimes[lv_timeIndex]; } if (writeToLogTimes[lv_timeIndex] < minWriteToLogTime) { minWriteToLogTime = writeToLogTimes[lv_timeIndex]; } if (lv_timeIndex == 49) { timeIndex.set(1); // Start over so we don't exceed the array size } if (lv_totalCommits == 9999) { avgCommitCheckTime = (double) (totalCommitCheckTime / lv_totalCommits); avgConflictTime = (double) (totalConflictTime / lv_totalCommits); avgPutTime = (double) (totalPutTime / lv_totalCommits); avgWriteToLogTime = (double) ((double) totalWriteToLogTime / (double) lv_totalCommits); if (LOG.isInfoEnabled()) LOG.info("commitRequest Report\n" + " Region: " + m_Region.getRegionInfo().getRegionNameAsString() + "\n" + " Total commits: " + lv_totalCommits + "\n" + " commitCheckLock time:\n" + " Min: " + minCommitCheckTime / 1000 + " microseconds\n" + " Max: " + maxCommitCheckTime / 1000 + " microseconds\n" + " Avg: " + avgCommitCheckTime / 1000 + " microseconds\n" + " hasConflict time:\n" + " Min: " + minConflictTime / 1000 + " microseconds\n" + " Max: " + maxConflictTime / 1000 + " microseconds\n" + " Avg: " + avgConflictTime / 1000 + " microseconds\n" + " putBySequence time:\n" + " Min: " + minPutTime / 1000 + " microseconds\n" + " Max: " + maxPutTime / 1000 + " microseconds\n" + " Avg: " + avgPutTime / 1000 + " microseconds\n" + " Ops: " + putBySequenceOperations.get() + "\n" + " writeToLog time:\n" + " Min: " + minWriteToLogTime / 1000 + " microseconds\n" + " Max: " + maxWriteToLogTime / 1000 + " microseconds\n" + " Avg: " + avgWriteToLogTime / 1000 + " microseconds\n" + " Ops: " + writeToLogOperations.get() + "\n\n"); totalCommits.set(0); writeToLogOperations.set(0); putBySequenceOperations.set(0); totalCommitCheckTime = 0; totalConflictTime = 0; totalPutTime = 0; totalWriteToLogTime = 0; minCommitCheckTime = 1000000000; maxCommitCheckTime = 0; avgCommitCheckTime = 0; minConflictTime = 1000000000; maxConflictTime = 0; avgConflictTime = 0; minPutTime = 1000000000; maxPutTime = 0; avgPutTime = 0; minWriteToLogTime = 1000000000; maxWriteToLogTime = 0; avgWriteToLogTime = 0; } } // end of LOG.Info if (returnPending) { return COMMIT_OK; } // Otherwise we were read-only and commitable, so we can forget it. state.setStatus(Status.COMMITED); retireTransaction(state, true); if (LOG.isDebugEnabled()) LOG.debug("TrxRegionEndpoint coprocessor: commitRequest READ ONLY -- EXIT txId: " + transactionId); return COMMIT_OK_READ_ONLY; } /** * Determines if the transaction has any conflicts * @param TrxTransactionState state * @return boolean */ private boolean hasConflict(final TrxTransactionState state) { // Check transactions that were committed while we were running synchronized (commitedTransactionsBySequenceNumber) { for (long i = state.getStartSequenceNumber(); i < nextSequenceId.get(); i++) { TrxTransactionState other = commitedTransactionsBySequenceNumber.get(i); if (other == null) { continue; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: hasConflict state.getStartSequenceNumber is " + i + ", nextSequenceId.get() is " + nextSequenceId.get() + ", state object is " + state.toString() + ", calling addTransactionToCheck"); state.addTransactionToCheck(other); } } return state.hasConflict(); } /** * Abort the transaction. * * @param transactionId * @throws IOException * @throws UnknownTransactionException */ public void abortTransaction(final long transactionId) throws IOException, UnknownTransactionException { long txid = 0; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abort transactionId: " + transactionId + " " + m_Region.getRegionInfo().getRegionNameAsString()); TrxTransactionState state; try { state = getTransactionState(transactionId); } catch (UnknownTransactionException e) { IOException ioe = new IOException("UnknownTransactionException"); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction - Unknown transaction [" + transactionId + "] in region [" + m_Region.getRegionInfo().getRegionNameAsString() + "], " + ioe.toString()); throw new IOException("UnknownTransactionException"); } synchronized (state.getXaOperationObject()) { if (state.getStatus().equals(Status.ABORTED)) { // already aborted, duplicate abort requested if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction - duplicate abort transaction Id: " + transactionId + " " + m_Region.getRegionInfo().getRegionNameAsString()); return; } state.setStatus(Status.ABORTED); } if (state.hasWrite()) { // TODO log // this.transactionLog.writeAbortToLog(m_Region.getRegionInfo(), // state.getTransactionId(), // m_Region.getTableDesc()); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction - abort write to HLOG"); Tag abortTag = state.formTransactionalContextTag(TS_ABORT); List<Tag> tagList = new ArrayList<Tag>(); tagList.add(abortTag); WALEdit e1 = state.getEdit(); WALEdit e = new WALEdit(); if (e1.getKeyValues().size() > 0) { // get 1st Cell to associated with the abort record as a workaround through HLOG async append Cell c = e1.getKeyValues().get(0); KeyValue kv = new KeyValue(c.getRowArray(), c.getRowOffset(), (int) c.getRowLength(), c.getFamilyArray(), c.getFamilyOffset(), (int) c.getFamilyLength(), c.getQualifierArray(), c.getQualifierOffset(), (int) c.getQualifierLength(), c.getTimestamp(), Type.codeToType(c.getTypeByte()), c.getValueArray(), c.getValueOffset(), c.getValueLength(), tagList); e.add(kv); try { txid = this.tHLog.appendNoSync(this.regionInfo, this.regionInfo.getTable(), e, new ArrayList<UUID>(), EnvironmentEdgeManager.currentTimeMillis(), this.m_Region.getTableDesc(), nextLogSequenceId, false, HConstants.NO_NONCE, HConstants.NO_NONCE); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: Y99 write abort HLOG " + transactionId + " HLog seq " + txid); } catch (IOException exp1) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: abortTransaction - abort writing to HLOG : Caught an exception " + exp1.toString()); throw exp1; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction -- EXIT txId: " + transactionId + " HLog seq " + txid); } } synchronized (commitPendingTransactions) { commitPendingTransactions.remove(state); } if (state.isReinstated()) { synchronized (indoubtTransactionsById) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Trafodion Recovery: abort reinstated indoubt transactions " + transactionId); indoubtTransactionsById.remove(state.getTransactionId()); int tmid = (int) (transactionId >> 32); int count = 0; // indoubtTransactionsCountByTmid protected by // indoubtTransactionsById synchronization if (indoubtTransactionsCountByTmid.containsKey(tmid)) { count = (int) indoubtTransactionsCountByTmid.get(tmid) - 1; if (count > 0) indoubtTransactionsCountByTmid.put(tmid, count); } // if all reinstated txns are resolved from a TM, remove it and delete associated zNode if (count == 0) { indoubtTransactionsCountByTmid.remove(tmid); String lv_encoded = m_Region.getRegionInfo().getEncodedName(); try { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Trafodion Recovery: delete in abort recovery zNode TM " + tmid + " region encoded name " + lv_encoded + " for 0 in-doubt transaction"); deleteRecoveryzNode(tmid, lv_encoded); } catch (IOException e) { LOG.error( "TrxRegionEndpoint coprocessor: Trafodion Recovery: delete recovery zNode failed"); } } if ((indoubtTransactionsById == null) || (indoubtTransactionsById.size() == 0)) { // change region state to STARTED, and archive the split-thlog if (indoubtTransactionsById == null) if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Trafodion Recovery: start region in abort with indoubtTransactionsById null"); else if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: Trafodion Recovery: start region in abort with indoubtTransactionsById size " + indoubtTransactionsById.size()); startRegionAfterRecovery(); } } } retireTransaction(state, true); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: abortTransaction looking for abort transaction " + transactionId + ", transactionsById " + transactionsById.size() + ", commitedTransactionsBySequenceNumber " + commitedTransactionsBySequenceNumber.size() + ", commitPendingTransactions" + commitPendingTransactions.size()); } /** * Determines if the transaction can be committed, and if possible commits the transaction. * @param long transactionId * @return boolean * @throws IOException */ public boolean commitIfPossible(final long transactionId) throws IOException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible -- ENTRY txId: " + transactionId); int status = commitRequest(transactionId); if (status == COMMIT_OK) { // Process local memory try { commit(transactionId); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible -- ENTRY txId: " + transactionId + " COMMIT_OK"); return true; } catch (Throwable e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible - txId " + transactionId + ", Caught exception after internal commit call " + e.getMessage() + " " + stackTraceToString(e)); throw new IOException(e.toString()); } } else if (status == COMMIT_OK_READ_ONLY) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible -- ENTRY txId: " + transactionId + " COMMIT_OK_READ_ONLY"); return true; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: commitIfPossible -- ENTRY txId: " + transactionId + " Commit Unsuccessful"); return false; } /** * Formats a cleanup message for a Throwable * @param Throwable t * @param String msg * @return Throwable */ private Throwable cleanup(final Throwable t, final String msg) { if (t instanceof NotServingRegionException) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: cleanup - NotServingRegionException; " + t.getMessage()); return t; } if (msg == null) { LOG.error("TrxRegionEndpoint coprocessor: cleanup - cleanup message was null"); } else { LOG.error("TrxRegionEndpoint coprocessor: cleanup - cleanup message was " + msg); } return t; } private IOException convertThrowableToIOE(final Throwable t) { return convertThrowableToIOE(t, null); } /* * @param t * * @param msg Message to put in new IOE if passed <code>t</code> * is not an IOE * * @return Make <code>t</code> an IOE if it isn't already. */ private IOException convertThrowableToIOE(final Throwable t, final String msg) { return (t instanceof IOException ? (IOException) t : msg == null || msg.length() == 0 ? new IOException(t) : new IOException(msg, t)); } /** * Checks if the file system is available * @return boolean */ public boolean checkFileSystem() { if (this.fs != null) { try { FSUtils.checkFileSystemAvailable(this.fs); } catch (IOException e) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: checkFileSystemAvailable - File System not available threw IOException " + e.getMessage()); return false; } } return true; } /** * Prepares the family keys if the scan has no families defined * @param Scan scan * @throws IOException */ public void prepareScanner(Scan scan) throws IOException { if (!scan.hasFamilies()) { for (byte[] family : this.m_Region.getTableDesc().getFamiliesKeys()) { scan.addFamily(family); } } } /** * Checks if the row is within this region's row range * @param byte[] row * @param String op * @throws IOException */ public void checkRow(final byte[] row, String op) throws IOException { if (!this.m_Region.rowIsInRange(this.regionInfo, row)) { throw new WrongRegionException("Requested row out of range for " + op + " on HRegion " + this + ", startKey='" + Bytes.toStringBinary(this.regionInfo.getStartKey()) + "', getEndKey()='" + Bytes.toStringBinary(this.regionInfo.getEndKey()) + "', row='" + Bytes.toStringBinary(row) + "'"); } } /** * Returns the scanner associated with the specified ID. * * @param long scannerId * @param long nextCallSeq * @return a Scanner or throws UnknownScannerException * @throws NotServingRegionException * @throws OutOfOrderscannerNextException * @throws UnknownScannerException */ protected synchronized RegionScanner getScanner(long scannerId, long nextCallSeq) throws NotServingRegionException, OutOfOrderScannerNextException, UnknownScannerException { RegionScanner scanner = null; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScanner - scanner id " + scannerId + ", count is " + scanners.size()); TransactionalRegionScannerHolder rsh = scanners.get(scannerId); if (rsh != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScanner - rsh is " + rsh + "rsh.s is " + rsh.s); } else { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScanner - rsh is null"); throw new UnknownScannerException( "TrxRegionEndpoint getScanner - scanner id " + scannerId + ", already closed?"); } scanner = rsh.s; if (scanner != null) { HRegionInfo hri = scanner.getRegionInfo(); if (this.m_Region != rsh.r) { // Yes, should be the same instance throw new NotServingRegionException("Region was re-opened after the scannerId" + scannerId + " was created: " + hri.getRegionNameAsString()); } } if (nextCallSeq != rsh.nextCallSeq) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: getScanner - scanner id " + scannerId + ", calling OutOfOrderScannerNextException, nextCallSeq is " + nextCallSeq + " rsh.nextCallSeq is " + rsh.nextCallSeq); throw new OutOfOrderScannerNextException("TrxRegionEndpoint coprocessor: getScanner - scanner id " + scannerId + ", Expected nextCallSeq: " + rsh.nextCallSeq + ", But the nextCallSeq received from client: " + nextCallSeq); } return scanner; } /** * Removes the scanner associated with the specified ID from the internal * id->scanner TransactionalRegionScannerHolder map * * @param long scannerId * @return a Scanner or throws UnknownScannerException * @throws UnknownScannerException */ protected synchronized RegionScanner removeScanner(long scannerId) throws UnknownScannerException { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeScanner - scanner id " + scannerId + ", before count is " + scanners.size()); TransactionalRegionScannerHolder rsh = scanners.remove(scannerId); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeScanner - scanner id " + scannerId + ", after count is " + scanners.size()); if (rsh != null) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeScanner - scanner id " + scannerId + ", rsh is " + rsh + ", rsh.s is " + rsh.s); RegionScanner s = rsh.s; rsh.cleanHolder(); return s; } else { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: removeScanner - scanner id " + scannerId + ", rsh is null"); throw new UnknownScannerException("ScannerId: " + scannerId + ", already closed?"); } } /** * Adds a region scanner to the TransactionalRegionScannerHolder map * @param RegionScanner s * @param HRegion r * @return long * @throws LeaseStillHeldException */ protected synchronized long addScanner(long transId, RegionScanner s, HRegion r) throws LeaseStillHeldException { long scannerId = performScannerId.getAndIncrement(); TransactionalRegionScannerHolder rsh = new TransactionalRegionScannerHolder(transId, scannerId, s, r); if (rsh != null) if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: addScanner - scanner id " + scannerId + ", rsh is " + rsh); else if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: addScanner - scanner id " + scannerId + ", rsh is null"); TransactionalRegionScannerHolder existing = scanners.putIfAbsent(scannerId, rsh); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: addScanner - scanner id " + scannerId + ", count is " + scanners.size()); /* scannerLeases.createLease(getScannerLeaseId(scannerId), this.scannerLeaseTimeoutPeriod, new TransactionalScannerListener(scannerId)); */ return scannerId; } /** * * Instantiated as a scanner lease. If the lease times out, the scanner is * * closed * */ /* private class TransactionalScannerListener implements LeaseListener { private final long scannerId; TransactionalScannerListener(final long id) { this.scannerId = id; } @Override public void leaseExpired() { TransactionalRegionScannerHolder rsh = scanners.remove(this.scannerId); if (rsh != null) { RegionScanner s = rsh.s; if (LOG.isTraceEnabled()) LOG.trace("Scanner " + this.scannerId + " lease expired on region " + s.getRegionInfo().getRegionNameAsString()); try { HRegion region = rsh.r; s.close(); } catch (IOException e) { LOG.error("Closing scanner for " + s.getRegionInfo().getRegionNameAsString(), e); } } else { if (LOG.isTraceEnabled()) LOG.trace("Scanner " + this.scannerId + " lease expired"); } } } */ /** * Formats the throwable stacktrace to a string * @param Throwable e * @return String */ public String stackTraceToString(Throwable e) { StringBuilder sb = new StringBuilder(); for (StackTraceElement element : e.getStackTrace()) { sb.append(element.toString()); sb.append("\n"); } return sb.toString(); } /** * Returns the Scanner Leases for this coprocessor * @return Leases */ //synchronized protected Leases getScannerLeases() { // return this.scannerLeases; //} /** * Returns the Leases for this coprocessor * @return Leases */ synchronized protected Leases getTransactionalLeases() { return this.transactionLeases; } /** * Removes unneeded committed transactions */ synchronized public void removeUnNeededCommitedTransactions() { Long minStartSeqNumber = getMinStartSequenceNumber(); TrxTransactionState state = null; int numRemoved = 0; long key = 0; if (minStartSeqNumber == null) { minStartSeqNumber = Long.MAX_VALUE; } synchronized (commitedTransactionsBySequenceNumber) { for (Entry<Long, TrxTransactionState> entry : new LinkedList<Entry<Long, TrxTransactionState>>( commitedTransactionsBySequenceNumber.entrySet())) { key = entry.getKey(); if (key >= minStartSeqNumber) { break; } state = commitedTransactionsBySequenceNumber.remove(key); if (state != null) { state.clearState(); numRemoved++; //if (LOG.isTraceEnabled()) LOG.trace("removeUnNeededCommitedTransactions: Transaction - entry key " + key + ", " + state.toString()); } } } if (LOG.isTraceEnabled()) { StringBuilder traceMessage = new StringBuilder(); if (numRemoved > 0) { traceMessage.append("TrxRegionEndpoint coprocessor: removeUnNeededCommitedTransactions: Removed [") .append(numRemoved).append("] commited transactions"); if (minStartSeqNumber == Long.MAX_VALUE) { traceMessage.append(" with any sequence number."); } else { traceMessage.append(" with sequence lower than [").append(minStartSeqNumber).append("]."); } if (!commitedTransactionsBySequenceNumber.isEmpty()) { traceMessage.append(" Still have [").append(commitedTransactionsBySequenceNumber.size()) .append("] left."); } else { traceMessage.append(" None left."); } LOG.trace(traceMessage.toString()); } else if (commitedTransactionsBySequenceNumber.size() > 0) { traceMessage.append("Could not remove any transactions, and still have ") .append(commitedTransactionsBySequenceNumber.size()).append(" left"); LOG.trace(traceMessage.toString()); } } } /** * Removes unneeded TransactionalRegionScannerHolder objects */ synchronized public void removeUnNeededStaleScanners() { long scannerId = 0L; long transId = 0L; long listSize = 0L; long scannerSize = 0L; Long transactionId = 0L; TransactionalRegionScannerHolder rsh = null; Iterator<Long> transIter = null; Iterator<Map.Entry<Long, TransactionalRegionScannerHolder>> scannerIter = null; synchronized (cleanScannersForTransactions) { listSize = cleanScannersForTransactions.size(); if (listSize == 0) return; if (scanners == null || scanners.isEmpty()) return; scannerSize = scanners.size(); scannerIter = scanners.entrySet().iterator(); if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeUnNeededStaleScanners - transactions list count is " + listSize + ", scanners size is " + scannerSize); for (transIter = cleanScannersForTransactions.iterator(); transIter.hasNext();) { transactionId = transIter.next(); while (scannerIter.hasNext()) { Map.Entry<Long, TransactionalRegionScannerHolder> entry = scannerIter.next(); rsh = entry.getValue(); if (rsh != null) { transId = rsh.transId; scannerId = rsh.scannerId; if (transId == transactionId) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeUnNeededStaleScanners - txId " + transactionId + ", scannerId " + scannerId + ", Removing stale scanner "); try { if (rsh.s != null) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: removeUnNeededStaleScanners - txId " + transactionId + ", scannerId " + scannerId + ", Scanner was not previously closed "); rsh.s.close(); } rsh.s = null; rsh.r = null; scannerIter.remove(); } catch (Exception e) { if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: removeUnNeededStaleScanners - txId " + transactionId + ", scannerId " + scannerId + ", Caught exception " + e.toString()); } } } } } // End of for loop cleanScannersForTransactions.clear(); } // End of synchronization } /** * Returns the minimum start sequence number * @return Integer */ private Long getMinStartSequenceNumber() { List<TrxTransactionState> transactionStates; synchronized (transactionsById) { transactionStates = new ArrayList<TrxTransactionState>(transactionsById.values()); } Long min = null; for (TrxTransactionState transactionState : transactionStates) { try { if (min == null || transactionState.getStartSequenceNumber() < min) { min = transactionState.getStartSequenceNumber(); } } catch (NullPointerException npe) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: getMinStartSequenceNumber ignoring NullPointerException "); } } return min; } /** * Returns the region name as a string * @return String */ public String getRegionNameAsString() { return this.m_Region.getRegionNameAsString(); } /** * Simple helper class that just keeps track of whether or not its stopped. */ private static class StoppableImplementation implements Stoppable { private volatile boolean stop = false; @Override public void stop(String why) { this.stop = true; } @Override public boolean isStopped() { return this.stop; } } synchronized public void checkMemoryUsage() { long memUsed = 0L; long memMax = 0L; if (memoryUsageThreshold < DEFAULT_MEMORY_THRESHOLD && memoryBean != null) { memUsed = memoryBean.getHeapMemoryUsage().getUsed(); memMax = memoryBean.getHeapMemoryUsage().getMax(); memoryPercentage = 0L; if (memMax != 0) { memoryPercentage = (memUsed * 100) / memMax; } memoryThrottle = false; if (memoryPercentage > memoryUsageThreshold) { // If configured to perform a garbage collection, // try to release memory before throttling the queries. if (memoryUsagePerformGC == true) { if (LOG.isTraceEnabled()) LOG.trace( "TrxRegionEndpoint coprocessor: checkMemoryUsage - before GC, memoryPercentage is " + memoryPercentage); System.gc(); // Calculate the memory usage again before // setting the throttle value or post a warning. memUsed = memoryBean.getHeapMemoryUsage().getUsed(); memMax = memoryBean.getHeapMemoryUsage().getMax(); memoryPercentage = 0L; if (memMax != 0) { memoryPercentage = (memUsed * 100) / memMax; } if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkMemoryUsage - after GC, memoryPercentage is " + memoryPercentage); if (memoryPercentage > memoryUsageThreshold) { if (memoryUsageWarnOnly == false) memoryThrottle = true; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkMemoryUsage - memoryPercentage is " + memoryPercentage + ", memoryThrottle is " + memoryThrottle); } } else { if (memoryUsageWarnOnly == false) memoryThrottle = true; if (LOG.isTraceEnabled()) LOG.trace("TrxRegionEndpoint coprocessor: checkMemoryUsage - memoryPercentage is " + memoryPercentage + ", memoryThrottle is " + memoryThrottle); } } } } } //1}