package com.navercorp.pinpoint.common.server.bo.serializer.trace.v2.bitfield;
import com.navercorp.pinpoint.common.server.bo.AnnotationBo;
import com.navercorp.pinpoint.common.server.bo.SpanEventBo;
import com.navercorp.pinpoint.common.util.BitFieldUtils;
import org.apache.commons.collections.CollectionUtils;
import java.util.List;
/**
* @author Woonduk Kang(emeroad)
*/
public class SpanEventBitField {
public static final int SET_ANNOTATION = 0;
public static final int SET_HAS_EXCEPTION = 1;
public static final int SET_NEXT_ASYNCID = 2;
public static final int SET_ASYNCID = 3;
public static final int SET_NEXT_SPANID = 4;
public static final int SET_ENDPOINT = 5;
public static final int SET_DESTINATIONID = 6;
public static final int SET_RPC = 7;
// firstSpan bitField -----------------------------------------------
public static final int START_ELAPSED_ENCODING_STRATEGY = 8;
public static final int SERVICE_TYPE_ENCODING_STRATEGY = 9;
public static final int SEQUENCE_ENCODING_STRATEGY = 10;
public static final int DEPTH_ENCODING_STRATEGY = 11;
public static final int API_ENCODING_STRATEGY = 13;
private short bitField = 0;
public static SpanEventBitField buildFirst(SpanEventBo spanEventBo) {
if (spanEventBo == null) {
throw new NullPointerException("spanEventBo must not be null");
}
final SpanEventBitField bitFiled = new SpanEventBitField();
if (spanEventBo.getRpc() != null) {
bitFiled.setRpc(true);
}
if (spanEventBo.getEndPoint() != null) {
bitFiled.setEndPoint(true);
}
if (spanEventBo.getDestinationId() != null) {
bitFiled.setDestinationId(true);
}
if (spanEventBo.getNextSpanId() != -1) {
bitFiled.setNextSpanId(true);
}
if (spanEventBo.hasException()) {
bitFiled.setHasException(true);
}
final List<AnnotationBo> annotationBoList = spanEventBo.getAnnotationBoList();
if (CollectionUtils.isNotEmpty(annotationBoList)) {
bitFiled.setAnnotation(true);
}
if (spanEventBo.getNextAsyncId() != -1) {
bitFiled.setNextAsyncId(true);
}
if (spanEventBo.getAsyncId() == -1 && spanEventBo.getAsyncSequence() == -1) {
bitFiled.setAsyncId(false);
} else {
bitFiled.setAsyncId(true);
}
return bitFiled;
}
public static SpanEventBitField build(SpanEventBo spanEventBo, SpanEventBo prevSpanEventBo) {
if (spanEventBo == null) {
throw new NullPointerException("spanEventBo must not be null");
}
if (prevSpanEventBo == null) {
throw new NullPointerException("prevSpanEventBo must not be null");
}
final SpanEventBitField bitFiled = buildFirst(spanEventBo);
if (spanEventBo.getStartElapsed() == prevSpanEventBo.getStartElapsed()) {
bitFiled.setStartElapsedEncodingStrategy(StartElapsedTimeEncodingStrategy.PREV_EQUALS);
} else {
bitFiled.setStartElapsedEncodingStrategy(StartElapsedTimeEncodingStrategy.PREV_DELTA);
}
// sequence prev: 5 current: 6 = 6 - 5= delta 1
final short sequenceDelta = (short) (spanEventBo.getSequence() - prevSpanEventBo.getSequence());
if (sequenceDelta == 1) {
bitFiled.setSequenceEncodingStrategy(SequenceEncodingStrategy.PREV_ADD1);
} else {
bitFiled.setSequenceEncodingStrategy(SequenceEncodingStrategy.PREV_DELTA);
}
if (spanEventBo.getDepth() == prevSpanEventBo.getDepth()) {
bitFiled.setDepthEncodingStrategy(DepthEncodingStrategy.PREV_EQUALS);
} else {
bitFiled.setDepthEncodingStrategy(DepthEncodingStrategy.RAW);
}
if (prevSpanEventBo.getServiceType() == spanEventBo.getServiceType()) {
bitFiled.setServiceTypeEncodingStrategy(ServiceTypeEncodingStrategy.PREV_EQUALS);
} else {
bitFiled.setServiceTypeEncodingStrategy(ServiceTypeEncodingStrategy.RAW);
}
return bitFiled;
}
public SpanEventBitField() {
}
public SpanEventBitField(short bitField) {
this.bitField = bitField;
}
// for test
void maskAll() {
bitField = -1;
}
public short getBitField() {
return bitField;
}
private void setBit(int position, boolean value) {
this.bitField = BitFieldUtils.setBit(bitField, position, value);
}
private boolean testBit(int position) {
return BitFieldUtils.testBit(bitField, position);
}
private int getBit(int position) {
return BitFieldUtils.getBit(bitField, position);
}
public boolean isSetHasException() {
return testBit(SET_HAS_EXCEPTION);
}
void setHasException(boolean hasException) {
setBit(SET_HAS_EXCEPTION, hasException);
}
public boolean isSetAnnotation() {
return testBit(SET_ANNOTATION);
}
void setAnnotation(boolean annotation) {
setBit(SET_ANNOTATION, annotation);
}
public boolean isSetNextAsyncId() {
return testBit(SET_NEXT_ASYNCID);
}
void setNextAsyncId(boolean nextAsyncSpanId) {
setBit(SET_NEXT_ASYNCID, nextAsyncSpanId);
}
public boolean isSetNextSpanId() {
return testBit(SET_NEXT_SPANID);
}
void setNextSpanId(boolean nextSpanId) {
setBit(SET_NEXT_SPANID, nextSpanId);
}
public boolean isSetEndPoint() {
return testBit(SET_ENDPOINT);
}
void setEndPoint(boolean endPoint) {
setBit(SET_ENDPOINT, endPoint);
}
public boolean isSetDestinationId() {
return testBit(SET_DESTINATIONID);
}
void setDestinationId(boolean destinationId) {
setBit(SET_DESTINATIONID, destinationId);
}
public boolean isSetRpc() {
return testBit(SET_RPC);
}
void setRpc(boolean rpc) {
setBit(SET_RPC, rpc);
}
public boolean isSetAsyncId() {
return testBit(SET_ASYNCID);
}
void setAsyncId(boolean asyncId) {
setBit(SET_ASYNCID, asyncId);
}
public StartElapsedTimeEncodingStrategy getStartElapsedEncodingStrategy() {
final int set = getBit(START_ELAPSED_ENCODING_STRATEGY);
switch (set) {
case 0:
return StartElapsedTimeEncodingStrategy.PREV_EQUALS;
case 1:
return StartElapsedTimeEncodingStrategy.PREV_DELTA;
default:
throw new IllegalArgumentException("SERVICE_TYPE_ENCODING_STRATEGY");
}
}
void setStartElapsedEncodingStrategy(StartElapsedTimeEncodingStrategy strategy) {
switch (strategy) {
case PREV_EQUALS:
setBit(START_ELAPSED_ENCODING_STRATEGY, false);
break;
case PREV_DELTA:
setBit(START_ELAPSED_ENCODING_STRATEGY, true);
break;
default:
throw new IllegalArgumentException("START_ELAPSED_ENCODING_STRATEGY");
}
}
public ServiceTypeEncodingStrategy getServiceTypeEncodingStrategy() {
final int set = getBit(SERVICE_TYPE_ENCODING_STRATEGY);
switch (set) {
case 0:
return ServiceTypeEncodingStrategy.PREV_EQUALS;
case 1:
return ServiceTypeEncodingStrategy.RAW;
default:
throw new IllegalArgumentException("SERVICE_TYPE_ENCODING_STRATEGY");
}
}
void setServiceTypeEncodingStrategy(ServiceTypeEncodingStrategy strategy) {
switch (strategy) {
case PREV_EQUALS:
setBit(SERVICE_TYPE_ENCODING_STRATEGY, false);
break;
case RAW:
setBit(SERVICE_TYPE_ENCODING_STRATEGY, true);
break;
default:
throw new IllegalArgumentException("SERVICE_TYPE_ENCODING_STRATEGY");
}
}
public SequenceEncodingStrategy getSequenceEncodingStrategy() {
final int set = getBit(SEQUENCE_ENCODING_STRATEGY);
switch (set) {
case 0:
return SequenceEncodingStrategy.PREV_ADD1;
case 1:
return SequenceEncodingStrategy.PREV_DELTA;
default:
throw new IllegalArgumentException("SEQUENCE_ENCODING_STRATEGY");
}
}
void setSequenceEncodingStrategy(SequenceEncodingStrategy strategy) {
switch (strategy) {
case PREV_ADD1:
setBit(SEQUENCE_ENCODING_STRATEGY, false);
break;
case PREV_DELTA:
setBit(SEQUENCE_ENCODING_STRATEGY, true);
break;
default:
throw new IllegalArgumentException("SEQUENCE_ENCODING_STRATEGY");
}
}
public DepthEncodingStrategy getDepthEncodingStrategy() {
final int set = getBit(DEPTH_ENCODING_STRATEGY);
switch (set) {
case 0:
return DepthEncodingStrategy.PREV_EQUALS;
case 1:
return DepthEncodingStrategy.RAW;
default:
throw new IllegalArgumentException("DEPTH_ENCODING_STRATEGY");
}
}
void setDepthEncodingStrategy(DepthEncodingStrategy strategy) {
switch (strategy) {
case PREV_EQUALS:
setBit(DEPTH_ENCODING_STRATEGY, false);
break;
case RAW:
setBit(DEPTH_ENCODING_STRATEGY, true);
break;
default:
throw new IllegalArgumentException("SEQUENCE_ENCODING_STRATEGY");
}
}
}