21
21
import static org .apache .accumulo .core .metadata .schema .TabletMetadata .ColumnType .FILES ;
22
22
import static org .apache .accumulo .core .metadata .schema .TabletMetadata .ColumnType .MERGEABILITY ;
23
23
import static org .apache .accumulo .core .metadata .schema .TabletMetadata .ColumnType .PREV_ROW ;
24
+ import static org .apache .accumulo .manager .merge .FindMergeableRangeTask .UnmergeableReason .MAX_FILE_COUNT ;
25
+ import static org .apache .accumulo .manager .merge .FindMergeableRangeTask .UnmergeableReason .MAX_TOTAL_SIZE ;
26
+ import static org .apache .accumulo .manager .merge .FindMergeableRangeTask .UnmergeableReason .NOT_CONTIGUOUS ;
27
+ import static org .apache .accumulo .manager .merge .FindMergeableRangeTask .UnmergeableReason .TABLET_MERGEABILITY ;
24
28
25
29
import java .util .Map ;
26
30
import java .util .Map .Entry ;
27
31
import java .util .Objects ;
32
+ import java .util .Optional ;
28
33
import java .util .Set ;
29
34
import java .util .function .Predicate ;
30
35
@@ -94,14 +99,14 @@ public void run() {
94
99
.fetch (PREV_ROW , FILES , MERGEABILITY ).filter (FILTER ).build ()) {
95
100
96
101
final MergeableRange current =
97
- new MergeableRange (manager .getSteadyTime (), tableId , maxFileCount , maxTotalSize );
102
+ new MergeableRange (tableId , manager .getSteadyTime (), maxFileCount , maxTotalSize );
98
103
99
104
for (var tm : tablets ) {
100
105
log .trace ("Checking tablet {}, {}" , tm .getExtent (), tm .getTabletMergeability ());
101
- if (! current .add (tm )) {
106
+ current .add (tm ). ifPresent ( e -> {
102
107
submit (current , type , table , namespaceId );
103
108
current .resetAndAdd (tm );
104
- }
109
+ });
105
110
}
106
111
107
112
submit (current , type , table , namespaceId );
@@ -120,17 +125,17 @@ void submit(MergeableRange range, FateInstanceType type, Entry<TableId,String> t
120
125
return ;
121
126
}
122
127
123
- log .debug ("Table {} found {} tablets that can be merged for table" , table .getValue (),
124
- range .tabletCount );
125
-
126
128
TableId tableId = table .getKey ();
127
129
String tableName = table .getValue ();
128
130
131
+ log .debug ("Table {} found {} tablets that can be merged for table" , tableName ,
132
+ range .tabletCount );
133
+
129
134
final Text startRow = range .startRow != null ? range .startRow : new Text ("" );
130
135
final Text endRow = range .endRow != null ? range .endRow : new Text ("" );
131
136
132
- String startRowStr = StringUtils .defaultIfBlank (startRow .toString (), "-inf" );
133
- String endRowStr = StringUtils .defaultIfBlank (endRow .toString (), "+inf" );
137
+ final String startRowStr = StringUtils .defaultIfBlank (startRow .toString (), "-inf" );
138
+ final String endRowStr = StringUtils .defaultIfBlank (endRow .toString (), "+inf" );
134
139
log .debug ("FindMergeableRangeTask: Creating merge op: {} from startRow: {} to endRow: {}" ,
135
140
tableId , startRowStr , endRowStr );
136
141
var fateKey = FateKey .forMerge (new KeyExtent (tableId , range .endRow , range .startRow ));
@@ -141,7 +146,36 @@ void submit(MergeableRange range, FateInstanceType type, Entry<TableId,String> t
141
146
true );
142
147
}
143
148
144
- static class MergeableRange {
149
+ public enum UnmergeableReason {
150
+ NOT_CONTIGUOUS , MAX_FILE_COUNT , MAX_TOTAL_SIZE , TABLET_MERGEABILITY ;
151
+
152
+ // Cache the Optional() reason objects as we will re-use these over and over
153
+ private static final Optional <UnmergeableReason > NOT_CONTIGUOUS_OPT =
154
+ Optional .of (NOT_CONTIGUOUS );
155
+ private static final Optional <UnmergeableReason > MAX_FILE_COUNT_OPT =
156
+ Optional .of (MAX_FILE_COUNT );
157
+ private static final Optional <UnmergeableReason > MAX_TOTAL_SIZE_OPT =
158
+ Optional .of (MAX_TOTAL_SIZE );
159
+ private static final Optional <UnmergeableReason > TABLET_MERGEABILITY_OPT =
160
+ Optional .of (TABLET_MERGEABILITY );
161
+
162
+ public Optional <UnmergeableReason > optional () {
163
+ switch (this ) {
164
+ case NOT_CONTIGUOUS :
165
+ return NOT_CONTIGUOUS_OPT ;
166
+ case MAX_FILE_COUNT :
167
+ return MAX_FILE_COUNT_OPT ;
168
+ case MAX_TOTAL_SIZE :
169
+ return MAX_TOTAL_SIZE_OPT ;
170
+ case TABLET_MERGEABILITY :
171
+ return TABLET_MERGEABILITY_OPT ;
172
+ default :
173
+ throw new IllegalArgumentException ("Unexpected enum type" );
174
+ }
175
+ }
176
+ }
177
+
178
+ public static class MergeableRange {
145
179
final SteadyTime currentTime ;
146
180
final TableId tableId ;
147
181
final long maxFileCount ;
@@ -153,15 +187,17 @@ static class MergeableRange {
153
187
long totalFileCount ;
154
188
long totalFileSize ;
155
189
156
- MergeableRange (SteadyTime currentTime , TableId tableId , long maxFileCount , long maxTotalSize ) {
157
- this . currentTime = currentTime ;
190
+ public MergeableRange (TableId tableId , SteadyTime currentTime , long maxFileCount ,
191
+ long maxTotalSize ) {
158
192
this .tableId = tableId ;
193
+ this .currentTime = currentTime ;
159
194
this .maxFileCount = maxFileCount ;
160
195
this .maxTotalSize = maxTotalSize ;
161
196
}
162
197
163
- boolean add (TabletMetadata tm ) {
164
- if (validate (tm )) {
198
+ public Optional <UnmergeableReason > add (TabletMetadata tm ) {
199
+ var failure = validate (tm );
200
+ if (failure .isEmpty ()) {
165
201
tabletCount ++;
166
202
log .trace ("Adding tablet {} to MergeableRange" , tm .getExtent ());
167
203
if (tabletCount == 1 ) {
@@ -170,12 +206,11 @@ boolean add(TabletMetadata tm) {
170
206
endRow = tm .getEndRow ();
171
207
totalFileCount += tm .getFiles ().size ();
172
208
totalFileSize += tm .getFileSize ();
173
- return true ;
174
209
}
175
- return false ;
210
+ return failure ;
176
211
}
177
212
178
- private boolean validate (TabletMetadata tm ) {
213
+ private Optional < UnmergeableReason > validate (TabletMetadata tm ) {
179
214
Preconditions .checkArgument (tableId .equals (tm .getTableId ()), "Unexpected tableId seen %s" ,
180
215
tm .getTableId ());
181
216
@@ -186,19 +221,23 @@ private boolean validate(TabletMetadata tm) {
186
221
// If this is not the first tablet, then verify its prevEndRow matches
187
222
// the last endRow tracked, the server filter will skip tablets marked as never
188
223
if (!tm .getPrevEndRow ().equals (endRow )) {
189
- return false ;
224
+ return NOT_CONTIGUOUS . optional () ;
190
225
}
191
226
}
192
227
193
228
if (!tm .getTabletMergeability ().isMergeable (currentTime )) {
194
- return false ;
229
+ return TABLET_MERGEABILITY . optional () ;
195
230
}
196
231
197
232
if (totalFileCount + tm .getFiles ().size () > maxFileCount ) {
198
- return false ;
233
+ return MAX_FILE_COUNT .optional ();
234
+ }
235
+
236
+ if (totalFileSize + tm .getFileSize () > maxTotalSize ) {
237
+ return MAX_TOTAL_SIZE .optional ();
199
238
}
200
239
201
- return totalFileSize + tm . getFileSize () <= maxTotalSize ;
240
+ return Optional . empty () ;
202
241
}
203
242
204
243
void resetAndAdd (TabletMetadata tm ) {
0 commit comments