[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201523938 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); --- End diff -- is this relevant anymore since magic number 64 is gone now ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201525176 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +assertNotNull(proxyUGI1.getUGI()); +} + +@Test +public void releaseWithoutForceClean() throws Exception { +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); + +cache.release(proxyUGI1, false); +// UGI wasn't cleaned up, so we can still get it +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(session); +assertEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void releaseWithForceClean()
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201523243 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); --- End diff -- assertSame for ref comparison ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201519410 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/servlet/SecurityServletFilter.java --- @@ -89,32 +106,49 @@ public Boolean run() throws IOException, ServletException { }; // create proxy user UGI from the UGI of the logged in user and execute the servlet chain as that user -UserGroupInformation proxyUGI = null; +UGICacheEntry timedProxyUGI = cache.getTimedProxyUGI(session); --- End diff -- name it proxyUGIEntry ? since actual UGI is a member of that object ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201517606 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICacheEntry.java --- @@ -0,0 +1,94 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICacheEntry implements Delayed { + +private volatile long startTime; +private UserGroupInformation proxyUGI; +private SessionId session; +private boolean cleaned = false; +private AtomicInteger inProgress = new AtomicInteger(); +private static long UGI_CACHE_EXPIRY = 15 * 60 * 1000L; // 15 Minutes --- End diff -- we need to parameterize this ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201523091 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); --- End diff -- do we want to assert ref count and expiration time set as a result of such get ? Do we want to see if the principal name under proxy ugi matches the user passed in ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201512843 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/SessionId.java --- @@ -0,0 +1,60 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +public class SessionId { --- End diff -- please javadoc class and all methods ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201524673 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +assertNotNull(proxyUGI1.getUGI()); +} + +@Test +public void releaseWithoutForceClean() throws Exception { +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); + +cache.release(proxyUGI1, false); +// UGI wasn't cleaned up, so we can still get it +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(session); +assertEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void releaseWithForceClean()
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201520779 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/servlet/SecurityServletFilter.java --- @@ -89,32 +106,49 @@ public Boolean run() throws IOException, ServletException { }; // create proxy user UGI from the UGI of the logged in user and execute the servlet chain as that user -UserGroupInformation proxyUGI = null; +UGICacheEntry timedProxyUGI = cache.getTimedProxyUGI(session); try { -LOG.debug("Creating proxy user = " + user); -proxyUGI = UserGroupInformation.createProxyUser(user, UserGroupInformation.getLoginUser()); -proxyUGI.doAs(action); +timedProxyUGI.getUGI().doAs(action); } catch (UndeclaredThrowableException ute) { // unwrap the real exception thrown by the action throw new ServletException(ute.getCause()); } catch (InterruptedException ie) { throw new ServletException(ie); -} finally { -try { -if (proxyUGI != null) { -LOG.debug("Closing FileSystem for proxy user = " + proxyUGI.getUserName()); -FileSystem.closeAllForUGI(proxyUGI); -} -} catch (Throwable t) { -LOG.warn("Error closing FileSystem for proxy user = " + proxyUGI.getUserName()); -} +} +finally { +// Optimization to cleanup the cache if it is the last fragment +boolean forceClean = (fragmentIndex != null && fragmentCount.equals(fragmentIndex)); +cache.release(timedProxyUGI, forceClean); } } else { // no user impersonation is configured chain.doFilter(request, response); } } + +private Integer getHeaderValueInt(ServletRequest request, String headerKey, boolean required) +throws IllegalArgumentException { +String value = getHeaderValue(request, headerKey, required); +return value != null ? Integer.valueOf(value) : null; --- End diff -- this will throw NumberFormatException ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201524234 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +assertNotNull(proxyUGI1.getUGI()); +} + +@Test +public void releaseWithoutForceClean() throws Exception { +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); + +cache.release(proxyUGI1, false); +// UGI wasn't cleaned up, so we can still get it +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(session); +assertEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); --- End diff -- check refcount still one and new expiration
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201515004 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private DelayQueue[] delayQueues = (DelayQueue[])new DelayQueue[64]; +private final UGIProvider ugiProvider; --- End diff -- again, only 1 final, if you bother with final members, then declare others as well, as they will not be changing ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201513628 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/SessionId.java --- @@ -0,0 +1,60 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +public class SessionId { + +private final String user; --- End diff -- why only 1 private field ? There are no setter methods for any of the other members either. ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201517214 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private DelayQueue[] delayQueues = (DelayQueue[])new DelayQueue[64]; +private final UGIProvider ugiProvider; + +public UGICache(UGIProvider provider) { +this.ugiProvider = provider; +for (int i = 0; i < delayQueues.length; i++) { +delayQueues[i] = new DelayQueue<>(); +} +} + +public UGICache() { +this(new UGIProvider()); +} + +// Create new proxy UGI if not found in cache and increment reference count +public UGICacheEntry getTimedProxyUGI(SessionId session) +throws IOException { + +Integer segmentId = session.getSegmentId(); +String user = session.getUser(); +synchronized (delayQueues[segmentId]) { +// Use the opportunity to cleanup any expired entries +cleanup(segmentId); +UGICacheEntry timedProxyUGI = cache.get(session); +if (timedProxyUGI == null) { +LOG.info(session.toString() + " Creating proxy user = " + user); +UserGroupInformation proxyUGI = ugiProvider.createProxyUGI(user); +timedProxyUGI = new UGICacheEntry(proxyUGI, session); +delayQueues[segmentId].offer(timedProxyUGI); +cache.put(session, timedProxyUGI); +} +timedProxyUGI.incrementCounter(); +return timedProxyUGI; +} +} + +// Poll segment expiration queue for all expired entries +// and clean them if possible +private void cleanup(Integer segmentId) { + +UGICacheEntry ugi = null; +while ((ugi = delayQueues[segmentId].poll()) != null) { +// Place it back in the queue if still in use and was not closed +if (!closeUGI(ugi)) { +delayQueues[segmentId].offer(ugi); +} +LOG.debug("Delay Queue Size for segment " + --- End diff -- surround with isDebugEnabled ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201517046 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private DelayQueue[] delayQueues = (DelayQueue[])new DelayQueue[64]; +private final UGIProvider ugiProvider; + +public UGICache(UGIProvider provider) { +this.ugiProvider = provider; +for (int i = 0; i < delayQueues.length; i++) { +delayQueues[i] = new DelayQueue<>(); +} +} + +public UGICache() { +this(new UGIProvider()); +} + +// Create new proxy UGI if not found in cache and increment reference count +public UGICacheEntry getTimedProxyUGI(SessionId session) +throws IOException { + +Integer segmentId = session.getSegmentId(); +String user = session.getUser(); +synchronized (delayQueues[segmentId]) { +// Use the opportunity to cleanup any expired entries +cleanup(segmentId); +UGICacheEntry timedProxyUGI = cache.get(session); +if (timedProxyUGI == null) { +LOG.info(session.toString() + " Creating proxy user = " + user); +UserGroupInformation proxyUGI = ugiProvider.createProxyUGI(user); +timedProxyUGI = new UGICacheEntry(proxyUGI, session); +delayQueues[segmentId].offer(timedProxyUGI); +cache.put(session, timedProxyUGI); +} +timedProxyUGI.incrementCounter(); +return timedProxyUGI; +} +} + +// Poll segment expiration queue for all expired entries +// and clean them if possible +private void cleanup(Integer segmentId) { --- End diff -- proper javadoc, please ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201518811 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/servlet/SecurityServletFilter.java --- @@ -42,8 +47,13 @@ private static final Log LOG = LogFactory.getLog(SecurityServletFilter.class); private static final String USER_HEADER = "X-GP-USER"; -private static final String MISSING_HEADER_ERROR = String.format("Header %s is missing in the request", USER_HEADER); -private static final String EMPTY_HEADER_ERROR = String.format("Header %s is empty in the request", USER_HEADER); +private static final String SEGMENT_ID_HEADER = "X-GP-SEGMENT-ID"; +private static final String TRANSACTION_ID_HEADER = "X-GP-XID"; +private static final String FRAGMENT_INDEX_HEADER = "X-GP-FRAGMENT-INDEX"; +private static final String FRAGMENT_COUNT_HEADER = "X-GP-FRAGMENT-COUNT"; +private static final String MISSING_HEADER_ERROR = "Header %s is missing in the request"; +private static final String EMPTY_HEADER_ERROR = "Header %s is empty in the request"; +private static UGICache cache = new UGICache(); --- End diff -- this doesn't have to be static, create a single instance in the init() method ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201525708 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +assertNotNull(proxyUGI1.getUGI()); +} + +@Test +public void releaseWithoutForceClean() throws Exception { +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); + +cache.release(proxyUGI1, false); +// UGI wasn't cleaned up, so we can still get it +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(session); +assertEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void releaseWithForceClean()
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201521673 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,154 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private final Map> queueMap = new HashMap<>(); +private final UGIProvider ugiProvider; + +public UGICache(UGIProvider provider) { +this.ugiProvider = provider; +} + +public UGICache() { +this(new UGIProvider()); +} + +private DelayQueue getDelayQueue(Integer segmentId) { +DelayQueue queue = queueMap.get(segmentId); +if (queue == null) { +synchronized (queueMap) { +queue = queueMap.get(segmentId); +if (queue == null) { +queue = new DelayQueue<>(); +queueMap.put(segmentId, queue); +} +} +} +return queue; +} + +// Create new proxy UGI if not found in cache and increment reference count +public UGICacheEntry getTimedProxyUGI(SessionId session) +throws IOException { + +Integer segmentId = session.getSegmentId(); +String user = session.getUser(); +DelayQueue delayQueue = getDelayQueue(segmentId); +synchronized (delayQueue) { +// Use the opportunity to cleanup any expired entries +cleanup(segmentId); +UGICacheEntry timedProxyUGI = cache.get(session); +if (timedProxyUGI == null) { +LOG.info(session.toString() + " Creating proxy user = " + user); +timedProxyUGI = new UGICacheEntry(ugiProvider.createProxyUGI(user), session); +delayQueue.offer(timedProxyUGI); +cache.put(session, timedProxyUGI); +} +timedProxyUGI.incrementCounter(); +return timedProxyUGI; +} +} + +// Poll segment expiration queue for all expired entries +// and clean them if possible +private void cleanup(Integer segmentId) { + +UGICacheEntry ugi = null; +DelayQueue delayQueue = getDelayQueue(segmentId); +while ((ugi = delayQueue.poll()) != null) { +// Place it back in the queue if still in use and was not closed +if (!closeUGI(ugi)) { +delayQueue.offer(ugi); +} +LOG.debug("Delay Queue Size for segment " + +segmentId + " = " + delayQueue.size()); --- End diff -- wrap with isDebugEnabled() ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201516439 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private DelayQueue[] delayQueues = (DelayQueue[])new DelayQueue[64]; +private final UGIProvider ugiProvider; + +public UGICache(UGIProvider provider) { +this.ugiProvider = provider; +for (int i = 0; i < delayQueues.length; i++) { +delayQueues[i] = new DelayQueue<>(); +} +} + +public UGICache() { +this(new UGIProvider()); +} + +// Create new proxy UGI if not found in cache and increment reference count +public UGICacheEntry getTimedProxyUGI(SessionId session) --- End diff -- since we return UGICacheEntry and method is called getTimedProxyUGI, it looks inconsistent ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201523390 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); --- End diff -- assert ref count == 2 ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201519133 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/servlet/SecurityServletFilter.java --- @@ -64,21 +75,28 @@ public void init(FilterConfig filterConfig) throws ServletException { * @param chain filter chain */ @Override -public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { +public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) +throws IOException, ServletException { if (SecureLogin.isUserImpersonationEnabled()) { // retrieve user header and make sure header is present and is not empty -final String user = ((HttpServletRequest) request).getHeader(USER_HEADER); -if (user == null) { -throw new IllegalArgumentException(MISSING_HEADER_ERROR); -} else if (user.trim().isEmpty()) { -throw new IllegalArgumentException(EMPTY_HEADER_ERROR); +final String user = getHeaderValue(request, USER_HEADER); +String transactionId = getHeaderValue(request, TRANSACTION_ID_HEADER); --- End diff -- why not mandate transaction id and segment id to be not null ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201522755 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { --- End diff -- if you use @RunWith(MockitoJUnitRunner.class) then you can use @Mock annotations, and do not have to verify if you trained the mock with specific values, not any . We discussed it with Scala, which didn't have that support. ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201519675 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/servlet/SecurityServletFilter.java --- @@ -89,32 +106,49 @@ public Boolean run() throws IOException, ServletException { }; // create proxy user UGI from the UGI of the logged in user and execute the servlet chain as that user -UserGroupInformation proxyUGI = null; +UGICacheEntry timedProxyUGI = cache.getTimedProxyUGI(session); try { -LOG.debug("Creating proxy user = " + user); -proxyUGI = UserGroupInformation.createProxyUser(user, UserGroupInformation.getLoginUser()); -proxyUGI.doAs(action); +timedProxyUGI.getUGI().doAs(action); } catch (UndeclaredThrowableException ute) { // unwrap the real exception thrown by the action throw new ServletException(ute.getCause()); } catch (InterruptedException ie) { throw new ServletException(ie); -} finally { -try { -if (proxyUGI != null) { -LOG.debug("Closing FileSystem for proxy user = " + proxyUGI.getUserName()); -FileSystem.closeAllForUGI(proxyUGI); -} -} catch (Throwable t) { -LOG.warn("Error closing FileSystem for proxy user = " + proxyUGI.getUserName()); -} +} +finally { +// Optimization to cleanup the cache if it is the last fragment +boolean forceClean = (fragmentIndex != null && fragmentCount.equals(fragmentIndex)); +cache.release(timedProxyUGI, forceClean); --- End diff -- if release throws exception, we do not want to propagate it to user, so restore catch (Throwable t) block ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201523834 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? --- End diff -- user existence is not required for proxy users, remove the method ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201513956 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/SessionId.java --- @@ -0,0 +1,60 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +public class SessionId { + +private final String user; +private Integer segmentId; +private String sessionId; + +public SessionId(Integer segmentId, String transactionId, String gpdbUser) { +this.segmentId = segmentId; +this.user = gpdbUser; +this.sessionId = segmentId + ":" + transactionId + ":" + gpdbUser; --- End diff -- I mentally scope in the other order: user > transaction > segment, so maybe reverse the order of components so it is easier to analyze when debugging / logging ? ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201516265 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { --- End diff -- javadocs please ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201524862 --- Diff: pxf/pxf-service/src/test/java/org/apache/hawq/pxf/service/UGICacheTest.java --- @@ -0,0 +1,197 @@ +package org.apache.hawq.pxf.service; + +import org.apache.hadoop.security.UserGroupInformation; +import org.junit.Before; +import org.junit.Test; +import org.mockito.stubbing.Answer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.powermock.api.mockito.PowerMockito.when; + +public class UGICacheTest { +private UGIProvider provider = null; +private SessionId session = null; +private UGICache cache = null; + +@Before +public void setUp() throws Exception { +provider = mock(UGIProvider.class); + + when(provider.createProxyUGI(any(String.class))).thenAnswer((Answer) invocation -> mock(UserGroupInformation.class)); + +session = new SessionId(0, "txn-id", "the-user"); + +cache = new UGICache(provider); +} + +@Test +public void getUGIFromEmptyCache() throws Exception { +UGICacheEntry entry = cache.getTimedProxyUGI(session); +assertNotNull(entry.getUGI()); +verify(provider).createProxyUGI("the-user"); +} + +@Test +public void getSameUGITwiceUsesCache() throws Exception { +UGICacheEntry entry1 = cache.getTimedProxyUGI(session); +UGICacheEntry entry2 = cache.getTimedProxyUGI(session); +assertEquals(entry1, entry2); +assertNotNull(entry1.getUGI()); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void getTwoUGIsWithDifferentSessionsForSameUser() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id-2", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(2)).createProxyUGI("the-user"); +// TODO: this seems weird. We're creating two UGIs with the same params, +// even though we have two different sessions. Why? +} + +@Test +public void getTwoUGIsWithDifferentUsers() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(otherSession); +assertNotEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getTwoUGIsWithDifferentUsersCachesBoth() throws Exception { +SessionId otherSession = new SessionId(0, "txn-id", "different-user"); +UGICacheEntry proxyUGI1a = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI1b = cache.getTimedProxyUGI(session); +UGICacheEntry proxyUGI2a = cache.getTimedProxyUGI(otherSession); +UGICacheEntry proxyUGI2b = cache.getTimedProxyUGI(otherSession); +assertEquals(proxyUGI1a, proxyUGI1b); +assertEquals(proxyUGI2a, proxyUGI2b); +assertNotEquals(proxyUGI1a, proxyUGI2a); +verify(provider, times(1)).createProxyUGI("the-user"); +verify(provider, times(1)).createProxyUGI("different-user"); +} + +@Test +public void getUGIWhenRequestedUserDoesNotExist() throws Exception { +// what does UserGroupInformation.createProxyUser() do in this scenario? +// how about getLoginUser()? +} + +@Test +public void anySegmentIdIsValid() throws Exception { +session = new SessionId(65, "txn-id", "the-user"); +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); +assertNotNull(proxyUGI1.getUGI()); +} + +@Test +public void releaseWithoutForceClean() throws Exception { +UGICacheEntry proxyUGI1 = cache.getTimedProxyUGI(session); + +cache.release(proxyUGI1, false); +// UGI wasn't cleaned up, so we can still get it +UGICacheEntry proxyUGI2 = cache.getTimedProxyUGI(session); +assertEquals(proxyUGI1, proxyUGI2); +verify(provider, times(1)).createProxyUGI("the-user"); +} + +@Test +public void releaseWithForceClean()
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201513391 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/SessionId.java --- @@ -0,0 +1,60 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +public class SessionId { + +private final String user; +private Integer segmentId; +private String sessionId; + +public SessionId(Integer segmentId, String transactionId, String gpdbUser) { +this.segmentId = segmentId; +this.user = gpdbUser; +this.sessionId = segmentId + ":" + transactionId + ":" + gpdbUser; +} + +public Integer getSegmentId() { +return segmentId; +} + +@Override +public int hashCode() { +return sessionId.hashCode(); +} + +@Override +public boolean equals(Object other) { +if (!(other instanceof SessionId)) { +return false; +} +SessionId that = (SessionId) other; +return this.sessionId.equals(that.sessionId); --- End diff -- I usually follow the pattern and utility methods from: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user denalex commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201515880 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/UGICache.java --- @@ -0,0 +1,143 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.DelayQueue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.security.UserGroupInformation; + +public class UGICache { + +private static final Log LOG = LogFactory.getLog(UGICache.class); +private Map cache = new ConcurrentHashMap<>(); +@SuppressWarnings("unchecked") +// There is a separate DelayQueue for each segment (also being used for locking) +private DelayQueue[] delayQueues = (DelayQueue[])new DelayQueue[64]; --- End diff -- can we use List backed by ArrayList -- similar performance without hacking the lack of generics support for arrays ---
[GitHub] incubator-hawq pull request #1379: HAWQ-1622. Cache PXF proxy UGI so that cl...
Github user lavjain commented on a diff in the pull request: https://github.com/apache/incubator-hawq/pull/1379#discussion_r201510484 --- Diff: pxf/pxf-service/src/main/java/org/apache/hawq/pxf/service/TimedProxyUGI.java --- @@ -0,0 +1,93 @@ +package org.apache.hawq.pxf.service; + +/* + * 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. + */ + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +import org.apache.hadoop.security.UserGroupInformation; + +public class TimedProxyUGI implements Delayed { + +private volatile long startTime; +private UserGroupInformation proxyUGI; +private SegmentTransactionId session; +private boolean cleaned = false; +AtomicInteger inProgress = new AtomicInteger(); + +public TimedProxyUGI(UserGroupInformation proxyUGI, SegmentTransactionId session) { +this.startTime = System.currentTimeMillis(); +this.proxyUGI = proxyUGI; +this.session = session; +} + +public UserGroupInformation getProxyUGI() { +return proxyUGI; +} + +public SegmentTransactionId getSession() { +return session; +} + +public boolean isCleaned() { +return cleaned; +} + +public void setCleaned() { +cleaned = true; +} + +public int getCounter() { +return inProgress.get(); +} + +public void incrementCounter() { +inProgress.incrementAndGet(); +} + +public void decrementCounter() { +inProgress.decrementAndGet(); +} + +public void resetTime() { +startTime = System.currentTimeMillis(); +} + +public void setExpired() { +startTime = -1L; +} + +@Override +public long getDelay(TimeUnit unit) { +return unit.convert(getDelayMillis(), TimeUnit.MILLISECONDS); +} + +@Override +public int compareTo(Delayed other) { +TimedProxyUGI that = (TimedProxyUGI) other; +return Long.compare(this.getDelayMillis(), that.getDelayMillis()); +} + +public long getDelayMillis() { --- End diff -- `Delayed` just expects you to implement `compareTo(Delayed other)` ---
[jira] [Commented] (HAWQ-1638) Issues with website
[ https://issues.apache.org/jira/browse/HAWQ-1638?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16538359#comment-16538359 ] ASF GitHub Bot commented on HAWQ-1638: -- Github user radarwave commented on the issue: https://github.com/apache/incubator-hawq-site/pull/17 Add @dyozie > Issues with website > --- > > Key: HAWQ-1638 > URL: https://issues.apache.org/jira/browse/HAWQ-1638 > Project: Apache HAWQ > Issue Type: Bug >Reporter: Sebb >Assignee: Radar Lei >Priority: Major > > The HAWQ page looks nice, however there are a few problems with it. > The phrase > "Plus, HAWQ® works Apache MADlib) machine learning libraries" > does not read well. Something missing? > The first/main references to ASF products such as Hadoop, YARN etc must use > the full name, i.e. Apache Hadoop etc. > The download section does not have any link to the KEYS file, nor any > instructions on how to use the KEYS+sig or hashes to validate downloads. > The download section still includes references to MD5 hashes. > These are deprecated and can be removed for older releases that have other > hashes -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[GitHub] incubator-hawq-site issue #17: HAWQ-1638. Add how to verify downloaded files...
Github user radarwave commented on the issue: https://github.com/apache/incubator-hawq-site/pull/17 Add @dyozie ---
[jira] [Commented] (HAWQ-1638) Issues with website
[ https://issues.apache.org/jira/browse/HAWQ-1638?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16538356#comment-16538356 ] ASF GitHub Bot commented on HAWQ-1638: -- Github user radarwave commented on the issue: https://github.com/apache/incubator-hawq-site/pull/17 @changleicn @edespino @jiny2 Please help to review, thanks. > Issues with website > --- > > Key: HAWQ-1638 > URL: https://issues.apache.org/jira/browse/HAWQ-1638 > Project: Apache HAWQ > Issue Type: Bug >Reporter: Sebb >Assignee: Radar Lei >Priority: Major > > The HAWQ page looks nice, however there are a few problems with it. > The phrase > "Plus, HAWQ® works Apache MADlib) machine learning libraries" > does not read well. Something missing? > The first/main references to ASF products such as Hadoop, YARN etc must use > the full name, i.e. Apache Hadoop etc. > The download section does not have any link to the KEYS file, nor any > instructions on how to use the KEYS+sig or hashes to validate downloads. > The download section still includes references to MD5 hashes. > These are deprecated and can be removed for older releases that have other > hashes -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (HAWQ-1638) Issues with website
[ https://issues.apache.org/jira/browse/HAWQ-1638?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16538353#comment-16538353 ] ASF GitHub Bot commented on HAWQ-1638: -- GitHub user radarwave opened a pull request: https://github.com/apache/incubator-hawq-site/pull/17 HAWQ-1638. Add how to verify downloaded files section, removed md5 keys. Added a section about how to verify downloaded files. Removed MD5 references. You can merge this pull request into a Git repository by running: $ git pull https://github.com/radarwave/incubator-hawq-site HAWQ-1638 Alternatively you can review and apply these changes as the patch at: https://github.com/apache/incubator-hawq-site/pull/17.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #17 commit fff3da1168b91ceec758dbfe6b1e0f8e6ae6fb4b Author: rlei Date: 2018-07-10T10:05:01Z HAWQ-1638. Add how to verify downloaded files section, removed md5 keys. > Issues with website > --- > > Key: HAWQ-1638 > URL: https://issues.apache.org/jira/browse/HAWQ-1638 > Project: Apache HAWQ > Issue Type: Bug >Reporter: Sebb >Assignee: Radar Lei >Priority: Major > > The HAWQ page looks nice, however there are a few problems with it. > The phrase > "Plus, HAWQ® works Apache MADlib) machine learning libraries" > does not read well. Something missing? > The first/main references to ASF products such as Hadoop, YARN etc must use > the full name, i.e. Apache Hadoop etc. > The download section does not have any link to the KEYS file, nor any > instructions on how to use the KEYS+sig or hashes to validate downloads. > The download section still includes references to MD5 hashes. > These are deprecated and can be removed for older releases that have other > hashes -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[GitHub] incubator-hawq-site pull request #17: HAWQ-1638. Add how to verify downloade...
GitHub user radarwave opened a pull request: https://github.com/apache/incubator-hawq-site/pull/17 HAWQ-1638. Add how to verify downloaded files section, removed md5 keys. Added a section about how to verify downloaded files. Removed MD5 references. You can merge this pull request into a Git repository by running: $ git pull https://github.com/radarwave/incubator-hawq-site HAWQ-1638 Alternatively you can review and apply these changes as the patch at: https://github.com/apache/incubator-hawq-site/pull/17.patch To close this pull request, make a commit to your master/trunk branch with (at least) the following in the commit message: This closes #17 commit fff3da1168b91ceec758dbfe6b1e0f8e6ae6fb4b Author: rlei Date: 2018-07-10T10:05:01Z HAWQ-1638. Add how to verify downloaded files section, removed md5 keys. ---