This is an automated email from the ASF dual-hosted git repository. wirebaron pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push: new 808d273 GEODE-4661: Implement KeySet protobuf message and handler (#1538) 808d273 is described below commit 808d273294d6b7e7723c111204df6be7009cb2b8 Author: Brian Rowe <br...@pivotal.io> AuthorDate: Fri Mar 2 10:13:33 2018 -0800 GEODE-4661: Implement KeySet protobuf message and handler (#1538) --- .../geode/experimental/driver/ProtobufRegion.java | 16 +++++ .../apache/geode/experimental/driver/Region.java | 9 +++ .../experimental/driver/RegionIntegrationTest.java | 15 ++++ .../src/main/proto/v1/clientProtocol.proto | 3 + .../src/main/proto/v1/region_API.proto | 8 +++ .../v1/operations/KeySetOperationHandler.java | 68 ++++++++++++++++++ .../registry/ProtobufOperationContextRegistry.java | 7 ++ .../v1/acceptance/CacheOperationsJUnitTest.java | 24 +++++++ .../KeySetOperationHandlerJUnitTest.java | 81 ++++++++++++++++++++++ 9 files changed, 231 insertions(+) diff --git a/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/ProtobufRegion.java b/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/ProtobufRegion.java index 9f99f25..a8d53b3 100644 --- a/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/ProtobufRegion.java +++ b/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/ProtobufRegion.java @@ -18,7 +18,9 @@ import java.io.IOException; import java.net.Socket; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.apache.geode.annotations.Experimental; import org.apache.geode.internal.protocol.protobuf.v1.BasicTypes; @@ -153,4 +155,18 @@ public class ProtobufRegion<K, V> implements Region<K, V> { protobufChannel.sendRequest(request, MessageTypeCase.REMOVERESPONSE); } + + @Override + public Set<K> keySet() throws IOException { + final Message request = Message.newBuilder() + .setKeySetRequest(RegionAPI.KeySetRequest.newBuilder().setRegionName(name)).build(); + final Message message = protobufChannel.sendRequest(request, MessageTypeCase.KEYSETRESPONSE); + final RegionAPI.KeySetResponse keySetResponse = message.getKeySetResponse(); + + Set<K> keys = new HashSet<>(keySetResponse.getKeysCount()); + for (BasicTypes.EncodedValue value : keySetResponse.getKeysList()) { + keys.add((K) ValueEncoder.decodeValue(value)); + } + return keys; + } } diff --git a/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/Region.java b/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/Region.java index f92d9a2..54c7138 100644 --- a/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/Region.java +++ b/geode-experimental-driver/src/main/java/org/apache/geode/experimental/driver/Region.java @@ -17,6 +17,7 @@ package org.apache.geode.experimental.driver; import java.io.IOException; import java.util.Collection; import java.util.Map; +import java.util.Set; import org.apache.geode.annotations.Experimental; @@ -85,4 +86,12 @@ public interface Region<K, V> { * @throws IOException */ void remove(K key) throws IOException; + + /** + * Gets all the keys for which this region has entries + * + * @return Set of keys in this region + * @throws IOException + */ + Set<K> keySet() throws IOException; } diff --git a/geode-experimental-driver/src/test/java/org/apache/geode/experimental/driver/RegionIntegrationTest.java b/geode-experimental-driver/src/test/java/org/apache/geode/experimental/driver/RegionIntegrationTest.java index 42c4bc6..1b6c085 100644 --- a/geode-experimental-driver/src/test/java/org/apache/geode/experimental/driver/RegionIntegrationTest.java +++ b/geode-experimental-driver/src/test/java/org/apache/geode/experimental/driver/RegionIntegrationTest.java @@ -14,17 +14,20 @@ */ package org.apache.geode.experimental.driver; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; @@ -106,6 +109,18 @@ public class RegionIntegrationTest extends IntegrationTestBase { assertNull(region.get(document)); } + @Test + public void keySetTest() throws Exception { + Region<String, String> region = driver.getRegion("region"); + Map<String, String> testMap = new HashMap<>(); + testMap.put("Key1", "foo"); + testMap.put("Key2", "foo"); + testMap.put("Key3", "foo"); + region.putAll(testMap); + assertArrayEquals(testMap.keySet().stream().sorted().toArray(), + region.keySet().stream().sorted().toArray()); + } + @Test(expected = IOException.class) public void putWithBadJSONKeyAndValue() throws IOException { Region<JSONWrapper, JSONWrapper> region = driver.getRegion("region"); diff --git a/geode-protobuf-messages/src/main/proto/v1/clientProtocol.proto b/geode-protobuf-messages/src/main/proto/v1/clientProtocol.proto index d049aec..184d6c4 100644 --- a/geode-protobuf-messages/src/main/proto/v1/clientProtocol.proto +++ b/geode-protobuf-messages/src/main/proto/v1/clientProtocol.proto @@ -69,6 +69,9 @@ message Message { OQLQueryRequest oqlQueryRequest = 26; OQLQueryResponse oqlQueryResponse = 27; + + KeySetRequest keySetRequest = 28; + KeySetResponse keySetResponse = 29; } } diff --git a/geode-protobuf-messages/src/main/proto/v1/region_API.proto b/geode-protobuf-messages/src/main/proto/v1/region_API.proto index c3465db..31039bf 100644 --- a/geode-protobuf-messages/src/main/proto/v1/region_API.proto +++ b/geode-protobuf-messages/src/main/proto/v1/region_API.proto @@ -100,3 +100,11 @@ message OQLQueryResponse { Table tableResult = 3; } } + +message KeySetRequest { + string regionName = 1; +} + +message KeySetResponse { + repeated EncodedValue keys = 1; +} diff --git a/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandler.java b/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandler.java new file mode 100644 index 0000000..ecab692 --- /dev/null +++ b/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandler.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.internal.protocol.protobuf.v1.operations; + +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.logging.log4j.Logger; + +import org.apache.geode.annotations.Experimental; +import org.apache.geode.cache.Region; +import org.apache.geode.internal.exception.InvalidExecutionContextException; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.protocol.operations.ProtobufOperationHandler; +import org.apache.geode.internal.protocol.protobuf.v1.BasicTypes; +import org.apache.geode.internal.protocol.protobuf.v1.Failure; +import org.apache.geode.internal.protocol.protobuf.v1.MessageExecutionContext; +import org.apache.geode.internal.protocol.protobuf.v1.ProtobufSerializationService; +import org.apache.geode.internal.protocol.protobuf.v1.RegionAPI; +import org.apache.geode.internal.protocol.protobuf.v1.Result; +import org.apache.geode.internal.protocol.protobuf.v1.Success; +import org.apache.geode.internal.protocol.protobuf.v1.serialization.exception.DecodingException; +import org.apache.geode.internal.protocol.protobuf.v1.serialization.exception.EncodingException; +import org.apache.geode.security.ResourcePermission; + +@Experimental +public class KeySetOperationHandler + implements ProtobufOperationHandler<RegionAPI.KeySetRequest, RegionAPI.KeySetResponse> { + private static final Logger logger = LogService.getLogger(); + + @Override + public Result<RegionAPI.KeySetResponse> process(ProtobufSerializationService serializationService, + RegionAPI.KeySetRequest request, MessageExecutionContext messageExecutionContext) + throws InvalidExecutionContextException, EncodingException, DecodingException { + String regionName = request.getRegionName(); + Region region = messageExecutionContext.getCache().getRegion(regionName); + if (region == null) { + logger.error("Received request for nonexistent region: {}", regionName); + return Failure.of(BasicTypes.ErrorCode.SERVER_ERROR, + "Region \"" + regionName + "\" not found"); + } + + Set keySet = region.keySet(); + RegionAPI.KeySetResponse.Builder builder = RegionAPI.KeySetResponse.newBuilder(); + keySet.stream().map(serializationService::encode) + .forEach(value -> builder.addKeys((BasicTypes.EncodedValue) value)); + + return Success.of(builder.build()); + } + + public static ResourcePermission determineRequiredPermission(RegionAPI.KeySetRequest request, + ProtobufSerializationService serializer) throws DecodingException { + return new ResourcePermission(ResourcePermission.Resource.DATA, + ResourcePermission.Operation.READ, request.getRegionName()); + } +} diff --git a/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/registry/ProtobufOperationContextRegistry.java b/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/registry/ProtobufOperationContextRegistry.java index 4811bac..3bca6fe 100644 --- a/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/registry/ProtobufOperationContextRegistry.java +++ b/geode-protobuf/src/main/java/org/apache/geode/internal/protocol/protobuf/v1/registry/ProtobufOperationContextRegistry.java @@ -32,6 +32,7 @@ import org.apache.geode.internal.protocol.protobuf.v1.operations.GetRegionNamesR import org.apache.geode.internal.protocol.protobuf.v1.operations.GetRegionRequestOperationHandler; import org.apache.geode.internal.protocol.protobuf.v1.operations.GetRequestOperationHandler; import org.apache.geode.internal.protocol.protobuf.v1.operations.GetServerOperationHandler; +import org.apache.geode.internal.protocol.protobuf.v1.operations.KeySetOperationHandler; import org.apache.geode.internal.protocol.protobuf.v1.operations.OqlQueryRequestOperationHandler; import org.apache.geode.internal.protocol.protobuf.v1.operations.PutAllRequestOperationHandler; import org.apache.geode.internal.protocol.protobuf.v1.operations.PutRequestOperationHandler; @@ -152,5 +153,11 @@ public class ProtobufOperationContextRegistry { new OqlQueryRequestOperationHandler(), opsResp -> ClientProtocol.Message.newBuilder().setOqlQueryResponse(opsResp), new ResourcePermission(Resource.DATA, Operation.READ))); + + operationContexts.put(MessageTypeCase.KEYSETREQUEST, + new ProtobufOperationContext<>(ClientProtocol.Message::getKeySetRequest, + new KeySetOperationHandler(), + opsResp -> ClientProtocol.Message.newBuilder().setKeySetResponse(opsResp), + KeySetOperationHandler::determineRequiredPermission)); } } diff --git a/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/acceptance/CacheOperationsJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/acceptance/CacheOperationsJUnitTest.java index 1d44676..848afff 100644 --- a/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/acceptance/CacheOperationsJUnitTest.java +++ b/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/acceptance/CacheOperationsJUnitTest.java @@ -31,9 +31,11 @@ import java.io.OutputStream; import java.net.Socket; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.awaitility.Awaitility; @@ -176,6 +178,13 @@ public class CacheOperationsJUnitTest { ProtobufUtilities.createProtobufRequestWithGetAllRequest(getAllRequest); protobufProtocolSerializer.serialize(getAllMessage, outputStream); validateGetAllResponse(socket, protobufProtocolSerializer); + + RegionAPI.KeySetRequest keySetRequest = + RegionAPI.KeySetRequest.newBuilder().setRegionName(TEST_REGION).build(); + ClientProtocol.Message keySetMessage = + ClientProtocol.Message.newBuilder().setKeySetRequest(keySetRequest).build(); + protobufProtocolSerializer.serialize(keySetMessage, outputStream); + validateKeySetResponse(socket, protobufProtocolSerializer); } @Test @@ -347,6 +356,21 @@ public class CacheOperationsJUnitTest { } } + private void validateKeySetResponse(Socket socket, + ProtobufProtocolSerializer protobufProtocolSerializer) throws Exception { + ClientProtocol.Message response = deserializeResponse(socket, protobufProtocolSerializer); + + assertEquals(ClientProtocol.Message.MessageTypeCase.KEYSETRESPONSE, + response.getMessageTypeCase()); + RegionAPI.KeySetResponse keySetResponse = response.getKeySetResponse(); + assertEquals(3, keySetResponse.getKeysCount()); + List responseKeys = keySetResponse.getKeysList().stream().map(serializationService::decode) + .collect(Collectors.toList()); + assertTrue(responseKeys.contains(TEST_MULTIOP_KEY1)); + assertTrue(responseKeys.contains(TEST_MULTIOP_KEY2)); + assertTrue(responseKeys.contains(TEST_MULTIOP_KEY3)); + } + private void validateRemoveResponse(Socket socket, ProtobufProtocolSerializer protobufProtocolSerializer) throws Exception { ClientProtocol.Message response = deserializeResponse(socket, protobufProtocolSerializer); diff --git a/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandlerJUnitTest.java b/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandlerJUnitTest.java new file mode 100644 index 0000000..56c216e --- /dev/null +++ b/geode-protobuf/src/test/java/org/apache/geode/internal/protocol/protobuf/v1/operations/KeySetOperationHandlerJUnitTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.internal.protocol.protobuf.v1.operations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.cache.Region; +import org.apache.geode.internal.protocol.TestExecutionContext; +import org.apache.geode.internal.protocol.protobuf.v1.BasicTypes; +import org.apache.geode.internal.protocol.protobuf.v1.ClientProtocol; +import org.apache.geode.internal.protocol.protobuf.v1.Failure; +import org.apache.geode.internal.protocol.protobuf.v1.ProtobufSerializationService; +import org.apache.geode.internal.protocol.protobuf.v1.RegionAPI; +import org.apache.geode.internal.protocol.protobuf.v1.Result; +import org.apache.geode.internal.protocol.protobuf.v1.Success; +import org.apache.geode.internal.protocol.protobuf.v1.serialization.exception.DecodingException; +import org.apache.geode.internal.protocol.protobuf.v1.serialization.exception.EncodingException; +import org.apache.geode.internal.protocol.protobuf.v1.utilities.ProtobufRequestUtilities; +import org.apache.geode.test.junit.categories.UnitTest; + +@Category(UnitTest.class) +public class KeySetOperationHandlerJUnitTest extends OperationHandlerJUnitTest { + private final String TEST_KEY1 = "Key1"; + private final String TEST_KEY2 = "Key2"; + private final String TEST_KEY3 = "Key3"; + private final String TEST_REGION = "test region"; + + @Before + public void setUp() throws Exception { + Region regionStub = mock(Region.class); + when(regionStub.keySet()) + .thenReturn(new HashSet<String>(Arrays.asList(TEST_KEY1, TEST_KEY2, TEST_KEY3))); + + when(cacheStub.getRegion(TEST_REGION)).thenReturn(regionStub); + operationHandler = new KeySetOperationHandler(); + } + + @Test + public void verifyKeySetReturnsExpectedKeys() throws Exception { + RegionAPI.KeySetRequest request = + RegionAPI.KeySetRequest.newBuilder().setRegionName(TEST_REGION).build(); + Result result = operationHandler.process(serializationService, request, + TestExecutionContext.getNoAuthCacheExecutionContext(cacheStub)); + + Assert.assertTrue(result instanceof Success); + RegionAPI.KeySetResponse response = (RegionAPI.KeySetResponse) result.getMessage(); + + List<Object> results = response.getKeysList().stream().map(serializationService::decode) + .collect(Collectors.toList()); + assertEquals(3, results.size()); + assertTrue(results.contains(TEST_KEY1)); + assertTrue(results.contains(TEST_KEY2)); + assertTrue(results.contains(TEST_KEY3)); + } +} -- To stop receiving notification emails like this one, please contact wireba...@apache.org.