package com.activequant.archive.hbase; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.HConnectionManager; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.util.Bytes; import com.activequant.domainmodel.TimeFrame; import com.activequant.domainmodel.TimeStamp; import com.activequant.domainmodel.Tuple; import com.activequant.interfaces.archive.IArchiveWriter; /** * * All timestamps are in UTC and in Nanoseconds. Flushing needs to be done * manually - no flushing will be done by the archive writer, which means that * all values stay in memory until flushed! Data loss is at your risk! * * Visibility on package level only is intended! compare the corresponding * factory class. * * @author ustaudinger * */ class HBaseArchiveWriter extends HBaseBase implements IArchiveWriter { private List<Put> puts = new ArrayList<Put>(); HBaseArchiveWriter(final String zookeeperHost, final TimeFrame tf) throws IOException { super(zookeeperHost, 2181, "TSDATA_" + tf.toString()); } HBaseArchiveWriter(final String zookeeperHost, final int zookeeperPort, final TimeFrame tf) throws IOException { super(zookeeperHost, zookeeperPort, "TSDATA_" + tf.toString()); } @Deprecated HBaseArchiveWriter(final TimeFrame tf) throws IOException { super("TSDATA_" + tf.toString()); } /* * (non-Javadoc) * * @see com.activequant.archive.IArchiveWriter#commit() */ public void commit() throws IOException { synchronized (puts) { htable.put(puts); puts.clear(); htable.flushCommits(); } } /* * (non-Javadoc) * * @see com.activequant.archive.IArchiveWriter#write(java.lang.String, * java.lang.Long, com.activequant.domainmodel.Tuple) */ public void write(String seriesId, TimeStamp timeStamp, Tuple<String, Double>... value) throws IOException { for (Tuple<String, Double> t : value) { write(seriesId, timeStamp, t.getA(), t.getB()); } } /* * (non-Javadoc) * * @see com.activequant.archive.IArchiveWriter#write(java.lang.String, * java.lang.Long, java.lang.String[], java.lang.Double[]) */ public void write(String seriesId, TimeStamp timeStamp, String[] keys, Double[] values) { assert (values != null); assert (keys != null); assert (keys.length == values.length); for (int i = 0; i < keys.length; i++) { write(seriesId, timeStamp, keys[i], values[i]); } } /* * (non-Javadoc) * * @see com.activequant.archive.IArchiveWriter#write(java.lang.String, * java.lang.Long, java.lang.String, java.lang.Double) */ public void write(String seriesId, TimeStamp timeStamp, String key, Double value) { assert (key != null); assert (value != null); String rowKey = seriesId + "_" + padded(timeStamp.toString()); Put p = new Put(rowKey.getBytes()); // p.add("numbers".getBytes(), key.getBytes(), Bytes.toBytes(value)); p.add("numbers".getBytes(), "ts".getBytes(), Bytes.toBytes(timeStamp.getNanoseconds())); // also add the key to the series/key map. Put p2 = new Put(("FIELDS_"+seriesId).getBytes()); p2.add("fields".getBytes(), key.getBytes(), Bytes.toBytes(1)); // relatively expensive call. have to find a way around. // maybe by using a special class. synchronized (puts) { puts.add(p); puts.add(p2); } } @Override public void delete(String seriesKey, String valueKey) throws IOException { delete(seriesKey, valueKey, new TimeStamp(0L), new TimeStamp(Long.MAX_VALUE)); } @Override public void delete(String seriesKey, String valueKey, TimeStamp from, TimeStamp to) throws IOException { ResultScanner scanner = null; try { scanner = getScanner(seriesKey, from, to); List<Delete> rows = new ArrayList<Delete>(); for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { if (rr.containsColumn("numbers".getBytes(), valueKey.getBytes())) { Delete del = new Delete(rr.getRow()); del.deleteColumn("numbers".getBytes(), valueKey.getBytes()); rows.add(del); } } htable.delete(rows); } finally { if (scanner != null) scanner.close(); } } @Override public void delete(String seriesKey) throws IOException { delete(seriesKey, new TimeStamp(0L), new TimeStamp(Long.MAX_VALUE)); } @Override public void delete(String seriesKey, TimeStamp from, TimeStamp to) throws IOException { ResultScanner scanner = null; try { scanner = getScanner(seriesKey, from, to); List<Delete> rows = new ArrayList<Delete>(); for (Result rr = scanner.next(); rr != null; rr = scanner.next()) { rows.add(new Delete(rr.getRow())); } htable.delete(rows); } finally { if (scanner != null) scanner.close(); } } @Override public void close() throws IOException { this.htable.close(); if(config!=null) HConnectionManager.deleteConnection(config); } }