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.regionserver.wal;
21
22 import java.io.DataInput;
23 import java.io.DataInputStream;
24 import java.io.DataOutput;
25 import java.io.DataOutputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.NavigableMap;
30 import java.util.TreeMap;
31 import java.util.UUID;
32
33 import org.apache.hadoop.hbase.KeyValue;
34 import org.apache.hadoop.hbase.codec.Decoder;
35 import org.apache.hadoop.hbase.codec.Encoder;
36 import org.apache.hadoop.hbase.io.HeapSize;
37 import org.apache.hadoop.hbase.util.Bytes;
38 import org.apache.hadoop.hbase.util.ClassSize;
39 import org.apache.hadoop.io.Writable;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class WALEdit implements Writable, HeapSize {
76
77
78
79
80
81
82
83
84 private static final String PREFIX_CLUSTER_KEY = ".";
85 private final int VERSION_2 = -1;
86
87 private final ArrayList<KeyValue> kvs = new ArrayList<KeyValue>(1);
88
89
90
91
92
93
94
95
96
97
98 private final NavigableMap<byte[], Integer> scopes = new TreeMap<byte[], Integer>(
99 Bytes.BYTES_COMPARATOR);
100
101
102
103
104 private WALEditCodec codec = new WALEditCodec();
105
106 public WALEdit() {
107 }
108
109
110
111
112
113 @SuppressWarnings("javadoc")
114 public void setCompressionContext(final CompressionContext compression) {
115 this.codec.setCompression(compression);
116 }
117
118 public void setCodec(WALEditCodec codec) {
119 this.codec = codec;
120 }
121
122
123 public void add(KeyValue kv) {
124 this.kvs.add(kv);
125 }
126
127 public boolean isEmpty() {
128 return kvs.isEmpty();
129 }
130
131 public int size() {
132 return kvs.size();
133 }
134
135 public List<KeyValue> getKeyValues() {
136 return kvs;
137 }
138
139 public Integer getFromScope(byte[] key) {
140 return scopes.get(key);
141 }
142
143
144
145
146
147 @Deprecated
148 public NavigableMap<byte[], Integer> getScopes() {
149 return scopes;
150 }
151
152
153
154
155
156
157 @Deprecated
158 public void setScopes(NavigableMap<byte[], Integer> scopes) {
159 this.scopes.clear();
160 this.scopes.putAll(scopes);
161 }
162
163 public void putIntoScope(byte[] key, Integer value) {
164 scopes.put(key, value);
165 }
166
167 public boolean hasKeyInScope(byte[] key) {
168 return scopes.containsKey(key);
169 }
170
171
172
173
174 public boolean hasClusterId(UUID clusterId) {
175 return hasKeyInScope(Bytes.toBytes(PREFIX_CLUSTER_KEY + clusterId.toString()));
176 }
177
178
179
180
181 public void addClusterId(UUID clusterId) {
182 scopes.put(Bytes.toBytes(PREFIX_CLUSTER_KEY + clusterId.toString()), 1);
183 }
184
185
186
187
188 public void addClusterIds(List<UUID> clusterIds) {
189 for (UUID clusterId : clusterIds) {
190 addClusterId(clusterId);
191 }
192 }
193
194
195
196
197 public List<UUID> getClusterIds() {
198 List<UUID> clusterIds = new ArrayList<UUID>();
199 for (byte[] keyBytes : scopes.keySet()) {
200 String key = Bytes.toString(keyBytes);
201 if (key.startsWith(PREFIX_CLUSTER_KEY)) {
202 clusterIds.add(UUID.fromString(key.substring(PREFIX_CLUSTER_KEY.length())));
203 }
204 }
205 return clusterIds;
206 }
207
208 public void readFields(DataInput in) throws IOException {
209 kvs.clear();
210 scopes.clear();
211 Decoder decoder = this.codec.getDecoder((DataInputStream) in);
212 int versionOrLength = in.readInt();
213 int length = versionOrLength;
214
215
216 if (versionOrLength == VERSION_2) {
217 length = in.readInt();
218 }
219
220
221 kvs.ensureCapacity(length);
222 for(int i=0; i< length && decoder.advance(); i++) {
223 kvs.add(decoder.current());
224 }
225
226
227 if (versionOrLength == VERSION_2) {
228 int numEntries = in.readInt();
229 if (numEntries > 0) {
230 for (int i = 0; i < numEntries; i++) {
231 byte[] key = Bytes.readByteArray(in);
232 int scope = in.readInt();
233 scopes.put(key, scope);
234 }
235 }
236 }
237 }
238
239 public void write(DataOutput out) throws IOException {
240 Encoder kvEncoder = codec.getEncoder((DataOutputStream) out);
241 out.writeInt(VERSION_2);
242
243
244 out.writeInt(kvs.size());
245 for(KeyValue kv: kvs){
246 kvEncoder.write(kv);
247 }
248 kvEncoder.flush();
249
250 out.writeInt(scopes.size());
251 for (byte[] key : scopes.keySet()) {
252 Bytes.writeByteArray(out, key);
253 out.writeInt(scopes.get(key));
254 }
255 }
256
257 public long heapSize() {
258 long ret = ClassSize.ARRAYLIST;
259 for (KeyValue kv : kvs) {
260 ret += kv.heapSize();
261 }
262 ret += ClassSize.TREEMAP;
263 ret += ClassSize.align(scopes.size() * ClassSize.MAP_ENTRY);
264
265 return ret;
266 }
267
268 public String toString() {
269 StringBuilder sb = new StringBuilder();
270
271 sb.append("[#edits: " + kvs.size() + " = <");
272 for (KeyValue kv : kvs) {
273 sb.append(kv.toString());
274 sb.append("; ");
275 }
276 sb.append(" scopes: " + scopes.toString());
277 sb.append(">]");
278 return sb.toString();
279 }
280 }