1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  package org.apache.hadoop.hbase;
21  
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.apache.hadoop.hbase.classification.InterfaceAudience;
27  import org.apache.hadoop.hbase.classification.InterfaceStability;
28  import org.apache.hadoop.hbase.util.Bytes;
29  
30  
31  
32  
33  @InterfaceAudience.Private
34  @InterfaceStability.Evolving
35  public class Tag {
36    public final static int TYPE_LENGTH_SIZE = Bytes.SIZEOF_BYTE;
37    public final static int TAG_LENGTH_SIZE = Bytes.SIZEOF_SHORT;
38    public final static int INFRASTRUCTURE_SIZE = TYPE_LENGTH_SIZE + TAG_LENGTH_SIZE;
39    public static final int MAX_TAG_LENGTH = (2 * Short.MAX_VALUE) + 1 - TAG_LENGTH_SIZE;
40  
41    private final byte type;
42    private final byte[] bytes;
43    private int offset = 0;
44    private int length = 0;
45  
46    
47    
48    
49    
50    public Tag(byte tagType, String tag) {
51      this(tagType, Bytes.toBytes(tag));
52    }
53  
54    
55  
56  
57  
58    public Tag(byte tagType, byte[] tag) {
59      
60  
61  
62  
63  
64      int tagLength = tag.length + TYPE_LENGTH_SIZE;
65      if (tagLength > MAX_TAG_LENGTH) {
66        throw new IllegalArgumentException(
67            "Invalid tag data being passed. Its length can not exceed " + MAX_TAG_LENGTH);
68      }
69      length = TAG_LENGTH_SIZE + tagLength;
70      bytes = new byte[length];
71      int pos = Bytes.putAsShort(bytes, 0, tagLength);
72      pos = Bytes.putByte(bytes, pos, tagType);
73      Bytes.putBytes(bytes, pos, tag, 0, tag.length);
74      this.type = tagType;
75    }
76  
77    
78  
79  
80  
81  
82  
83  
84  
85  
86  
87    public Tag(byte[] bytes, int offset) {
88      this(bytes, offset, getLength(bytes, offset));
89    }
90  
91    private static int getLength(byte[] bytes, int offset) {
92      return TAG_LENGTH_SIZE + Bytes.readAsInt(bytes, offset, TAG_LENGTH_SIZE);
93    }
94  
95    
96  
97  
98  
99  
100 
101 
102 
103 
104 
105 
106   public Tag(byte[] bytes, int offset, int length) {
107     if (length > MAX_TAG_LENGTH) {
108       throw new IllegalArgumentException(
109           "Invalid tag data being passed. Its length can not exceed " + MAX_TAG_LENGTH);
110     }
111     this.bytes = bytes;
112     this.offset = offset;
113     this.length = length;
114     this.type = bytes[offset + TAG_LENGTH_SIZE];
115   }
116 
117   
118 
119 
120   public byte[] getBuffer() {
121     return this.bytes;
122   }
123 
124   
125 
126 
127   public byte getType() {
128     return this.type;
129   }
130 
131   
132 
133 
134   public int getTagLength() {
135     return this.length - INFRASTRUCTURE_SIZE;
136   }
137 
138   
139 
140 
141   public int getTagOffset() {
142     return this.offset + INFRASTRUCTURE_SIZE;
143   }
144 
145   
146 
147 
148 
149 
150 
151 
152   public byte[] getValue() {
153     int tagLength = getTagLength();
154     byte[] tag = new byte[tagLength];
155     Bytes.putBytes(tag, 0, bytes, getTagOffset(), tagLength);
156     return tag;
157   }
158 
159   
160 
161 
162 
163 
164 
165 
166 
167   public static List<Tag> asList(byte[] b, int offset, int length) {
168     List<Tag> tags = new ArrayList<Tag>();
169     int pos = offset;
170     while (pos < offset + length) {
171       int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
172       tags.add(new Tag(b, pos, tagLen + TAG_LENGTH_SIZE));
173       pos += TAG_LENGTH_SIZE + tagLen;
174     }
175     return tags;
176   }
177 
178   
179 
180 
181 
182 
183   public static byte[] fromList(List<Tag> tags) {
184     if (tags == null || tags.size() <= 0) return null;
185     int length = 0;
186     for (Tag tag: tags) {
187       length += tag.length;
188     }
189     byte[] b = new byte[length];
190     int pos = 0;
191     for (Tag tag: tags) {
192       System.arraycopy(tag.bytes, tag.offset, b, pos, tag.length);
193       pos += tag.length;
194     }
195     return b;
196   }
197 
198   
199 
200 
201 
202 
203 
204 
205 
206   public static Tag getTag(byte[] b, int offset, int length, byte type) {
207     int pos = offset;
208     while (pos < offset + length) {
209       int tagLen = Bytes.readAsInt(b, pos, TAG_LENGTH_SIZE);
210       if(b[pos + TAG_LENGTH_SIZE] == type) {
211         return new Tag(b, pos, tagLen + TAG_LENGTH_SIZE);
212       }
213       pos += TAG_LENGTH_SIZE + tagLen;
214     }
215     return null;
216   }
217 
218   
219 
220 
221   int getLength() {
222     return this.length;
223   }
224 
225   
226 
227 
228   int getOffset() {
229     return this.offset;
230   }
231 
232 
233   
234 
235 
236   public static List<Tag> carryForwardTags(final Cell cell) {
237     return carryForwardTags(null, cell);
238   }
239 
240   
241 
242 
243 
244 
245   public static List<Tag> carryForwardTags(final List<Tag> tagsOrNull, final Cell cell) {
246     List<Tag> tags = tagsOrNull;
247     if (cell.getTagsLength() <= 0) return tags;
248     Iterator<Tag> itr =
249         CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(), cell.getTagsLength());
250     if (tags == null) tags = new ArrayList<Tag>();
251     while (itr.hasNext()) {
252       tags.add(itr.next());
253     }
254     return tags;
255   }
256 }