@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { delegate1.addGarbageCollectionSentinelValues(tableRef, cells); delegate2.addGarbageCollectionSentinelValues(tableRef, cells); }
@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { getDelegate(tableRef).addGarbageCollectionSentinelValues(tableRef, cells); }
@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { delegate().addGarbageCollectionSentinelValues(tableRef, cells); }
@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { try { delegate().addGarbageCollectionSentinelValues( tableMapper.getMappedTableName(tableRef), cells); } catch (TableMappingNotFoundException e) { throw new IllegalArgumentException(e); } }
private void deleteCellsAtTimestamps(TransactionManager txManager, TableReference tableRef, Multimap<Cell, Long> cellToTimestamp, Transaction.TransactionType transactionType) { if (!cellToTimestamp.isEmpty()) { for (Follower follower : followers) { follower.run(txManager, tableRef, cellToTimestamp.keySet(), transactionType); } keyValueService.addGarbageCollectionSentinelValues(tableRef, cellToTimestamp.keySet()); for (List<Entry<Cell, Long>> batch : Iterables.partition(cellToTimestamp.entries(), MAX_DELETES_IN_BATCH)) { Builder<Cell, Long> builder = ImmutableMultimap.builder(); batch.stream().forEach(e -> builder.put(e)); keyValueService.delete(tableRef, builder.build()); } } }
@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { //noinspection unused - try-with-resources closes trace try (CloseableTrace trace = startLocalTrace("addGarbageCollectionSentinelValues({}, {} cells)", LoggingArgs.safeTableOrPlaceholder(tableRef), Iterables.size(cells))) { delegate().addGarbageCollectionSentinelValues(tableRef, cells); } }
@Test public void deleteTimestampRangesIncludingSentinelsDeletesSentinels() { long latestTs = 15L; keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); keyValueService.put(TEST_TABLE, ImmutableMap.of(TEST_CELL, val(1, 0)), latestTs); keyValueService.deleteAllTimestamps(TEST_TABLE, ImmutableMap.of(TEST_CELL, latestTs), true); assertThat(getAllTimestampsForTestCell(), contains(latestTs)); }
@Test public void deleteTimestampRangesLeavesSentinels() { long latestTs = 15L; keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); keyValueService.put(TEST_TABLE, ImmutableMap.of(TEST_CELL, val(1, 0)), latestTs); keyValueService.deleteAllTimestamps(TEST_TABLE, ImmutableMap.of(TEST_CELL, latestTs), false); assertThat(getAllTimestampsForTestCell(), contains(Value.INVALID_VALUE_TIMESTAMP, latestTs)); assertThat(keyValueService.get(TEST_TABLE, ImmutableMap.of(TEST_CELL, Value.INVALID_VALUE_TIMESTAMP + 1L)) .get(TEST_CELL), equalTo(Value.create(new byte[0], Value.INVALID_VALUE_TIMESTAMP))); }
@Test public void addGarbageCollectionSentinelValues() throws Exception { ImmutableSet<Cell> cells = ImmutableSet.of(CELL); kvs.addGarbageCollectionSentinelValues(TABLE_REF, cells); checkSpan("atlasdb-kvs.addGarbageCollectionSentinelValues({table}, 1 cells)"); verify(delegate).addGarbageCollectionSentinelValues(TABLE_REF, cells); verifyNoMoreInteractions(delegate); }
@Override public void addGarbageCollectionSentinelValues(TableReference tableRef, Iterable<Cell> cells) { long startTime = System.currentTimeMillis(); maybeLog(() -> delegate.addGarbageCollectionSentinelValues(tableRef, cells), (logger, stopwatch) -> logger.log( "Call to KVS.addGarbageCollectionSentinelValues at time {}, on table {} over {} cells took {} ms.", LoggingArgs.startTimeMillis(startTime), LoggingArgs.tableRef(tableRef), LoggingArgs.cellCount(Iterables.size(cells)), LoggingArgs.durationMillis(stopwatch))); }
@Test public void sentinelsArentAddedIfNoCellsToSweep() { sweeper.sweepCells(TABLE_REFERENCE, ImmutableMultimap.of(), SINGLE_CELL_SET); verify(mockKvs, never()).addGarbageCollectionSentinelValues(TABLE_REFERENCE, SINGLE_CELL_SET); }
@Test public void ensureNoActionTakenIfNoCellsToSweep() { sweeper.sweepCells(TABLE_REFERENCE, ImmutableMultimap.of(), ImmutableSet.of()); verify(mockKvs, never()).delete(any(), any()); verify(mockKvs, never()).addGarbageCollectionSentinelValues(any(), any()); verify(mockPlm, never()).acquirePersistentLockWithRetry(); }
@Test public void acquireTheBackupLockBeforeDeletingButAfterAddingSentinels() { sweeper.sweepCells(TABLE_REFERENCE, SINGLE_CELL_TS_PAIR, SINGLE_CELL_SET); InOrder ordering = inOrder(mockPlm, mockKvs); ordering.verify(mockKvs, atLeastOnce()).addGarbageCollectionSentinelValues(TABLE_REFERENCE, SINGLE_CELL_SET); ordering.verify(mockPlm, times(1)).acquirePersistentLockWithRetry(); ordering.verify(mockKvs, atLeastOnce()).delete(TABLE_REFERENCE, SINGLE_CELL_TS_PAIR); }
@Test public void deleteTimestampRangesEdgeCases() { long minTs = 0; keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); keyValueService.putWithTimestamps(TEST_TABLE, ImmutableMultimap.of( TEST_CELL, Value.create(val(0, 5), minTs), TEST_CELL, Value.create(val(0, 7), TEST_TIMESTAMP - 1), TEST_CELL, Value.create(val(0, 9), TEST_TIMESTAMP))); keyValueService.deleteAllTimestamps(TEST_TABLE, ImmutableMap.of(TEST_CELL, TEST_TIMESTAMP), false); assertThat(getAllTimestampsForTestCell(), contains(Value.INVALID_VALUE_TIMESTAMP, TEST_TIMESTAMP)); }
@Test public void testAddGcSentinelValues() { putTestDataForMultipleTimestamps(); Multimap<Cell, Long> timestampsBefore = getTestTimestamps(); assertEquals(2, timestampsBefore.size()); assertFalse(timestampsBefore.containsEntry(TEST_CELL, Value.INVALID_VALUE_TIMESTAMP)); keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); Multimap<Cell, Long> timestampsAfter1 = getTestTimestamps(); assertEquals(3, timestampsAfter1.size()); assertTrue(timestampsAfter1.containsEntry(TEST_CELL, Value.INVALID_VALUE_TIMESTAMP)); keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); Multimap<Cell, Long> timestampsAfter2 = getTestTimestamps(); assertEquals(3, timestampsAfter2.size()); assertTrue(timestampsAfter2.containsEntry(TEST_CELL, Value.INVALID_VALUE_TIMESTAMP)); }
@Test public void ensureSentinelsAreAddedToKvs() { sweeper.sweepCells(TABLE_REFERENCE, SINGLE_CELL_TS_PAIR, SINGLE_CELL_SET); verify(mockKvs).addGarbageCollectionSentinelValues(TABLE_REFERENCE, SINGLE_CELL_SET); }
@Test public void deleteTimestampRangesIncludingSentinelsEdgeCases() { long minTs = 0; keyValueService.addGarbageCollectionSentinelValues(TEST_TABLE, ImmutableSet.of(TEST_CELL)); keyValueService.putWithTimestamps(TEST_TABLE, ImmutableMultimap.of( TEST_CELL, Value.create(val(0, 5), minTs), TEST_CELL, Value.create(val(0, 7), TEST_TIMESTAMP - 1), TEST_CELL, Value.create(val(0, 9), TEST_TIMESTAMP))); keyValueService.deleteAllTimestamps(TEST_TABLE, ImmutableMap.of(TEST_CELL, TEST_TIMESTAMP), true); assertThat(getAllTimestampsForTestCell(), contains(TEST_TIMESTAMP)); }
@Test public void releaseTheBackupLockAfterDeleteAndAddingSentinels() { sweeper.sweepCells(TABLE_REFERENCE, SINGLE_CELL_TS_PAIR, SINGLE_CELL_SET); InOrder ordering = inOrder(mockPlm, mockKvs); ordering.verify(mockKvs, atLeastOnce()).addGarbageCollectionSentinelValues(TABLE_REFERENCE, SINGLE_CELL_SET); ordering.verify(mockKvs, atLeastOnce()).delete(TABLE_REFERENCE, SINGLE_CELL_TS_PAIR); ordering.verify(mockPlm, times(1)).releasePersistentLock(); }
@Test public void sweepSentinelsAreWrittenAtFreshTimestamp() throws Exception { TableReference tableReference = TableReference.createFromFullyQualifiedName("test." + RandomStringUtils.randomAlphanumeric(16)); keyValueService.createTable(tableReference, AtlasDbConstants.GENERIC_TABLE_METADATA); keyValueService.addGarbageCollectionSentinelValues(tableReference, ImmutableList.of(CELL)); putDummyValueAtCellAndTimestamp( tableReference, CELL, Value.INVALID_VALUE_TIMESTAMP, STARTING_ATLAS_TIMESTAMP - 1); Map<Cell, Value> results = keyValueService.get(tableReference, ImmutableMap.of(CELL, 1L)); byte[] contents = results.get(CELL).getContents(); assertThat(Arrays.equals(contents, PtBytes.EMPTY_BYTE_ARRAY), is(true)); }
@Test public void thoroughSweepDeletesExistingSentinel() { spiedKvs.addGarbageCollectionSentinelValues(TABLE_THOR, ImmutableList.of(DEFAULT_CELL)); assertReadAtTimestampReturnsSentinel(TABLE_THOR, 0L); enqueueWriteCommitted(TABLE_THOR, 10L); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, 0L); }