1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.client;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.TreeMap;
28 import java.util.UUID;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.KeyValue;
34 import org.apache.hadoop.hbase.util.Bytes;
35
36 import com.google.common.io.ByteArrayDataInput;
37 import com.google.common.io.ByteArrayDataOutput;
38 import com.google.common.io.ByteStreams;
39
40 public abstract class Mutation extends OperationWithAttributes implements Row {
41 private static final Log LOG = LogFactory.getLog(Mutation.class);
42
43 private static final String CLUSTER_ID_ATTR = "_c.id_";
44 private static final String DURABILITY_ID_ATTR = "_dur_";
45
46
47
48
49 private static final String CONSUMED_CLUSTER_IDS = "_cs.id";
50 protected byte [] row = null;
51 protected long ts = HConstants.LATEST_TIMESTAMP;
52 protected long lockId = -1L;
53 protected boolean writeToWAL = true;
54 protected Map<byte [], List<KeyValue>> familyMap =
55 new TreeMap<byte [], List<KeyValue>>(Bytes.BYTES_COMPARATOR);
56
57
58
59
60
61
62
63 @Override
64 public Map<String, Object> getFingerprint() {
65 Map<String, Object> map = new HashMap<String, Object>();
66 List<String> families = new ArrayList<String>();
67
68
69 map.put("families", families);
70 for (Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
71 families.add(Bytes.toStringBinary(entry.getKey()));
72 }
73 return map;
74 }
75
76
77
78
79
80
81
82
83 @Override
84 public Map<String, Object> toMap(int maxCols) {
85
86 Map<String, Object> map = getFingerprint();
87
88
89 Map<String, List<Map<String, Object>>> columns =
90 new HashMap<String, List<Map<String, Object>>>();
91 map.put("families", columns);
92 map.put("row", Bytes.toStringBinary(this.row));
93 int colCount = 0;
94
95 for (Map.Entry<byte [], List<KeyValue>> entry : this.familyMap.entrySet()) {
96
97 List<Map<String, Object>> qualifierDetails =
98 new ArrayList<Map<String, Object>>();
99 columns.put(Bytes.toStringBinary(entry.getKey()), qualifierDetails);
100 colCount += entry.getValue().size();
101 if (maxCols <= 0) {
102 continue;
103 }
104
105 for (KeyValue kv : entry.getValue()) {
106 if (--maxCols <= 0 ) {
107 continue;
108 }
109 Map<String, Object> kvMap = kv.toStringMap();
110
111 kvMap.remove("row");
112 kvMap.remove("family");
113 qualifierDetails.add(kvMap);
114 }
115 }
116 map.put("totalColumns", colCount);
117
118 if (getId() != null) {
119 map.put("id", getId());
120 }
121 return map;
122 }
123
124
125
126
127
128 public boolean getWriteToWAL() {
129 return this.writeToWAL;
130 }
131
132
133
134
135
136
137
138
139 public void setWriteToWAL(boolean write) {
140 setDurability(write ? Durability.USE_DEFAULT : Durability.SKIP_WAL);
141 }
142
143
144
145
146
147
148
149 public void setDurability(Durability d) {
150 setAttribute(DURABILITY_ID_ATTR, Bytes.toBytes(d.ordinal()));
151 this.writeToWAL = d != Durability.SKIP_WAL;
152 }
153
154
155 public Durability getDurability() {
156 byte[] attr = getAttribute(DURABILITY_ID_ATTR);
157 if (attr != null) {
158 try {
159 return Durability.valueOf(Bytes.toInt(attr));
160 } catch (IllegalArgumentException iax) {
161 LOG.warn("Invalid or unknown durability settting", iax);
162 }
163 }
164 return writeToWAL ? Durability.USE_DEFAULT : Durability.SKIP_WAL;
165 }
166
167
168
169
170
171 public Map<byte [], List<KeyValue>> getFamilyMap() {
172 return this.familyMap;
173 }
174
175
176
177
178 public void setFamilyMap(Map<byte [], List<KeyValue>> map) {
179 this.familyMap = map;
180 }
181
182
183
184
185
186 public boolean isEmpty() {
187 return familyMap.isEmpty();
188 }
189
190
191
192
193
194 @Override
195 public byte [] getRow() {
196 return this.row;
197 }
198
199 public int compareTo(final Row d) {
200 return Bytes.compareTo(this.getRow(), d.getRow());
201 }
202
203
204
205
206
207
208 public RowLock getRowLock() {
209 return new RowLock(this.row, this.lockId);
210 }
211
212
213
214
215
216
217
218 public long getLockId() {
219 return this.lockId;
220 }
221
222
223
224
225
226 public long getTimeStamp() {
227 return this.ts;
228 }
229
230
231
232
233
234 public void setClusterId(UUID clusterId) {
235 if (clusterId == null) return;
236 byte[] val = new byte[2*Bytes.SIZEOF_LONG];
237 Bytes.putLong(val, 0, clusterId.getMostSignificantBits());
238 Bytes.putLong(val, Bytes.SIZEOF_LONG, clusterId.getLeastSignificantBits());
239 setAttribute(CLUSTER_ID_ATTR, val);
240 }
241
242
243
244
245 public UUID getClusterId() {
246 byte[] attr = getAttribute(CLUSTER_ID_ATTR);
247 if (attr == null) {
248 return HConstants.DEFAULT_CLUSTER_ID;
249 }
250 return new UUID(Bytes.toLong(attr,0), Bytes.toLong(attr, Bytes.SIZEOF_LONG));
251 }
252
253
254
255
256
257 public void setClusterIds(List<UUID> clusterIds) {
258 ByteArrayDataOutput out = ByteStreams.newDataOutput();
259 out.writeInt(clusterIds.size());
260 for (UUID clusterId : clusterIds) {
261 out.writeLong(clusterId.getMostSignificantBits());
262 out.writeLong(clusterId.getLeastSignificantBits());
263 }
264 setAttribute(CONSUMED_CLUSTER_IDS, out.toByteArray());
265 }
266
267
268
269
270 public List<UUID> getClusterIds() {
271 List<UUID> clusterIds = new ArrayList<UUID>();
272 byte[] bytes = getAttribute(CONSUMED_CLUSTER_IDS);
273 if(bytes != null) {
274 ByteArrayDataInput in = ByteStreams.newDataInput(bytes);
275 int numClusters = in.readInt();
276 for(int i=0; i<numClusters; i++){
277 clusterIds.add(new UUID(in.readLong(), in.readLong()));
278 }
279 }
280 return clusterIds;
281 }
282
283
284
285
286 public int size() {
287 int size = 0;
288 for(List<KeyValue> kvList : this.familyMap.values()) {
289 size += kvList.size();
290 }
291 return size;
292 }
293
294
295
296
297 public int numFamilies() {
298 return familyMap.size();
299 }
300 }