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.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.KeyValue;
28  import org.apache.hadoop.hbase.KeyValue.KVComparator;
29  import org.apache.hadoop.hbase.client.Scan;
30  
31  /**
32   * ReversedStoreScanner extends from StoreScanner, and is used to support
33   * reversed scanning.
34   */
35  @InterfaceAudience.Private
36  class ReversedStoreScanner extends StoreScanner implements KeyValueScanner {
37  
38    /**
39     * Opens a scanner across memstore, snapshot, and all StoreFiles. Assumes we
40     * are not in a compaction.
41     * 
42     * @param store who we scan
43     * @param scanInfo
44     * @param scan the spec
45     * @param columns which columns we are scanning
46     * @throws IOException
47     */
48    ReversedStoreScanner(Store store, ScanInfo scanInfo, Scan scan,
49        NavigableSet<byte[]> columns, long readPt)
50        throws IOException {
51      super(store, scanInfo, scan, columns, readPt);
52    }
53  
54    /** Constructor for testing. */
55    ReversedStoreScanner(final Scan scan, ScanInfo scanInfo, ScanType scanType,
56        final NavigableSet<byte[]> columns, final List<KeyValueScanner> scanners)
57        throws IOException {
58      super(scan, scanInfo, scanType, columns, scanners,
59          HConstants.LATEST_TIMESTAMP);
60    }
61  
62    @Override
63    protected void resetKVHeap(List<? extends KeyValueScanner> scanners,
64        KVComparator comparator) throws IOException {
65      // Combine all seeked scanners with a heap
66      heap = new ReversedKeyValueHeap(scanners, comparator);
67    }
68  
69    @Override
70    protected void seekScanners(List<? extends KeyValueScanner> scanners,
71        KeyValue seekKey, boolean isLazy, boolean isParallelSeek)
72        throws IOException {
73      // Seek all scanners to the start of the Row (or if the exact matching row
74      // key does not exist, then to the start of the previous matching Row).
75      if (seekKey.matchingRow(HConstants.EMPTY_START_ROW)) {
76        for (KeyValueScanner scanner : scanners) {
77          scanner.seekToLastRow();
78        }
79      } else {
80        for (KeyValueScanner scanner : scanners) {
81          scanner.backwardSeek(seekKey);
82        }
83      }
84    }
85  
86    @Override
87    protected boolean seekToNextRow(KeyValue kv) throws IOException {
88      return seekToPreviousRow(kv);
89    }
90  
91    /**
92     * Do a backwardSeek in a reversed StoreScanner(scan backward)
93     */
94    @Override
95    protected boolean seekAsDirection(KeyValue kv) throws IOException {
96      return backwardSeek(kv);
97    }
98  
99    @Override
100   protected void checkScanOrder(KeyValue prevKV, KeyValue kv,
101       KeyValue.KVComparator comparator) throws IOException {
102     // Check that the heap gives us KVs in an increasing order for same row and
103     // decreasing order for different rows.
104     assert prevKV == null || comparator == null || comparator.compareRows(kv, prevKV) < 0
105         || (comparator.matchingRows(kv, prevKV) && comparator.compare(kv,
106             prevKV) >= 0) : "Key " + prevKV
107         + " followed by a " + "error order key " + kv + " in cf " + store
108         + " in reversed scan";
109   }
110 
111   @Override
112   public boolean reseek(KeyValue kv) throws IOException {
113     throw new IllegalStateException(
114         "reseek cannot be called on ReversedStoreScanner");
115   }
116 
117   @Override
118   public boolean seek(KeyValue key) throws IOException {
119     throw new IllegalStateException(
120         "seek cannot be called on ReversedStoreScanner");
121   }
122 
123   @Override
124   public boolean seekToPreviousRow(KeyValue key) throws IOException {
125     lock.lock();
126     try {
127       checkReseek();
128       return this.heap.seekToPreviousRow(key);
129     } finally {
130       lock.unlock();
131     }
132 
133   }
134   
135   @Override
136   public boolean backwardSeek(KeyValue key) throws IOException {
137     lock.lock();
138     try {
139       checkReseek();
140       return this.heap.backwardSeek(key);
141     } finally {
142       lock.unlock();
143     }
144   }
145 }