/**
* CopyRight by Chinamobile
*
* SuperStepCommand.java
*/
package com.chinamobile.bcbsp.sync;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
import com.chinamobile.bcbsp.Constants;
/**
* SuperStepCommand
*
* SuperStepCommand maintains the actions which JobInProgress generates and the
* aggregation information
*
* @author
* @version
*/
public class SuperStepCommand implements Writable {
private static final Log LOG = LogFactory.getLog(SuperStepCommand.class);
private int commandType;
private String initWritePath = "initWritePath";
private String initReadPath = "initReadPath";
private int ableCheckPoint = 0;
private int nextSuperStepNum = 0;
private int oldCheckPoint = 0;
private HashMap<Integer, String> partitionToWorkerManagerNameAndPort = null;
// For aggregation values
private String[] aggValues;
public SuperStepCommand() {
this.aggValues = new String[0];
this.partitionToWorkerManagerNameAndPort = new HashMap<Integer, String>();
}
public SuperStepCommand(int commandType) {
this.commandType = commandType;
}
public SuperStepCommand(int commandType, String initWritePath,
String initReadPath, int ableCheckPoint, int nextSuperStepNum) {
this.commandType = commandType;
this.initWritePath = initWritePath;
this.initReadPath = initReadPath;
this.ableCheckPoint = ableCheckPoint;
this.nextSuperStepNum = nextSuperStepNum;
}
public SuperStepCommand(int commandType, String initWritePath,
String initReadPath, int ableCheckPoint, int nextSuperStepNum,
String[] aggValues) {
this.commandType = commandType;
this.initWritePath = initWritePath;
this.initReadPath = initReadPath;
this.ableCheckPoint = ableCheckPoint;
this.nextSuperStepNum = nextSuperStepNum;
this.aggValues = aggValues;
}
public SuperStepCommand(String s) {
String[] tmp = s.split(Constants.SSC_SPLIT_FLAG);
int length = tmp.length;
int index = 0;
if (length < 6) {
} else {
this.commandType = Integer.valueOf(tmp[index++]);
this.initWritePath = tmp[index++];
this.initReadPath = tmp[index++];
this.ableCheckPoint = Integer.valueOf(tmp[index++]);
this.nextSuperStepNum = Integer.valueOf(tmp[index++]);
this.oldCheckPoint = Integer.valueOf(tmp[index++]);
}
LOG.info("[SuperStepCommand]--[index]" + index);
LOG.info("[SuperStepCommand]--[CommandType]" + this.commandType);
if (this.commandType == Constants.COMMAND_TYPE.START_AND_RECOVERY) {
String str = tmp[index++];//{1=a, 2=b, 3=c}
LOG.info("[SuperStepCommand]--[routeString]" + str);
//remove "{" and "}"
String regEx = "[\\{\\}]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
str = m.replaceAll("");//1=a, 2=b, 3=c
str = str.replace(" ", "");//1=a,2=b,3=c
this.partitionToWorkerManagerNameAndPort = new HashMap<Integer, String>();
String[] strMap = str.split(",");//1=a|2=b|3=c
for(int i=0; i<strMap.length; i++) {
String[] strKV = strMap[i].split("=");//1 a | 2 b | 3 c
if(strKV.length == 2) {
this.partitionToWorkerManagerNameAndPort.put(Integer.parseInt(strKV[0]), strKV[1]);
} else {
}
}
}
if (index < length) {
/**
* To decode the aggValues after the judgeFlag.
* The content of the string should be in the form as follows:
* ["judgeFlag:aggName1\taggValue:aggName2\taggValue:...:aggNameN\taggValueN"]
*/
int count = length -index; // Subtract 5 for above attributes.
this.aggValues = new String[count];
for (int i = 0; i < count; i ++) {
this.aggValues[i] = tmp[index++];
}
}
}
public int getOldCheckPoint() {
return oldCheckPoint;
}
public void setOldCheckPoint(int oldCheckPoint) {
this.oldCheckPoint = oldCheckPoint;
}
/**
* Set the Type of Command.
*
* @param commandType
*/
public void setCommandType(int commandType) {
this.commandType = commandType;
}
/**
* Get the Type of Command.
*
* @return
*/
public int getCommandType() {
return this.commandType;
}
/**
* Set the initial path for writing CheckPoint.
*
* @param initWritePath
*/
public void setInitWritePath(String initWritePath) {
this.initWritePath = initWritePath;
}
/**
* Get the initial path for writing CheckPoint.
*
* @return
*/
public String getInitWritePath() {
return this.initWritePath;
}
/**
* Set the initial path for loading CheckPoint.
*
* @param initReadPath
*/
public void setInitReadPath(String initReadPath) {
this.initReadPath = initReadPath;
}
/**
* Get the initial path for loading CheckPoint.
*
* @return
*/
public String getInitReadPath() {
return this.initReadPath;
}
/**
* Set the last available CheckPoint.
* the available CheckPoint is denoted by the SuperStepCounter.
*
* @param ableCheckPoint
*/
public void setAbleCheckPoint(int ableCheckPoint) {
this.ableCheckPoint = ableCheckPoint;
}
/**
* Get the last available CheckPoint.
*
* @return
*/
public int getAbleCheckPoint() {
return this.ableCheckPoint;
}
/**
* Set the next SuperStepCounter.
* All staffs will read it and set themselves SuperStepCounter.
*
* @param nextSuperStepNum
*/
public void setNextSuperStepNum(int nextSuperStepNum) {
this.nextSuperStepNum = nextSuperStepNum;
}
/**
* Get the next SuperStepCounter.
*
* @return
*/
public int getNextSuperStepNum() {
return this.nextSuperStepNum;
}
/**
* Set the aggregate values.
*
* @param aggValues the aggValues to set
*/
public void setAggValues(String[] aggValues) {
this.aggValues = aggValues;
}
/**
* Get the aggregate values.
*
* @return the aggValues
*/
public String[] getAggValues() {
return aggValues;
}
public void setPartitionToWorkerManagerNameAndPort(
HashMap<Integer, String> partitionToWorkerManagerNameAndPort) {
this.partitionToWorkerManagerNameAndPort = partitionToWorkerManagerNameAndPort;
}
public HashMap<Integer, String> getPartitionToWorkerManagerNameAndPort() {
return partitionToWorkerManagerNameAndPort;
}
@Override
public void readFields(DataInput in) throws IOException {
this.commandType = in.readInt();
this.initWritePath = Text.readString(in);
this.initReadPath = Text.readString(in);
this.ableCheckPoint = in.readInt();
this.nextSuperStepNum = in.readInt();
this.oldCheckPoint = in.readInt();
// For aggregation values
int count = in.readInt();
this.aggValues = new String[count];
for (int i = 0; i < count; i++) {
this.aggValues[i] = Text.readString(in);
}
//nc
int size = WritableUtils.readVInt(in);
if(size > 0) {
String[] partitionToWMName = WritableUtils.readCompressedStringArray(in);
this.partitionToWorkerManagerNameAndPort = new HashMap<Integer, String>();
for(int j=0; j<size; j++) {
this.partitionToWorkerManagerNameAndPort.put(j, partitionToWMName[j]);
}
}//
}
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(this.commandType);
Text.writeString(out, this.initWritePath);
Text.writeString(out, this.initReadPath);
out.writeInt(this.ableCheckPoint);
out.writeInt(this.nextSuperStepNum);
out.writeInt(this.oldCheckPoint);
// For aggregation values
out.writeInt(this.aggValues.length);
int count = this.aggValues.length;
for (int i = 0; i < count; i++) {
Text.writeString(out, this.aggValues[i]);
}
//nc
if(partitionToWorkerManagerNameAndPort == null) {
WritableUtils.writeVInt(out, 0);
} else {
WritableUtils.writeVInt(out, partitionToWorkerManagerNameAndPort.size());
String[] partitionToWMName = null;
for(Integer i : this.partitionToWorkerManagerNameAndPort.keySet()) {
partitionToWMName[i] = partitionToWorkerManagerNameAndPort.get(i);
}
WritableUtils.writeCompressedStringArray(out, partitionToWMName);
}//
}
@Override
public String toString() {
String content = this.commandType + Constants.SSC_SPLIT_FLAG
+ this.initWritePath + Constants.SSC_SPLIT_FLAG + this.initReadPath
+ Constants.SSC_SPLIT_FLAG + this.ableCheckPoint
+ Constants.SSC_SPLIT_FLAG + this.nextSuperStepNum
+ Constants.SSC_SPLIT_FLAG + this.oldCheckPoint;
if(this.commandType == Constants.COMMAND_TYPE.START_AND_RECOVERY) {
if (this.partitionToWorkerManagerNameAndPort == null) {
LOG.error("This partitionToWorkerManagerNameAndPort is null");
} else {
content = content + Constants.SSC_SPLIT_FLAG + this.partitionToWorkerManagerNameAndPort;
}
}
/**
* To encapsulate the aggValues after the judgeFlag.
* The content of the string should be in the form as follows:
* ["judgeFlag:aggName1\taggValue:aggName2\taggValue:...:aggNameN\taggValueN"]
*/
for (int i = 0; i < this.aggValues.length; i ++) {
content = content + Constants.SSC_SPLIT_FLAG + this.aggValues[i];
}
return content;
}
}