DATAREDIS-744 - Polishing
Move binary lookup methods to ByteUtils, update license headers and restore altered tests by creating additional ones. Original Pull Request: #298
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ public class RedisKeyExpiredEvent<T> extends RedisKeyspaceEvent {
|
||||
/**
|
||||
* Use {@literal UTF-8} as default charset.
|
||||
*/
|
||||
public static final Charset CHARSET = Charset.forName("UTF-8");
|
||||
static final Charset CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private final BinaryKeyspaceIdentifier objectId;
|
||||
private final Object value;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1248,11 +1248,11 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
Assert.isTrue(isValid(key), String.format("Invalid key %s", new String(key)));
|
||||
|
||||
boolean phantomKey = startsWith(key, PHANTOM_SUFFIX, key.length - PHANTOM_SUFFIX.length);
|
||||
boolean phantomKey = ByteUtils.startsWith(key, PHANTOM_SUFFIX, key.length - PHANTOM_SUFFIX.length);
|
||||
|
||||
int keyspaceEndIndex = find(key, DELIMITTER);
|
||||
byte[] keyspace = getKeyspace(key, keyspaceEndIndex);
|
||||
byte[] id = getId(key, phantomKey, keyspaceEndIndex);
|
||||
int keyspaceEndIndex = ByteUtils.indexOf(key, DELIMITTER);
|
||||
byte[] keyspace = extractKeyspace(key, keyspaceEndIndex);
|
||||
byte[] id = extractId(key, phantomKey, keyspaceEndIndex);
|
||||
|
||||
return new BinaryKeyspaceIdentifier(keyspace, id, phantomKey);
|
||||
}
|
||||
@@ -1270,12 +1270,12 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyspaceEndIndex = find(key, DELIMITTER);
|
||||
int keyspaceEndIndex = ByteUtils.indexOf(key, DELIMITTER);
|
||||
|
||||
return keyspaceEndIndex > 0 && key.length > keyspaceEndIndex;
|
||||
}
|
||||
|
||||
private static byte[] getId(byte[] key, boolean phantomKey, int keyspaceEndIndex) {
|
||||
private static byte[] extractId(byte[] key, boolean phantomKey, int keyspaceEndIndex) {
|
||||
|
||||
int idSize;
|
||||
|
||||
@@ -1292,42 +1292,12 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
return id;
|
||||
}
|
||||
|
||||
private static byte[] getKeyspace(byte[] key, int keyspaceEndIndex) {
|
||||
private static byte[] extractKeyspace(byte[] key, int keyspaceEndIndex) {
|
||||
|
||||
byte[] keyspace = new byte[keyspaceEndIndex];
|
||||
System.arraycopy(key, 0, keyspace, 0, keyspaceEndIndex);
|
||||
|
||||
return keyspace;
|
||||
}
|
||||
|
||||
private static boolean startsWith(byte[] haystack, byte[] prefix, int offset) {
|
||||
|
||||
int to = offset;
|
||||
int prefixOffset = 0;
|
||||
int prefixLength = prefix.length;
|
||||
|
||||
if ((offset < 0) || (offset > haystack.length - prefixLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (--prefixLength >= 0) {
|
||||
if (haystack[to++] != prefix[prefixOffset++]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int find(byte[] haystack, byte needle) {
|
||||
|
||||
for (int i = 0; i < haystack.length; i++) {
|
||||
if (haystack[i] == needle) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,4 +98,65 @@ public final class ByteUtils {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the {@code haystack} starts with the given {@code prefix}.
|
||||
*
|
||||
* @param haystack the source to scan.
|
||||
* @param prefix the prefix to find.
|
||||
* @return {@literal true} if {@code haystack} at position {@code offset} starts with {@code prefix}.
|
||||
* @since 1.8.10
|
||||
* @see #startsWith(byte[], byte[], int)
|
||||
*/
|
||||
public static boolean startsWith(byte[] haystack, byte[] prefix) {
|
||||
return startsWith(haystack, prefix, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the {@code haystack} beginning at the specified {@code offset} starts with the given {@code prefix}.
|
||||
*
|
||||
* @param haystack the source to scan.
|
||||
* @param prefix the prefix to find.
|
||||
* @param offset the offset to start at.
|
||||
* @return {@literal true} if {@code haystack} at position {@code offset} starts with {@code prefix}.
|
||||
* @since 1.8.10
|
||||
*/
|
||||
public static boolean startsWith(byte[] haystack, byte[] prefix, int offset) {
|
||||
|
||||
int to = offset;
|
||||
int prefixOffset = 0;
|
||||
int prefixLength = prefix.length;
|
||||
|
||||
if ((offset < 0) || (offset > haystack.length - prefixLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (--prefixLength >= 0) {
|
||||
if (haystack[to++] != prefix[prefixOffset++]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the specified array of bytes for the specified value. Returns the index of the first matching value in the
|
||||
* {@code haystack}s natural order or {@code -1} of {@code needle} could not be found.
|
||||
*
|
||||
* @param haystack the source to scan.
|
||||
* @param needle the value to scan for.
|
||||
* @return index of first appearance, or -1 if not found.
|
||||
* @since 1.8.10
|
||||
*/
|
||||
public static int indexOf(byte[] haystack, byte needle) {
|
||||
|
||||
for (int i = 0; i < haystack.length; i++) {
|
||||
if (haystack[i] == needle) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -215,9 +215,23 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().members("persons:address.country:Andor"), hasItems("1"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425, DATAREDIS-744
|
||||
@Test // DATAREDIS-425
|
||||
public void getShouldReadSimpleObjectCorrectly() {
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<String, String>();
|
||||
map.put("_class", Person.class.getName());
|
||||
map.put("age", "24");
|
||||
template.opsForHash().putAll("persons:load-1", map);
|
||||
|
||||
Object loaded = adapter.get("load-1", "persons");
|
||||
|
||||
assertThat(loaded, instanceOf(Person.class));
|
||||
assertThat(((Person) loaded).age, is(24));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void getShouldReadSimpleObjectWithColonInIdCorrectly() {
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<String, String>();
|
||||
map.put("_class", Person.class.getName());
|
||||
map.put("age", "24");
|
||||
@@ -288,7 +302,7 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().members("persons:firstname:rand"), not(hasItem("1")));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425, DATAREDIS-744
|
||||
@Test // DATAREDIS-425
|
||||
public void keyExpiredEventShouldRemoveHelperStructures() throws Exception {
|
||||
|
||||
assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
|
||||
@@ -298,6 +312,34 @@ public class RedisKeyValueAdapterTests {
|
||||
map.put("firstname", "rand");
|
||||
map.put("address.country", "Andor");
|
||||
|
||||
template.opsForHash().putAll("persons:1", map);
|
||||
|
||||
template.opsForSet().add("persons", "1");
|
||||
template.opsForSet().add("persons:firstname:rand", "1");
|
||||
template.opsForSet().add("persons:1:idx", "persons:firstname:rand");
|
||||
|
||||
template.expire("persons:1", 100, TimeUnit.MILLISECONDS);
|
||||
|
||||
waitUntilKeyIsGone(template, "persons:1");
|
||||
waitUntilKeyIsGone(template, "persons:1:phantom");
|
||||
waitUntilKeyIsGone(template, "persons:firstname:rand");
|
||||
|
||||
assertThat(template.hasKey("persons:1"), is(false));
|
||||
assertThat(template.hasKey("persons:firstname:rand"), is(false));
|
||||
assertThat(template.hasKey("persons:1:idx"), is(false));
|
||||
assertThat(template.opsForSet().members("persons"), not(hasItem("1")));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void keyExpiredEventShouldRemoveHelperStructuresForObjectsWithColonInId() throws Exception {
|
||||
|
||||
assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<String, String>();
|
||||
map.put("_class", Person.class.getName());
|
||||
map.put("firstname", "rand");
|
||||
map.put("address.country", "Andor");
|
||||
|
||||
template.opsForHash().putAll("persons:1:b", map);
|
||||
|
||||
template.opsForSet().add("persons", "1");
|
||||
@@ -379,12 +421,31 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().isMember("persons:mat:idx", "persons:firstname:mat"), is(true));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-471, DATAREDIS-744
|
||||
@Test // DATAREDIS-471
|
||||
public void updateShouldAlterIndexDataCorrectly() {
|
||||
|
||||
Person rand = new Person();
|
||||
rand.firstname = "rand";
|
||||
|
||||
adapter.put("1", rand, "persons");
|
||||
|
||||
assertThat(template.hasKey("persons:firstname:rand"), is(true));
|
||||
|
||||
PartialUpdate<Person> update = new PartialUpdate<Person>("1", Person.class) //
|
||||
.set("firstname", "mat");
|
||||
|
||||
adapter.update(update);
|
||||
|
||||
assertThat(template.hasKey("persons:firstname:rand"), is(false));
|
||||
assertThat(template.hasKey("persons:firstname:mat"), is(true));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void updateShouldAlterIndexDataForObjectsWithColonInIdCorrectly() {
|
||||
|
||||
Person rand = new Person();
|
||||
rand.firstname = "rand";
|
||||
|
||||
adapter.put("1:a", rand, "persons");
|
||||
|
||||
assertThat(template.hasKey("persons:firstname:rand"), is(true));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
Reference in New Issue
Block a user