From 78b987eeba10f4572c791ea1c8306ecb27a68470 Mon Sep 17 00:00:00 2001 From: "arnett, stu" Date: Thu, 2 Jul 2015 18:13:48 -0400 Subject: [PATCH] v2.0.1 --- build.gradle | 2 +- .../object/s3/jersey/GeoPinningFilter.java | 35 ++++++++---- .../emc/object/s3/AbstractS3ClientTest.java | 5 ++ .../com/emc/object/s3/GeoPinningTest.java | 57 +++++++++++++++++-- .../com/emc/object/s3/S3JerseyClientTest.java | 2 - 5 files changed, 82 insertions(+), 19 deletions(-) diff --git a/build.gradle b/build.gradle index a8cf95f5..62f2c5ad 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ apply from: "$commonBuildDir/ecs-publish.gradle" dependencies { compile 'com.emc.ecs:smart-client:2.0.1', - 'com.emc.ecs:object-transform:1.0.0', + 'com.emc.ecs:object-transform:1.0.1', 'org.jdom:jdom2:2.0.5' testCompile 'junit:junit:4.11' } diff --git a/src/main/java/com/emc/object/s3/jersey/GeoPinningFilter.java b/src/main/java/com/emc/object/s3/jersey/GeoPinningFilter.java index bdc0da29..126a58f7 100644 --- a/src/main/java/com/emc/object/s3/jersey/GeoPinningFilter.java +++ b/src/main/java/com/emc/object/s3/jersey/GeoPinningFilter.java @@ -27,6 +27,7 @@ package com.emc.object.s3.jersey; import com.emc.object.ObjectConfig; +import com.emc.object.s3.S3Constants; import com.emc.rest.smart.ecs.Vdc; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; @@ -49,9 +50,19 @@ public GeoPinningFilter(ObjectConfig objectConfig) { this.objectConfig = objectConfig; } - protected String getRequestGuid(ClientRequest cr) { - String key = cr.getURI().getPath(); + /** + * If this is a bucket request, the bucket is the ID. + * If this is an object request, the key is the ID. + */ + protected String getGeoId(ClientRequest request, String bucketName) { + String key = request.getURI().getPath(); + + if (key == null) return bucketName; + if (key.startsWith("/")) key = key.substring(1); + + if (key.length() == 0) return bucketName; + return key; } @@ -62,18 +73,22 @@ protected int getGeoPinIndex(String guid, int vdcCount) { } @Override - public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { - List healthyVdcs = new ArrayList(); + public ClientResponse handle(ClientRequest request) throws ClientHandlerException { + // if there's no bucket, we don't need to pin the request (there's no write or read) + String bucketName = (String) request.getProperties().get(S3Constants.PROPERTY_BUCKET_NAME); + if (bucketName != null) { + List healthyVdcs = new ArrayList(); - for (Vdc vdc : objectConfig.getVdcs()) { - if (vdc.isHealthy()) healthyVdcs.add(vdc); - } + for (Vdc vdc : objectConfig.getVdcs()) { + if (vdc.isHealthy()) healthyVdcs.add(vdc); + } - int geoPinIndex = getGeoPinIndex(getRequestGuid(cr), healthyVdcs.size()); + int geoPinIndex = getGeoPinIndex(getGeoId(request, bucketName), healthyVdcs.size()); - cr.getProperties().put(GeoPinningRule.PROP_GEO_PINNED_VDC, healthyVdcs.get(geoPinIndex)); + request.getProperties().put(GeoPinningRule.PROP_GEO_PINNED_VDC, healthyVdcs.get(geoPinIndex)); + } - return getNext().handle(cr); + return getNext().handle(request); } public ObjectConfig getObjectConfig() { diff --git a/src/test/java/com/emc/object/s3/AbstractS3ClientTest.java b/src/test/java/com/emc/object/s3/AbstractS3ClientTest.java index 875369ca..2c7ab2f8 100644 --- a/src/test/java/com/emc/object/s3/AbstractS3ClientTest.java +++ b/src/test/java/com/emc/object/s3/AbstractS3ClientTest.java @@ -57,6 +57,11 @@ public void dumpLBStats() { } } + @After + public void shutdownClient() { + if (client != null) client.shutdown(); + } + @Override protected void createBucket(String bucketName) throws Exception { client.createBucket(bucketName); diff --git a/src/test/java/com/emc/object/s3/GeoPinningTest.java b/src/test/java/com/emc/object/s3/GeoPinningTest.java index b8e1bfdf..ce92256a 100644 --- a/src/test/java/com/emc/object/s3/GeoPinningTest.java +++ b/src/test/java/com/emc/object/s3/GeoPinningTest.java @@ -79,11 +79,19 @@ public void testGuidExtraction() throws Exception { GeoPinningTestFilter filter = new GeoPinningTestFilter(s3Config); Assert.assertEquals("my/object/key", - filter.getRequestGuid(new ClientRequestImpl(new URI("http://foo.s3.bar.com/my/object/key"), null))); + filter.getGeoId(new ClientRequestImpl(new URI("http://foo.s3.bar.com/my/object/key"), null), getTestBucket())); Assert.assertEquals("/my/object/key", - filter.getRequestGuid(new ClientRequestImpl(new URI("http://foo.s3.bar.com//my/object/key"), null))); + filter.getGeoId(new ClientRequestImpl(new URI("http://foo.s3.bar.com//my/object/key"), null), getTestBucket())); Assert.assertEquals("/my/object/key", - filter.getRequestGuid(new ClientRequestImpl(new URI("http://foo.s3.bar.com/%2Fmy/object/key"), null))); + filter.getGeoId(new ClientRequestImpl(new URI("http://foo.s3.bar.com/%2Fmy/object/key"), null), getTestBucket())); + + String bucketName = getTestBucket(); + Assert.assertEquals(bucketName, + filter.getGeoId(new ClientRequestImpl(new URI("http://foo.s3.bar.com"), null), bucketName)); + Assert.assertEquals(bucketName, + filter.getGeoId(new ClientRequestImpl(new URI("http://foo.s3.bar.com/"), null), bucketName)); + Assert.assertEquals(bucketName, + filter.getGeoId(new ClientRequestImpl(new URI("http://s3.bar.com/"), null), bucketName)); } @Test @@ -130,6 +138,13 @@ public void testVdcDistribution() { testKeyDistribution(key1, hash1 % vdcs.size()); testKeyDistribution(key2, hash2 % vdcs.size()); testKeyDistribution(key3, hash3 % vdcs.size()); + + String bucket1 = "my-test-bucket", bucket2 = "foo-bar3baz", bucket3 = "test-bucket-12345-xxzz-blah"; + + int bHash1 = 0xc6c1ae, bHash2 = 0x2d4526, bHash3 = 0x9e3f48; + testBucketDistribution(bucket1, bHash1 % vdcs.size()); + testBucketDistribution(bucket2, bHash2 % vdcs.size()); + testBucketDistribution(bucket3, bHash3 % vdcs.size()); } protected void testKeyDistribution(String key, int vdcIndex) { @@ -146,7 +161,37 @@ protected void testKeyDistribution(String key, int vdcIndex) { Assert.assertEquals(10, loadBalancer.getTotalConnections()); for (HostStats stats : loadBalancer.getHostStats()) { - if (vdcs.get(vdcIndex) == ((VdcHost) stats).getVdc()) { + if (vdcs.get(vdcIndex).equals(((VdcHost) stats).getVdc())) { + // all hosts in the appropriate VDC should have been used at least once + Assert.assertTrue(stats.getTotalConnections() > 0); + } else { + // hosts in other VDCs should *not* be used + Assert.assertEquals(0, stats.getTotalConnections()); + } + } + } + + protected void testBucketDistribution(String bucket, int vdcIndex) { + LoadBalancer loadBalancer = ((S3JerseyClient) client).getLoadBalancer(); + loadBalancer.resetStats(); + + // make some requests to the bucket + int requestCount = 8; + client.createBucket(bucket); + client.getBucketAcl(bucket); + client.getBucketLocation(bucket); + client.getBucketLocation(bucket); + client.getBucketLocation(bucket); + client.getBucketLocation(bucket); + client.getBucketLocation(bucket); + client.deleteBucket(bucket); + + // check no errors and total count + Assert.assertEquals(0, loadBalancer.getTotalErrors()); + Assert.assertEquals(requestCount, loadBalancer.getTotalConnections()); + + for (HostStats stats : loadBalancer.getHostStats()) { + if (vdcs.get(vdcIndex).equals(((VdcHost) stats).getVdc())) { // all hosts in the appropriate VDC should have been used at least once Assert.assertTrue(stats.getTotalConnections() > 0); } else { @@ -162,8 +207,8 @@ public GeoPinningTestFilter(ObjectConfig objectConfig) { } @Override - public String getRequestGuid(ClientRequest cr) { - return super.getRequestGuid(cr); + public String getGeoId(ClientRequest cr, String bucketName) { + return super.getGeoId(cr, bucketName); } @Override diff --git a/src/test/java/com/emc/object/s3/S3JerseyClientTest.java b/src/test/java/com/emc/object/s3/S3JerseyClientTest.java index 8a30e93f..3fb18876 100644 --- a/src/test/java/com/emc/object/s3/S3JerseyClientTest.java +++ b/src/test/java/com/emc/object/s3/S3JerseyClientTest.java @@ -89,8 +89,6 @@ public void testMultipleVdcs() throws Exception { S3JerseyClient tempClient = new S3JerseyClient(config); - Thread.sleep(500); // wait for polling daemon to finish initial poll - Assert.assertTrue(vdc1.getHosts().size() > 1); Assert.assertTrue(vdc2.getHosts().size() > 1); Assert.assertEquals(vdc1.getHosts().size() + vdc2.getHosts().size(),