/**
* 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 io.horizondb.db.series;
import io.horizondb.io.ByteReader;
import io.horizondb.io.ByteWriter;
import io.horizondb.io.encoding.VarInts;
import io.horizondb.io.serialization.Parser;
import io.horizondb.io.serialization.Serializable;
import io.horizondb.model.core.Field;
import io.horizondb.model.schema.DatabaseDefinition;
import io.horizondb.model.schema.TimeSeriesDefinition;
import java.io.IOException;
import javax.annotation.concurrent.Immutable;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import com.google.common.collect.Range;
import static io.horizondb.model.core.util.SerializationUtils.computeRangeSerializedSize;
import static io.horizondb.model.core.util.SerializationUtils.parseRangeFrom;
import static io.horizondb.model.core.util.SerializationUtils.writeRange;
/**
* ID used to identify uniquely a time series partition.
*/
@Immutable
final class PartitionId implements Comparable<PartitionId>, Serializable {
/**
* The parser instance.
*/
private static final Parser<PartitionId> PARSER = new Parser<PartitionId>() {
/**
* {@inheritDoc}
*/
@Override
public PartitionId parseFrom(ByteReader reader) throws IOException {
String database = VarInts.readString(reader);
long databaseTimestamp = VarInts.readLong(reader);
String timeSeries = VarInts.readString(reader);
long timeSeriesTimestamp = VarInts.readLong(reader);
Range<Field> range = parseRangeFrom(reader);
return new PartitionId(database, databaseTimestamp, timeSeries, timeSeriesTimestamp, range);
}
};
/**
* The database name.
*/
private final String databaseName;
/**
* The database creation time.
*/
private final long databaseTimestamp;
/**
* The time series name.
*/
private final String seriesName;
/**
* The time series creation time.
*/
private final long seriesTimestamp;
/**
* The partition time range.
*/
private final Range<Field> range;
/**
* Creates a new <code>PartitionId</code> for the partition belonging to the specified database and time series.
*
* @param databaseDefinition the database definition
* @param timeSeriesDefinition the time series definition
* @param range the partition time range
*/
public PartitionId(DatabaseDefinition databaseDefinition,
TimeSeriesDefinition timeSeriesDefinition,
Range<Field> range) {
this(databaseDefinition.getName(),
databaseDefinition.getTimestamp(),
timeSeriesDefinition.getName(),
timeSeriesDefinition.getTimestamp(),
range);
}
/**
* Creates a new <code>PartitionId</code>.
*
* @param databaseName the database name
* @param databaseTimestamp the database creation time
* @param seriesName the time series name
* @param seriesTimestamp the time series creation time
* @param range the partition time range
*/
public PartitionId(String databaseName,
long databaseTimestamp,
String seriesName,
long seriesTimestamp,
Range<Field> range) {
this.databaseName = databaseName.toLowerCase();
this.databaseTimestamp = databaseTimestamp;
this.seriesName = seriesName.toLowerCase();
this.seriesTimestamp = seriesTimestamp;
this.range = range;
}
/**
* Creates a new <code>TimeSeriesId</code> by reading the data from the specified reader.
*
* @param reader the reader to read from.
* @throws IOException if an I/O problem occurs
*/
public static PartitionId parseFrom(ByteReader reader) throws IOException {
return getParser().parseFrom(reader);
}
/**
* Returns the parser that can be used to deserialize <code>TimeSeriesId</code> instances.
*
* @return the parser that can be used to deserialize <code>TimeSeriesId</code> instances.
*/
public static Parser<PartitionId> getParser() {
return PARSER;
}
/**
* Returns the database name.
*
* @return the database name.
*/
public String getDatabaseName() {
return this.databaseName;
}
/**
* Returns the time series name.
*
* @return the time series name.
*/
public String getSeriesName() {
return this.seriesName;
}
/**
* Returns the database creation time.
* @return the database creation time
*/
public long getDatabaseTimestamp() {
return this.databaseTimestamp;
}
/**
* Returns the time series creation time.
* @return the time series creation time
*/
public long getSeriesTimestamp() {
return this.seriesTimestamp;
}
/**
* Returns the partition range.
*
* @return the partition range.
*/
public Range<Field> getRange() {
return this.range;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (!(object instanceof PartitionId)) {
return false;
}
PartitionId rhs = (PartitionId) object;
return new EqualsBuilder().append(this.databaseName, rhs.databaseName)
.append(this.databaseTimestamp, rhs.databaseTimestamp)
.append(this.seriesName, rhs.seriesName)
.append(this.seriesTimestamp, rhs.seriesTimestamp)
.append(this.range, rhs.range)
.isEquals();
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return new HashCodeBuilder(-881768609, -777990173).append(this.databaseName)
.append(this.databaseTimestamp)
.append(this.seriesName)
.append(this.seriesTimestamp)
.append(this.range)
.toHashCode();
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return new StringBuilder().append(this.databaseName)
.append('.')
.append(this.seriesName)
.append('[')
.append(this.range.lowerEndpoint().getTimestampInMillis())
.append("..")
.append(this.range.upperEndpoint().getTimestampInMillis())
.append(')')
.toString();
}
/**
* {@inheritDoc}
*/
@Override
public int compareTo(PartitionId other) {
return new CompareToBuilder().append(this.databaseName, other.databaseName)
.append(this.databaseTimestamp, other.databaseTimestamp)
.append(this.seriesName, other.seriesName)
.append(this.seriesTimestamp, other.seriesTimestamp)
.append(this.range.lowerEndpoint(), other.range.lowerEndpoint())
.append(this.range.upperEndpoint(), other.range.upperEndpoint())
.toComparison();
}
/**
* {@inheritDoc}
*/
@Override
public int computeSerializedSize() {
return VarInts.computeStringSize(this.databaseName)
+ VarInts.computeLongSize(this.databaseTimestamp)
+ VarInts.computeStringSize(this.seriesName)
+ VarInts.computeLongSize(this.seriesTimestamp)
+ computeRangeSerializedSize(this.range);
}
/**
* {@inheritDoc}
*/
@Override
public void writeTo(ByteWriter writer) throws IOException {
VarInts.writeString(writer, this.databaseName);
VarInts.writeLong(writer, this.databaseTimestamp);
VarInts.writeString(writer, this.seriesName);
VarInts.writeLong(writer, this.seriesTimestamp);
writeRange(writer, this.range);
}
}