Skip to content

Commit 765a6d1

Browse files
DATAREDIS-744 - Polishing
Move binary lookup methods to ByteUtils, update license headers and restore altered tests by creating additional ones. Original Pull Request: #298
1 parent c6ad238 commit 765a6d1

File tree

8 files changed

+140
-48
lines changed

8 files changed

+140
-48
lines changed

src/main/java/org/springframework/data/redis/core/RedisKeyExpiredEvent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2017 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,7 +33,7 @@ public class RedisKeyExpiredEvent<T> extends RedisKeyspaceEvent {
3333
/**
3434
* Use {@literal UTF-8} as default charset.
3535
*/
36-
public static final Charset CHARSET = Charset.forName("UTF-8");
36+
static final Charset CHARSET = Charset.forName("UTF-8");
3737

3838
private final BinaryKeyspaceIdentifier objectId;
3939
private final Object value;

src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2017 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/main/java/org/springframework/data/redis/core/convert/MappingRedisConverter.java

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2017 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -1248,11 +1248,11 @@ public static BinaryKeyspaceIdentifier of(byte[] key) {
12481248

12491249
Assert.isTrue(isValid(key), String.format("Invalid key %s", new String(key)));
12501250

1251-
boolean phantomKey = startsWith(key, PHANTOM_SUFFIX, key.length - PHANTOM_SUFFIX.length);
1251+
boolean phantomKey = ByteUtils.startsWith(key, PHANTOM_SUFFIX, key.length - PHANTOM_SUFFIX.length);
12521252

1253-
int keyspaceEndIndex = find(key, DELIMITTER);
1254-
byte[] keyspace = getKeyspace(key, keyspaceEndIndex);
1255-
byte[] id = getId(key, phantomKey, keyspaceEndIndex);
1253+
int keyspaceEndIndex = ByteUtils.indexOf(key, DELIMITTER);
1254+
byte[] keyspace = extractKeyspace(key, keyspaceEndIndex);
1255+
byte[] id = extractId(key, phantomKey, keyspaceEndIndex);
12561256

12571257
return new BinaryKeyspaceIdentifier(keyspace, id, phantomKey);
12581258
}
@@ -1270,12 +1270,12 @@ public static boolean isValid(byte[] key) {
12701270
return false;
12711271
}
12721272

1273-
int keyspaceEndIndex = find(key, DELIMITTER);
1273+
int keyspaceEndIndex = ByteUtils.indexOf(key, DELIMITTER);
12741274

12751275
return keyspaceEndIndex > 0 && key.length > keyspaceEndIndex;
12761276
}
12771277

1278-
private static byte[] getId(byte[] key, boolean phantomKey, int keyspaceEndIndex) {
1278+
private static byte[] extractId(byte[] key, boolean phantomKey, int keyspaceEndIndex) {
12791279

12801280
int idSize;
12811281

@@ -1292,42 +1292,12 @@ private static byte[] getId(byte[] key, boolean phantomKey, int keyspaceEndIndex
12921292
return id;
12931293
}
12941294

1295-
private static byte[] getKeyspace(byte[] key, int keyspaceEndIndex) {
1295+
private static byte[] extractKeyspace(byte[] key, int keyspaceEndIndex) {
12961296

12971297
byte[] keyspace = new byte[keyspaceEndIndex];
12981298
System.arraycopy(key, 0, keyspace, 0, keyspaceEndIndex);
12991299

13001300
return keyspace;
13011301
}
1302-
1303-
private static boolean startsWith(byte[] haystack, byte[] prefix, int offset) {
1304-
1305-
int to = offset;
1306-
int prefixOffset = 0;
1307-
int prefixLength = prefix.length;
1308-
1309-
if ((offset < 0) || (offset > haystack.length - prefixLength)) {
1310-
return false;
1311-
}
1312-
1313-
while (--prefixLength >= 0) {
1314-
if (haystack[to++] != prefix[prefixOffset++]) {
1315-
return false;
1316-
}
1317-
}
1318-
1319-
return true;
1320-
}
1321-
1322-
private static int find(byte[] haystack, byte needle) {
1323-
1324-
for (int i = 0; i < haystack.length; i++) {
1325-
if (haystack[i] == needle) {
1326-
return i;
1327-
}
1328-
}
1329-
1330-
return -1;
1331-
}
13321302
}
13331303
}

src/main/java/org/springframework/data/redis/util/ByteUtils.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,65 @@ public static byte[][] mergeArrays(byte[] firstArray, byte[]... additionalArrays
9898

9999
return result;
100100
}
101+
102+
/**
103+
* Tests if the {@code haystack} starts with the given {@code prefix}.
104+
*
105+
* @param haystack the source to scan.
106+
* @param prefix the prefix to find.
107+
* @return {@literal true} if {@code haystack} at position {@code offset} starts with {@code prefix}.
108+
* @since 1.8.10
109+
* @see #startsWith(byte[], byte[], int)
110+
*/
111+
public static boolean startsWith(byte[] haystack, byte[] prefix) {
112+
return startsWith(haystack, prefix, 0);
113+
}
114+
115+
/**
116+
* Tests if the {@code haystack} beginning at the specified {@code offset} starts with the given {@code prefix}.
117+
*
118+
* @param haystack the source to scan.
119+
* @param prefix the prefix to find.
120+
* @param offset the offset to start at.
121+
* @return {@literal true} if {@code haystack} at position {@code offset} starts with {@code prefix}.
122+
* @since 1.8.10
123+
*/
124+
public static boolean startsWith(byte[] haystack, byte[] prefix, int offset) {
125+
126+
int to = offset;
127+
int prefixOffset = 0;
128+
int prefixLength = prefix.length;
129+
130+
if ((offset < 0) || (offset > haystack.length - prefixLength)) {
131+
return false;
132+
}
133+
134+
while (--prefixLength >= 0) {
135+
if (haystack[to++] != prefix[prefixOffset++]) {
136+
return false;
137+
}
138+
}
139+
140+
return true;
141+
}
142+
143+
/**
144+
* Searches the specified array of bytes for the specified value. Returns the index of the first matching value in the
145+
* {@code haystack}s natural order or {@code -1} of {@code needle} could not be found.
146+
*
147+
* @param haystack the source to scan.
148+
* @param needle the value to scan for.
149+
* @return index of first appearance, or -1 if not found.
150+
* @since 1.8.10
151+
*/
152+
public static int indexOf(byte[] haystack, byte needle) {
153+
154+
for (int i = 0; i < haystack.length; i++) {
155+
if (haystack[i] == needle) {
156+
return i;
157+
}
158+
}
159+
160+
return -1;
161+
}
101162
}

src/test/java/org/springframework/data/redis/core/RedisKeyExpiredEventUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2017 the original author or authors.
2+
* Copyright 2015-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -215,9 +215,23 @@ public void putWritesSimpleNestedIndexValuesCorrectly() {
215215
assertThat(template.opsForSet().members("persons:address.country:Andor"), hasItems("1"));
216216
}
217217

218-
@Test // DATAREDIS-425, DATAREDIS-744
218+
@Test // DATAREDIS-425
219219
public void getShouldReadSimpleObjectCorrectly() {
220220

221+
Map<String, String> map = new LinkedHashMap<String, String>();
222+
map.put("_class", Person.class.getName());
223+
map.put("age", "24");
224+
template.opsForHash().putAll("persons:load-1", map);
225+
226+
Object loaded = adapter.get("load-1", "persons");
227+
228+
assertThat(loaded, instanceOf(Person.class));
229+
assertThat(((Person) loaded).age, is(24));
230+
}
231+
232+
@Test // DATAREDIS-744
233+
public void getShouldReadSimpleObjectWithColonInIdCorrectly() {
234+
221235
Map<String, String> map = new LinkedHashMap<String, String>();
222236
map.put("_class", Person.class.getName());
223237
map.put("age", "24");
@@ -288,7 +302,7 @@ public void deleteCleansIndexedDataCorrectly() {
288302
assertThat(template.opsForSet().members("persons:firstname:rand"), not(hasItem("1")));
289303
}
290304

291-
@Test // DATAREDIS-425, DATAREDIS-744
305+
@Test // DATAREDIS-425
292306
public void keyExpiredEventShouldRemoveHelperStructures() throws Exception {
293307

294308
assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
@@ -298,6 +312,34 @@ public void keyExpiredEventShouldRemoveHelperStructures() throws Exception {
298312
map.put("firstname", "rand");
299313
map.put("address.country", "Andor");
300314

315+
template.opsForHash().putAll("persons:1", map);
316+
317+
template.opsForSet().add("persons", "1");
318+
template.opsForSet().add("persons:firstname:rand", "1");
319+
template.opsForSet().add("persons:1:idx", "persons:firstname:rand");
320+
321+
template.expire("persons:1", 100, TimeUnit.MILLISECONDS);
322+
323+
waitUntilKeyIsGone(template, "persons:1");
324+
waitUntilKeyIsGone(template, "persons:1:phantom");
325+
waitUntilKeyIsGone(template, "persons:firstname:rand");
326+
327+
assertThat(template.hasKey("persons:1"), is(false));
328+
assertThat(template.hasKey("persons:firstname:rand"), is(false));
329+
assertThat(template.hasKey("persons:1:idx"), is(false));
330+
assertThat(template.opsForSet().members("persons"), not(hasItem("1")));
331+
}
332+
333+
@Test // DATAREDIS-744
334+
public void keyExpiredEventShouldRemoveHelperStructuresForObjectsWithColonInId() throws Exception {
335+
336+
assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
337+
338+
Map<String, String> map = new LinkedHashMap<String, String>();
339+
map.put("_class", Person.class.getName());
340+
map.put("firstname", "rand");
341+
map.put("address.country", "Andor");
342+
301343
template.opsForHash().putAll("persons:1:b", map);
302344

303345
template.opsForSet().add("persons", "1");
@@ -379,12 +421,31 @@ public void putWritesIndexDataCorrectly() {
379421
assertThat(template.opsForSet().isMember("persons:mat:idx", "persons:firstname:mat"), is(true));
380422
}
381423

382-
@Test // DATAREDIS-471, DATAREDIS-744
424+
@Test // DATAREDIS-471
383425
public void updateShouldAlterIndexDataCorrectly() {
384426

385427
Person rand = new Person();
386428
rand.firstname = "rand";
387429

430+
adapter.put("1", rand, "persons");
431+
432+
assertThat(template.hasKey("persons:firstname:rand"), is(true));
433+
434+
PartialUpdate<Person> update = new PartialUpdate<Person>("1", Person.class) //
435+
.set("firstname", "mat");
436+
437+
adapter.update(update);
438+
439+
assertThat(template.hasKey("persons:firstname:rand"), is(false));
440+
assertThat(template.hasKey("persons:firstname:mat"), is(true));
441+
}
442+
443+
@Test // DATAREDIS-744
444+
public void updateShouldAlterIndexDataForObjectsWithColonInIdCorrectly() {
445+
446+
Person rand = new Person();
447+
rand.firstname = "rand";
448+
388449
adapter.put("1:a", rand, "persons");
389450

390451
assertThat(template.hasKey("persons:firstname:rand"), is(true));

src/test/java/org/springframework/data/redis/core/convert/BinaryKeyspaceIdentifierUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

src/test/java/org/springframework/data/redis/core/convert/KeyspaceIdentifierUnitTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)