PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/tools/src/main/java/org/apache/oozie/tools/ECPolicyDisabler.java

https://github.com/apache/oozie
Java | 174 lines | 130 code | 20 blank | 24 comment | 21 complexity | 0729892052248d461baccd236ee72d76 MD5 | raw file
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.apache.oozie.tools;
  19. import java.lang.reflect.InvocationTargetException;
  20. import java.lang.reflect.Method;
  21. import org.apache.hadoop.fs.FileSystem;
  22. import org.apache.hadoop.fs.Path;
  23. import org.apache.hadoop.hdfs.DistributedFileSystem;
  24. import org.apache.hadoop.ipc.RemoteException;
  25. import org.apache.hadoop.ipc.protobuf.RpcHeaderProtos.RpcResponseHeaderProto.RpcErrorCodeProto;
  26. import org.apache.commons.lang3.tuple.Pair;
  27. /**
  28. * Utility class which can disable Erasure Coding for a given path.
  29. *
  30. * Note that Erasure Coding was introduced in Hadoop 3, so in order for this class
  31. * to be compilable, reflection is used. Later, when we drop support for Hadoop 2.x,
  32. * this can be rewritten.
  33. */
  34. public final class ECPolicyDisabler {
  35. private static final String GETREPLICATIONPOLICY_METHOD = "getReplicationPolicy";
  36. private static final String ERASURECODING_POLICIES_CLASS = "org.apache.hadoop.hdfs.protocol.SystemErasureCodingPolicies";
  37. private static final String GETNAME_METHOD = "getName";
  38. private static final String SETERASURECODINGPOLICY_METHOD = "setErasureCodingPolicy";
  39. private static final String GETERASURECODINGPOLICY_METHOD = "getErasureCodingPolicy";
  40. enum Result {
  41. DONE, NO_SUCH_METHOD, ALREADY_SET, NOT_SUPPORTED;
  42. }
  43. public static void tryDisableECPolicyForPath(FileSystem fs, Path path) {
  44. switch (check(fs, path)) {
  45. case DONE:
  46. System.out.println("Done");
  47. break;
  48. case ALREADY_SET:
  49. System.out.println("Current policy is already replication");
  50. break;
  51. case NOT_SUPPORTED:
  52. System.out.println("Found Hadoop that does not support Erasure Coding. Not taking any action.");
  53. break;
  54. case NO_SUCH_METHOD:
  55. System.out.println("HDFS Namenode doesn't support Erasure Coding.");
  56. break;
  57. }
  58. }
  59. static Result check(FileSystem fs, Path path) {
  60. if (fs instanceof DistributedFileSystem && supportsErasureCoding()) {
  61. System.out.println("Found Hadoop that supports Erasure Coding. Trying to disable Erasure Coding for path: "+ path);
  62. DistributedFileSystem dfs = (DistributedFileSystem) fs;
  63. final Object replicationPolicy = getReplicationPolicy();
  64. Method getErasureCodingPolicyMethod = getMethod(dfs, GETERASURECODINGPOLICY_METHOD);
  65. final Pair<Object,Result> currentECPolicy = safeInvokeMethod(getErasureCodingPolicyMethod, dfs, path);
  66. if (currentECPolicy.getRight() != null) {
  67. return currentECPolicy.getRight();
  68. }
  69. if (currentECPolicy.getLeft() != replicationPolicy) {
  70. Method setECPolicyMethod = getMethod(dfs, SETERASURECODINGPOLICY_METHOD);
  71. Method policyGetNameMethod = getMethod(replicationPolicy, GETNAME_METHOD);
  72. Pair<String,Result> pairName = safeInvokeMethod(policyGetNameMethod, replicationPolicy);
  73. if (pairName.getRight() != null) {
  74. return pairName.getRight();
  75. }
  76. Pair<String,Result> result = safeInvokeMethod(setECPolicyMethod, dfs, path, pairName.getLeft());
  77. if (result.getRight() != null) {
  78. return result.getRight();
  79. }
  80. return Result.DONE;
  81. } else {
  82. return Result.ALREADY_SET;
  83. }
  84. } else {
  85. return Result.NOT_SUPPORTED;
  86. }
  87. }
  88. private static <X> Pair<X, Result> safeInvokeMethod(Method method, Object instance, Object... args) {
  89. try {
  90. return Pair.of((X) invokeMethod(method, instance, args), null);
  91. } catch (RuntimeException e) {
  92. RpcErrorCodeProto errorCode = unwrapRemote(e);
  93. if (errorCode == RpcErrorCodeProto.ERROR_NO_SUCH_METHOD) {
  94. return Pair.of(null, Result.NO_SUCH_METHOD);
  95. }
  96. throw e;
  97. }
  98. }
  99. private static RpcErrorCodeProto unwrapRemote(Throwable e) {
  100. if (e instanceof InvocationTargetException) {
  101. return unwrapRemote(e.getCause());
  102. }
  103. if (e instanceof RuntimeException) {
  104. return unwrapRemote(e.getCause());
  105. }
  106. return (e instanceof RemoteException) ? ((RemoteException) e).getErrorCode() : null;
  107. }
  108. private static boolean supportsErasureCoding() {
  109. try {
  110. getECPoliciesClass();
  111. return true;
  112. } catch (ClassNotFoundException e) {
  113. return false;
  114. }
  115. }
  116. private static Object getReplicationPolicy() {
  117. try {
  118. Class<?> c = getECPoliciesClass();
  119. Method m = c.getMethod(GETREPLICATIONPOLICY_METHOD);
  120. return m.invoke(null);
  121. } catch (Exception e) {
  122. System.err.println("Error accessing method with reflection");
  123. throw new RuntimeException(e);
  124. }
  125. }
  126. private static Class<?> getECPoliciesClass() throws ClassNotFoundException {
  127. return Class.forName(ERASURECODING_POLICIES_CLASS);
  128. }
  129. private static Method getMethod(Object object, String methodName) {
  130. Method[] methods = object.getClass().getMethods();
  131. Method method = null;
  132. for (Method m : methods) {
  133. if (m.getName().equals(methodName)) {
  134. method = m;
  135. break;
  136. }
  137. }
  138. if (method == null) {
  139. throw new RuntimeException("Method " + methodName + "() not found");
  140. }
  141. return method;
  142. }
  143. private static Object invokeMethod(Method m, Object instance, Object... args) {
  144. try {
  145. return m.invoke(instance, args);
  146. } catch (RuntimeException e) {
  147. System.err.println("Error invoking method with reflection");
  148. return e;
  149. } catch (Exception e) {
  150. System.err.println("Error invoking method with reflection");
  151. throw new RuntimeException(e);
  152. }
  153. }
  154. }