package com.jivesoftware.os.amza.service.take;
import com.jivesoftware.os.amza.api.AmzaInterner;
import com.jivesoftware.os.amza.api.partition.VersionedPartitionName;
import com.jivesoftware.os.amza.api.ring.RingMember;
import com.jivesoftware.os.amza.api.scan.RowStream;
import com.jivesoftware.os.amza.api.stream.RowType;
import com.jivesoftware.os.amza.service.PropertiesNotPresentException;
import com.jivesoftware.os.amza.service.take.AvailableRowsTaker.AvailableStream;
import com.jivesoftware.os.amza.service.take.AvailableRowsTaker.PingStream;
import com.jivesoftware.os.mlogger.core.MetricLogger;
import com.jivesoftware.os.mlogger.core.MetricLoggerFactory;
import java.io.DataInputStream;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
public class StreamingTakesConsumer {
private static final MetricLogger LOG = MetricLoggerFactory.getLogger();
private final AmzaInterner amzaInterner;
public StreamingTakesConsumer(AmzaInterner amzaInterner) {
this.amzaInterner = amzaInterner;
}
public void consume(DataInputStream dis, AvailableStream updatedPartitionsStream, PingStream pingStream) throws Exception {
while (dis.read() == 1) {
int partitionNameLength = dis.readInt();
if (partitionNameLength == 0) {
pingStream.ping();
continue;
}
byte[] versionedPartitionNameBytes = new byte[partitionNameLength];
dis.readFully(versionedPartitionNameBytes);
long txId = dis.readLong();
try {
VersionedPartitionName versionedPartitionName = amzaInterner.internVersionedPartitionName(versionedPartitionNameBytes, 0,
versionedPartitionNameBytes.length);
updatedPartitionsStream.available(versionedPartitionName, txId);
} catch (PropertiesNotPresentException e) {
LOG.warn(e.getMessage());
} catch (Throwable t) {
LOG.error("Encountered problem while streaming available rows", t);
}
}
}
public StreamingTakeConsumed consume(DataInputStream is, RowStream tookRowUpdates) throws Exception {
Map<RingMember, Long> neighborsHighwaterMarks = new HashMap<>();
long leadershipToken;
long partitionVersion;
boolean isOnline;
long bytes = 0;
boolean streamedToEnd = false;
try (DataInputStream dis = is) {
leadershipToken = dis.readLong();
partitionVersion = dis.readLong();
isOnline = dis.readByte() == 1;
while (dis.readByte() == 1) {
byte[] ringMemberBytes = new byte[dis.readInt()];
dis.readFully(ringMemberBytes);
long highwaterMark = dis.readLong();
neighborsHighwaterMarks.put(amzaInterner.internRingMember(ringMemberBytes, 0, ringMemberBytes.length), highwaterMark);
bytes += 1 + 4 + ringMemberBytes.length + 8;
}
while (dis.readByte() == 1) {
long rowTxId = dis.readLong();
RowType rowType = RowType.fromByte(dis.readByte());
byte[] rowBytes = new byte[dis.readInt()];
dis.readFully(rowBytes);
bytes += 1 + 8 + 1 + 4 + rowBytes.length;
if (rowType != null) {
if (!tookRowUpdates.row(-1, rowTxId, rowType, rowBytes)) {
break;
}
}
}
streamedToEnd = dis.readByte() == 1;
}
return new StreamingTakeConsumed(leadershipToken, partitionVersion, isOnline, neighborsHighwaterMarks, bytes, streamedToEnd);
}
public static class StreamingTakeConsumed {
public final long leadershipToken;
public final long partitionVersion;
public final boolean isOnline;
public final Map<RingMember, Long> neighborsHighwaterMarks;
public final long bytes;
public final boolean streamedToEnd;
public StreamingTakeConsumed(long leadershipToken,
long partitionVersion,
boolean isOnline,
Map<RingMember, Long> neighborsHighwaterMarks,
long bytes,
boolean streamedToEnd) {
this.leadershipToken = leadershipToken;
this.partitionVersion = partitionVersion;
this.isOnline = isOnline;
this.neighborsHighwaterMarks = neighborsHighwaterMarks;
this.bytes = bytes;
this.streamedToEnd = streamedToEnd;
}
}
}