incubator-blur-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From amccu...@apache.org
Subject git commit: Adding a hook to be able to filter both queries and data fetchs outside the normal user api. This should allow for security to be embedded within the data.
Date Fri, 20 Dec 2013 14:26:02 GMT
Updated Branches:
  refs/heads/apache-blur-0.2 33f083166 -> 179d53864


Adding a hook to be able to filter both queries and data fetchs outside the normal user api.  This should allow for security to be embedded within the data.


Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/179d5386
Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/179d5386
Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/179d5386

Branch: refs/heads/apache-blur-0.2
Commit: 179d53864ec4f47a98426b1555935d63d78ac256
Parents: 33f0831
Author: Aaron McCurry <amccurry@gmail.com>
Authored: Fri Dec 20 09:25:16 2013 -0500
Committer: Aaron McCurry <amccurry@gmail.com>
Committed: Fri Dec 20 09:25:16 2013 -0500

----------------------------------------------------------------------
 .../org/apache/blur/manager/IndexManager.java   |  89 +++++++++---
 .../apache/blur/manager/ReadInterceptor.java    |  34 +++++
 .../results/BlurResultIterableSearcher.java     |   9 +-
 .../org/apache/blur/server/TableContext.java    |  37 +++++
 .../blur/thrift/ThriftBlurShardServer.java      |   8 +-
 .../java/org/apache/blur/utils/BlurUtil.java    |  42 +++++-
 .../org/apache/blur/utils/HighlightHelper.java  |   5 +-
 .../apache/blur/manager/IndexManagerTest.java   | 137 +++++++++++++++++--
 .../IndexManagerTestReadInterceptor.java        |  46 +++++++
 .../org/apache/blur/utils/BlurUtilsTest.java    |   6 +-
 .../org/apache/blur/mapreduce/BlurReducer.java  |   2 +-
 .../blur/lucene/search/IterablePaging.java      |  55 ++++----
 .../lucene/search/TestingPagingCollector.java   |   2 +-
 .../org/apache/blur/utils/BlurConstants.java    |   1 +
 .../src/main/resources/blur-default.properties  |   3 +
 docs/cluster-setup.html                         |   2 +-
 16 files changed, 403 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java b/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
index babe21f..9915483 100644
--- a/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
+++ b/blur-core/src/main/java/org/apache/blur/manager/IndexManager.java
@@ -93,10 +93,13 @@ import org.apache.blur.utils.HighlightHelper;
 import org.apache.blur.utils.ResetableDocumentStoredFieldVisitor;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.AtomicReader;
+import org.apache.lucene.index.BaseCompositeReader;
+import org.apache.lucene.index.BaseCompositeReaderUtil;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.SegmentReader;
 import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
@@ -104,6 +107,8 @@ import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.queryparser.classic.ParseException;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.DocIdSet;
+import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TermQuery;
@@ -214,7 +219,7 @@ public class IndexManager {
         @Override
         public FetchResult call() throws Exception {
           FetchResult fetchResult = new FetchResult();
-          fetchRow(table, selector, fetchResult);
+          fetchRow(table, selector, fetchResult, false);
           return fetchResult;
         }
       }));
@@ -234,7 +239,19 @@ public class IndexManager {
   }
 
   public void fetchRow(String table, Selector selector, FetchResult fetchResult) throws BlurException {
+    fetchRow(table, selector, fetchResult, false);
+  }
+
+  public void fetchRow(String table, Selector selector, FetchResult fetchResult, boolean mutation) throws BlurException {
     validSelector(selector);
+    TableContext tableContext = getTableContext(table);
+    ReadInterceptor interceptor = tableContext.getReadInterceptor();
+    Filter filter;
+    if (mutation) {
+      filter = interceptor.getFilterForMutation();
+    } else {
+      filter = interceptor.getFilter();
+    }
     BlurIndex index = null;
     String shard = null;
     Tracer trace = Trace.trace("manager fetch", Trace.param("table", table));
@@ -244,7 +261,7 @@ public class IndexManager {
         // Not looking up by location id so we should resetSearchers.
         ShardServerContext.resetSearchers();
         shard = MutationHelper.getShardName(table, selector.rowId, getNumberOfShards(table), _blurPartitioner);
-        index = getBlurIndex(table,shard);
+        index = getBlurIndex(table, shard);
         searcher = index.getIndexSearcher();
         populateSelector(searcher, shard, table, selector);
       }
@@ -258,7 +275,7 @@ public class IndexManager {
         shard = getShard(locationId);
       }
       if (index == null) {
-        index = getBlurIndex(table,shard);
+        index = getBlurIndex(table, shard);
       }
     } catch (BlurException e) {
       throw e;
@@ -278,13 +295,12 @@ public class IndexManager {
         searcher = index.getIndexSearcher();
         usedCache = false;
       }
-      TableContext tableContext = getTableContext(table);
       FieldManager fieldManager = tableContext.getFieldManager();
 
       Query highlightQuery = getHighlightQuery(selector, table, fieldManager);
 
       fetchRow(searcher.getIndexReader(), table, shard, selector, fetchResult, highlightQuery, fieldManager,
-          _maxHeapPerRowFetch, tableContext);
+          _maxHeapPerRowFetch, tableContext, filter);
 
       if (fetchResult.rowResult != null) {
         if (fetchResult.rowResult.row != null && fetchResult.rowResult.row.records != null) {
@@ -455,8 +471,9 @@ public class IndexManager {
           preFilter, getScoreType(simpleQuery.scoreType), context);
       Query facetedQuery = getFacetedQuery(blurQuery, userQuery, facetedCounts, fieldManager, context, postFilter,
           preFilter);
-      call = new SimpleQueryParallelCall(running, table, status, facetedQuery, blurQuery.selector,
-          _queriesInternalMeter, shardServerContext, runSlow, _fetchCount, _maxHeapPerRowFetch,
+      ReadInterceptor interceptor = context.getReadInterceptor();
+      call = new SimpleQueryParallelCall(running, table, status, facetedQuery, interceptor.getFilter(),
+          blurQuery.selector, _queriesInternalMeter, shardServerContext, runSlow, _fetchCount, _maxHeapPerRowFetch,
           context.getSimilarity(), context);
       trace.done();
       MergerBlurResultIterable merger = new MergerBlurResultIterable(blurQuery);
@@ -549,14 +566,14 @@ public class IndexManager {
   }
 
   public static void fetchRow(IndexReader reader, String table, String shard, Selector selector,
-      FetchResult fetchResult, Query highlightQuery, int maxHeap, TableContext tableContext)
+      FetchResult fetchResult, Query highlightQuery, int maxHeap, TableContext tableContext, Filter filter)
       throws CorruptIndexException, IOException {
-    fetchRow(reader, table, shard, selector, fetchResult, highlightQuery, null, maxHeap, tableContext);
+    fetchRow(reader, table, shard, selector, fetchResult, highlightQuery, null, maxHeap, tableContext, filter);
   }
 
   public static void fetchRow(IndexReader reader, String table, String shard, Selector selector,
-      FetchResult fetchResult, Query highlightQuery, FieldManager fieldManager, int maxHeap, TableContext tableContext)
-      throws CorruptIndexException, IOException {
+      FetchResult fetchResult, Query highlightQuery, FieldManager fieldManager, int maxHeap, TableContext tableContext,
+      Filter filter) throws CorruptIndexException, IOException {
     fetchResult.table = table;
     String locationId = selector.locationId;
     int lastSlash = locationId.lastIndexOf('/');
@@ -578,7 +595,11 @@ public class IndexManager {
     ResetableDocumentStoredFieldVisitor fieldVisitor = getFieldSelector(selector);
     if (selector.isRecordOnly()) {
       // select only the row for the given data or location id.
-      if (liveDocs != null && !liveDocs.get(docId)) {
+      if (isFiltered(docId, reader, filter)) {
+        fetchResult.exists = false;
+        fetchResult.deleted = false;
+        return;
+      } else if (liveDocs != null && !liveDocs.get(docId)) {
         fetchResult.exists = false;
         fetchResult.deleted = true;
         return;
@@ -612,7 +633,6 @@ public class IndexManager {
         } else {
           fetchResult.exists = true;
           fetchResult.deleted = false;
-
           if (returnIdsOnly) {
             String rowId = selector.getRowId();
             if (rowId == null) {
@@ -635,12 +655,12 @@ public class IndexManager {
               String postTag = highlightOptions.getPostTag();
               Tracer docTrace = Trace.trace("fetchRow - Document w/Highlight read");
               docs = HighlightHelper.highlightDocuments(reader, term, fieldVisitor, selector, highlightQuery,
-                  fieldManager, preTag, postTag);
+                  fieldManager, preTag, postTag, filter);
               docTrace.done();
             } else {
               Tracer docTrace = Trace.trace("fetchRow - Document read");
               docs = BlurUtil.fetchDocuments(reader, fieldVisitor, selector, maxHeap, table + "/" + shard,
-                  tableContext.getDefaultPrimeDocTerm());
+                  tableContext.getDefaultPrimeDocTerm(), filter);
               docTrace.done();
             }
             Tracer rowTrace = Trace.trace("fetchRow - Row create");
@@ -655,6 +675,37 @@ public class IndexManager {
     }
   }
 
+  @SuppressWarnings("unchecked")
+  private static boolean isFiltered(int notAdjustedDocId, IndexReader reader, Filter filter) throws IOException {
+    if (filter == null) {
+      return false;
+    }
+    if (reader instanceof BaseCompositeReader) {
+      BaseCompositeReader<IndexReader> indexReader = (BaseCompositeReader<IndexReader>) reader;
+      List<? extends IndexReader> sequentialSubReaders = BaseCompositeReaderUtil.getSequentialSubReaders(indexReader);
+      int readerIndex = BaseCompositeReaderUtil.readerIndex(indexReader, notAdjustedDocId);
+      int readerBase = BaseCompositeReaderUtil.readerBase(indexReader, readerIndex);
+      int docId = notAdjustedDocId - readerBase;
+      IndexReader orgReader = sequentialSubReaders.get(readerIndex);
+      SegmentReader sReader = BlurUtil.getSegmentReader(orgReader);
+      if (sReader != null) {
+        SegmentReader segmentReader = (SegmentReader) sReader;
+        DocIdSet docIdSet = filter.getDocIdSet(segmentReader.getContext(), segmentReader.getLiveDocs());
+        DocIdSetIterator iterator = docIdSet.iterator();
+        if (iterator == null) {
+          return true;
+        }
+        if (iterator.advance(docId) == docId) {
+          return false;
+        }
+        return true;
+      }
+      throw new RuntimeException("Reader has to be a SegmentReader [" + orgReader + "]");
+    } else {
+      throw new RuntimeException("Reader has to be a BaseCompositeReader [" + reader + "]");
+    }
+  }
+
   private static String getRowId(IndexReader reader, int docId) throws CorruptIndexException, IOException {
     reader.document(docId, new StoredFieldVisitor() {
       @Override
@@ -986,7 +1037,7 @@ public class IndexManager {
     FetchResult fetchResult = new FetchResult();
     Selector selector = new Selector();
     selector.setRowId(mutation.rowId);
-    fetchRow(mutation.table, selector, fetchResult);
+    fetchRow(mutation.table, selector, fetchResult, true);
     Row existingRow;
     if (fetchResult.exists) {
       // We will examine the contents of the existing row and add records
@@ -1098,8 +1149,9 @@ public class IndexManager {
     private final int _maxHeapPerRowFetch;
     private final Similarity _similarity;
     private final TableContext _context;
+    private final Filter _filter;
 
-    public SimpleQueryParallelCall(AtomicBoolean running, String table, QueryStatus status, Query query,
+    public SimpleQueryParallelCall(AtomicBoolean running, String table, QueryStatus status, Query query, Filter filter,
         Selector selector, Meter queriesInternalMeter, ShardServerContext shardServerContext, boolean runSlow,
         int fetchCount, int maxHeapPerRowFetch, Similarity similarity, TableContext context) {
       _running = running;
@@ -1114,6 +1166,7 @@ public class IndexManager {
       _maxHeapPerRowFetch = maxHeapPerRowFetch;
       _similarity = similarity;
       _context = context;
+      _filter = filter;
     }
 
     @Override
@@ -1150,7 +1203,7 @@ public class IndexManager {
         // context is null.
         trace2 = Trace.trace("query initial search");
         return new BlurResultIterableSearcher(_running, rewrite, _table, shard, searcher, _selector,
-            _shardServerContext == null, _runSlow, _fetchCount, _maxHeapPerRowFetch, _context);
+            _shardServerContext == null, _runSlow, _fetchCount, _maxHeapPerRowFetch, _context, _filter);
       } catch (BlurException e) {
         switch (_status.getQueryStatus().getState()) {
         case INTERRUPTED:

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/manager/ReadInterceptor.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/manager/ReadInterceptor.java b/blur-core/src/main/java/org/apache/blur/manager/ReadInterceptor.java
new file mode 100644
index 0000000..fdd5244
--- /dev/null
+++ b/blur-core/src/main/java/org/apache/blur/manager/ReadInterceptor.java
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.blur.manager;
+
+import org.apache.blur.BlurConfiguration;
+import org.apache.lucene.search.Filter;
+
+public abstract class ReadInterceptor {
+
+  public ReadInterceptor(BlurConfiguration configuration) {
+
+  }
+
+  public abstract Filter getFilter();
+
+  public Filter getFilterForMutation() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/manager/results/BlurResultIterableSearcher.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/manager/results/BlurResultIterableSearcher.java b/blur-core/src/main/java/org/apache/blur/manager/results/BlurResultIterableSearcher.java
index a6d8519..1129b92 100644
--- a/blur-core/src/main/java/org/apache/blur/manager/results/BlurResultIterableSearcher.java
+++ b/blur-core/src/main/java/org/apache/blur/manager/results/BlurResultIterableSearcher.java
@@ -35,6 +35,7 @@ import org.apache.blur.thrift.generated.Selector;
 import org.apache.blur.utils.BlurIterator;
 import org.apache.blur.utils.Converter;
 import org.apache.blur.utils.IteratorConverter;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
 
@@ -57,10 +58,11 @@ public class BlurResultIterableSearcher implements BlurResultIterable {
   private final boolean _runSlow;
   private final int _maxHeapPerRowFetch;
   private final TableContext _context;
+  private final Filter _filter;
 
   public BlurResultIterableSearcher(AtomicBoolean running, Query query, String table, String shard,
       IndexSearcherClosable searcher, Selector selector, boolean closeSearcher, boolean runSlow, int fetchCount,
-      int maxHeapPerRowFetch, TableContext context) throws BlurException {
+      int maxHeapPerRowFetch, TableContext context, Filter filter) throws BlurException {
     _running = running;
     _table = table;
     _query = query;
@@ -72,12 +74,13 @@ public class BlurResultIterableSearcher implements BlurResultIterable {
     _fetchCount = fetchCount;
     _maxHeapPerRowFetch = maxHeapPerRowFetch;
     _context = context;
+    _filter = filter;
     performSearch();
   }
 
   private void performSearch() throws BlurException {
     IterablePaging iterablePaging = new IterablePaging(_running, _searcher, _query, _fetchCount, _totalHitsRef,
-        _progressRef, _runSlow);
+        _progressRef, _runSlow, _filter);
     _iterator = new IteratorConverter<ScoreDoc, BlurResult, BlurException>(iterablePaging.iterator(),
         new Converter<ScoreDoc, BlurResult, BlurException>() {
           @Override
@@ -98,7 +101,7 @@ public class BlurResultIterableSearcher implements BlurResultIterable {
     IndexManager.validSelector(_selector);
     try {
       IndexManager.fetchRow(_searcher.getIndexReader(), _table, _shard, _selector, fetchResult, null,
-          _maxHeapPerRowFetch, _context);
+          _maxHeapPerRowFetch, _context, _filter);
     } catch (IOException e) {
       throw new BlurException("Unknown IO error", null, ErrorType.UNKNOWN);
     }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/server/TableContext.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/server/TableContext.java b/blur-core/src/main/java/org/apache/blur/server/TableContext.java
index 303fd8a..7c867ca 100644
--- a/blur-core/src/main/java/org/apache/blur/server/TableContext.java
+++ b/blur-core/src/main/java/org/apache/blur/server/TableContext.java
@@ -20,6 +20,7 @@ import static org.apache.blur.utils.BlurConstants.BLUR_FIELDTYPE;
 import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_BLURINDEX_CLASS;
 import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_INDEX_DELETION_POLICY_MAXAGE;
 import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_INDEX_SIMILARITY;
+import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_READ_INTERCEPTOR;
 import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_TIME_BETWEEN_COMMITS;
 import static org.apache.blur.utils.BlurConstants.BLUR_SHARD_TIME_BETWEEN_REFRESHS;
 import static org.apache.blur.utils.BlurConstants.SUPER;
@@ -44,6 +45,7 @@ import org.apache.blur.log.Log;
 import org.apache.blur.log.LogFactory;
 import org.apache.blur.lucene.search.FairSimilarity;
 import org.apache.blur.lucene.store.refcounter.DirectoryReferenceFileGC;
+import org.apache.blur.manager.ReadInterceptor;
 import org.apache.blur.manager.writer.BlurIndex;
 import org.apache.blur.manager.writer.BlurIndexCloser;
 import org.apache.blur.manager.writer.BlurIndexRefresher;
@@ -58,6 +60,7 @@ import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.lucene.index.IndexDeletionPolicy;
 import org.apache.lucene.index.KeepOnlyLastCommitDeletionPolicy;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.store.Directory;
 
@@ -72,6 +75,18 @@ public class TableContext {
   private static Configuration _systemConfiguration;
   private static BlurConfiguration _systemBlurConfiguration;
 
+  private static final ReadInterceptor DEFAULT_INTERCEPTOR = new ReadInterceptor(null) {
+    @Override
+    public Filter getFilterForMutation() {
+      return null;
+    }
+
+    @Override
+    public Filter getFilter() {
+      return null;
+    }
+  };
+
   private Path _tablePath;
   private Path _walTablePath;
   private String _defaultFieldName;
@@ -86,6 +101,7 @@ public class TableContext {
   private Term _defaultPrimeDocTerm;
   private FieldManager _fieldManager;
   private BlurConfiguration _blurConfiguration;
+  private ReadInterceptor _readInterceptor;
 
   protected TableContext() {
 
@@ -159,6 +175,23 @@ public class TableContext {
     Class<?> c2 = configuration.getClass(BLUR_SHARD_INDEX_SIMILARITY, FairSimilarity.class);
     tableContext._similarity = (Similarity) configure(ReflectionUtils.newInstance(c2, configuration), tableContext);
 
+    String readInterceptorClass = blurConfiguration.get(BLUR_SHARD_READ_INTERCEPTOR);
+    if (readInterceptorClass == null || readInterceptorClass.trim().isEmpty()) {
+      tableContext._readInterceptor = DEFAULT_INTERCEPTOR;
+    } else {
+      try {
+        @SuppressWarnings("unchecked")
+        Class<? extends ReadInterceptor> clazz = (Class<? extends ReadInterceptor>) Class.forName(readInterceptorClass);
+        Constructor<? extends ReadInterceptor> constructor = clazz
+            .getConstructor(new Class[] { BlurConfiguration.class });
+        tableContext._readInterceptor = constructor.newInstance(blurConfiguration);
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+    }
+    tableContext._similarity = (Similarity) configure(ReflectionUtils.newInstance(c2, configuration), tableContext);
+    // DEFAULT_INTERCEPTOR
+
     _cache.put(name, tableContext);
     return tableContext;
   }
@@ -328,4 +361,8 @@ public class TableContext {
       throw new IOException(e);
     }
   }
+
+  public ReadInterceptor getReadInterceptor() {
+    return _readInterceptor;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/thrift/ThriftBlurShardServer.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/thrift/ThriftBlurShardServer.java b/blur-core/src/main/java/org/apache/blur/thrift/ThriftBlurShardServer.java
index 4159b91..8339c42 100644
--- a/blur-core/src/main/java/org/apache/blur/thrift/ThriftBlurShardServer.java
+++ b/blur-core/src/main/java/org/apache/blur/thrift/ThriftBlurShardServer.java
@@ -232,7 +232,7 @@ public class ThriftBlurShardServer extends ThriftServer {
     shardServer.setMaxRecordsPerRowFetchRequest(configuration.getInt(BLUR_MAX_RECORDS_PER_ROW_FETCH_REQUEST, 1000));
     shardServer.setConfiguration(configuration);
     shardServer.init();
-    
+
     final TraceStorage traceStorage = setupTraceStorage(configuration);
     Trace.setStorage(traceStorage);
     Trace.setNodeName(nodeName);
@@ -253,7 +253,7 @@ public class ThriftBlurShardServer extends ThriftServer {
     int threadCount = configuration.getInt(BLUR_SHARD_SERVER_THRIFT_THREAD_COUNT, 32);
 
     ShardServerEventHandler eventHandler = new ShardServerEventHandler();
-    
+
     final ThriftBlurShardServer server = new ThriftBlurShardServer();
     server.setNodeName(nodeName);
     server.setServerTransport(tNonblockingServerSocket);
@@ -270,8 +270,8 @@ public class ThriftBlurShardServer extends ThriftServer {
       @Override
       public void shutdown() {
         ThreadWatcher threadWatcher = ThreadWatcher.instance();
-        quietClose(traceStorage, refresher, server, shardServer, indexManager, indexServer, threadWatcher, clusterStatus, zooKeeper,
-            httpServer);
+        quietClose(traceStorage, refresher, server, shardServer, indexManager, indexServer, threadWatcher,
+            clusterStatus, zooKeeper, httpServer);
       }
     };
     server.setShutdown(shutdown);

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/utils/BlurUtil.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/utils/BlurUtil.java b/blur-core/src/main/java/org/apache/blur/utils/BlurUtil.java
index 428317a..3e4004f 100644
--- a/blur-core/src/main/java/org/apache/blur/utils/BlurUtil.java
+++ b/blur-core/src/main/java/org/apache/blur/utils/BlurUtil.java
@@ -111,6 +111,9 @@ import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.search.DocIdSet;
+import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
@@ -768,12 +771,13 @@ public class BlurUtil {
    * 
    * @param selector
    * @param primeDocTerm
+   * @param filter
    * 
    * @throws IOException
    */
   @SuppressWarnings("unchecked")
   public static List<Document> fetchDocuments(IndexReader reader, ResetableDocumentStoredFieldVisitor fieldSelector,
-      Selector selector, int maxHeap, String context, Term primeDocTerm) throws IOException {
+      Selector selector, int maxHeap, String context, Term primeDocTerm, Filter filter) throws IOException {
     if (reader instanceof BaseCompositeReader) {
       BaseCompositeReader<IndexReader> indexReader = (BaseCompositeReader<IndexReader>) reader;
       List<? extends IndexReader> sequentialSubReaders = BaseCompositeReaderUtil.getSequentialSubReaders(indexReader);
@@ -791,6 +795,7 @@ public class BlurUtil {
       if (sReader != null) {
         SegmentReader segmentReader = (SegmentReader) sReader;
         Bits liveDocs = segmentReader.getLiveDocs();
+
         OpenBitSet bitSet = PrimeDocCache.getPrimeDocBitSet(primeDocTerm, segmentReader);
         int nextPrimeDoc = bitSet.nextSetBit(primeDocId + 1);
         int numberOfDocsInRow;
@@ -799,14 +804,14 @@ public class BlurUtil {
         } else {
           numberOfDocsInRow = nextPrimeDoc - primeDocId;
         }
-        OpenBitSet docsInRowSpanToFetch = getDocsToFetch(primeDocId, segmentReader, selector, primeDocId,
-            numberOfDocsInRow, liveDocs);
+        OpenBitSet docsInRowSpanToFetch = getDocsToFetch(segmentReader, selector, primeDocId, numberOfDocsInRow,
+            liveDocs, filter);
         int start = selector.getStartRecord();
         int maxDocsToFetch = selector.getMaxRecordsToFetch();
         int startingPosition = getStartingPosition(docsInRowSpanToFetch, start);
         List<Document> docs = new ArrayList<Document>();
         if (startingPosition < 0) {
-          //nothing to fetch
+          // nothing to fetch
           return docs;
         }
         int totalHeap = 0;
@@ -872,7 +877,7 @@ public class BlurUtil {
     return ordering;
   }
 
-  private static SegmentReader getSegmentReader(IndexReader indexReader) {
+  public static SegmentReader getSegmentReader(IndexReader indexReader) {
     if (indexReader instanceof SegmentReader) {
       return (SegmentReader) indexReader;
     }
@@ -894,10 +899,15 @@ public class BlurUtil {
     return docStartingPosition;
   }
 
-  private static OpenBitSet getDocsToFetch(int primeDocId, SegmentReader segmentReader, Selector selector,
-      int primeDocRowId, int numberOfDocsInRow, Bits liveDocs) throws IOException {
+  private static OpenBitSet getDocsToFetch(SegmentReader segmentReader, Selector selector, int primeDocRowId,
+      int numberOfDocsInRow, Bits liveDocs, Filter filter) throws IOException {
     Set<String> alreadyProcessed = new HashSet<String>();
     OpenBitSet bits = new OpenBitSet(numberOfDocsInRow);
+    OpenBitSet mask = null;
+    if (filter != null) {
+      DocIdSet docIdSet = filter.getDocIdSet(segmentReader.getContext(), liveDocs);
+      mask = getMask(docIdSet, primeDocRowId, numberOfDocsInRow);
+    }
     List<String> columnFamiliesToFetch = selector.getColumnFamiliesToFetch();
     boolean fetchAll = true;
     if (columnFamiliesToFetch != null) {
@@ -913,9 +923,27 @@ public class BlurUtil {
     if (fetchAll) {
       bits.set(0, numberOfDocsInRow);
     }
+    if (mask != null) {
+      bits.intersect(mask);
+    }
     return bits;
   }
 
+  private static OpenBitSet getMask(DocIdSet docIdSet, int primeDocRowId, int numberOfDocsInRow) throws IOException {
+    OpenBitSet mask = new OpenBitSet(numberOfDocsInRow);
+    DocIdSetIterator iterator = docIdSet.iterator();
+    if (iterator == null) {
+      return mask;
+    }
+    int docId = iterator.advance(primeDocRowId);
+    int end = numberOfDocsInRow + primeDocRowId;
+    while (docId < end) {
+      mask.set(docId - primeDocRowId);
+      docId = iterator.nextDoc();
+    }
+    return mask;
+  }
+
   private static void applyColumns(Set<String> alreadyProcessed, OpenBitSet bits,
       Map<String, Set<String>> columnsToFetch, SegmentReader segmentReader, int primeDocRowId, int numberOfDocsInRow,
       Bits liveDocs) throws IOException {

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/main/java/org/apache/blur/utils/HighlightHelper.java
----------------------------------------------------------------------
diff --git a/blur-core/src/main/java/org/apache/blur/utils/HighlightHelper.java b/blur-core/src/main/java/org/apache/blur/utils/HighlightHelper.java
index 2f63aca..5ae9baa 100644
--- a/blur-core/src/main/java/org/apache/blur/utils/HighlightHelper.java
+++ b/blur-core/src/main/java/org/apache/blur/utils/HighlightHelper.java
@@ -37,6 +37,7 @@ import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MultiPhraseQuery;
 import org.apache.lucene.search.NumericRangeQuery;
@@ -71,7 +72,7 @@ public class HighlightHelper {
 
   public static List<Document> highlightDocuments(IndexReader reader, Term term,
       ResetableDocumentStoredFieldVisitor fieldSelector, Selector selector, Query highlightQuery,
-      FieldManager fieldManager, String preTag, String postTag) throws IOException {
+      FieldManager fieldManager, String preTag, String postTag, Filter filter) throws IOException {
     IndexSearcher indexSearcher = new IndexSearcher(reader);
     int docFreq = reader.docFreq(term);
     BooleanQuery booleanQueryForFamily = null;
@@ -87,7 +88,7 @@ public class HighlightHelper {
       booleanQuery.add(booleanQueryForFamily, BooleanClause.Occur.MUST);
     }
     Query query = booleanQuery == null ? new TermQuery(term) : booleanQuery;
-    TopDocs topDocs = indexSearcher.search(query, docFreq);
+    TopDocs topDocs = indexSearcher.search(query, filter, docFreq);
     int totalHits = topDocs.totalHits;
     List<Document> docs = new ArrayList<Document>();
 

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTest.java
----------------------------------------------------------------------
diff --git a/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTest.java b/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTest.java
index 7d498dd..9da2db1 100644
--- a/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTest.java
+++ b/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTest.java
@@ -74,6 +74,10 @@ import org.apache.blur.trace.TraceStorage;
 import org.apache.blur.utils.BlurConstants;
 import org.apache.blur.utils.BlurIterator;
 import org.apache.blur.utils.BlurUtil;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.search.QueryWrapperFilter;
+import org.apache.lucene.search.TermQuery;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -88,7 +92,6 @@ public class IndexManagerTest {
   private static final String FAMILY2 = "test-family2";
   private LocalIndexServer server;
   private IndexManager indexManager;
-
   private File base;
 
   @Before
@@ -100,11 +103,15 @@ public class IndexManagerTest {
     File file = new File(base, TABLE);
     file.mkdirs();
 
+    IndexManagerTestReadInterceptor.interceptor = null;
+
     final TableDescriptor tableDescriptor = new TableDescriptor();
     tableDescriptor.setName(TABLE);
     tableDescriptor.setTableUri(file.toURI().toString());
     tableDescriptor.putToTableProperties("blur.shard.time.between.refreshs", Long.toString(100));
     tableDescriptor.setShardCount(1);
+    tableDescriptor.putToTableProperties(BlurConstants.BLUR_SHARD_READ_INTERCEPTOR,
+        IndexManagerTestReadInterceptor.class.getName());
     server = new LocalIndexServer(tableDescriptor, true);
 
     BlurFilterCache filterCache = new DefaultBlurFilterCache(new BlurConfiguration());
@@ -287,13 +294,11 @@ public class IndexManagerTest {
       }
     });
 
-    
-
     for (int i = 0; i < 1000; i++) {
       Thread thread = new Thread(new Runnable() {
         @Override
         public void run() {
-//          Trace.setupTrace(rowId);
+          // Trace.setupTrace(rowId);
           Selector selector = new Selector().setRowId(rowId);
           FetchResult fetchResult = new FetchResult();
           long s = System.nanoTime();
@@ -304,7 +309,7 @@ public class IndexManagerTest {
           }
           long e = System.nanoTime();
           assertNotNull(fetchResult.rowResult.row);
-//          Trace.tearDownTrace();
+          // Trace.tearDownTrace();
           System.out.println((e - s) / 1000000.0);
         }
       });
@@ -314,7 +319,7 @@ public class IndexManagerTest {
     }
 
     Trace.setStorage(oldReporter);
-    
+
   }
 
   private RowMutation getLargeRow(String rowId) {
@@ -591,6 +596,40 @@ public class IndexManagerTest {
   }
 
   @Test
+  public void testFetchRowByRowIdWithFilter() throws Exception {
+    IndexManagerTestReadInterceptor.interceptor = new ReadInterceptor(null) {
+      @Override
+      public Filter getFilter() {
+        return new QueryWrapperFilter(new TermQuery(new Term(FAMILY + ".testcol12", "value110")));
+      }
+    };
+    Selector selector = new Selector().setRowId("row-6");
+    FetchResult fetchResult = new FetchResult();
+    indexManager.fetchRow(TABLE, selector, fetchResult);
+    assertNotNull(fetchResult.rowResult.row);
+    Row row = newRow("row-6",
+        newRecord(FAMILY, "record-6A", newColumn("testcol12", "value110"), newColumn("testcol13", "value102")));
+    row.recordCount = 1;
+    assertEquals(row, fetchResult.rowResult.row);
+  }
+
+  @Test
+  public void testFetchRowByRowIdWithFilterNoRow() throws Exception {
+    IndexManagerTestReadInterceptor.interceptor = new ReadInterceptor(null) {
+      @Override
+      public Filter getFilter() {
+        return new QueryWrapperFilter(new TermQuery(new Term(FAMILY + ".testcol12", "NOROW-1")));
+      }
+    };
+    Selector selector = new Selector().setRowId("row-6");
+    FetchResult fetchResult = new FetchResult();
+    indexManager.fetchRow(TABLE, selector, fetchResult);
+    assertTrue(fetchResult.exists);
+    assertFalse(fetchResult.deleted);
+    assertNull(fetchResult.rowResult.row);
+  }
+
+  @Test
   public void testFetchRowByRowIdBatch() throws Exception {
     List<Selector> selectors = new ArrayList<Selector>();
     selectors.add(new Selector().setRowId("row-1"));
@@ -622,12 +661,12 @@ public class IndexManagerTest {
     Selector selector = new Selector().setRowId("row-6");
     FetchResult fetchResult = new FetchResult();
     indexManager.fetchRow(TABLE, selector, fetchResult);
-    
+
     List<Record> records = fetchResult.rowResult.row.getRecords();
-    for (Record record :records){
+    for (Record record : records) {
       System.out.println(record);
     }
-    
+
     selector = new Selector().setRowId("row-6").setStartRecord(0).setMaxRecordsToFetch(1);
     fetchResult = new FetchResult();
     indexManager.fetchRow(TABLE, selector, fetchResult);
@@ -715,6 +754,51 @@ public class IndexManagerTest {
   }
 
   @Test
+  public void testFetchRowByRecordIdWithFilterHit() throws Exception {
+    IndexManagerTestReadInterceptor.interceptor = new ReadInterceptor(null) {
+      @Override
+      public Filter getFilter() {
+        return new QueryWrapperFilter(new TermQuery(new Term(FAMILY + ".testcol1", "value1")));
+      }
+    };
+    Selector selector = new Selector().setRowId("row-1").setRecordId("record-1").setRecordOnly(true);
+    FetchResult fetchResult = new FetchResult();
+    indexManager.fetchRow(TABLE, selector, fetchResult);
+    assertFalse(fetchResult.deleted);
+    assertTrue(fetchResult.exists);
+    assertEquals(TABLE, fetchResult.table);
+    assertNull(fetchResult.rowResult);
+    assertNotNull(fetchResult.recordResult);
+    FetchRecordResult recordResult = fetchResult.recordResult;
+    assertEquals(FAMILY, recordResult.record.family);
+    assertEquals("record-1", recordResult.record.recordId);
+    assertEquals("row-1", recordResult.rowid);
+
+    Record record = newRecord(FAMILY, "record-1", newColumn("testcol1", "value1"), newColumn("testcol2", "value2"),
+        newColumn("testcol3", "value3"));
+    assertEquals(record, recordResult.record);
+
+  }
+
+  @Test
+  public void testFetchRowByRecordIdWithFilterNoHit() throws Exception {
+    IndexManagerTestReadInterceptor.interceptor = new ReadInterceptor(null) {
+      @Override
+      public Filter getFilter() {
+        return new QueryWrapperFilter(new TermQuery(new Term(FAMILY + ".testcol1", "NOHIT")));
+      }
+    };
+    Selector selector = new Selector().setRowId("row-1").setRecordId("record-1").setRecordOnly(true);
+    FetchResult fetchResult = new FetchResult();
+    indexManager.fetchRow(TABLE, selector, fetchResult);
+    assertFalse(fetchResult.deleted);
+    assertFalse(fetchResult.exists);
+    assertEquals(TABLE, fetchResult.table);
+    assertNull(fetchResult.rowResult);
+    assertNull(fetchResult.recordResult);
+  }
+
+  @Test
   public void testRecordFrequency() throws Exception {
     assertEquals(2, indexManager.recordFrequency(TABLE, FAMILY, "testcol1", "value1"));
     assertEquals(0, indexManager.recordFrequency(TABLE, FAMILY, "testcol1", "NO VALUE"));
@@ -750,6 +834,41 @@ public class IndexManagerTest {
   }
 
   @Test
+  public void testQuerySuperQueryTrueWithFilter() throws Exception {
+    IndexManagerTestReadInterceptor.interceptor = new ReadInterceptor(null) {
+      @Override
+      public Filter getFilter() {
+        return new QueryWrapperFilter(new TermQuery(new Term(FAMILY + ".testcol2", "value2")));
+      }
+    };
+    BlurQuery blurQuery = new BlurQuery();
+    blurQuery.query = new Query();
+    blurQuery.query.query = "test-family.testcol1:value1";
+    blurQuery.query.rowQuery = true;
+    blurQuery.query.scoreType = ScoreType.SUPER;
+    blurQuery.fetch = 10;
+    blurQuery.minimumNumberOfResults = Long.MAX_VALUE;
+    blurQuery.maxQueryTime = Long.MAX_VALUE;
+    blurQuery.uuid = "1";
+
+    BlurResultIterable iterable = indexManager.query(TABLE, blurQuery, null);
+    assertEquals(1, iterable.getTotalResults());
+    BlurIterator<BlurResult, BlurException> iterator = iterable.iterator();
+    while (iterator.hasNext()) {
+      BlurResult result = iterator.next();
+      Selector selector = new Selector().setLocationId(result.getLocationId());
+      FetchResult fetchResult = new FetchResult();
+      indexManager.fetchRow(TABLE, selector, fetchResult);
+      assertNotNull(fetchResult.rowResult);
+      assertNull(fetchResult.recordResult);
+    }
+
+    assertFalse(indexManager.currentQueries(TABLE).isEmpty());
+    Thread.sleep(2000);// wait for cleanup to fire
+    assertTrue(indexManager.currentQueries(TABLE).isEmpty());
+  }
+
+  @Test
   public void testQuerySuperQueryTrueWithSelector() throws Exception {
     BlurQuery blurQuery = new BlurQuery();
     blurQuery.query = new Query();

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTestReadInterceptor.java
----------------------------------------------------------------------
diff --git a/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTestReadInterceptor.java b/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTestReadInterceptor.java
new file mode 100644
index 0000000..f0968af
--- /dev/null
+++ b/blur-core/src/test/java/org/apache/blur/manager/IndexManagerTestReadInterceptor.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.blur.manager;
+
+import org.apache.blur.BlurConfiguration;
+import org.apache.lucene.search.Filter;
+
+public class IndexManagerTestReadInterceptor extends ReadInterceptor {
+  
+  public static ReadInterceptor interceptor;
+
+  public IndexManagerTestReadInterceptor(BlurConfiguration configuration) {
+    super(configuration);
+  }
+
+  @Override
+  public Filter getFilterForMutation() {
+    if (interceptor == null) {
+      return null;
+    }
+    return interceptor.getFilterForMutation();
+  }
+
+  @Override
+  public Filter getFilter() {
+    if (interceptor == null) {
+      return null;
+    }
+    return interceptor.getFilter();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-core/src/test/java/org/apache/blur/utils/BlurUtilsTest.java
----------------------------------------------------------------------
diff --git a/blur-core/src/test/java/org/apache/blur/utils/BlurUtilsTest.java b/blur-core/src/test/java/org/apache/blur/utils/BlurUtilsTest.java
index 288c257..8585117 100644
--- a/blur-core/src/test/java/org/apache/blur/utils/BlurUtilsTest.java
+++ b/blur-core/src/test/java/org/apache/blur/utils/BlurUtilsTest.java
@@ -174,7 +174,7 @@ public class BlurUtilsTest {
     // "test-context", new
     // Term(BlurConstants.PRIME_DOC,BlurConstants.PRIME_DOC_VALUE));
     List<Document> docs = BlurUtil.fetchDocuments(getReader(), resetableDocumentStoredFieldVisitor, selector, 10000000,
-        "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE));
+        "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE), null);
     assertEquals(docs.size(), 1);
   }
 
@@ -190,7 +190,7 @@ public class BlurUtilsTest {
 
     ResetableDocumentStoredFieldVisitor resetableDocumentStoredFieldVisitor = new ResetableDocumentStoredFieldVisitor();
     List<Document> docs = BlurUtil.fetchDocuments(getReaderWithDocsHavingFamily(), resetableDocumentStoredFieldVisitor,
-        selector, 10000000, "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE));
+        selector, 10000000, "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE), null);
     assertEquals(docs.size(), 2);
     assertEquals(docs.get(0).getField("family").stringValue(), "f1");
     assertEquals(docs.get(1).getField("family").stringValue(), "f2");
@@ -202,7 +202,7 @@ public class BlurUtilsTest {
     selector.setLocationId("shard/0");
     ResetableDocumentStoredFieldVisitor resetableDocumentStoredFieldVisitor = new ResetableDocumentStoredFieldVisitor();
     List<Document> docs = BlurUtil.fetchDocuments(getReader(), resetableDocumentStoredFieldVisitor, selector, 10000000,
-        "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE));
+        "test-context", new Term(BlurConstants.PRIME_DOC, BlurConstants.PRIME_DOC_VALUE), null);
     assertEquals(docs.size(), 2);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-mapred/src/main/java/org/apache/blur/mapreduce/BlurReducer.java
----------------------------------------------------------------------
diff --git a/blur-mapred/src/main/java/org/apache/blur/mapreduce/BlurReducer.java b/blur-mapred/src/main/java/org/apache/blur/mapreduce/BlurReducer.java
index 793494f..67f0b92 100644
--- a/blur-mapred/src/main/java/org/apache/blur/mapreduce/BlurReducer.java
+++ b/blur-mapred/src/main/java/org/apache/blur/mapreduce/BlurReducer.java
@@ -251,7 +251,7 @@ public class BlurReducer extends Reducer<Text, BlurMutate, Text, BlurMutate> {
   protected void fetchOldRecords() throws IOException {
     List<Document> docs = BlurUtil.fetchDocuments(_reader, new ResetableDocumentStoredFieldVisitor(), new Selector()
         .setRowId(_rowIdTerm.text()), Integer.MAX_VALUE, "reducer-context", new Term(BlurConstants.PRIME_DOC,
-        BlurConstants.PRIME_DOC_VALUE));
+        BlurConstants.PRIME_DOC_VALUE), null);
     for (Document document : docs) {
       String recordId = document.get(RECORD_ID);
       // add them to the new records if the new records do not contain them.

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-query/src/main/java/org/apache/blur/lucene/search/IterablePaging.java
----------------------------------------------------------------------
diff --git a/blur-query/src/main/java/org/apache/blur/lucene/search/IterablePaging.java b/blur-query/src/main/java/org/apache/blur/lucene/search/IterablePaging.java
index a050ee9..80b9ed8 100644
--- a/blur-query/src/main/java/org/apache/blur/lucene/search/IterablePaging.java
+++ b/blur-query/src/main/java/org/apache/blur/lucene/search/IterablePaging.java
@@ -29,6 +29,7 @@ import org.apache.blur.thrift.generated.ErrorType;
 import org.apache.blur.utils.BlurIterable;
 import org.apache.blur.utils.BlurIterator;
 import org.apache.lucene.search.Collector;
+import org.apache.lucene.search.Filter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
@@ -40,29 +41,31 @@ import org.apache.lucene.search.TopScoreDocCollector;
  */
 public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
 
-  private final IndexSearcher searcher;
-  private final Query query;
-  private final AtomicBoolean running;
-  private final int numHitsToCollect;
+  private final IndexSearcher _searcher;
+  private final Query _query;
+  private final AtomicBoolean _running;
+  private final int _numHitsToCollect;
   private final boolean _runSlow;
+  private final Filter _filter;
 
-  private TotalHitsRef totalHitsRef;
-  private ProgressRef progressRef;
+  private TotalHitsRef _totalHitsRef;
+  private ProgressRef _progressRef;
   private int skipTo;
   private int gather = -1;
 
   public IterablePaging(AtomicBoolean running, IndexSearcher searcher, Query query, int numHitsToCollect,
-      TotalHitsRef totalHitsRef, ProgressRef progressRef, boolean runSlow) throws BlurException {
-    this.running = running;
+      TotalHitsRef totalHitsRef, ProgressRef progressRef, boolean runSlow, Filter filter) throws BlurException {
+    _running = running;
+    _filter = filter;
     try {
-      this.query = searcher.rewrite(query);
+      _query = searcher.rewrite(query);
     } catch (IOException e) {
       throw new BException("Unknown error during rewrite", e);
     }
-    this.searcher = searcher;
-    this.numHitsToCollect = numHitsToCollect;
-    this.totalHitsRef = totalHitsRef == null ? new TotalHitsRef() : totalHitsRef;
-    this.progressRef = progressRef == null ? new ProgressRef() : progressRef;
+    _searcher = searcher;
+    _numHitsToCollect = numHitsToCollect;
+    _totalHitsRef = totalHitsRef == null ? new TotalHitsRef() : totalHitsRef;
+    _progressRef = progressRef == null ? new ProgressRef() : progressRef;
     _runSlow = runSlow;
   }
 
@@ -107,7 +110,7 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
    * @return the total hits.
    */
   public int getTotalHits() {
-    return totalHitsRef.totalHits();
+    return _totalHitsRef.totalHits();
   }
 
   /**
@@ -118,7 +121,7 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
    * @return this.
    */
   public IterablePaging totalHits(TotalHitsRef ref) {
-    totalHitsRef = ref;
+    _totalHitsRef = ref;
     return this;
   }
 
@@ -154,7 +157,7 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
    * @return this.
    */
   public IterablePaging progress(ProgressRef ref) {
-    this.progressRef = ref;
+    this._progressRef = ref;
     return this;
   }
 
@@ -182,15 +185,15 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
 
     void search() throws BlurException {
       long s = System.currentTimeMillis();
-      progressRef.searchesPerformed.incrementAndGet();
+      _progressRef.searchesPerformed.incrementAndGet();
       try {
-        TopScoreDocCollector collector = TopScoreDocCollector.create(numHitsToCollect, lastScoreDoc, true);
-        Collector col = new StopExecutionCollector(collector, running);
+        TopScoreDocCollector collector = TopScoreDocCollector.create(_numHitsToCollect, lastScoreDoc, true);
+        Collector col = new StopExecutionCollector(collector, _running);
         if (_runSlow) {
           col = new SlowCollector(col);
         }
-        searcher.search(query, col);
-        totalHitsRef.totalHits.set(collector.getTotalHits());
+        _searcher.search(_query, _filter, col);
+        _totalHitsRef.totalHits.set(collector.getTotalHits());
         TopDocs topDocs = collector.topDocs();
         scoreDocs = topDocs.scoreDocs;
       } catch (StopExecutionCollectorException e) {
@@ -206,12 +209,12 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
         lastScoreDoc = null;
       }
       long e = System.currentTimeMillis();
-      progressRef.queryTime.addAndGet(e - s);
+      _progressRef.queryTime.addAndGet(e - s);
     }
 
     @Override
     public boolean hasNext() {
-      return counter < totalHitsRef.totalHits() && counter < endPosition ? true : false;
+      return counter < _totalHitsRef.totalHits() && counter < endPosition ? true : false;
     }
 
     @Override
@@ -220,7 +223,7 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
         search();
         offset = 0;
       }
-      progressRef.currentHitPosition.set(counter);
+      _progressRef.currentHitPosition.set(counter);
       counter++;
       return scoreDocs[offset++];
     }
@@ -232,10 +235,10 @@ public class IterablePaging implements BlurIterable<ScoreDoc, BlurException> {
 
   private BlurIterator<ScoreDoc, BlurException> skipHits(BlurIterator<ScoreDoc, BlurException> iterator)
       throws BlurException {
-    progressRef.skipTo.set(skipTo);
+    _progressRef.skipTo.set(skipTo);
     for (int i = 0; i < skipTo && iterator.hasNext(); i++) {
       // eats the hits, and moves the iterator to the desired skip to position.
-      progressRef.currentHitPosition.set(i);
+      _progressRef.currentHitPosition.set(i);
       iterator.next();
     }
     return iterator;

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
----------------------------------------------------------------------
diff --git a/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java b/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
index 48884af..7c00f9d 100644
--- a/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
+++ b/blur-query/src/test/java/org/apache/blur/lucene/search/TestingPagingCollector.java
@@ -59,7 +59,7 @@ public class TestingPagingCollector {
     ProgressRef progressRef = new ProgressRef();
 
     TermQuery query = new TermQuery(new Term("f1", "value"));
-    IterablePaging paging = new IterablePaging(new AtomicBoolean(true), searcher, query, 100, null, null, false);
+    IterablePaging paging = new IterablePaging(new AtomicBoolean(true), searcher, query, 100, null, null, false, null);
     IterablePaging itPaging = paging.skipTo(90).gather(20).totalHits(totalHitsRef).progress(progressRef);
     BlurIterator<ScoreDoc, BlurException> iterator = itPaging.iterator();
     while (iterator.hasNext()) {

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-util/src/main/java/org/apache/blur/utils/BlurConstants.java
----------------------------------------------------------------------
diff --git a/blur-util/src/main/java/org/apache/blur/utils/BlurConstants.java b/blur-util/src/main/java/org/apache/blur/utils/BlurConstants.java
index b2622f7..6c1ea4b 100644
--- a/blur-util/src/main/java/org/apache/blur/utils/BlurConstants.java
+++ b/blur-util/src/main/java/org/apache/blur/utils/BlurConstants.java
@@ -64,6 +64,7 @@ public class BlurConstants {
   public static final String BLUR_SHARD_FETCHCOUNT = "blur.shard.fetchcount";
   public static final String BLUR_MAX_HEAP_PER_ROW_FETCH = "blur.max.heap.per.row.fetch";
   public static final String BLUR_MAX_RECORDS_PER_ROW_FETCH_REQUEST = "blur.max.records.per.row.fetch.request";
+  public static final String BLUR_SHARD_READ_INTERCEPTOR = "blur.shard.read.interceptor";
 
   public static final String BLUR_SHARD_SERVER_THRIFT_THREAD_COUNT = "blur.shard.server.thrift.thread.count";
   public static final String BLUR_SHARD_CACHE_MAX_TIMETOLIVE = "blur.shard.cache.max.timetolive";

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/blur-util/src/main/resources/blur-default.properties
----------------------------------------------------------------------
diff --git a/blur-util/src/main/resources/blur-default.properties b/blur-util/src/main/resources/blur-default.properties
index b6f4b58..41d0283 100644
--- a/blur-util/src/main/resources/blur-default.properties
+++ b/blur-util/src/main/resources/blur-default.properties
@@ -181,6 +181,9 @@ blur.shard.filtered.server.class=
 # Defines the blur index class to be used to handle index requests.  This class has to extend org.apache.blur.manager.writer.BlurIndex.  This can be defined globally as well as per table.
 blur.shard.blurindex.class=
 
+# Defines the blur read interceptor class that can mask data from query results as well as data fetches.
+blur.shard.read.interceptor=
+
 
 ### Controller Server Configuration
 

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/179d5386/docs/cluster-setup.html
----------------------------------------------------------------------
diff --git a/docs/cluster-setup.html b/docs/cluster-setup.html
index 9a17f0e..3b2929c 100644
--- a/docs/cluster-setup.html
+++ b/docs/cluster-setup.html
@@ -204,7 +204,7 @@ Swap can kill java perform, you may want to consider disabling swap.</div>
 			<h4>Default Properties</h4>
 			<table class="table-bordered table-striped table-condensed">
 			<tr><td>Property</td><td>Description</td></tr>
-<tr><td>blur.shard.hostname</td><td>The hostname for the shard, if blank the hostname is automatically detected</td></tr><tr><td>blur.shard.bind.address (0.0.0.0)</td><td>The binding address of the shard</td></tr><tr><td>blur.shard.bind.port (40020)</td><td>The default binding port of the shard server</td></tr><tr><td>blur.shard.data.fetch.thread.count (8)</td><td>The number of fetcher threads</td></tr><tr><td>blur.shard.server.thrift.thread.count (8)</td><td>The number of the thrift threads</td></tr><tr><td>blur.shard.thrift.selector.threads (2)</td><td>The number of threads used for selector processing inside the thrift server.</td></tr><tr><td>blur.shard.thrift.max.read.buffer.bytes (9223372036854775807)</td><td>The maximum number of bytes used for reading requests in the thrift server.</td></tr><tr><td>blur.shard.thrift.accept.queue.size.per.thread (4)</td><td>The size of the blocking queue per selector thread for passing accepted connections to the selector thread.</td></tr><tr
 ><td>blur.shard.opener.thread.count (8)</td><td>The number of threads that are used for opening indexes</td></tr><tr><td>blur.shard.cache.max.querycache.elements (128)</td><td>The number of cached queries</td></tr><tr><td>blur.shard.cache.max.timetolive (60000)</td><td>The time to live for the cache query</td></tr><tr><td>blur.shard.filter.cache.class (org.apache.blur.manager.DefaultBlurFilterCache)</td><td>Default implementation of the blur cache filter, which is a pass through filter that does nothing</td></tr><tr><td>blur.shard.index.warmup.class (org.apache.blur.manager.indexserver.DefaultBlurIndexWarmup)</td><td>Default Blur index warmup class that warms the fields provided in the table descriptor</td></tr><tr><td>blur.shard.index.warmup.throttle (30000000)</td><td>Throttles the warmup to 30MB/s across all the warmup threads</td></tr><tr><td>blur.shard.block.cache.version (v2)</td><td>By default the v2 version of the block cache is enabled</td></tr><tr><td>blur.shard.block.cach
 e.total.size</td><td>By default the total amount of memory block cache will use is -XX:MaxDirectMemorySize - 64 MiB</td></tr><tr><td>blur.shard.blockcache.direct.memory.allocation (true)</td><td>v1 version of block cache only. By default the block cache using off heap memory</td></tr><tr><td>blur.shard.blockcache.slab.count (-1)</td><td>v1 version of block cache only. The slabs in the blockcache are automatically configured by default (-1) otherwise 1 slab equals 128MB.  The auto config is detected through the MaxDirectoryMemorySize provided to the JVM</td></tr><tr><td>blur.shard.block.cache.v2.fileBufferSize (8192)</td><td>v2 version of block cache only. File buffer size, this is the buffer size used to read and write to data to HDFS.  For production this will likely be increased.</td></tr><tr><td>blur.shard.block.cache.v2.cacheBlockSize (8192)</td><td>v2 version of block cache only. The is the size of the blocks in the off heap cache, it is good practice to have this match 'blur.s
 hard.block.cache.v2.fileBufferSize'.  For production this will likely be increased.</td></tr><tr><td>blur.shard.block.cache.v2.cacheBlockSize.filter (33554432)</td><td>blur.shard.block.cache.v2.cacheBlockSize.<ext>=</td></tr><tr><td>blur.shard.block.cache.v2.store (OFF_HEAP)</td><td>v2 version of block cache only. This is used to control if the block are created on or off heap.  Values are OFF_HEAP | ON_HEAP</td></tr><tr><td>blur.shard.block.cache.v2.read.cache.ext</td><td>v2 version of block cache only. This specifies what file types should be cached during reads.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.read.nocache.ext (fdt)</td><td>v2 version of block cache only. This specifies what file types should NOT be cached during reads.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.read.default (true)</td><td>v2 version of block cache only. This specifies the default behavior if a file type is not specified in the cache or nocache lists during
  reads.  Values true | false</td></tr><tr><td>blur.shard.block.cache.v2.write.cache.ext</td><td>v2 version of block cache only. This specifies what file types should be cached during writes.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.write.nocache.ext (fdt)</td><td>v2 version of block cache only. This specifies what file types should NOT be cached during writes.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.write.default (true)</td><td>v2 version of block cache only. This specifies the default behavior if a file type is not specified in the cache or nocache lists during writes.  Values true | false</td></tr><tr><td>blur.shard.index.compressionmode (FAST)</td><td>Sets the compression of used in the storing of the fields. Valid entries are FAST FAST_DECOMPRESSION HIGH_COMPRESSION</td></tr><tr><td>blur.shard.index.chunksize (16384)</td><td>Sets the chunksize of the compression in the storing of the fields. Larger values may produce smaller fdt
  files at the small cost of fetch performance.</td></tr><tr><td>blur.shard.buffercache.8192 (67108864)</td><td>The amount of memory to be used by 8K byte buffers.  Note if you change the "blur.shard.block.cache.v2.cacheBlockSize" or "blur.shard.block.cache.v2.fileBufferSize" you should adjust the buffer sizes as well as the total memory allocated.  For example if you increased the "blur.shard.block.cache.v2.fileBufferSize" to 64K (65536) then this property should to "blur.shard.buffercache.65536".  You can also define as many of these properties as needed.</td></tr><tr><td>blur.shard.buffercache.1024 (8388608)</td><td>The amount of memory to be used by 1K byte buffers.  Note if you change the "blur.shard.block.cache.v2.cacheBlockSize" or "blur.shard.block.cache.v2.fileBufferSize" you should adjust the buffer sizes as well as the total memory allocated.</td></tr><tr><td>blur.shard.safemodedelay (5000)</td><td>The number of milliseconds to wait for the cluster to settle once changes h
 ave ceased</td></tr><tr><td>blur.shard.time.between.commits (30000)</td><td>The default time between index commits</td></tr><tr><td>blur.shard.time.between.refreshs (3000)</td><td>The default time between index refreshs</td></tr><tr><td>blur.shard.merge.thread.count (3)</td><td>The max number of threads used during index merges</td></tr><tr><td>blur.shard.balancer.period (300000)</td><td>The time period in which the balancer will recalculate the shard distribution.  NOTE: This is time is per shard server so the checking may occur more often.</td></tr><tr><td>blur.max.clause.count (1024)</td><td>The maximum number of clauses in a BooleanQuery</td></tr><tr><td>blur.indexmanager.search.thread.count (8)</td><td>The number of thread used for parallel searching in the index manager</td></tr><tr><td>blur.indexmanager.mutate.thread.count (8)</td><td>The number of thread used for parallel mutating in the index manager</td></tr><tr><td>blur.shard.internal.search.thread.count (8)</td><td>The n
 umber of threads used for parallel searching in the index searchers</td></tr><tr><td>blur.shard.warmup.thread.count (8)</td><td>Number of threads used for warming up the index</td></tr><tr><td>blur.shard.fetchcount (100)</td><td>The fetch count per Lucene search, this fetches pointers to hits</td></tr><tr><td>blur.max.heap.per.row.fetch (10000000)</td><td>Heap limit on row fetch, once this limit has been reached the request will return</td></tr><tr><td>blur.max.records.per.row.fetch.request (1000)</td><td>The maximum number of records in a single row fetch</td></tr><tr><td>blur.gui.shard.port (40090)</td><td>The http status page port for the shard server</td></tr><tr><td>blur.shard.filtered.server.class</td><td>To intercept the calls made to the shard server and perform server side changes to the calls extend org.apache.blur.server.FilteredBlurServer.</td></tr>
+<tr><td>blur.shard.hostname</td><td>The hostname for the shard, if blank the hostname is automatically detected</td></tr><tr><td>blur.shard.bind.address (0.0.0.0)</td><td>The binding address of the shard</td></tr><tr><td>blur.shard.bind.port (40020)</td><td>The default binding port of the shard server</td></tr><tr><td>blur.shard.data.fetch.thread.count (8)</td><td>The number of fetcher threads</td></tr><tr><td>blur.shard.server.thrift.thread.count (8)</td><td>The number of the thrift threads</td></tr><tr><td>blur.shard.thrift.selector.threads (2)</td><td>The number of threads used for selector processing inside the thrift server.</td></tr><tr><td>blur.shard.thrift.max.read.buffer.bytes (9223372036854775807)</td><td>The maximum number of bytes used for reading requests in the thrift server.</td></tr><tr><td>blur.shard.thrift.accept.queue.size.per.thread (4)</td><td>The size of the blocking queue per selector thread for passing accepted connections to the selector thread.</td></tr><tr
 ><td>blur.shard.opener.thread.count (8)</td><td>The number of threads that are used for opening indexes</td></tr><tr><td>blur.shard.cache.max.querycache.elements (128)</td><td>The number of cached queries</td></tr><tr><td>blur.shard.cache.max.timetolive (60000)</td><td>The time to live for the cache query</td></tr><tr><td>blur.shard.filter.cache.class (org.apache.blur.manager.DefaultBlurFilterCache)</td><td>Default implementation of the blur cache filter, which is a pass through filter that does nothing</td></tr><tr><td>blur.shard.index.warmup.class (org.apache.blur.manager.indexserver.DefaultBlurIndexWarmup)</td><td>Default Blur index warmup class that warms the fields provided in the table descriptor</td></tr><tr><td>blur.shard.index.warmup.throttle (30000000)</td><td>Throttles the warmup to 30MB/s across all the warmup threads</td></tr><tr><td>blur.shard.block.cache.version (v2)</td><td>By default the v2 version of the block cache is enabled</td></tr><tr><td>blur.shard.block.cach
 e.total.size</td><td>By default the total amount of memory block cache will use is -XX:MaxDirectMemorySize - 64 MiB</td></tr><tr><td>blur.shard.blockcache.direct.memory.allocation (true)</td><td>v1 version of block cache only. By default the block cache using off heap memory</td></tr><tr><td>blur.shard.blockcache.slab.count (-1)</td><td>v1 version of block cache only. The slabs in the blockcache are automatically configured by default (-1) otherwise 1 slab equals 128MB.  The auto config is detected through the MaxDirectoryMemorySize provided to the JVM</td></tr><tr><td>blur.shard.block.cache.v2.fileBufferSize (8192)</td><td>v2 version of block cache only. File buffer size, this is the buffer size used to read and write to data to HDFS.  For production this will likely be increased.</td></tr><tr><td>blur.shard.block.cache.v2.cacheBlockSize (8192)</td><td>v2 version of block cache only. The is the size of the blocks in the off heap cache, it is good practice to have this match 'blur.s
 hard.block.cache.v2.fileBufferSize'.  For production this will likely be increased.</td></tr><tr><td>blur.shard.block.cache.v2.cacheBlockSize.filter (33554432)</td><td>blur.shard.block.cache.v2.cacheBlockSize.<ext>=</td></tr><tr><td>blur.shard.block.cache.v2.store (OFF_HEAP)</td><td>v2 version of block cache only. This is used to control if the block are created on or off heap.  Values are OFF_HEAP | ON_HEAP</td></tr><tr><td>blur.shard.block.cache.v2.read.cache.ext</td><td>v2 version of block cache only. This specifies what file types should be cached during reads.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.read.nocache.ext (fdt)</td><td>v2 version of block cache only. This specifies what file types should NOT be cached during reads.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.read.default (true)</td><td>v2 version of block cache only. This specifies the default behavior if a file type is not specified in the cache or nocache lists during
  reads.  Values true | false</td></tr><tr><td>blur.shard.block.cache.v2.write.cache.ext</td><td>v2 version of block cache only. This specifies what file types should be cached during writes.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.write.nocache.ext (fdt)</td><td>v2 version of block cache only. This specifies what file types should NOT be cached during writes.  Comma delimited list.</td></tr><tr><td>blur.shard.block.cache.v2.write.default (true)</td><td>v2 version of block cache only. This specifies the default behavior if a file type is not specified in the cache or nocache lists during writes.  Values true | false</td></tr><tr><td>blur.shard.index.compressionmode (FAST)</td><td>Sets the compression of used in the storing of the fields. Valid entries are FAST FAST_DECOMPRESSION HIGH_COMPRESSION</td></tr><tr><td>blur.shard.index.chunksize (16384)</td><td>Sets the chunksize of the compression in the storing of the fields. Larger values may produce smaller fdt
  files at the small cost of fetch performance.</td></tr><tr><td>blur.shard.buffercache.8192 (67108864)</td><td>The amount of memory to be used by 8K byte buffers.  Note if you change the "blur.shard.block.cache.v2.cacheBlockSize" or "blur.shard.block.cache.v2.fileBufferSize" you should adjust the buffer sizes as well as the total memory allocated.  For example if you increased the "blur.shard.block.cache.v2.fileBufferSize" to 64K (65536) then this property should to "blur.shard.buffercache.65536".  You can also define as many of these properties as needed.</td></tr><tr><td>blur.shard.buffercache.1024 (8388608)</td><td>The amount of memory to be used by 1K byte buffers.  Note if you change the "blur.shard.block.cache.v2.cacheBlockSize" or "blur.shard.block.cache.v2.fileBufferSize" you should adjust the buffer sizes as well as the total memory allocated.</td></tr><tr><td>blur.shard.safemodedelay (5000)</td><td>The number of milliseconds to wait for the cluster to settle once changes h
 ave ceased</td></tr><tr><td>blur.shard.time.between.commits (30000)</td><td>The default time between index commits</td></tr><tr><td>blur.shard.time.between.refreshs (3000)</td><td>The default time between index refreshs</td></tr><tr><td>blur.shard.merge.thread.count (3)</td><td>The max number of threads used during index merges</td></tr><tr><td>blur.max.clause.count (1024)</td><td>The maximum number of clauses in a BooleanQuery</td></tr><tr><td>blur.indexmanager.search.thread.count (8)</td><td>The number of thread used for parallel searching in the index manager</td></tr><tr><td>blur.indexmanager.mutate.thread.count (8)</td><td>The number of thread used for parallel mutating in the index manager</td></tr><tr><td>blur.shard.internal.search.thread.count (8)</td><td>The number of threads used for parallel searching in the index searchers</td></tr><tr><td>blur.shard.warmup.thread.count (8)</td><td>Number of threads used for warming up the index</td></tr><tr><td>blur.shard.fetchcount (10
 0)</td><td>The fetch count per Lucene search, this fetches pointers to hits</td></tr><tr><td>blur.max.heap.per.row.fetch (10000000)</td><td>Heap limit on row fetch, once this limit has been reached the request will return</td></tr><tr><td>blur.max.records.per.row.fetch.request (1000)</td><td>The maximum number of records in a single row fetch</td></tr><tr><td>blur.gui.shard.port (40090)</td><td>The http status page port for the shard server</td></tr><tr><td>blur.shard.filtered.server.class</td><td>To intercept the calls made to the shard server and perform server side changes to the calls extend org.apache.blur.server.FilteredBlurServer.</td></tr><tr><td>blur.shard.blurindex.class</td><td>Defines the blur index class to be used to handle index requests.  This class has to extend org.apache.blur.manager.writer.BlurIndex.  This can be defined globally as well as per table.</td></tr><tr><td>blur.shard.read.interceptor</td><td>Defines the blur read interceptor class that can mask data f
 rom query results as well as data fetches.</td></tr>
 			</table>
 
             <h3 id="shard-blur-env">blur-env.sh</h3>


Mime
View raw message