long totalRowsDeleted = 0L;
long totalVersionsDeleted = 0L;
BulkDeleteResponse response = new BulkDeleteResponse();
HRegion region = ((RegionCoprocessorEnvironment) getEnvironment()).getRegion();
boolean hasMore = true;
RegionScanner scanner = null;
if (scan.getFilter() == null && deleteType == DeleteType.ROW) {
// What we need is just the rowkeys. So only 1st KV from any row is enough.
// Only when it is a row delete, we can apply this filter
// In other types we rely on the scan to know which all columns to be deleted.
scan.setFilter(new FirstKeyOnlyFilter());
}
// When the delete is based on some conditions so that Filters are available in the scan,
// we assume that the scan is perfect having necessary column(s) only.
try {
scanner = region.getScanner(scan);
while (hasMore) {
List<List<KeyValue>> deleteRows = new ArrayList<List<KeyValue>>(rowBatchSize);
for (int i = 0; i < rowBatchSize; i++) {
List<KeyValue> results = new ArrayList<KeyValue>();
hasMore = scanner.next(results);
if (results.size() > 0) {
deleteRows.add(results);
}
if (!hasMore) {
// There are no more rows.
break;
}
}
if (deleteRows.size() > 0) {
Pair<Mutation, Integer>[] deleteWithLockArr = new Pair[deleteRows.size()];
int i = 0;
for (List<KeyValue> deleteRow : deleteRows) {
Delete delete = createDeleteMutation(deleteRow, deleteType, timestamp);
deleteWithLockArr[i++] = new Pair<Mutation, Integer>(delete, null);
}
OperationStatus[] opStatus = region.batchMutate(deleteWithLockArr);
for (i = 0; i < opStatus.length; i++) {
if (opStatus[i].getOperationStatusCode() != OperationStatusCode.SUCCESS) {
break;
}
totalRowsDeleted++;
if (deleteType == DeleteType.VERSION) {
byte[] versionsDeleted = deleteWithLockArr[i].getFirst().getAttribute(
NO_OF_VERSIONS_TO_DELETE);
if (versionsDeleted != null) {
totalVersionsDeleted += Bytes.toInt(versionsDeleted);
}
}
}
}
}
} catch (IOException ioe) {
LOG.error(ioe);
response.setIoException(ioe);
} finally {
if (scanner != null) {
try {
scanner.close();
} catch (IOException ioe) {
LOG.error(ioe);
}
}
}