@Override public void apply() { delegate.delete(row, columns); } });
private void deleteColumns(SortedMap<byte[], ? extends SortedMap<byte[], Long>> updates) { for (Map.Entry<byte[], ? extends SortedMap<byte[], Long>> entry : updates.entrySet()) { byte[] row = entry.getKey(); Set<byte[]> columnSet = entry.getValue().keySet(); byte[][] columns = columnSet.toArray(new byte[columnSet.size()][]); // Only delete from v2 table. This is because for gauge metrics, put operation gets translated into 2 operations // 1.) Delete column from v2 table if it exists // 2.) Put column in v3 table. // This is the way to differentiate gauge and count metrics. So that when we scan both tables we know all the // remaining columns in v2 table are increments so just sum them up if (v2HBaseTable != null) { try { v2HBaseTable.delete(row, columns); } catch (Exception e) { handleV2TableException(e, "Delete", getV2MetricsTableDatasetId().getDataset()); } } } }
/** * Delete entries in fact table. * @param scan specifies deletion criteria */ public void delete(FactScan scan) { try (Scanner scanner = getScanner(scan)) { Row row; while ((row = scanner.next()) != null) { List<byte[]> columns = Lists.newArrayList(); boolean exhausted = false; for (byte[] column : row.getColumns().keySet()) { long ts = codec.getTimestamp(row.getRow(), column); if (ts < scan.getStartTs()) { continue; } if (ts > scan.getEndTs()) { exhausted = true; break; } columns.add(column); } // todo: do deletes efficiently, in batches, not one-by-one timeSeriesTable.delete(row.getRow(), columns.toArray(new byte[columns.size()][])); if (exhausted) { break; } } } }
v2MetricsTable.delete(rowKey, deletes);
/** * Delete entries in fact table. * @param scan specifies deletion criteria */ public void delete(FactScan scan) { try (Scanner scanner = getScanner(scan)) { Row row; while ((row = scanner.next()) != null) { List<byte[]> columns = Lists.newArrayList(); boolean exhausted = false; for (byte[] column : row.getColumns().keySet()) { long ts = codec.getTimestamp(row.getRow(), column); if (ts < scan.getStartTs()) { continue; } if (ts > scan.getEndTs()) { exhausted = true; break; } columns.add(column); } // todo: do deletes efficiently, in batches, not one-by-one timeSeriesTable.delete(row.getRow(), columns.toArray(new byte[columns.size()][])); if (exhausted) { break; } } } }
@Test public void testDeleteIncrements() throws Exception { // note: this is pretty important test case for tables with counters, e.g. metrics MetricsTable table = getTable("testDeleteIncrements"); // delete increment and increment again table.increment(A, ImmutableMap.of(B, 5L)); table.increment(A, ImmutableMap.of(B, 2L)); Assert.assertEquals(7L, Bytes.toLong(table.get(A, B))); table.delete(A, new byte[][]{B}); Assert.assertNull(table.get(A, B)); table.increment(A, ImmutableMap.of(B, 3L)); Assert.assertEquals(3L, Bytes.toLong(table.get(A, B))); }
@Test public void testDelete() throws Exception { MetricsTable table = getTable("testDelete"); NavigableMap<byte[], SortedMap<byte[], Long>> writes = Maps.newTreeMap(Bytes.BYTES_COMPARATOR); for (int i = 0; i < 1024; i++) { writes.put(Bytes.toBytes(i << 22), mapOf(A, Bytes.toLong(X))); } table.put(writes); // verify the first and last are there (sanity test for correctness of test logic) Assert.assertArrayEquals(X, table.get(Bytes.toBytes(0x00000000), A)); Assert.assertArrayEquals(X, table.get(Bytes.toBytes(0xffc00000), A)); List<byte[]> toDelete = ImmutableList.of( Bytes.toBytes(0xa1000000), Bytes.toBytes(0xb2000000), Bytes.toBytes(0xc3000000)); // verify these three are there, and delete them for (byte[] row : toDelete) { Assert.assertArrayEquals(X, table.get(row, A)); table.delete(row, new byte[][] {A}); } // verify these three are now gone. for (byte[] row : toDelete) { Assert.assertNull(table.get(row, A)); } // verify nothing else is gone by counting all entries in a scan Assert.assertEquals(1021, countRange(table, null, null)); }