From 820fe3b68eb2cc963f0ec5201046818a2b78a8fa Mon Sep 17 00:00:00 2001 From: Nikita Koksharov Date: Sun, 6 Jan 2019 16:41:52 +0300 Subject: [PATCH] Fixed - RGeo.pos throws ClassCastException #1837 --- .../main/java/org/redisson/RedissonGeo.java | 56 ++++++++----------- .../client/handler/CommandDecoder.java | 4 ++ .../org/redisson/client/handler/State.java | 8 +++ .../protocol/decoder/ListMultiDecoder.java | 19 ++++++- .../java/org/redisson/RedissonGeoTest.java | 38 +++++++++++++ 5 files changed, 90 insertions(+), 35 deletions(-) diff --git a/redisson/src/main/java/org/redisson/RedissonGeo.java b/redisson/src/main/java/org/redisson/RedissonGeo.java index 8b8afe814..eebaedd13 100644 --- a/redisson/src/main/java/org/redisson/RedissonGeo.java +++ b/redisson/src/main/java/org/redisson/RedissonGeo.java @@ -55,6 +55,10 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> postitionDecoder = new ListMultiDecoder(new CodecDecoder(), new GeoPositionDecoder(), new ObjectListReplayDecoder(ListMultiDecoder.RESET), new GeoMapReplayDecoder()); private static final MultiDecoder> distanceDecoder = new ListMultiDecoder(new GeoDistanceDecoder(), new GeoMapReplayDecoder()); + private static final RedisCommand> GEORADIUS_RO_DISTANCE = new RedisCommand>("GEORADIUS_RO", distanceDecoder); + private static final RedisCommand> GEORADIUS_RO_POS = new RedisCommand>("GEORADIUS_RO", postitionDecoder); + private static final RedisCommand> GEORADIUSBYMEMBER_RO_DISTANCE = new RedisCommand>("GEORADIUSBYMEMBER_RO", distanceDecoder); + private static final RedisCommand> GEORADIUSBYMEMBER_RO_POS = new RedisCommand>("GEORADIUSBYMEMBER_RO", postitionDecoder); public RedissonGeo(CommandAsyncExecutor connectionManager, String name, RedissonClient redisson) { super(connectionManager, name, redisson); @@ -134,7 +138,9 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> decoder = new ListMultiDecoder(new GeoPositionDecoder(), new ObjectListReplayDecoder(ListMultiDecoder.RESET), new GeoPositionMapDecoder((List)Arrays.asList(members))); + MultiDecoder> decoder = new ListMultiDecoder(0, new GeoPositionDecoder(), +// new ObjectListReplayDecoder(ListMultiDecoder.RESET), + new GeoPositionMapDecoder((List)Arrays.asList(members))); RedisCommand> command = new RedisCommand>("GEOPOS", decoder); return commandExecutor.readAsync(getName(), StringCodec.INSTANCE, command, params.toArray()); } @@ -189,8 +195,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(double longitude, double latitude, double radius, GeoUnit geoUnit) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_DISTANCE, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHDIST"); } @@ -201,8 +206,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_DISTANCE, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHDIST", "COUNT", count); } @@ -213,8 +217,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_DISTANCE, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHDIST", geoOrder); } @@ -225,8 +228,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_DISTANCE, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder); } @@ -237,8 +239,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(double longitude, double latitude, double radius, GeoUnit geoUnit) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHCOORD"); + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_POS, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHCOORD"); } @Override @@ -248,8 +249,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_POS, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHCOORD", "COUNT", count); } @@ -260,8 +260,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_POS, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHCOORD", geoOrder); } @@ -272,8 +271,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(double longitude, double latitude, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUS_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), convert(longitude), convert(latitude), + return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_POS, getName(), convert(longitude), convert(latitude), radius, geoUnit, "WITHCOORD", "COUNT", count, geoOrder); } @@ -324,8 +322,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit) { - RedisCommand command = new RedisCommand("GEORADIUSBYMEMBER_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHDIST"); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getName(), encode(member), radius, geoUnit, "WITHDIST"); } @Override @@ -335,8 +332,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit, int count) { - RedisCommand command = new RedisCommand("GEORADIUSBYMEMBER_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHDIST", "COUNT", count); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getName(), encode(member), radius, geoUnit, "WITHDIST", "COUNT", count); } @Override @@ -346,8 +342,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) { - RedisCommand command = new RedisCommand("GEORADIUSBYMEMBER_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHDIST", geoOrder); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getName(), encode(member), radius, geoUnit, "WITHDIST", geoOrder); } @Override @@ -357,8 +352,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithDistanceAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) { - RedisCommand command = new RedisCommand("GEORADIUSBYMEMBER_RO", distanceDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_DISTANCE, getName(), encode(member), radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder); } @Override @@ -368,8 +362,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit) { - RedisCommand> command = new RedisCommand>("GEORADIUSBYMEMBER_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHCOORD"); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_POS, getName(), encode(member), radius, geoUnit, "WITHCOORD"); } @Override @@ -379,8 +372,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUSBYMEMBER_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHCOORD", "COUNT", count); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_POS, getName(), encode(member), radius, geoUnit, "WITHCOORD", "COUNT", count); } @Override @@ -390,8 +382,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) { - RedisCommand> command = new RedisCommand>("GEORADIUSBYMEMBER_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHCOORD", geoOrder); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_POS, getName(), encode(member), radius, geoUnit, "WITHCOORD", geoOrder); } @Override @@ -401,8 +392,7 @@ public class RedissonGeo extends RedissonScoredSortedSet implements RGeo> radiusWithPositionAsync(V member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) { - RedisCommand> command = new RedisCommand>("GEORADIUSBYMEMBER_RO", postitionDecoder); - return commandExecutor.readAsync(getName(), codec, command, getName(), encode(member), radius, geoUnit, "WITHCOORD", "COUNT", count, geoOrder); + return commandExecutor.readAsync(getName(), codec, GEORADIUSBYMEMBER_RO_POS, getName(), encode(member), radius, geoUnit, "WITHCOORD", "COUNT", count, geoOrder); } @Override diff --git a/redisson/src/main/java/org/redisson/client/handler/CommandDecoder.java b/redisson/src/main/java/org/redisson/client/handler/CommandDecoder.java index 9476c189a..b64dab10f 100644 --- a/redisson/src/main/java/org/redisson/client/handler/CommandDecoder.java +++ b/redisson/src/main/java/org/redisson/client/handler/CommandDecoder.java @@ -340,8 +340,12 @@ public class CommandDecoder extends ReplayingDecoder { state().addLevel(lastLevel); } + state().incLevel(); + decodeList(in, data, parts, ctx, size, respParts, skipConvertor); + state().decLevel(); + if (state().isMakeCheckpoint()) { if (lastLevel == state().getLastLevel() && lastLevel.isFull()) { state().removeLastLevel(); diff --git a/redisson/src/main/java/org/redisson/client/handler/State.java b/redisson/src/main/java/org/redisson/client/handler/State.java index 57c794666..db6fccc2a 100644 --- a/redisson/src/main/java/org/redisson/client/handler/State.java +++ b/redisson/src/main/java/org/redisson/client/handler/State.java @@ -54,6 +54,14 @@ public class State { return levels.get(level); } + public void incLevel() { + level++; + } + + public void decLevel() { + level--; + } + public void addLevel(StateLevel stateLevel) { if (levels == null) { levels = new ArrayList(2); diff --git a/redisson/src/main/java/org/redisson/client/protocol/decoder/ListMultiDecoder.java b/redisson/src/main/java/org/redisson/client/protocol/decoder/ListMultiDecoder.java index a3af51352..cec71dc51 100644 --- a/redisson/src/main/java/org/redisson/client/protocol/decoder/ListMultiDecoder.java +++ b/redisson/src/main/java/org/redisson/client/protocol/decoder/ListMultiDecoder.java @@ -115,12 +115,23 @@ public class ListMultiDecoder implements MultiDecoder { public ListMultiDecoder(MultiDecoder ... decoders) { this.decoders = decoders; } + + private Integer fixedIndex; + + public ListMultiDecoder(Integer fixedIndex, MultiDecoder ... decoders) { + this.fixedIndex = fixedIndex; + this.decoders = decoders; + } @Override public Decoder getDecoder(int paramNum, State state) { if (paramNum == 0) { NestedDecoderState s = getDecoder(state); - s.incIndex(); + if (fixedIndex != null) { + s.setIndex(fixedIndex); + } else { + s.incIndex(); + } s.resetPartsIndex(); } @@ -152,7 +163,11 @@ public class ListMultiDecoder implements MultiDecoder { int index = s.getIndex(); index += s.incPartsIndex(); - if (index == -1) { + if (fixedIndex != null && parts.isEmpty()) { + s.resetPartsIndex(); + } + + if (index == -1 || (fixedIndex != null && state.getLevel() == 0)) { return decoders[decoders.length-1].decode(parts, state); } diff --git a/redisson/src/test/java/org/redisson/RedissonGeoTest.java b/redisson/src/test/java/org/redisson/RedissonGeoTest.java index 69ab4fedf..fa2b2d5e2 100644 --- a/redisson/src/test/java/org/redisson/RedissonGeoTest.java +++ b/redisson/src/test/java/org/redisson/RedissonGeoTest.java @@ -74,8 +74,46 @@ public class RedissonGeoTest extends BaseTest { assertThat(geo.hash("Palermo", "Catania")).isEmpty(); } + + @Test + public void testPos4() { + RGeo geo = redisson.getGeo("test"); + geo.add(new GeoEntry(13.361389, 38.115556, "Palermo"), new GeoEntry(15.087269, 37.502669, "Catania")); + + Map expected = new LinkedHashMap(); + expected.put("Palermo", new GeoPosition(13.361389338970184, 38.115556395496299)); + expected.put("Catania", new GeoPosition(15.087267458438873, 37.50266842333162)); + assertThat(geo.pos("Palermo", "Catania")).isEqualTo(expected); + } + @Test + public void testPos1() { + RGeo geo = redisson.getGeo("test"); + geo.add(0.123,0.893,"hi"); + Map res = geo.pos("hi"); + assertThat(res.get("hi").getLatitude()).isNotNull(); + assertThat(res.get("hi").getLongitude()).isNotNull(); + } + @Test + public void testPos3() { + RGeo geo = redisson.getGeo("test"); + geo.add(0.123,0.893,"hi"); + Map res = geo.pos("hi", "123f", "sdfdsf"); + assertThat(res.get("hi").getLatitude()).isNotNull(); + assertThat(res.get("hi").getLongitude()).isNotNull(); + } + + @Test + public void testPos2() { + RGeo geo = redisson.getGeo("test"); + geo.add(new GeoEntry(13.361389, 38.115556, "Palermo")); + + Map expected = new LinkedHashMap(); + expected.put("Palermo", new GeoPosition(13.361389338970184, 38.115556395496299)); + assertThat(geo.pos("test2", "Palermo", "test3", "Catania", "test1")).isEqualTo(expected); + } + @Test public void testPos() { RGeo geo = redisson.getGeo("test");