View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements. See the NOTICE file distributed with this
6    * work for additional information regarding copyright ownership. The ASF
7    * licenses this file to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16   * License for the specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import java.io.IOException;
22  import java.util.List;
23  import java.util.NavigableSet;
24  
25  import org.apache.hadoop.hbase.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.Cell;
27  import org.apache.hadoop.hbase.CellUtil;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.KeyValue;
30  import org.apache.hadoop.hbase.KeyValue.KVComparator;
31  import org.apache.hadoop.hbase.client.Scan;
32  
33  /**
34   * ReversedStoreScanner extends from StoreScanner, and is used to support
35   * reversed scanning.
36   */
37  @InterfaceAudience.Private
38  class ReversedStoreScanner extends StoreScanner implements KeyValueScanner {
39  
40    /**
41     * Opens a scanner across memstore, snapshot, and all StoreFiles. Assumes we
42     * are not in a compaction.
43     * 
44     * @param store who we scan
45     * @param scanInfo
46     * @param scan the spec
47     * @param columns which columns we are scanning
48     * @throws IOException
49     */
50    ReversedStoreScanner(Store store, ScanInfo scanInfo, Scan scan,
51        NavigableSet<byte[]> columns, long readPt)
52        throws IOException {
53      super(store, scanInfo, scan, columns, readPt);
54    }
55  
56    /** Constructor for testing. */
57    ReversedStoreScanner(final Scan scan, ScanInfo scanInfo, ScanType scanType,
58        final NavigableSet<byte[]> columns, final List<KeyValueScanner> scanners)
59        throws IOException {
60      super(scan, scanInfo, scanType, columns, scanners,
61          HConstants.LATEST_TIMESTAMP);
62    }
63  
64    @Override
65    protected void resetKVHeap(List<? extends KeyValueScanner> scanners,
66        KVComparator comparator) throws IOException {
67      // Combine all seeked scanners with a heap
68      heap = new ReversedKeyValueHeap(scanners, comparator);
69    }
70  
71    @Override
72    protected void seekScanners(List<? extends KeyValueScanner> scanners,
73        Cell seekKey, boolean isLazy, boolean isParallelSeek)
74        throws IOException {
75      // Seek all scanners to the start of the Row (or if the exact matching row
76      // key does not exist, then to the start of the previous matching Row).
77      if (CellUtil.matchingRow(seekKey, HConstants.EMPTY_START_ROW)) {
78        for (KeyValueScanner scanner : scanners) {
79          scanner.seekToLastRow();
80        }
81      } else {
82        for (KeyValueScanner scanner : scanners) {
83          scanner.backwardSeek(seekKey);
84        }
85      }
86    }
87  
88    @Override
89    protected boolean seekToNextRow(Cell kv) throws IOException {
90      return seekToPreviousRow(kv);
91    }
92  
93    /**
94     * Do a backwardSeek in a reversed StoreScanner(scan backward)
95     */
96    @Override
97    protected boolean seekAsDirection(Cell kv) throws IOException {
98      return backwardSeek(kv);
99    }
100 
101   @Override
102   protected void checkScanOrder(Cell prevKV, Cell kv,
103       KeyValue.KVComparator comparator) throws IOException {
104     // Check that the heap gives us KVs in an increasing order for same row and
105     // decreasing order for different rows.
106     assert prevKV == null || comparator == null || comparator.compareRows(kv, prevKV) < 0
107         || (comparator.matchingRows(kv, prevKV) && comparator.compare(kv,
108             prevKV) >= 0) : "Key " + prevKV
109         + " followed by a " + "error order key " + kv + " in cf " + store
110         + " in reversed scan";
111   }
112 
113   @Override
114   public boolean reseek(Cell kv) throws IOException {
115     throw new IllegalStateException(
116         "reseek cannot be called on ReversedStoreScanner");
117   }
118 
119   @Override
120   public boolean seek(Cell key) throws IOException {
121     throw new IllegalStateException(
122         "seek cannot be called on ReversedStoreScanner");
123   }
124 
125   @Override
126   public boolean seekToPreviousRow(Cell key) throws IOException {
127     lock.lock();
128     try {
129       checkReseek();
130       return this.heap.seekToPreviousRow(key);
131     } finally {
132       lock.unlock();
133     }
134 
135   }
136   
137   @Override
138   public boolean backwardSeek(Cell key) throws IOException {
139     lock.lock();
140     try {
141       checkReseek();
142       return this.heap.backwardSeek(key);
143     } finally {
144       lock.unlock();
145     }
146   }
147 }