/* * Copyright (C) 2014 Indeed 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 com.indeed.imhotep; import com.google.common.primitives.Longs; import com.indeed.imhotep.protobuf.ShardInfoMessage; import org.apache.log4j.Logger; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.util.Collection; /** * @author jsgroth */ public class ShardInfo implements Comparable<ShardInfo> { private static final Logger log = Logger.getLogger(ShardInfo.class); private static final DateTimeFormatter yyyymmdd = DateTimeFormat.forPattern("yyyyMMdd").withZone(DateTimeZone.forOffsetHours(-6)); private static final DateTimeFormatter yyyymmddhh = DateTimeFormat.forPattern("yyyyMMdd.HH").withZone(DateTimeZone.forOffsetHours(-6)); public final String dataset; public final String shardId; public final Collection<String> loadedMetrics; public final int numDocs; public final long version; private DateTimeRange range; // lazily computed public ShardInfo(String dataset, String shardId, Collection<String> loadedMetrics, int numDocs, long version) { this.dataset = dataset; this.shardId = shardId; this.loadedMetrics = loadedMetrics; this.numDocs = numDocs; this.version = version; } public String getDataset() { return dataset; } public String getShardId() { return shardId; } public Collection<String> getLoadedMetrics() { return loadedMetrics; } public int getNumDocs() { return numDocs; } public long getVersion() { return version; } public DateTime getStart() { if(range == null) { // this is not thread safe but the operation should be deterministic with no side effects range = parseDateTime(shardId); } return range.start; } public DateTime getEnd() { if(range == null) { range = parseDateTime(shardId); } return range.end; } public DateTimeRange getRange() { if(range == null) { range = parseDateTime(shardId); } return range; } public static ShardInfo fromProto(ShardInfoMessage protoShard) { return new ShardInfo( protoShard.getDataset(), protoShard.getShardId(), protoShard.getLoadedMetricList(), protoShard.getNumDocs(), protoShard.getVersion() ); } public ShardInfoMessage toProto() { return ShardInfoMessage.newBuilder() .setDataset(dataset) .setShardId(shardId) .addAllLoadedMetric(loadedMetrics) .setNumDocs(numDocs) .setVersion(version) .build(); } @Override public int compareTo(ShardInfo o) { final int c = dataset.compareTo(o.dataset); if (c != 0) return c; final int c2 = shardId.compareTo(o.shardId); if (c2 != 0) return c2; return Longs.compare(version, o.version); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ShardInfo shardInfo = (ShardInfo) o; if (numDocs != shardInfo.numDocs) return false; if (version != shardInfo.version) return false; if (dataset != null ? !dataset.equals(shardInfo.dataset) : shardInfo.dataset != null) return false; if (loadedMetrics != null ? !loadedMetrics.equals(shardInfo.loadedMetrics) : shardInfo.loadedMetrics != null) return false; if (shardId != null ? !shardId.equals(shardInfo.shardId) : shardInfo.shardId != null) return false; return true; } @Override public int hashCode() { int result = dataset != null ? dataset.hashCode() : 0; result = 31 * result + (shardId != null ? shardId.hashCode() : 0); result = 31 * result + (loadedMetrics != null ? loadedMetrics.hashCode() : 0); result = 31 * result + numDocs; result = 31 * result + (int) (version ^ (version >>> 32)); return result; } @Override public String toString() { return "["+dataset+":"+shardId+"]"; } public static DateTimeRange parseDateTime(String shardId) { try { if (shardId.length() > 16) { final DateTime start = yyyymmddhh.parseDateTime(shardId.substring(5, 16)); final DateTime end = yyyymmddhh.parseDateTime(shardId.substring(17, 28)); return new DateTimeRange(start, end); } else if (shardId.length() > 13) { final DateTime start = yyyymmddhh.parseDateTime(shardId.substring(5, 16)); final DateTime end = start.plusHours(1); return new DateTimeRange(start, end); } else { final DateTime start = yyyymmdd.parseDateTime(shardId.substring(5, 13)); final DateTime end = start.plusDays(1); return new DateTimeRange(start, end); } } catch (IllegalArgumentException e) { return null; } } public static final class DateTimeRange { public final DateTime start; public final DateTime end; public DateTimeRange(DateTime start, DateTime end) { this.start = start; this.end = end; } } }