<commit_before>package com.splicemachine.si.impl;

import com.carrotsearch.hppc.LongArrayList;
import com.carrotsearch.hppc.LongOpenHashSet;
import com.splicemachine.constants.SIConstants;
import com.splicemachine.si.api.ReadResolver;
import com.splicemachine.si.api.TxnSupplier;
import com.splicemachine.si.api.TxnView;
import com.splicemachine.si.data.api.IHTable;
import com.splicemachine.si.impl.store.ActiveTxnCacheSupplier;
import com.splicemachine.utils.ByteSlice;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.Filter;
import java.io.IOException;

/**
 * Transaction filter which performs basic transactional filtering (i.e. row visibility, tombstones,
 * anti-tombstones, etc.)
 *
 * @author <NAME>
 * Date: 6/23/14
 */
public class SimpleTxnFilter<RowLock,Data> implements TxnFilter<Data> {
		private final TxnSupplier transactionStore;
		private final TxnView myTxn;
		private final DataStore<RowLock,Data,Mutation,Put,Delete,Get,Scan,IHTable> dataStore;
		private final ReadResolver readResolver;
		//per row fields
		private final LongOpenHashSet visitedTxnIds = new LongOpenHashSet();
		private final LongArrayList tombstonedTxnRows = new LongArrayList(1); //usually, there are very few deletes
		private final LongArrayList antiTombstonedTxnRows = new LongArrayList(1);
		private final ByteSlice rowKey = new ByteSlice();

    /*
     * The most common case for databases is insert-only--that is, that there
     * are few updates and deletes relative to the number of inserts. As a result,
     * we can assume that *most* rows will only have a single version of data *most*
     * of the time. This enables us to bypass transaction caching whenever we have
     * a transaction--that is, the first time we look up a transaction, we stash it
     * in this variable. Then, the next time we want the transaction information, we check
     * this variable first. That way, we avoid potentially expensive locking through the
     * transaction supplier.
     */
    private TxnView currentTxn;

		@SuppressWarnings("unchecked")
		public SimpleTxnFilter(TxnSupplier transactionStore,
													 TxnView myTxn,
													 ReadResolver readResolver,
													 DataStore dataStore) {
				this.transactionStore = new ActiveTxnCacheSupplier(transactionStore, SIConstants.activeTransactionCacheSize); //cache active transactions, but only on this thread
				this.myTxn = myTxn;
				assert readResolver != null && dataStore != null;
				this.readResolver = readResolver;
				this.dataStore = dataStore;
		}

		@Override
		public KeyValueType getType(Data element) throws IOException {
				return dataStore.getKeyValueType(element);
		}

		@Override
		public Filter.ReturnCode filterKeyValue(Data element) throws IOException {
				KeyValueType type = dataStore.getKeyValueType(element);
				if(type==KeyValueType.COMMIT_TIMESTAMP){
						ensureTransactionIsCached(element);
						return Filter.ReturnCode.SKIP;
				}

				readResolve(element);
				switch(dataStore.getKeyValueType(element)){
						case TOMBSTONE:
								addToTombstoneCache(element);
								return Filter.ReturnCode.SKIP;
						case ANTI_TOMBSTONE:
								addToAntiTombstoneCache(element);
								return Filter.ReturnCode.SKIP;
						case USER_DATA:
								return checkVisibility(element);
						default:
								//TODO -sf- do better with this?
								throw new AssertionError("Unexpected Data type: "+ dataStore.getKeyValueType(element));
				}
		}

		@Override
		public void nextRow() {
				//clear row-specific fields
				visitedTxnIds.clear();
				tombstonedTxnRows.clear();
				antiTombstonedTxnRows.clear();
				rowKey.reset();
		}

		@Override public Data produceAccumulatedKeyValue() { return null; }
		@Override public boolean getExcludeRow() { return false; }<commit_msg>DB-2219: SimpleTxnFilter: minor optimization, only get KeyValue type once in filterKeyValue method.<commit_after>package com.splicemachine.si.impl;

import com.carrotsearch.hppc.LongArrayList;
import com.carrotsearch.hppc.LongOpenHashSet;
import com.splicemachine.constants.SIConstants;
import com.splicemachine.si.api.ReadResolver;
import com.splicemachine.si.api.TxnSupplier;
import com.splicemachine.si.api.TxnView;
import com.splicemachine.si.data.api.IHTable;
import com.splicemachine.si.impl.store.ActiveTxnCacheSupplier;
import com.splicemachine.utils.ByteSlice;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.Filter;
import java.io.IOException;

/**
 * Transaction filter which performs basic transactional filtering (i.e. row visibility, tombstones,
 * anti-tombstones, etc.)
 *
 * @author <NAME>
 * Date: 6/23/14
 */
public class SimpleTxnFilter<RowLock,Data> implements TxnFilter<Data> {
		private final TxnSupplier transactionStore;
		private final TxnView myTxn;
		private final DataStore<RowLock,Data,Mutation,Put,Delete,Get,Scan,IHTable> dataStore;
		private final ReadResolver readResolver;
		//per row fields
		private final LongOpenHashSet visitedTxnIds = new LongOpenHashSet();
		private final LongArrayList tombstonedTxnRows = new LongArrayList(1); //usually, there are very few deletes
		private final LongArrayList antiTombstonedTxnRows = new LongArrayList(1);
		private final ByteSlice rowKey = new ByteSlice();

    /*
     * The most common case for databases is insert-only--that is, that there
     * are few updates and deletes relative to the number of inserts. As a result,
     * we can assume that *most* rows will only have a single version of data *most*
     * of the time. This enables us to bypass transaction caching whenever we have
     * a transaction--that is, the first time we look up a transaction, we stash it
     * in this variable. Then, the next time we want the transaction information, we check
     * this variable first. That way, we avoid potentially expensive locking through the
     * transaction supplier.
     */
    private TxnView currentTxn;

		@SuppressWarnings("unchecked")
		public SimpleTxnFilter(TxnSupplier transactionStore,
													 TxnView myTxn,
													 ReadResolver readResolver,
													 DataStore dataStore) {
				this.transactionStore = new ActiveTxnCacheSupplier(transactionStore, SIConstants.activeTransactionCacheSize); //cache active transactions, but only on this thread
				this.myTxn = myTxn;
				assert readResolver != null && dataStore != null;
				this.readResolver = readResolver;
				this.dataStore = dataStore;
		}

		@Override
		public KeyValueType getType(Data element) throws IOException {
				return dataStore.getKeyValueType(element);
		}

		@Override
		public Filter.ReturnCode filterKeyValue(Data element) throws IOException {
				KeyValueType type = dataStore.getKeyValueType(element);
				if(type==KeyValueType.COMMIT_TIMESTAMP){
						ensureTransactionIsCached(element);
						return Filter.ReturnCode.SKIP;
				}

				readResolve(element);
				switch(type){
						case TOMBSTONE:
								addToTombstoneCache(element);
								return Filter.ReturnCode.SKIP;
						case ANTI_TOMBSTONE:
								addToAntiTombstoneCache(element);
								return Filter.ReturnCode.SKIP;
						case USER_DATA:
								return checkVisibility(element);
						default:
								//TODO -sf- do better with this?
								throw new AssertionError("Unexpected Data type: "+ type);
				}
		}

		@Override
		public void nextRow() {
				//clear row-specific fields
				visitedTxnIds.clear();
				tombstonedTxnRows.clear();
				antiTombstonedTxnRows.clear();
				rowKey.reset();
		}

		@Override public Data produceAccumulatedKeyValue() { return null; }
		@Override public boolean getExcludeRow() { return false; }
{'fraction_non_alphanumeric': 0.08272155217619297, 'fraction_numerical': 0.0023597273203985318, 'mean_word_length': 3.941062176165803, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7060727', 'n_tokens_mistral': 2596, 'n_tokens_neox': 2187, 'n_words': 617}