/*
* 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.data.stream;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import org.apache.twill.filesystem.Location;
import org.apache.twill.filesystem.LocationFactory;
import java.net.URI;
/**
* Represents offset information for single stream file. The comparison of offset instance
* is done by comparing event location path followed by offset.
*/
public final class StreamFileOffset {
private final Location eventLocation;
private final Location indexLocation;
private final long partitionStart;
private final long partitionEnd;
private final String namePrefix;
private final int seqId;
private final long offset;
private final int generation;
/**
* Clones from another {@link StreamFileOffset}.
* @param other The instance to clone from.
*/
public StreamFileOffset(StreamFileOffset other) {
this(other, other.getOffset());
}
/**
* Clones from another {@link StreamFileOffset} but with a different offset value.
*
* @param other The instance to clone from
* @param offset file offset
*/
public StreamFileOffset(StreamFileOffset other, long offset) {
this.eventLocation = other.eventLocation;
this.indexLocation = other.indexLocation;
this.partitionStart = other.partitionStart;
this.partitionEnd = other.partitionEnd;
this.namePrefix = other.namePrefix;
this.seqId = other.seqId;
this.generation = other.generation;
this.offset = offset;
}
public StreamFileOffset(Location eventLocation, long offset, int generation) {
Preconditions.checkNotNull(eventLocation, "Event file location cannot be null.");
this.eventLocation = eventLocation;
this.indexLocation = createIndexLocation(eventLocation);
this.offset = offset;
// See StreamInputFormat for the path format
String partitionName = StreamUtils.getPartitionName(eventLocation);
this.partitionStart = StreamUtils.getPartitionStartTime(partitionName);
this.partitionEnd = StreamUtils.getPartitionEndTime(partitionName);
this.namePrefix = StreamUtils.getNamePrefix(eventLocation.getName());
this.seqId = StreamUtils.getSequenceId(eventLocation.getName());
this.generation = generation;
}
public Location getEventLocation() {
return eventLocation;
}
public Location getIndexLocation() {
return indexLocation;
}
public long getOffset() {
return offset;
}
public long getPartitionStart() {
return partitionStart;
}
public long getPartitionEnd() {
return partitionEnd;
}
public String getNamePrefix() {
return namePrefix;
}
public int getSequenceId() {
return seqId;
}
public int getGeneration() {
return generation;
}
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("event", eventLocation)
.add("offset", getOffset())
.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StreamFileOffset other = (StreamFileOffset) o;
return (offset == other.offset) && Objects.equal(eventLocation, other.eventLocation);
}
@Override
public int hashCode() {
return Objects.hashCode(eventLocation, offset);
}
/**
* Creates the index file location from the event file location.
*
* @param eventLocation Location for the event file.
* @return Location of the index file.
*/
private Location createIndexLocation(Location eventLocation) {
LocationFactory factory = eventLocation.getLocationFactory();
String eventPath = eventLocation.toURI().toString();
int extLength = StreamFileType.EVENT.getSuffix().length();
return factory.create(URI.create(String.format("%s%s",
eventPath.substring(0, eventPath.length() - extLength),
StreamFileType.INDEX.getSuffix())));
}
}