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;
21
22 import java.util.SortedSet;
23 import java.util.TreeSet;
24
25 import org.apache.hadoop.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.KeyValue;
27 import org.apache.hadoop.hbase.util.Bytes;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 @InterfaceAudience.Private
45 public class ScanDeleteTracker implements DeleteTracker {
46
47 private boolean hasFamilyStamp = false;
48 private long familyStamp = 0L;
49 private SortedSet<Long> familyVersionStamps = new TreeSet<Long>();
50 private byte [] deleteBuffer = null;
51 private int deleteOffset = 0;
52 private int deleteLength = 0;
53 private byte deleteType = 0;
54 private long deleteTimestamp = 0L;
55
56
57
58
59 public ScanDeleteTracker() {
60 super();
61 }
62
63
64
65
66
67
68
69
70
71
72
73
74 @Override
75 public void add(byte[] buffer, int qualifierOffset, int qualifierLength,
76 long timestamp, byte type) {
77 if (!hasFamilyStamp || timestamp > familyStamp) {
78 if (type == KeyValue.Type.DeleteFamily.getCode()) {
79 hasFamilyStamp = true;
80 familyStamp = timestamp;
81 return;
82 } else if (type == KeyValue.Type.DeleteFamilyVersion.getCode()) {
83 familyVersionStamps.add(timestamp);
84 return;
85 }
86
87 if (deleteBuffer != null && type < deleteType) {
88
89 if (Bytes.equals(deleteBuffer, deleteOffset, deleteLength,
90 buffer, qualifierOffset, qualifierLength)){
91 return;
92 }
93 }
94
95 deleteBuffer = buffer;
96 deleteOffset = qualifierOffset;
97 deleteLength = qualifierLength;
98 deleteType = type;
99 deleteTimestamp = timestamp;
100 }
101
102 }
103
104
105
106
107
108
109
110
111
112
113
114 @Override
115 public DeleteResult isDeleted(byte [] buffer, int qualifierOffset,
116 int qualifierLength, long timestamp) {
117 if (hasFamilyStamp && timestamp <= familyStamp) {
118 return DeleteResult.FAMILY_DELETED;
119 }
120
121 if (familyVersionStamps.contains(Long.valueOf(timestamp))) {
122 return DeleteResult.FAMILY_VERSION_DELETED;
123 }
124
125 if (deleteBuffer != null) {
126 int ret = Bytes.compareTo(deleteBuffer, deleteOffset, deleteLength,
127 buffer, qualifierOffset, qualifierLength);
128
129 if (ret == 0) {
130 if (deleteType == KeyValue.Type.DeleteColumn.getCode()) {
131 return DeleteResult.COLUMN_DELETED;
132 }
133
134
135 if (timestamp == deleteTimestamp) {
136 return DeleteResult.VERSION_DELETED;
137 }
138
139 assert timestamp < deleteTimestamp;
140
141
142 deleteBuffer = null;
143 } else if(ret < 0){
144
145 deleteBuffer = null;
146 } else {
147 throw new IllegalStateException("isDelete failed: deleteBuffer="
148 + Bytes.toStringBinary(deleteBuffer, deleteOffset, deleteLength)
149 + ", qualifier="
150 + Bytes.toStringBinary(buffer, qualifierOffset, qualifierLength)
151 + ", timestamp=" + timestamp + ", comparison result: " + ret);
152 }
153 }
154
155 return DeleteResult.NOT_DELETED;
156 }
157
158 @Override
159 public boolean isEmpty() {
160 return deleteBuffer == null && !hasFamilyStamp &&
161 familyVersionStamps.isEmpty();
162 }
163
164 @Override
165
166 public void reset() {
167 hasFamilyStamp = false;
168 familyStamp = 0L;
169 familyVersionStamps.clear();
170 deleteBuffer = null;
171 }
172
173 @Override
174
175 public void update() {
176 this.reset();
177 }
178 }