Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix calculation of tokens per repair #571

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Version 1.2.0 (Not yet released)

* Fix calculation of tokens per repair - Issue #570
* Repairs not scheduled when statistics disabled - Issue #175

### Merged from 1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,11 @@ private BigInteger getTokensPerRepair(VnodeRepairStates vnodeRepairStates)

BigInteger targetSizeInBytes = BigInteger.valueOf(myRepairConfiguration.getTargetRepairSizeInBytes());

BigInteger targetRepairs = tableSizeInBytes.divide(targetSizeInBytes);
tokensPerRepair = fullRangeSize.divide(targetRepairs);
if (tableSizeInBytes.compareTo(targetSizeInBytes) > 0)
{
BigInteger targetRepairs = tableSizeInBytes.divide(targetSizeInBytes);
tokensPerRepair = fullRangeSize.divide(targetRepairs);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public class TestTableRepairJob
private static final long RUN_INTERVAL_IN_DAYS = 1;
private static final long GC_GRACE_DAYS = 10;

private static final long ONE_MB_IN_BYTES = 1 * 1024 * 1024;
private static final long HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
private static final long THOUSAND_MB_IN_BYTES = 1000 * 1024 * 1024;

Expand Down Expand Up @@ -624,6 +625,108 @@ public void testIteratorWithTargetSize()
}
}

@Test
public void testIteratorWithTargetSizeBiggerThanTableSize()
{
LongTokenRange tokenRange1 = new LongTokenRange(0, 10);
LongTokenRange tokenRange2 = new LongTokenRange(10, 20);
LongTokenRange tokenRange3 = new LongTokenRange(20, 30);
List<LongTokenRange> expectedTokenRanges = Arrays.asList(
tokenRange1,
tokenRange2,
tokenRange3
);
ImmutableSet<Host> replicas = ImmutableSet.of(mock(Host.class), mock(Host.class));
ImmutableList<LongTokenRange> vnodes = ImmutableList.of(tokenRange1, tokenRange2, tokenRange3);

VnodeRepairStates vnodeRepairStates = VnodeRepairStatesImpl.newBuilder(
ImmutableList.of(
new VnodeRepairState(tokenRange1, replicas, 1234L),
new VnodeRepairState(tokenRange2, replicas, 1234L),
new VnodeRepairState(tokenRange3, replicas, 1234L))).build();
ReplicaRepairGroup replicaRepairGroup = new ReplicaRepairGroup(replicas, vnodes, System.currentTimeMillis());

RepairStateSnapshot repairStateSnapshot = RepairStateSnapshot.newBuilder()
.withReplicaRepairGroups(Collections.singletonList(replicaRepairGroup))
.withLastRepairedAt(1234L)
.withVnodeRepairStates(vnodeRepairStates)
.build();
when(myRepairState.getSnapshot()).thenReturn(repairStateSnapshot);
// 100 MB target size, 1 MB in table
when(myTableStorageStates.getDataSize(eq(myTableReference))).thenReturn(ONE_MB_IN_BYTES);

Iterator<ScheduledTask> iterator = myRepairJob.iterator();

ScheduledTask task = iterator.next();
assertThat(task).isInstanceOf(RepairGroup.class);
Collection<RepairTask> repairTasks = ((RepairGroup) task).getRepairTasks();

assertThat(repairTasks).hasSize(expectedTokenRanges.size());

Iterator<RepairTask> repairTaskIterator = repairTasks.iterator();
for (LongTokenRange expectedRange : expectedTokenRanges)
{
assertThat(repairTaskIterator.hasNext()).isTrue();
RepairTask repairTask = repairTaskIterator.next();
assertThat(repairTask.getReplicas()).containsExactlyInAnyOrderElementsOf(replicas);
assertThat(repairTask.getRepairConfiguration()).isEqualTo(myRepairConfiguration);
assertThat(repairTask.getTableReference()).isEqualTo(myTableReference);

assertThat(repairTask.getTokenRanges()).containsExactly(expectedRange);
}
}

@Test
public void testIteratorWithTargetSizeSameAsTableSize()
{
LongTokenRange tokenRange1 = new LongTokenRange(0, 10);
LongTokenRange tokenRange2 = new LongTokenRange(10, 20);
LongTokenRange tokenRange3 = new LongTokenRange(20, 30);
List<LongTokenRange> expectedTokenRanges = Arrays.asList(
tokenRange1,
tokenRange2,
tokenRange3
);
ImmutableSet<Host> replicas = ImmutableSet.of(mock(Host.class), mock(Host.class));
ImmutableList<LongTokenRange> vnodes = ImmutableList.of(tokenRange1, tokenRange2, tokenRange3);

VnodeRepairStates vnodeRepairStates = VnodeRepairStatesImpl.newBuilder(
ImmutableList.of(
new VnodeRepairState(tokenRange1, replicas, 1234L),
new VnodeRepairState(tokenRange2, replicas, 1234L),
new VnodeRepairState(tokenRange3, replicas, 1234L))).build();
ReplicaRepairGroup replicaRepairGroup = new ReplicaRepairGroup(replicas, vnodes, System.currentTimeMillis());

RepairStateSnapshot repairStateSnapshot = RepairStateSnapshot.newBuilder()
.withReplicaRepairGroups(Collections.singletonList(replicaRepairGroup))
.withLastRepairedAt(1234L)
.withVnodeRepairStates(vnodeRepairStates)
.build();
when(myRepairState.getSnapshot()).thenReturn(repairStateSnapshot);
// 100 MB target size, 100 MB in table
when(myTableStorageStates.getDataSize(eq(myTableReference))).thenReturn(HUNDRED_MB_IN_BYTES);

Iterator<ScheduledTask> iterator = myRepairJob.iterator();

ScheduledTask task = iterator.next();
assertThat(task).isInstanceOf(RepairGroup.class);
Collection<RepairTask> repairTasks = ((RepairGroup) task).getRepairTasks();

assertThat(repairTasks).hasSize(expectedTokenRanges.size());

Iterator<RepairTask> repairTaskIterator = repairTasks.iterator();
for (LongTokenRange expectedRange : expectedTokenRanges)
{
assertThat(repairTaskIterator.hasNext()).isTrue();
RepairTask repairTask = repairTaskIterator.next();
assertThat(repairTask.getReplicas()).containsExactlyInAnyOrderElementsOf(replicas);
assertThat(repairTask.getRepairConfiguration()).isEqualTo(myRepairConfiguration);
assertThat(repairTask.getTableReference()).isEqualTo(myTableReference);

assertThat(repairTask.getTokenRanges()).containsExactly(expectedRange);
}
}

public void testGetRealPriority()
{
long lastRepaired = System.currentTimeMillis();
Expand Down