Storm-Tuple部分源码分析(2)
2121SC@SDUSC
一、tuple
分析以注释形式嵌在代码中
public interface Tuple extends ITuple {
/**
* 返回该元组的全局流id (component + stream)。
*/
GlobalStreamId getSourceGlobalStreamId();
/**
* 获取创建此元组的组件的id。
*/
String getSourceComponent();
/**
* 获取创建此元组的任务的id。
*/
int getSourceTask();
/**
* 获取此元组被触发的流的id。
*/
String getSourceStreamId();
/**
*获取与此元组关联的消息id。
*/
MessageId getMessageId();
/**
* 获取与元组关联的拓扑上下文。
*/
GeneralTopologyContext getContext();
}
- 这是一个继承自Ituple的接口类,定义了元组的相关方法,元组是Storm中的主要数据结构。元组是一个指定的值列表,其中每个值可以是任何类型。元组是动态类型——字段的类型不需要声明。元组getInteger和getString等帮助器方法字段值,而不必强制转换结果。
- Storm需要知道如何序列化元组中的所有值。默认情况下,Storm知道如何序列化原始类型,字符串和字节数组。如果想使用另一种类型,则需要为该类型实现并注册一个序列化器。
二、values
import java.util.ArrayList;
/**
A convenience class for making tuple values using new Values(“field1”, 2, 3) syntax.
*/
public class Values extends ArrayList{
public Values() {
}
public Values(Object... vals) {
super(vals.length);
for (Object o : vals) {
add(o);
}
}
}
一个封装 ArrayList 的类,可以使用new values ("field1", 2,3)语法创建元组值。
- ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征,可以随时从链表中添加或删除一个元素,ArrayList实现了List接口。与数组array相比,ArrayList是可以动态改变大小的,当我们不知道到底有多少个数据元素的时候,就可使用ArrayList。
- value是一个封装 ArrayList 的类,使用new values (“field1”, 2,3)语法创建元组值。
三、AddressedTuple
/**
指向目标的元组
/
public final class AddressedTuple {
/*
*在广播元组时使用的目的地。
*/
public static final int BROADCAST_DEST = -2;
public final Tuple tuple;
public final int dest;
public AddressedTuple(int dest, Tuple tuple) {
this.dest = dest;
this.tuple = tuple;
}
public static AddressedTuple createFlushTuple(GeneralTopologyContext workerTopologyContext) {
TupleImpl tuple = new TupleImpl(workerTopologyContext, new Values(), Constants.SYSTEM_COMPONENT_ID,
(int) Constants.SYSTEM_TASK_ID, Constants.SYSTEM_FLUSH_STREAM_ID);
return new AddressedTuple(AddressedTuple.BROADCAST_DEST, tuple); // one instance per executor avoids false sharing of CPU cache
}
// 每个执行器一个实例可以避免错误的CPU缓存共享
public Tuple getTuple() {
return tuple;
}
public int getDest() {
return dest;
}
@Override
public String toString() {
return "[dest: " + dest + " tuple: " + tuple + "]";
}
四、Fields
public class Fields implements Iterable, Serializable {
private static final long serialVersionUID = -3377931843059975424L;
private List fields;
private Map<String, Integer> index = new HashMap<>();
public Fields(String... fields) {
this(Arrays.asList(fields));
}
public Fields(List<String> fields) {
this.fields = new ArrayList<>(fields.size());
for (String field : fields) {
if (this.fields.contains(field)) {
throw new IllegalArgumentException(
String.format("duplicate field '%s'", field)
);
}
this.fields.add(field);
}
index();
}
/**
* 注意,如果选择器中的字段,这个函数可能抛NullPointerException
(在索引中找不到)。
* 要选择的字段
* @param tuple要选择的元组
*/
public List<Object> select(Fields selector, List<Object> tuple) {
List<Object> ret = new ArrayList<>(selector.size());
for (String s : selector) {
ret.add(tuple.get(fieldIndex(s)));
}
return ret;
}
public List<String> toList() {
return new ArrayList<>(fields);
}
/**
* 返回此集合中的字段数。
*/
public int size() {
return fields.size();
}
/**
* 获取集合中位置索引处的字段。
*
* @Param index返回字段的索引
* @抛出IndexOutOfBoundsException——如果索引超出范围
*(index < 0 || index >= size())
*/
public String get(int index) {
return fields.get(index);
}
@Override
public Iterator<String> iterator() {
return fields.iterator();
}
/**
* 返回指定命名字段的位置。
*
* @param field要计算的命名字段
* @如果字段不存在,抛出IllegalArgumentException
*/
public int fieldIndex(String field) {
Integer ret = index.get(field);
if (ret == null) {
throw new IllegalArgumentException(field + " does not exist");
}
return ret;
}
/**
*检查包含。
* @如果包含指定的字段名,则返回true。
*/
public boolean contains(String field) {
return index.containsKey(field);
}
private void index() {
for (int i = 0; i < fields.size(); i++) {
index.put(fields.get(i), i);
}
}
@Override
public String toString() {
return fields.toString();
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other instanceof Fields) {
Fields of = (Fields) other;
return fields.equals(of.fields);
}
return false;
}
@Override
public int hashCode() {
return fields.hashCode();
}
}