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
46 @InterfaceAudience.Private
47 public class ScanDeleteTracker implements DeleteTracker {
48
49 protected boolean hasFamilyStamp = false;
50 protected long familyStamp = 0L;
51 protected SortedSet<Long> familyVersionStamps = new TreeSet<Long>();
52 protected byte [] deleteBuffer = null;
53 protected int deleteOffset = 0;
54 protected int deleteLength = 0;
55 protected byte deleteType = 0;
56 protected long deleteTimestamp = 0L;
57
58
59
60
61 public ScanDeleteTracker() {
62 super();
63 }
64
65
66
67
68
69
70
71
72 @Override
73 public void add(Cell cell) {
74 long timestamp = cell.getTimestamp();
75 int qualifierOffset = cell.getQualifierOffset();
76 int qualifierLength = cell.getQualifierLength();
77 byte type = cell.getTypeByte();
78 if (!hasFamilyStamp || timestamp > familyStamp) {
79 if (type == KeyValue.Type.DeleteFamily.getCode()) {
80 hasFamilyStamp = true;
81 familyStamp = timestamp;
82 return;
83 } else if (type == KeyValue.Type.DeleteFamilyVersion.getCode()) {
84 familyVersionStamps.add(timestamp);
85 return;
86 }
87
88 if (deleteBuffer != null && type < deleteType) {
89
90 if (Bytes.equals(deleteBuffer, deleteOffset, deleteLength,
91 cell.getQualifierArray(), qualifierOffset, qualifierLength)){
92 return;
93 }
94 }
95
96 deleteBuffer = cell.getQualifierArray();
97 deleteOffset = qualifierOffset;
98 deleteLength = qualifierLength;
99 deleteType = type;
100 deleteTimestamp = timestamp;
101 }
102
103 }
104
105
106
107
108
109
110
111
112 @Override
113 public DeleteResult isDeleted(Cell cell) {
114 long timestamp = cell.getTimestamp();
115 int qualifierOffset = cell.getQualifierOffset();
116 int qualifierLength = cell.getQualifierLength();
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 cell.getQualifierArray(), 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(cell.getQualifierArray(), 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 }