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