/**
* Copyright 2009 The Apache Software Foundation
*
* 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.hadoop.hbase.client.ccindex;
import java.io.IOException;
import java.util.HashMap;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Writables;
public class SimpleOptimizer extends Thread implements Optimizer {
static final Log LOG = LogFactory.getLog(SimpleOptimizer.class);
private final HBaseConfiguration conf;
private static HashMap<String, Vector<HRegionInfo>> tableToRegion = new HashMap<String, Vector<HRegionInfo>>();
IndexedTable father;
private long inter = 60000;
public int whichToScan(Range[] ranges) {
long[][] regionSize = new long[ranges.length][];
for (int i = 0; i < ranges.length; i++) {
regionSize[i] = this.getEstimatedRegionDisAndNumDis(ranges[i]);
//System.out.println(ranges[i]);
}
int min = this.getMin(regionSize);
LOG.info("mini range is:" + min);
return min;
}
private long disCompare(long[] dis1, long[] dis2) {
for (int i = 0; i < dis1.length; i++) {
if (dis1[i] != dis2[i])
return (dis1[i] - dis2[i]);
}
return 0;
}
private int getMin(long[][] dis) {
long[] tmp = new long[] { Long.MAX_VALUE, Long.MAX_VALUE,
Long.MAX_VALUE };
int min = 0;
for (int i = 0; i < dis.length; i++) {
if (this.disCompare(dis[i], tmp) < 0L) {
tmp = dis[i];
min = i;
}
}
return min;
}
public long[] getRegionDis(Vector<HRegionInfo> v) {
if (v.size() == 0) {
return new long[] { 0, 0 };
}
long indexDis = 0;
long numDis = 0;
long completeRegion = 0;
for (HRegionInfo info : v) {
if (info.getStartKey().length != 0 && info.getEndKey().length != 0) {
completeRegion++;
long dis[] = Utilities.disRowKey(info.getStartKey(), info
.getEndKey());
indexDis += dis[0];
numDis += dis[1];
}
}
if (completeRegion == 0) {
if (v.get(0).getStartKey().length != 0) {
return Utilities.disRowKey(v.get(0).getStartKey(), null);
} else {
return new long[] { 0, 0 };
}
}
return new long[] {
(long) Math.ceil(((float) indexDis / completeRegion)),
(long) Math.ceil(((float) numDis / completeRegion)) };
}
public long[] getEstimatedRegionDisAndNumDis(Range r) {
byte[] startKey = null;
byte[] endKey = null;
if (r.getStart() != null)
startKey = r.getStart();
if (r.getEnd() != null) {
endKey = r.getEnd();
}
byte[] index = this.father.getColumnToIndexID().get(
r.getColumn());
HTable t = this.father.getIndexIdToTable().get(index);
String tableName = new String(t.getTableName());
if (this.tableToRegion.size() == 0) {
this.refresh();
}
Vector<HRegionInfo> infos = this.tableToRegion.get(tableName);
if (infos == null)
return new long[] { 0, 0, 0 };
int startRegion = 0;
int endRegion = 0;
boolean startset = false;
boolean endset = false;
for (int i = 0; i < infos.size(); i++) {
if (startset && endset)
break;
if (startKey != null) {
if (infos.get(i).getStartKey().length != 0) {
if (Bytes.compareTo(startKey, infos.get(i).getStartKey()) >= 0) {
startRegion = i;
} else {
startset = true;
}
}
}
if (endKey != null && (!endset)) {
if (infos.get(i).getEndKey().length != 0) {
if (Bytes.compareTo(endKey, infos.get(i).getEndKey()) < 0) {
endRegion = i;
endset = true;
}
} else {
endRegion = i;
endset = true;
}
} else if (endKey == null) {
endRegion = i;
}
}
if (startKey != null && endKey != null) {
long[] ndis = Utilities.dis(startKey, endKey);
return new long[] { endRegion - startRegion, ndis[0], ndis[1] };
} else if (startKey == null && endKey == null) {
return new long[] { endRegion - startRegion, Long.MAX_VALUE,
Long.MAX_VALUE };
} else if (startKey == null && endKey != null) {
startKey = infos.get(startRegion).getEndKey().length == 0 ? infos
.get(startRegion).getEndKey() : infos.get(startRegion)
.getStartKey();
if (startKey.length == 0) {
return new long[] { endRegion - startRegion, 0, 0 };
} else {
long[] ndis = Utilities.dis(startKey, endKey);
return new long[] { endRegion - startRegion, ndis[0], ndis[1] };
}
} else if (startKey != null && endKey == null) {
endKey = infos.get(endRegion).getStartKey().length == 0 ? infos
.get(endRegion).getStartKey() : infos.get(endRegion)
.getEndKey();
if (endKey.length == 0) {
return new long[] { endRegion - startRegion, 0, 0 };
} else {
long[] ndis = Utilities.dis(startKey, endKey);
return new long[] { endRegion - startRegion, ndis[0], ndis[1] };
}
}
return new long[] { endRegion - startRegion, 0, 0 };
}
private long[] disAdd(long[] dis, long[] dis2) {
long[] ret = new long[3];
ret[0] = dis[0] + dis2[0];
if (dis[1] == dis2[1]) {
ret[1] = dis[1];
ret[2] = Math.max(dis[2], dis2[2]);
} else {
ret[1] = Math.max(dis[1], dis2[1]);
ret[2] = dis[1] > dis2[2] ? dis[2] : dis2[2];
}
return ret;
}
public SimpleOptimizer(final HBaseConfiguration conf, IndexedTable father) {
this.father = father;
this.conf = conf;
this.refresh();
}
synchronized public void refresh() {
HTable metaTable;
try {
metaTable = new HTable(conf, HConstants.META_TABLE_NAME);
metaTable.setAutoFlush(false);
metaTable.setWriteBufferSize(1024 * 1024 * 12);
metaTable.setScannerCaching(1000);
Scan indexScan = new Scan();
indexScan.setCaching(1000);
ResultScanner indexScanner = metaTable.getScanner(indexScan);
Result r = null;
while ((r = indexScanner.next()) != null) {
// System.out.println(r);
byte[] value = r.getValue(HConstants.CATALOG_FAMILY,
HConstants.REGIONINFO_QUALIFIER);
if (value == null || value.length == 0) {
throw new IOException("HRegionInfo was null or empty in ");
}
// convert the row result into the HRegionLocation we need!
HRegionInfo regionInfo = (HRegionInfo) Writables.getWritable(
value, new HRegionInfo());
if (this.tableToRegion.get(regionInfo.getTableDesc()
.getNameAsString()) == null) {
this.tableToRegion.put(regionInfo.getTableDesc()
.getNameAsString(), new Vector<HRegionInfo>());
}
this.tableToRegion.get(
regionInfo.getTableDesc().getNameAsString()).add(
regionInfo);
// System.out.println("StartKey:"+new
// String(regionInfo.getStartKey())+"EndKey:"+new
// String(regionInfo.getEndKey()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
while (true) {
this.refresh();
try {
sleep(this.inter);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String args[]) {
SimpleOptimizer r = new SimpleOptimizer(null, null);
r.refresh();
}
}