2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
;
21 import java
.io
.IOException
;
23 import org
.apache
.hadoop
.hbase
.client
.Delete
;
24 import org
.apache
.hadoop
.hbase
.client
.Get
;
25 import org
.apache
.hadoop
.hbase
.client
.Put
;
26 import org
.apache
.hadoop
.hbase
.client
.Result
;
27 import org
.apache
.hadoop
.hbase
.client
.ResultScanner
;
28 import org
.apache
.hadoop
.hbase
.client
.Scan
;
29 import org
.apache
.hadoop
.hbase
.client
.Table
;
30 import org
.apache
.hadoop
.hbase
.client
.Durability
;
31 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
32 import org
.junit
.Assert
;
35 * Tests user specifiable time stamps putting, getting and scanning. Also
36 * tests same in presence of deletes. Test cores are written so can be
37 * run against an HRegion and against an HTable: i.e. both local and remote.
39 public class TimestampTestBase
{
40 private static final long T0
= 10L;
41 private static final long T1
= 100L;
42 private static final long T2
= 200L;
44 public static final byte [] FAMILY_NAME
= Bytes
.toBytes("colfamily11");
45 private static final byte [] QUALIFIER_NAME
= Bytes
.toBytes("contents");
47 private static final byte [] ROW
= Bytes
.toBytes("row");
49 interface FlushCache
{
50 void flushcache() throws IOException
;
54 * Run test that delete works according to description in <a
55 * href="https://issues.apache.org/jira/browse/HADOOP-1784">hadoop-1784</a>.
60 public static void doTestDelete(final Table table
, FlushCache flusher
)
62 // Add values at various timestamps (Values are timestampes as bytes).
67 // Verify that returned versions match passed timestamps.
68 assertVersions(table
, new long [] {HConstants
.LATEST_TIMESTAMP
, T2
, T1
});
70 // If I delete w/o specifying a timestamp, this means I'm deleting the latest.
72 // Verify that I get back T2 through T1 -- that the latest version has been deleted.
73 assertVersions(table
, new long [] {T2
, T1
, T0
});
75 // Flush everything out to disk and then retry
77 assertVersions(table
, new long [] {T2
, T1
, T0
});
79 // Now add, back a latest so I can test remove other than the latest.
81 assertVersions(table
, new long [] {HConstants
.LATEST_TIMESTAMP
, T2
, T1
});
83 assertVersions(table
, new long [] {HConstants
.LATEST_TIMESTAMP
, T1
, T0
});
84 // Flush everything out to disk and then retry
86 assertVersions(table
, new long [] {HConstants
.LATEST_TIMESTAMP
, T1
, T0
});
88 // Now try deleting all from T2 back inclusive (We first need to add T2
89 // back into the mix and to make things a little interesting, delete and then readd T1.
94 Delete delete
= new Delete(ROW
);
95 delete
.addColumns(FAMILY_NAME
, QUALIFIER_NAME
, T2
);
98 // Should only be current value in set. Assert this is so
99 assertOnlyLatest(table
, HConstants
.LATEST_TIMESTAMP
);
101 // Flush everything out to disk and then redo above tests
102 flusher
.flushcache();
103 assertOnlyLatest(table
, HConstants
.LATEST_TIMESTAMP
);
106 private static void assertOnlyLatest(final Table incommon
, final long currentTime
)
110 get
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
);
112 Result result
= incommon
.get(get
);
113 Assert
.assertEquals(1, result
.size());
114 long time
= Bytes
.toLong(CellUtil
.cloneValue(result
.rawCells()[0]));
115 Assert
.assertEquals(time
, currentTime
);
119 * Assert that returned versions match passed in timestamps and that results
120 * are returned in the right order. Assert that values when converted to
121 * longs match the corresponding passed timestamp.
124 * @throws IOException
126 public static void assertVersions(final Table incommon
, final long [] tss
)
128 // Assert that 'latest' is what we expect.
131 get
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
);
132 Result r
= incommon
.get(get
);
133 byte [] bytes
= r
.getValue(FAMILY_NAME
, QUALIFIER_NAME
);
134 long t
= Bytes
.toLong(bytes
);
135 Assert
.assertEquals(tss
[0], t
);
137 // Now assert that if we ask for multiple versions, that they come out in
140 get
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
);
141 get
.readVersions(tss
.length
);
142 Result result
= incommon
.get(get
);
143 Cell
[] kvs
= result
.rawCells();
144 Assert
.assertEquals(kvs
.length
, tss
.length
);
145 for(int i
=0;i
<kvs
.length
;i
++) {
146 t
= Bytes
.toLong(CellUtil
.cloneValue(kvs
[i
]));
147 Assert
.assertEquals(tss
[i
], t
);
150 // Determine highest stamp to set as next max stamp
151 long maxStamp
= kvs
[0].getTimestamp();
153 // Specify a timestamp get multiple versions.
155 get
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
);
156 get
.setTimeRange(0, maxStamp
);
157 get
.readVersions(kvs
.length
- 1);
158 result
= incommon
.get(get
);
159 kvs
= result
.rawCells();
160 Assert
.assertEquals(kvs
.length
, tss
.length
- 1);
161 for(int i
=1;i
<kvs
.length
;i
++) {
162 t
= Bytes
.toLong(CellUtil
.cloneValue(kvs
[i
-1]));
163 Assert
.assertEquals(tss
[i
], t
);
166 // Test scanner returns expected version
167 assertScanContentTimestamp(incommon
, tss
[0]);
171 * Run test scanning different timestamps.
174 * @throws IOException
176 public static void doTestTimestampScanning(final Table incommon
,
177 final FlushCache flusher
)
179 // Add a couple of values for three different timestamps.
182 put(incommon
, HConstants
.LATEST_TIMESTAMP
);
183 // Get count of latest items.
184 int count
= assertScanContentTimestamp(incommon
,
185 HConstants
.LATEST_TIMESTAMP
);
186 // Assert I get same count when I scan at each timestamp.
187 Assert
.assertEquals(count
, assertScanContentTimestamp(incommon
, T0
));
188 Assert
.assertEquals(count
, assertScanContentTimestamp(incommon
, T1
));
189 // Flush everything out to disk and then retry
190 flusher
.flushcache();
191 Assert
.assertEquals(count
, assertScanContentTimestamp(incommon
, T0
));
192 Assert
.assertEquals(count
, assertScanContentTimestamp(incommon
, T1
));
196 * Assert that the scan returns only values < timestamp.
199 * @return Count of items scanned.
200 * @throws IOException
202 public static int assertScanContentTimestamp(final Table in
, final long ts
)
204 Scan scan
= new Scan().withStartRow(HConstants
.EMPTY_START_ROW
);
205 scan
.addFamily(FAMILY_NAME
);
206 scan
.setTimeRange(0, ts
);
207 ResultScanner scanner
= in
.getScanner(scan
);
211 // HStoreKey key = new HStoreKey();
212 // TreeMap<byte [], Cell>value =
213 // new TreeMap<byte [], Cell>(Bytes.BYTES_COMPARATOR);
214 // while (scanner.next(key, value)) {
215 // assertTrue(key.getTimestamp() <= ts);
216 // // Content matches the key or HConstants.LATEST_TIMESTAMP.
217 // // (Key does not match content if we 'put' with LATEST_TIMESTAMP).
218 // long l = Bytes.toLong(value.get(COLUMN).getValue());
219 // assertTrue(key.getTimestamp() == l ||
220 // HConstants.LATEST_TIMESTAMP == l);
230 public static void put(final Table loader
, final long ts
)
232 put(loader
, Bytes
.toBytes(ts
), ts
);
235 public static void put(final Table loader
)
237 long ts
= HConstants
.LATEST_TIMESTAMP
;
238 put(loader
, Bytes
.toBytes(ts
), ts
);
246 * @throws IOException
248 public static void put(final Table loader
, final byte [] bytes
,
251 Put put
= new Put(ROW
, ts
);
252 put
.setDurability(Durability
.SKIP_WAL
);
253 put
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
, bytes
);
257 public static void delete(final Table loader
) throws IOException
{
258 delete(loader
, null);
261 public static void delete(final Table loader
, final byte [] column
)
263 delete(loader
, column
, HConstants
.LATEST_TIMESTAMP
);
266 public static void delete(final Table loader
, final long ts
)
268 delete(loader
, null, ts
);
271 public static void delete(final Table loader
, final byte [] column
,
274 Delete delete
= ts
== HConstants
.LATEST_TIMESTAMP?
275 new Delete(ROW
): new Delete(ROW
, ts
);
276 delete
.addColumn(FAMILY_NAME
, QUALIFIER_NAME
, ts
);
277 loader
.delete(delete
);
280 public static Result
get(final Table loader
) throws IOException
{
281 return loader
.get(new Get(ROW
));