Java tutorial
/* * 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.accumulo.core.client.admin; import java.io.ByteArrayOutputStream; import java.math.BigInteger; import java.util.Iterator; import java.util.Map.Entry; import org.apache.accumulo.core.client.IteratorSetting; import org.apache.accumulo.core.client.Scanner; import org.apache.accumulo.core.client.TableNotFoundException; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.PartialKey; import org.apache.accumulo.core.data.Range; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.iterators.SortedKeyIterator; import org.apache.hadoop.io.Text; public class FindMax { private static void appendZeros(ByteArrayOutputStream baos, int num) { for (int i = 0; i < num; i++) baos.write(0); } private static Text findMidPoint(Text minBS, Text maxBS) { ByteArrayOutputStream startOS = new ByteArrayOutputStream(); startOS.write(0); // add a leading zero so bigint does not think its negative startOS.write(minBS.getBytes(), 0, minBS.getLength()); ByteArrayOutputStream endOS = new ByteArrayOutputStream(); endOS.write(0);// add a leading zero so bigint does not think its negative endOS.write(maxBS.getBytes(), 0, maxBS.getLength()); // make the numbers of the same magnitude if (startOS.size() < endOS.size()) appendZeros(startOS, endOS.size() - startOS.size()); else if (endOS.size() < startOS.size()) appendZeros(endOS, startOS.size() - endOS.size()); BigInteger min = new BigInteger(startOS.toByteArray()); BigInteger max = new BigInteger(endOS.toByteArray()); BigInteger mid = max.subtract(min).divide(BigInteger.valueOf(2)).add(min); byte[] ba = mid.toByteArray(); Text ret = new Text(); if (ba.length == startOS.size()) { if (ba[0] != 0) throw new RuntimeException(); // big int added a zero so it would not be negative, drop it ret.set(ba, 1, ba.length - 1); } else { int expLen = Math.max(minBS.getLength(), maxBS.getLength()); // big int will drop leading 0x0 bytes for (int i = ba.length; i < expLen; i++) { ret.append(new byte[] { 0 }, 0, 1); } ret.append(ba, 0, ba.length); } // remove trailing 0x0 bytes while (ret.getLength() > 0 && ret.getBytes()[ret.getLength() - 1] == 0 && ret.compareTo(minBS) > 0) { Text t = new Text(); t.set(ret.getBytes(), 0, ret.getLength() - 1); ret = t; } return ret; } private static Text _findMax(Scanner scanner, Text start, boolean inclStart, Text end, boolean inclEnd) { // System.out.printf("findMax(%s, %s, %s, %s)%n", Key.toPrintableString(start.getBytes(), 0, start.getLength(), 1000), inclStart, // Key.toPrintableString(end.getBytes(), 0, end.getLength(), 1000), inclEnd); int cmp = start.compareTo(end); if (cmp >= 0) { if (inclStart && inclEnd && cmp == 0) { scanner.setRange(new Range(start, true, end, true)); Iterator<Entry<Key, Value>> iter = scanner.iterator(); if (iter.hasNext()) return iter.next().getKey().getRow(); } return null; } Text mid = findMidPoint(start, end); // System.out.println("mid = :"+Key.toPrintableString(mid.getBytes(), 0, mid.getLength(), 1000)+":"); scanner.setRange(new Range(mid, mid.equals(start) ? inclStart : true, end, inclEnd)); Iterator<Entry<Key, Value>> iter = scanner.iterator(); if (iter.hasNext()) { Key next = iter.next().getKey(); int count = 0; while (count < 10 && iter.hasNext()) { next = iter.next().getKey(); count++; } if (!iter.hasNext()) return next.getRow(); Text ret = _findMax(scanner, next.followingKey(PartialKey.ROW).getRow(), true, end, inclEnd); if (ret == null) return next.getRow(); else return ret; } else { return _findMax(scanner, start, inclStart, mid, mid.equals(start) ? inclStart : false); } } private static Text findInitialEnd(Scanner scanner) { Text end = new Text(new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }); scanner.setRange(new Range(end, null)); while (scanner.iterator().hasNext()) { Text t = new Text(); t.append(end.getBytes(), 0, end.getLength()); t.append(end.getBytes(), 0, end.getLength()); end = t; scanner.setRange(new Range(end, null)); } return end; } public static Text findMax(Scanner scanner, Text start, boolean is, Text end, boolean ie) throws TableNotFoundException { scanner.setBatchSize(12); IteratorSetting cfg = new IteratorSetting(Integer.MAX_VALUE, SortedKeyIterator.class); scanner.addScanIterator(cfg); if (start == null) { start = new Text(); is = true; } if (end == null) end = findInitialEnd(scanner); return _findMax(scanner, start, is, end, ie); } }