Skip to content

Commit 697d903

Browse files
authored
JAVA-1404: Fix min token handling in TokenRange.contains (apache#813)
1 parent a7044d5 commit 697d903

4 files changed

Lines changed: 76 additions & 8 deletions

File tree

changelog/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## Changelog
22

3+
### 3.0.8 (in progress)
4+
5+
- [bug] JAVA-1404: Fix min token handling in TokenRange.contains.
6+
7+
38
### 3.0.7
49

510
- [bug] JAVA-1371: Reintroduce connection pool timeout.

driver-core/src/main/java/com/datastax/driver/core/TokenRange.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public List<TokenRange> intersectWith(TokenRange that) {
215215
* Checks whether this range contains a given token.
216216
*
217217
* @param token the token to check for.
218-
* @return whether this range contains the token, i.e. {@code range.start &lt; token &lt;= range.end}.
218+
* @return whether this range contains the token, i.e. {@code range.start < token <= range.end}.
219219
*/
220220
public boolean contains(Token token) {
221221
return contains(token, false);
@@ -224,13 +224,27 @@ public boolean contains(Token token) {
224224
// isStart handles the case where the token is the start of another range, for example:
225225
// * ]1,2] contains 2, but it does not contain the start of ]2,3]
226226
// * ]1,2] does not contain 1, but it contains the start of ]1,3]
227-
private boolean contains(Token token, boolean isStart) {
228-
boolean isAfterStart = isStart ? token.compareTo(start) >= 0 : token.compareTo(start) > 0;
229-
boolean isBeforeEnd = end.equals(factory.minToken()) ||
230-
(isStart ? token.compareTo(end) < 0 : token.compareTo(end) <= 0);
231-
return isWrappedAround()
232-
? isAfterStart || isBeforeEnd
233-
: isAfterStart && isBeforeEnd;
227+
@VisibleForTesting
228+
boolean contains(Token token, boolean isStart) {
229+
if (isEmpty()) {
230+
return false;
231+
}
232+
Token minToken = factory.minToken();
233+
if (end.equals(minToken)) {
234+
if (start.equals(minToken)) { // ]min, min] = full ring, contains everything
235+
return true;
236+
} else if (token.equals(minToken)) {
237+
return !isStart;
238+
} else {
239+
return isStart ? token.compareTo(start) >= 0 : token.compareTo(start) > 0;
240+
}
241+
} else {
242+
boolean isAfterStart = isStart ? token.compareTo(start) >= 0 : token.compareTo(start) > 0;
243+
boolean isBeforeEnd = isStart ? token.compareTo(end) < 0 : token.compareTo(end) <= 0;
244+
return isWrappedAround()
245+
? isAfterStart || isBeforeEnd // ####]----]####
246+
: isAfterStart && isBeforeEnd; // ----]####]----
247+
}
234248
}
235249

236250
/**

driver-core/src/test/java/com/datastax/driver/core/TokenRangeAssert.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,14 @@ public TokenRangeAssert doesNotIntersect(TokenRange... that) {
9999
}
100100
return this;
101101
}
102+
103+
public TokenRangeAssert contains(Token token, boolean isStart) {
104+
assertThat(actual.contains(token, isStart)).isTrue();
105+
return this;
106+
}
107+
108+
public TokenRangeAssert doesNotContain(Token token, boolean isStart) {
109+
assertThat(actual.contains(token, isStart)).isFalse();
110+
return this;
111+
}
102112
}

driver-core/src/test/java/com/datastax/driver/core/TokenRangeTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,45 @@ public void should_create_empty_token_ranges_if_too_many_splits() {
235235
}
236236
}
237237

238+
@Test(groups = "unit")
239+
public void should_check_if_range_contains_token() {
240+
// ]1,2] contains 2, but it does not contain the start of ]2,3]
241+
assertThat(tokenRange(1, 2))
242+
.contains(newM3PToken(2), false)
243+
.doesNotContain(newM3PToken(2), true);
244+
// ]1,2] does not contain 1, but it contains the start of ]1,3]
245+
assertThat(tokenRange(1, 2))
246+
.doesNotContain(newM3PToken(1), false)
247+
.contains(newM3PToken(1), true);
248+
249+
// ]2,1] contains the start of ]min,5]
250+
assertThat(tokenRange(2, 1))
251+
.contains(minToken, true);
252+
253+
// ]min, 1] does not contain min, but it contains the start of ]min, 2]
254+
assertThat(tokenRange(minToken, 1))
255+
.doesNotContain(minToken, false)
256+
.contains(minToken, true);
257+
// ]1, min] contains min, but not the start of ]min, 2]
258+
assertThat(tokenRange(1, minToken))
259+
.contains(minToken, false)
260+
.doesNotContain(minToken, true);
261+
262+
// An empty range contains nothing
263+
assertThat(tokenRange(1, 1))
264+
.doesNotContain(newM3PToken(1), true)
265+
.doesNotContain(newM3PToken(1), false)
266+
.doesNotContain(minToken, true)
267+
.doesNotContain(minToken, false);
268+
269+
// The whole ring contains everything
270+
assertThat(tokenRange(minToken, minToken))
271+
.contains(minToken, true)
272+
.contains(minToken, false)
273+
.contains(newM3PToken(1), true)
274+
.contains(newM3PToken(1), false);
275+
}
276+
238277
private TokenRange tokenRange(long start, long end) {
239278
return new TokenRange(newM3PToken(start), newM3PToken(end), factory);
240279
}

0 commit comments

Comments
 (0)