/* * Copyright © 2014 Cask Data, Inc. * * Licensed 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 co.cask.cdap.api.dataset.lib; import co.cask.cdap.api.common.Bytes; import co.cask.cdap.api.dataset.DatasetSpecification; import co.cask.cdap.api.dataset.table.Table; import java.util.Iterator; import java.util.NoSuchElementException; /** * A Dataset for incrementing counts over time periods. This Dataset provides an extension to {@link TimeseriesTable} * for long values and provides increment methods for counting. * * <p>For more information on choosing values for <code>rowPartitionIntervalSize</code> and tag usage, please see the * {@link TimeseriesTable} class description.</p> * * @see TimeseriesTable */ public class CounterTimeseriesTable extends TimeseriesDataset { /** * Creates an instance of the DataSet. */ public CounterTimeseriesTable(DatasetSpecification spec, Table table) { super(spec, table); } /** * Increments the value for a counter for a row and timestamp. * * @param counter the name of the counter to increment * @param amount the amount to increment by * @param timestamp timestamp of the entry * @param tags optional list of tags associated with the counter. See {@link TimeseriesTable} class description * for more details. * @return value of the entry after increment */ public long increment(byte[] counter, long amount, long timestamp, byte[]... tags) { return internalIncrement(counter, amount, timestamp, tags); } /** * Set the value for a counter. * * @param counter the name of the counter to set * @param value the value to set * @param timestamp timestamp of the entry * @param tags optional list of tags associated with the counter. See {@link TimeseriesTable} class description * for more details. */ public void set(byte[] counter, long value, long timestamp, byte[]... tags) { write(counter, Bytes.toBytes(value), timestamp, tags); } /** * Reads entries for a given time range and returns an <code>Iterator<Counter></code>. * NOTE: A limit is placed on the max number of time intervals to be scanned during a read, as defined by * {@link #MAX_ROWS_TO_SCAN_PER_READ}. * * @param counter name of the counter to read * @param startTime defines start of the time range to read, inclusive * @param endTime defines end of the time range to read, inclusive * @param tags a set of tags which entries returned must contain. Tags for entries are defined at write-time and an * entry is only returned if it contains all of these tags. * @return an iterator over entries that satisfy provided conditions */ public Iterator<Counter> read(byte[] counter, long startTime, long endTime, byte[]... tags) { final Iterator<Entry> internalItor = readInternal(counter, startTime, endTime, tags); return new Iterator<Counter>() { @Override public boolean hasNext() { return internalItor.hasNext(); } @Override public Counter next() { Entry entry = internalItor.next(); return new Counter(entry.getKey(), Bytes.toLong(entry.getValue()), entry.getTimestamp(), entry.getTags()); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Reads entries for a given time range and returns an <code>Iterator<Counter></code>. * Provides the same functionality as {@link #read(byte[], long, long, byte[][]) read(byte[], long, long, byte[]...)} * but accepts additional parameters for pagination purposes. * * @param counter name of the counter to read * @param startTime defines start of the time range to read, inclusive * @param endTime defines end of the time range to read, inclusive * @param offset the number of initial entries to ignore and not add to the results * @param limit upper limit on number of results returned. If limit is exceeded, the first <code>limit</code> results * are returned. * @param tags a set of tags which entries returned must contain. Tags for entries are defined at write-time and an * entry is only returned if it contains all of these tags. * @return an iterator over entries that satisfy provided conditions */ public Iterator<Counter> read(byte[] counter, long startTime, long endTime, int offset, final int limit, byte[]... tags) { if (offset < 0) { throw new IllegalArgumentException("Offset cannot be < 0"); } if (limit < 0) { throw new IllegalArgumentException("Limit cannot be < 0"); } final Iterator<Counter> iterator = read(counter, startTime, endTime, tags); // Move to offset for (int i = 0; i < offset && iterator.hasNext(); i++) { iterator.next(); } // Returns a limiting Iterator return new Iterator<Counter>() { private int count = 0; @Override public boolean hasNext() { return count < limit && iterator.hasNext(); } @Override public Counter next() { if (!hasNext()) { throw new NoSuchElementException(); } count++; return iterator.next(); } @Override public void remove() { iterator.remove(); } }; } /** * Defines an object for counters in {@link CounterTimeseriesTable}. */ public static final class Counter { private byte[] counter; private long value; private long timestamp; private byte[][] tags; /** * Creates an instance of a time series counter. * @param counter name of the counter * @param value value of the counter * @param timestamp timestamp of the counter * @param tags optional list of tags associated with the counter. See {@link TimeseriesTable} class description * for more details. */ private Counter(byte[] counter, long value, long timestamp, byte[]... tags) { this.counter = counter; this.value = value; this.timestamp = timestamp; this.tags = tags; } /** * Returns the name of the counter. * @return the name of the counter */ public byte[] getCounter() { return counter; } /** * Returns the count value of the counter. * @return the count value of the counter */ public long getValue() { return value; } /** * Returns the timestamp of the counter. * @return the timestamp of the counter */ public long getTimestamp() { return timestamp; } /** * Returns the tags associated with the counter. * @return the tags associated with the counter */ public byte[][] getTags() { return tags; } } }