From 30807fec82e80044cd39fb154208c6fb32d980da Mon Sep 17 00:00:00 2001 From: Eli Collins Date: Sun, 3 Jun 2012 22:14:16 +0000 Subject: [PATCH] HADOOP-8450. Remove src/test/system. Contributed by Eli Collins git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1345794 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 2 + .../test/system/DaemonProtocolAspect.aj | 400 ------ .../src/test/system/c++/runAs/main.c | 59 - .../src/test/system/c++/runAs/runAs.c | 107 -- .../src/test/system/c++/runAs/runAs.h | 53 - .../system/conf/hadoop-policy-system-test.xml | 68 - .../test/system/AbstractDaemonClient.java | 599 --------- .../test/system/AbstractDaemonCluster.java | 537 -------- .../hadoop/test/system/ControlAction.java | 86 -- .../hadoop/test/system/DaemonProtocol.java | 204 --- .../hadoop/test/system/ProcessInfo.java | 77 -- .../hadoop/test/system/ProcessInfoImpl.java | 159 --- .../test/system/ProxyUserDefinitions.java | 90 -- .../system/process/ClusterProcessManager.java | 99 -- .../process/HadoopDaemonRemoteCluster.java | 404 ------ .../MultiUserHadoopDaemonRemoteCluster.java | 96 -- .../test/system/process/RemoteProcess.java | 74 -- .../apache/hadoop/util/RemoteExecution.java | 27 - .../hadoop/util/SSHRemoteExecution.java | 203 --- .../src/test/system/scripts/pushConfig.sh | 48 - .../hadoop/util/TestSSHRemoteExecution.java | 50 - .../hadoop/hdfs/HDFSPolicyProviderAspect.aj | 63 - .../hdfs/server/datanode/DataNodeAspect.aj | 70 - .../hdfs/server/namenode/NameNodeAspect.aj | 77 -- .../src/test/system/conf/system-test-hdfs.xml | 147 --- .../hadoop/hdfs/test/system/DNClient.java | 99 -- .../hadoop/hdfs/test/system/DNProtocol.java | 36 - .../hadoop/hdfs/test/system/HDFSCluster.java | 149 --- .../hdfs/test/system/HDFSDaemonClient.java | 46 - .../hadoop/hdfs/test/system/NNClient.java | 88 -- .../hadoop/hdfs/test/system/NNProtocol.java | 36 - .../org/apache/hadoop/hdfs/TestHL040.java | 86 -- .../mapred/gridmix/GridmixSystemTestCase.java | 231 ---- ...onForMapsAndReducesWithCustomInterval.java | 108 -- ...nForMapsAndReducesWithDefaultInterval.java | 105 -- ...CPUEmulationForMapsWithCustomInterval.java | 105 -- ...PUEmulationForMapsWithDefaultInterval.java | 103 -- ...ssionEmulationEnableForAllTypesOfJobs.java | 96 -- ...mulationForCompressInAndUncompressOut.java | 98 -- ...mulationForUncompressInAndCompressOut.java | 93 -- .../TestDisableGridmixEmulationOfHighRam.java | 65 - .../TestEmulationOfHDFSAndLocalFSDCFiles.java | 95 -- ...EmulationOfHDFSDCFileUsesMultipleJobs.java | 91 -- ...fHDFSDCFilesWithDifferentVisibilities.java | 92 -- ...TestEmulationOfHighRamAndNormalMRJobs.java | 64 - .../TestEmulationOfLocalFSDCFiles.java | 93 -- .../gridmix/TestGridMixDataGeneration.java | 229 ---- .../mapred/gridmix/TestGridMixFilePool.java | 128 -- .../TestGridmixCompressedInputGeneration.java | 173 --- ...CompressionEmulationWithCompressInput.java | 102 -- ...stGridmixEmulationOfHDFSPrivateDCFile.java | 89 -- ...estGridmixEmulationOfHDFSPublicDCFile.java | 91 -- ...estGridmixEmulationOfHighRamJobsCase1.java | 64 - ...estGridmixEmulationOfHighRamJobsCase2.java | 67 - ...estGridmixEmulationOfHighRamJobsCase3.java | 64 - ...EmulationOfMultipleHDFSPrivateDCFiles.java | 91 -- ...xEmulationOfMultipleHDFSPublicDCFiles.java | 92 -- .../gridmix/TestGridmixWith10minTrace.java | 67 - .../gridmix/TestGridmixWith12minTrace.java | 62 - .../gridmix/TestGridmixWith1minTrace.java | 59 - .../TestGridmixWith2minStreamingJobTrace.java | 64 - .../TestGridmixWith3minStreamingJobTrace.java | 68 - .../gridmix/TestGridmixWith3minTrace.java | 62 - .../TestGridmixWith5minStreamingJobTrace.java | 65 - .../gridmix/TestGridmixWith5minTrace.java | 62 - .../gridmix/TestGridmixWith7minTrace.java | 62 - ...EmulForMapsAndReducesWithCustomIntrvl.java | 106 -- ...mulForMapsAndReducesWithDefaultIntrvl.java | 106 -- ...mEmulForMapsWithCustomHeapMemoryRatio.java | 108 -- .../TestMemEmulForMapsWithCustomIntrvl.java | 106 -- .../TestMemEmulForMapsWithDefaultIntrvl.java | 104 -- .../gridmix/test/system/GridMixConfig.java | 285 ---- .../gridmix/test/system/GridMixRunMode.java | 34 - .../gridmix/test/system/GridmixJobStory.java | 86 -- .../test/system/GridmixJobSubmission.java | 82 -- .../test/system/GridmixJobVerification.java | 1166 ----------------- .../gridmix/test/system/UtilsForGridmix.java | 513 -------- .../system/resources/2m_stream_trace.json.gz | Bin 62467 -> 0 bytes .../system/resources/3m_stream_trace.json.gz | Bin 87384 -> 0 bytes .../system/resources/5m_stream_trace.json.gz | Bin 191702 -> 0 bytes .../resources/compression_case1_trace.json.gz | Bin 39157 -> 0 bytes .../resources/compression_case2_trace.json.gz | Bin 39686 -> 0 bytes .../resources/compression_case3_trace.json.gz | Bin 29064 -> 0 bytes .../resources/compression_case4_trace.json.gz | Bin 68202 -> 0 bytes .../system/resources/cpu_emul_case1.json.gz | Bin 33081 -> 0 bytes .../system/resources/cpu_emul_case2.json.gz | Bin 34517 -> 0 bytes .../resources/distcache_case1_trace.json.gz | Bin 29118 -> 0 bytes .../resources/distcache_case2_trace.json.gz | Bin 56683 -> 0 bytes .../resources/distcache_case3_trace.json.gz | Bin 29099 -> 0 bytes .../resources/distcache_case4_trace.json.gz | Bin 56885 -> 0 bytes .../resources/distcache_case5_trace.json.gz | Bin 122860 -> 0 bytes .../resources/distcache_case6_trace.json.gz | Bin 74708 -> 0 bytes .../resources/distcache_case7_trace.json.gz | Bin 29003 -> 0 bytes .../resources/distcache_case8_trace.json.gz | Bin 74723 -> 0 bytes .../resources/distcache_case9_trace.json.gz | Bin 87180 -> 0 bytes .../resources/highram_mr_jobs_case1.json.gz | Bin 24227 -> 0 bytes .../resources/highram_mr_jobs_case2.json.gz | Bin 37048 -> 0 bytes .../resources/highram_mr_jobs_case3.json.gz | Bin 37242 -> 0 bytes .../resources/highram_mr_jobs_case4.json.gz | Bin 25844 -> 0 bytes .../system/resources/mem_emul_case1.json.gz | Bin 33472 -> 0 bytes .../system/resources/mem_emul_case2.json.gz | Bin 29310 -> 0 bytes .../test/system/resources/trace_10m.json.gz | Bin 202359 -> 0 bytes .../test/system/resources/trace_12m.json.gz | Bin 313866 -> 0 bytes .../test/system/resources/trace_1m.json.gz | Bin 37083 -> 0 bytes .../test/system/resources/trace_3m.json.gz | Bin 77975 -> 0 bytes .../test/system/resources/trace_5m.json.gz | Bin 193811 -> 0 bytes .../test/system/resources/trace_7m.json.gz | Bin 246223 -> 0 bytes .../apache/hadoop/mapred/JTProtocolAspect.aj | 82 -- .../apache/hadoop/mapred/JobClientAspect.aj | 35 - .../hadoop/mapred/JobInProgressAspect.aj | 73 -- .../apache/hadoop/mapred/JobTrackerAspect.aj | 221 ---- .../mapred/MapReducePolicyProviderAspect.aj | 58 - .../org/apache/hadoop/mapred/TaskAspect.aj | 114 -- .../apache/hadoop/mapred/TaskTrackerAspect.aj | 155 --- .../apache/hadoop/mapreduce/ClusterAspect.aj | 27 - .../test/system/conf/system-test-mapred.xml | 133 -- .../org/apache/hadoop/mapred/JobInfoImpl.java | 215 --- .../org/apache/hadoop/mapred/TTInfoImpl.java | 72 - .../apache/hadoop/mapred/TTTaskInfoImpl.java | 165 --- .../apache/hadoop/mapred/TaskInfoImpl.java | 159 --- .../test/system/FinishTaskControlAction.java | 70 - .../mapreduce/test/system/JTClient.java | 348 ----- .../mapreduce/test/system/JTProtocol.java | 121 -- .../hadoop/mapreduce/test/system/JobInfo.java | 139 -- .../mapreduce/test/system/MRCluster.java | 173 --- .../mapreduce/test/system/MRDaemonClient.java | 47 - .../mapreduce/test/system/TTClient.java | 109 -- .../hadoop/mapreduce/test/system/TTInfo.java | 42 - .../mapreduce/test/system/TTProtocol.java | 81 -- .../mapreduce/test/system/TTTaskInfo.java | 78 -- .../mapreduce/test/system/TaskInfo.java | 91 -- .../org/apache/hadoop/mapred/TestCluster.java | 325 ----- .../hadoop/mapred/TestControlledJob.java | 122 -- .../TestDistributedCacheModifiedFile.java | 346 ----- .../TestDistributedCachePrivateFile.java | 284 ---- .../TestDistributedCacheUnModifiedFile.java | 305 ----- .../apache/hadoop/mapred/TestFileOwner.java | 225 ---- .../org/apache/hadoop/mapred/TestJobKill.java | 185 --- .../apache/hadoop/mapred/TestPushConfig.java | 163 --- .../hadoop/mapred/TestSortValidate.java | 181 --- .../apache/hadoop/mapred/TestTaskKilling.java | 640 --------- .../apache/hadoop/mapred/TestTaskOwner.java | 130 -- 142 files changed, 2 insertions(+), 15947 deletions(-) delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/aop/org/apache/hadoop/test/system/DaemonProtocolAspect.aj delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/c++/runAs/main.c delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.c delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.h delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/conf/hadoop-policy-system-test.xml delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonClient.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonCluster.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ControlAction.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/DaemonProtocol.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfo.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfoImpl.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProxyUserDefinitions.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/ClusterProcessManager.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/HadoopDaemonRemoteCluster.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/MultiUserHadoopDaemonRemoteCluster.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/RemoteProcess.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/RemoteExecution.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/SSHRemoteExecution.java delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/scripts/pushConfig.sh delete mode 100644 hadoop-common-project/hadoop-common/src/test/system/validation/org/apache/hadoop/util/TestSSHRemoteExecution.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/HDFSPolicyProviderAspect.aj delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/datanode/DataNodeAspect.aj delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/namenode/NameNodeAspect.aj delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/conf/system-test-hdfs.xml delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNClient.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNProtocol.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSCluster.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSDaemonClient.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNClient.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNProtocol.java delete mode 100644 hadoop-hdfs-project/hadoop-hdfs/src/test/system/test/org/apache/hadoop/hdfs/TestHL040.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/GridmixSystemTestCase.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithCustomInterval.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithDefaultInterval.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithCustomInterval.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithDefaultInterval.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationEnableForAllTypesOfJobs.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForCompressInAndUncompressOut.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForUncompressInAndCompressOut.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestDisableGridmixEmulationOfHighRam.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSAndLocalFSDCFiles.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFileUsesMultipleJobs.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFilesWithDifferentVisibilities.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHighRamAndNormalMRJobs.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfLocalFSDCFiles.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixDataGeneration.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixFilePool.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressedInputGeneration.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressionEmulationWithCompressInput.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPrivateDCFile.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPublicDCFile.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase1.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase2.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase3.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPrivateDCFiles.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPublicDCFiles.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith10minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith12minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith1minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith2minStreamingJobTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minStreamingJobTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minStreamingJobTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith7minTrace.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithCustomIntrvl.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithDefaultIntrvl.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomHeapMemoryRatio.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomIntrvl.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithDefaultIntrvl.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixConfig.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixRunMode.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobStory.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobSubmission.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobVerification.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/UtilsForGridmix.java delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/2m_stream_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/3m_stream_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/5m_stream_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case1_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case2_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case3_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case4_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/cpu_emul_case1.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/cpu_emul_case2.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case1_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case2_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case3_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case4_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case5_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case6_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case7_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case8_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/distcache_case9_trace.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/highram_mr_jobs_case1.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/highram_mr_jobs_case2.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/highram_mr_jobs_case3.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/highram_mr_jobs_case4.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/mem_emul_case1.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/mem_emul_case2.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_10m.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_12m.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_1m.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_3m.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_5m.json.gz delete mode 100644 hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/trace_7m.json.gz delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/JTProtocolAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/JobClientAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/JobInProgressAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/JobTrackerAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/MapReducePolicyProviderAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/TaskAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapred/TaskTrackerAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/aop/org/apache/hadoop/mapreduce/ClusterAspect.aj delete mode 100644 hadoop-mapreduce-project/src/test/system/conf/system-test-mapred.xml delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapred/JobInfoImpl.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapred/TTInfoImpl.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapred/TTTaskInfoImpl.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapred/TaskInfoImpl.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/FinishTaskControlAction.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/JTClient.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/JTProtocol.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/JobInfo.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/MRCluster.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/MRDaemonClient.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/TTClient.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/TTInfo.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/TTProtocol.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/TTTaskInfo.java delete mode 100644 hadoop-mapreduce-project/src/test/system/java/org/apache/hadoop/mapreduce/test/system/TaskInfo.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestCluster.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestControlledJob.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestDistributedCacheModifiedFile.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestDistributedCachePrivateFile.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestDistributedCacheUnModifiedFile.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestFileOwner.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestJobKill.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestPushConfig.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestSortValidate.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestTaskKilling.java delete mode 100644 hadoop-mapreduce-project/src/test/system/test/org/apache/hadoop/mapred/TestTaskOwner.java diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 1cb1fda52bd..9dee4cc208e 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -228,6 +228,8 @@ Release 2.0.1-alpha - UNRELEASED HADOOP-8368. Use CMake rather than autotools to build native code (ccccabe via tucu) + HADOOP-8450. Remove src/test/system. (eli) + BUG FIXES HADOOP-8372. NetUtils.normalizeHostName() incorrectly handles hostname diff --git a/hadoop-common-project/hadoop-common/src/test/system/aop/org/apache/hadoop/test/system/DaemonProtocolAspect.aj b/hadoop-common-project/hadoop-common/src/test/system/aop/org/apache/hadoop/test/system/DaemonProtocolAspect.aj deleted file mode 100644 index 76f51294098..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/aop/org/apache/hadoop/test/system/DaemonProtocolAspect.aj +++ /dev/null @@ -1,400 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.File; -import java.io.IOException; -import java.security.PrivilegedExceptionAction; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.Map; -import java.util.Properties; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.io.Writable; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.Shell.ShellCommandExecutor; -import org.apache.hadoop.util.Shell; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.permission.FsAction; -import org.apache.hadoop.fs.permission.FsPermission; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.conf.Configuration; - -/** - * Default DaemonProtocolAspect which is used to provide default implementation - * for all the common daemon methods. If a daemon requires more specialized - * version of method, it is responsibility of the DaemonClient to introduce the - * same in woven classes. - * - */ -public aspect DaemonProtocolAspect { - - private boolean DaemonProtocol.ready; - - @SuppressWarnings("unchecked") - private HashMap> DaemonProtocol.actions = - new HashMap>(); - private static final Log LOG = LogFactory.getLog( - DaemonProtocolAspect.class.getName()); - - private static FsPermission defaultPermission = new FsPermission( - FsAction.READ_WRITE, FsAction.READ_WRITE, FsAction.READ_WRITE); - - /** - * Set if the daemon process is ready or not, concrete daemon protocol should - * implement pointcuts to determine when the daemon is ready and use the - * setter to set the ready state. - * - * @param ready - * true if the Daemon is ready. - */ - public void DaemonProtocol.setReady(boolean ready) { - this.ready = ready; - } - - /** - * Checks if the daemon process is alive or not. - * - * @throws IOException - * if daemon is not alive. - */ - public void DaemonProtocol.ping() throws IOException { - } - - /** - * Checks if the daemon process is ready to accepting RPC connections after it - * finishes initialization.
- * - * @return true if ready to accept connection. - * - * @throws IOException - */ - public boolean DaemonProtocol.isReady() throws IOException { - return ready; - } - - /** - * Returns the process related information regarding the daemon process.
- * - * @return process information. - * @throws IOException - */ - public ProcessInfo DaemonProtocol.getProcessInfo() throws IOException { - int activeThreadCount = Thread.activeCount(); - long currentTime = System.currentTimeMillis(); - long maxmem = Runtime.getRuntime().maxMemory(); - long freemem = Runtime.getRuntime().freeMemory(); - long totalmem = Runtime.getRuntime().totalMemory(); - Map envMap = System.getenv(); - Properties sysProps = System.getProperties(); - Map props = new HashMap(); - for (Map.Entry entry : sysProps.entrySet()) { - props.put((String) entry.getKey(), (String) entry.getValue()); - } - ProcessInfo info = new ProcessInfoImpl(activeThreadCount, currentTime, - freemem, maxmem, totalmem, envMap, props); - return info; - } - - public void DaemonProtocol.enable(List> faults) throws IOException { - } - - public void DaemonProtocol.disableAll() throws IOException { - } - - public abstract Configuration DaemonProtocol.getDaemonConf() - throws IOException; - - public FileStatus DaemonProtocol.getFileStatus(String path, boolean local) - throws IOException { - Path p = new Path(path); - FileSystem fs = getFS(p, local); - p.makeQualified(fs); - FileStatus fileStatus = fs.getFileStatus(p); - return cloneFileStatus(fileStatus); - } - - /** - * Create a file with given permissions in a file system. - * @param path - source path where the file has to create. - * @param fileName - file name. - * @param permission - file permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void DaemonProtocol.createFile(String path, String fileName, - FsPermission permission, boolean local) throws IOException { - Path p = new Path(path); - FileSystem fs = getFS(p, local); - Path filePath = new Path(path, fileName); - fs.create(filePath); - if (permission == null) { - fs.setPermission(filePath, defaultPermission); - } else { - fs.setPermission(filePath, permission); - } - fs.close(); - } - - /** - * Create a folder with given permissions in a file system. - * @param path - source path where the file has to be creating. - * @param folderName - folder name. - * @param permission - folder permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void DaemonProtocol.createFolder(String path, String folderName, - FsPermission permission, boolean local) throws IOException { - Path p = new Path(path); - FileSystem fs = getFS(p, local); - Path folderPath = new Path(path, folderName); - fs.mkdirs(folderPath); - if (permission == null) { - fs.setPermission(folderPath, defaultPermission); - } else { - fs.setPermission(folderPath, permission); - } - fs.close(); - } - - public FileStatus[] DaemonProtocol.listStatus(String path, boolean local) - throws IOException { - Path p = new Path(path); - FileSystem fs = getFS(p, local); - FileStatus[] status = fs.listStatus(p); - if (status != null) { - FileStatus[] result = new FileStatus[status.length]; - int i = 0; - for (FileStatus fileStatus : status) { - result[i++] = cloneFileStatus(fileStatus); - } - return result; - } - return status; - } - - /** - * FileStatus object may not be serializable. Clone it into raw FileStatus - * object. - */ - private FileStatus DaemonProtocol.cloneFileStatus(FileStatus fileStatus) { - return new FileStatus(fileStatus.getLen(), - fileStatus.isDir(), - fileStatus.getReplication(), - fileStatus.getBlockSize(), - fileStatus.getModificationTime(), - fileStatus.getAccessTime(), - fileStatus.getPermission(), - fileStatus.getOwner(), - fileStatus.getGroup(), - fileStatus.getPath()); - } - - private FileSystem DaemonProtocol.getFS(final Path path, final boolean local) - throws IOException { - FileSystem ret = null; - try { - ret = UserGroupInformation.getLoginUser().doAs ( - new PrivilegedExceptionAction() { - public FileSystem run() throws IOException { - FileSystem fs = null; - if (local) { - fs = FileSystem.getLocal(getDaemonConf()); - } else { - fs = path.getFileSystem(getDaemonConf()); - } - return fs; - } - }); - } catch (InterruptedException ie) { - } - return ret; - } - - @SuppressWarnings("unchecked") - public ControlAction[] DaemonProtocol.getActions(Writable key) - throws IOException { - synchronized (actions) { - List actionList = actions.get(key); - if(actionList == null) { - return new ControlAction[0]; - } else { - return (ControlAction[]) actionList.toArray(new ControlAction[actionList - .size()]); - } - } - } - - - @SuppressWarnings("unchecked") - public void DaemonProtocol.sendAction(ControlAction action) - throws IOException { - synchronized (actions) { - List actionList = actions.get(action.getTarget()); - if(actionList == null) { - actionList = new ArrayList(); - actions.put(action.getTarget(), actionList); - } - actionList.add(action); - } - } - - @SuppressWarnings("unchecked") - public boolean DaemonProtocol.isActionPending(ControlAction action) - throws IOException{ - synchronized (actions) { - List actionList = actions.get(action.getTarget()); - if(actionList == null) { - return false; - } else { - return actionList.contains(action); - } - } - } - - - @SuppressWarnings("unchecked") - public void DaemonProtocol.removeAction(ControlAction action) - throws IOException { - synchronized (actions) { - List actionList = actions.get(action.getTarget()); - if(actionList == null) { - return; - } else { - actionList.remove(action); - } - } - } - - public void DaemonProtocol.clearActions() throws IOException { - synchronized (actions) { - actions.clear(); - } - } - - public String DaemonProtocol.getFilePattern() { - //We use the environment variable HADOOP_LOGFILE to get the - //pattern to use in the search. - String logDir = System.getProperty("hadoop.log.dir"); - String daemonLogPattern = System.getProperty("hadoop.log.file"); - if(daemonLogPattern == null && daemonLogPattern.isEmpty()) { - return "*"; - } - return logDir+File.separator+daemonLogPattern+"*"; - } - - public int DaemonProtocol.getNumberOfMatchesInLogFile(String pattern, - String[] list) throws IOException { - StringBuffer filePattern = new StringBuffer(getFilePattern()); - String[] cmd = null; - if (list != null) { - StringBuffer filterExpPattern = new StringBuffer(); - int index=0; - for (String excludeExp : list) { - if (index++ < list.length -1) { - filterExpPattern.append("grep -v " + excludeExp + " | "); - } else { - filterExpPattern.append("grep -v " + excludeExp + " | wc -l"); - } - } - cmd = new String[] { - "bash", - "-c", - "grep " - + pattern + " " + filePattern + " | " - + filterExpPattern}; - } else { - cmd = new String[] { - "bash", - "-c", - "grep -c " - + pattern + " " + filePattern - + " | awk -F: '{s+=$2} END {print s}'" }; - } - ShellCommandExecutor shexec = new ShellCommandExecutor(cmd); - shexec.execute(); - String output = shexec.getOutput(); - return Integer.parseInt(output.replaceAll("\n", "").trim()); - } - - /** - * This method is used for suspending the process. - * @param pid process id - * @throws IOException if an I/O error occurs. - * @return true if process is suspended otherwise false. - */ - public boolean DaemonProtocol.suspendProcess(String pid) throws IOException { - String suspendCmd = getDaemonConf().get("test.system.hdrc.suspend.cmd", - "kill -SIGSTOP"); - String [] command = {"bash", "-c", suspendCmd + " " + pid}; - ShellCommandExecutor shexec = new ShellCommandExecutor(command); - try { - shexec.execute(); - } catch (Shell.ExitCodeException e) { - LOG.warn("suspended process throws an exitcode " - + "exception for not being suspended the given process id."); - return false; - } - LOG.info("The suspend process command is :" - + shexec.toString() - + " and the output for the command is " - + shexec.getOutput()); - return true; - } - - /** - * This method is used for resuming the process - * @param pid process id of suspended process. - * @throws IOException if an I/O error occurs. - * @return true if suspeneded process is resumed otherwise false. - */ - public boolean DaemonProtocol.resumeProcess(String pid) throws IOException { - String resumeCmd = getDaemonConf().get("test.system.hdrc.resume.cmd", - "kill -SIGCONT"); - String [] command = {"bash", "-c", resumeCmd + " " + pid}; - ShellCommandExecutor shexec = new ShellCommandExecutor(command); - try { - shexec.execute(); - } catch(Shell.ExitCodeException e) { - LOG.warn("Resume process throws an exitcode " - + "exception for not being resumed the given process id."); - return false; - } - LOG.info("The resume process command is :" - + shexec.toString() - + " and the output for the command is " - + shexec.getOutput()); - return true; - } - - private String DaemonProtocol.user = null; - - public String DaemonProtocol.getDaemonUser() { - return user; - } - - public void DaemonProtocol.setUser(String user) { - this.user = user; - } -} - diff --git a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/main.c b/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/main.c deleted file mode 100644 index e31635f9235..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/main.c +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 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. - */ - -#include "runAs.h" - -/** - * The binary would be accepting the command of following format: - * cluster-controller user hostname hadoop-daemon.sh-command - */ -int main(int argc, char **argv) { - int errorcode; - char *user; - char *hostname; - char *command; - struct passwd user_detail; - int i = 1; - /* - * Minimum number of arguments required for the binary to perform. - */ - if (argc < 4) { - fprintf(stderr, "Invalid number of arguments passed to the binary\n"); - return INVALID_ARGUMENT_NUMER; - } - - user = argv[1]; - if (user == NULL) { - fprintf(stderr, "Invalid user name\n"); - return INVALID_USER_NAME; - } - - if (getuserdetail(user, &user_detail) != 0) { - fprintf(stderr, "Invalid user name\n"); - return INVALID_USER_NAME; - } - - if (user_detail.pw_gid == 0 || user_detail.pw_uid == 0) { - fprintf(stderr, "Cannot run tasks as super user\n"); - return SUPER_USER_NOT_ALLOWED_TO_RUN_COMMANDS; - } - - hostname = argv[2]; - command = argv[3]; - return process_controller_command(user, hostname, command); -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.c b/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.c deleted file mode 100644 index 888201dca0f..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.c +++ /dev/null @@ -1,107 +0,0 @@ -/** - * 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. - */ - -#include "runAs.h" - -#include "config.h" - -/* - * Function to get the user details populated given a user name. - */ -int getuserdetail(char *user, struct passwd *user_detail) { - struct passwd *tempPwdPtr; - int size = sysconf(_SC_GETPW_R_SIZE_MAX); - char pwdbuffer[size]; - if ((getpwnam_r(user, user_detail, pwdbuffer, size, &tempPwdPtr)) != 0) { - fprintf(stderr, "Invalid user provided to getpwnam\n"); - return -1; - } - return 0; -} - -/** - * Function to switch the user identity and set the appropriate - * group control as the user specified in the argument. - */ -int switchuser(char *user) { - //populate the user details - struct passwd user_detail; - if ((getuserdetail(user, &user_detail)) != 0) { - return INVALID_USER_NAME; - } - //set the right supplementary groups for the user. - if (initgroups(user_detail.pw_name, user_detail.pw_gid) != 0) { - fprintf(stderr, "Init groups call for the user : %s failed\n", - user_detail.pw_name); - return INITGROUPS_FAILED; - } - errno = 0; - //switch the group. - setgid(user_detail.pw_gid); - if (errno != 0) { - fprintf(stderr, "Setgid for the user : %s failed\n", user_detail.pw_name); - return SETUID_OPER_FAILED; - } - errno = 0; - //swith the user - setuid(user_detail.pw_uid); - if (errno != 0) { - fprintf(stderr, "Setuid for the user : %s failed\n", user_detail.pw_name); - return SETUID_OPER_FAILED; - } - errno = 0; - //set the effective user id. - seteuid(user_detail.pw_uid); - if (errno != 0) { - fprintf(stderr, "Seteuid for the user : %s failed\n", user_detail.pw_name); - return SETUID_OPER_FAILED; - } - return 0; -} - -/* - * Top level method which processes a cluster management - * command. - */ -int process_cluster_command(char * user, char * node , char *command) { - char cmd[4096]; - int len; - int errorcode = 0; - if (strncmp(command, "", strlen(command)) == 0) { - fprintf(stderr, "Invalid command passed\n"); - return INVALID_COMMAND_PASSED; - } - snprintf(cmd, sizeof(cmd), "%s/bin/hadoop-daemon.sh %s", - HADOOP_RUNAS_HOME, command); - errorcode = switchuser(user); - if (errorcode != 0) { - fprintf(stderr, "switch user failed\n"); - return errorcode; - } - execlp(SSH_COMMAND, SSH_COMMAND, node, cmd, NULL); - fprintf(stderr, "Excelp failed dude to : %s\n", strerror(errno)); - return 0; -} - -/* - * Process cluster controller command the API exposed to the - * main in order to execute the cluster commands. - */ -int process_controller_command(char *user, char * node, char *command) { - return process_cluster_command(user, node, command); -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.h b/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.h deleted file mode 100644 index 2282ae8f7bd..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/c++/runAs/runAs.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* -* List of possible error codes. -*/ -enum errorcodes { - INVALID_ARGUMENT_NUMER = 1, - INVALID_USER_NAME, //2 - SUPER_USER_NOT_ALLOWED_TO_RUN_COMMANDS, //3 - INITGROUPS_FAILED, //4 - SETUID_OPER_FAILED, //5 - INVALID_COMMAND_PASSED, //6 -}; - -#define SSH_COMMAND "ssh" - -/* - * Function to get the user details populated given a user name. - */ -int getuserdetails(char *user, struct passwd *user_detail); - - /* - * Process cluster controller command the API exposed to the - * main in order to execute the cluster commands. - */ -int process_controller_command(char *user, char *node, char *command); diff --git a/hadoop-common-project/hadoop-common/src/test/system/conf/hadoop-policy-system-test.xml b/hadoop-common-project/hadoop-common/src/test/system/conf/hadoop-policy-system-test.xml deleted file mode 100644 index b2c3735e285..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/conf/hadoop-policy-system-test.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - security.daemon.protocol.acl - * - ACL for DaemonProtocol, extended by all other - Herriot RPC protocols. - The ACL is a comma-separated list of user and group names. The user and - group list is separated by a blank. For e.g. "alice,bob users,wheel". - A special value of "*" means all users are allowed. - - - - security.nn.protocol.acl - * - ACL for NNProtocol, used by the - Herriot AbstractDaemonCluster's implementations to connect to a remote - NameNode. - The ACL is a comma-separated list of user and group names. The user and - group list is separated by a blank. For e.g. "alice,bob users,wheel". - A special value of "*" means all users are allowed. - - - - security.dn.protocol.acl - * - ACL for DNProtocol, used by the - Herriot AbstractDaemonCluster's implementations to connect to a remote - DataNode. - The ACL is a comma-separated list of user and group names. The user and - group list is separated by a blank. For e.g. "alice,bob users,wheel". - A special value of "*" means all users are allowed. - - - - security.tt.protocol.acl - * - ACL for TTProtocol, used by the - Herriot AbstractDaemonCluster's implementations to connect to a remote - TaskTracker. - The ACL is a comma-separated list of user and group names. The user and - group list is separated by a blank. For e.g. "alice,bob users,wheel". - A special value of "*" means all users are allowed. - - diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonClient.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonClient.java deleted file mode 100644 index 7254aa782fa..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonClient.java +++ /dev/null @@ -1,599 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.IOException; -import java.util.*; - -import org.junit.Assert; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.permission.FsPermission; -import org.apache.hadoop.test.system.process.RemoteProcess; - -import javax.management.*; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; - -/** - * Abstract class which encapsulates the DaemonClient which is used in the - * system tests.
- * - * @param PROXY the proxy implementation of a specific Daemon - */ -public abstract class AbstractDaemonClient { - private Configuration conf; - private Boolean jmxEnabled = null; - private MBeanServerConnection connection; - private int jmxPortNumber = -1; - private RemoteProcess process; - private boolean connected; - - private static final Log LOG = LogFactory.getLog(AbstractDaemonClient.class); - private static final String HADOOP_JMX_DOMAIN = "Hadoop"; - private static final String HADOOP_OPTS_ENV = "HADOOP_OPTS"; - - /** - * Create a Daemon client.
- * - * @param conf client to be used by proxy to connect to Daemon. - * @param process the Daemon process to manage the particular daemon. - * - * @throws IOException on RPC error - */ - public AbstractDaemonClient(Configuration conf, RemoteProcess process) - throws IOException { - this.conf = conf; - this.process = process; - } - - /** - * Gets if the client is connected to the Daemon
- * - * @return true if connected. - */ - public boolean isConnected() { - return connected; - } - - protected void setConnected(boolean connected) { - this.connected = connected; - } - - /** - * Create an RPC proxy to the daemon
- * - * @throws IOException on RPC error - */ - public abstract void connect() throws IOException; - - /** - * Disconnect the underlying RPC proxy to the daemon.
- * @throws IOException in case of communication errors - */ - public abstract void disconnect() throws IOException; - - /** - * Get the proxy to connect to a particular service Daemon.
- * - * @return proxy to connect to a particular service Daemon. - */ - protected abstract PROXY getProxy(); - - /** - * Gets the daemon level configuration.
- * - * @return configuration using which daemon is running - */ - public Configuration getConf() { - return conf; - } - - /** - * Gets the host on which Daemon is currently running.
- * - * @return hostname - */ - public String getHostName() { - return process.getHostName(); - } - - /** - * Gets if the Daemon is ready to accept RPC connections.
- * - * @return true if daemon is ready. - * @throws IOException on RPC error - */ - public boolean isReady() throws IOException { - return getProxy().isReady(); - } - - /** - * Kills the Daemon process
- * @throws IOException on RPC error - */ - public void kill() throws IOException { - process.kill(); - } - - /** - * Checks if the Daemon process is alive or not
- * @throws IOException on RPC error - */ - public void ping() throws IOException { - getProxy().ping(); - } - - /** - * Start up the Daemon process.
- * @throws IOException on RPC error - */ - public void start() throws IOException { - process.start(); - } - - /** - * Get system level view of the Daemon process. - * - * @return returns system level view of the Daemon process. - * - * @throws IOException on RPC error. - */ - public ProcessInfo getProcessInfo() throws IOException { - return getProxy().getProcessInfo(); - } - - /** - * Abstract method to retrieve the name of a daemon specific env. var - * @return name of Hadoop environment variable containing a daemon options - */ - abstract public String getHadoopOptsEnvName (); - - /** - * Checks remote daemon process info to see if certain JMX sys. properties - * are available and reckon if the JMX service is enabled on the remote side - * - * @return boolean code indicating availability of remote JMX - * @throws IOException is throws in case of communication errors - */ - public boolean isJmxEnabled() throws IOException { - return isJmxEnabled(HADOOP_OPTS_ENV) || - isJmxEnabled(getHadoopOptsEnvName()); - } - - /** - * Checks remote daemon process info to see if certain JMX sys. properties - * are available and reckon if the JMX service is enabled on the remote side - * - * @param envivar name of an evironment variable to be searched - * @return boolean code indicating availability of remote JMX - * @throws IOException is throws in case of communication errors - */ - protected boolean isJmxEnabled(String envivar) throws IOException { - if (jmxEnabled != null) return jmxEnabled; - boolean ret = false; - String jmxRemoteString = "-Dcom.sun.management.jmxremote"; - String hadoopOpts = getProcessInfo().getEnv().get(envivar); - LOG.debug("Looking into " + hadoopOpts + " from " + envivar); - List options = Arrays.asList(hadoopOpts.split(" ")); - ret = options.contains(jmxRemoteString); - jmxEnabled = ret; - return ret; - } - - /** - * Checks remote daemon process info to find remote JMX server port number - * By default this method will look into "HADOOP_OPTS" variable only. - * @return number of remote JMX server or -1 if it can't be found - * @throws IOException is throws in case of communication errors - * @throws IllegalArgumentException if non-integer port is set - * in the remote process info - */ - public int getJmxPortNumber() throws IOException, IllegalArgumentException { - int portNo = getJmxPortNumber(HADOOP_OPTS_ENV); - return portNo != -1 ? portNo : getJmxPortNumber(getHadoopOptsEnvName()); - } - - /** - * Checks remote daemon process info to find remote JMX server port number - * - * @param envivar name of the env. var. to look for JMX specific settings - * @return number of remote JMX server or -1 if it can't be found - * @throws IOException is throws in case of communication errors - * @throws IllegalArgumentException if non-integer port is set - * in the remote process info - */ - protected int getJmxPortNumber(final String envivar) throws - IOException, IllegalArgumentException { - if (jmxPortNumber != -1) return jmxPortNumber; - String jmxPortString = "-Dcom.sun.management.jmxremote.port"; - - String hadoopOpts = getProcessInfo().getEnv().get(envivar); - int portNumber = -1; - boolean found = false; - String[] options = hadoopOpts.split(" "); - for (String option : options) { - if (option.startsWith(jmxPortString)) { - found = true; - try { - portNumber = Integer.parseInt(option.split("=")[1]); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("JMX port number isn't integer"); - } - break; - } - } - if (!found) - throw new IllegalArgumentException("Can't detect JMX port number"); - jmxPortNumber = portNumber; - return jmxPortNumber; - } - - /** - * Return a file status object that represents the path. - * @param path - * given path - * @param local - * whether the path is local or not - * @return a FileStatus object - * @throws IOException see specific implementation - */ - public FileStatus getFileStatus(String path, boolean local) throws IOException { - return getProxy().getFileStatus(path, local); - } - - /** - * Create a file with full permissions in a file system. - * @param path - source path where the file has to create. - * @param fileName - file name - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void createFile(String path, String fileName, - boolean local) throws IOException { - getProxy().createFile(path, fileName, null, local); - } - - /** - * Create a file with given permissions in a file system. - * @param path - source path where the file has to create. - * @param fileName - file name. - * @param permission - file permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void createFile(String path, String fileName, - FsPermission permission, boolean local) throws IOException { - getProxy().createFile(path, fileName, permission, local); - } - - /** - * Create a folder with default permissions in a file system. - * @param path - source path where the file has to be creating. - * @param folderName - folder name. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void createFolder(String path, String folderName, - boolean local) throws IOException { - getProxy().createFolder(path, folderName, null, local); - } - - /** - * Create a folder with given permissions in a file system. - * @param path - source path where the file has to be creating. - * @param folderName - folder name. - * @param permission - folder permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void createFolder(String path, String folderName, - FsPermission permission, boolean local) throws IOException { - getProxy().createFolder(path, folderName, permission, local); - } - - /** - * List the statuses of the files/directories in the given path if the path is - * a directory. - * - * @param path - * given path - * @param local - * whether the path is local or not - * @return the statuses of the files/directories in the given patch - * @throws IOException on RPC error. - */ - public FileStatus[] listStatus(String path, boolean local) - throws IOException { - return getProxy().listStatus(path, local); - } - - /** - * List the statuses of the files/directories in the given path if the path is - * a directory recursive/nonrecursively depending on parameters - * - * @param path - * given path - * @param local - * whether the path is local or not - * @param recursive - * whether to recursively get the status - * @return the statuses of the files/directories in the given patch - * @throws IOException is thrown on RPC error. - */ - public FileStatus[] listStatus(String path, boolean local, boolean recursive) - throws IOException { - List status = new ArrayList(); - addStatus(status, path, local, recursive); - return status.toArray(new FileStatus[0]); - } - - private void addStatus(List status, String f, - boolean local, boolean recursive) - throws IOException { - FileStatus[] fs = listStatus(f, local); - if (fs != null) { - for (FileStatus fileStatus : fs) { - if (!f.equals(fileStatus.getPath().toString())) { - status.add(fileStatus); - if (recursive) { - addStatus(status, fileStatus.getPath().toString(), local, recursive); - } - } - } - } - } - - /** - * Gets number of times FATAL log messages where logged in Daemon logs. - *
- * Pattern used for searching is FATAL.
- * @param excludeExpList list of exception to exclude - * @return number of occurrence of fatal message. - * @throws IOException in case of communication errors - */ - public int getNumberOfFatalStatementsInLog(String [] excludeExpList) - throws IOException { - DaemonProtocol proxy = getProxy(); - String pattern = "FATAL"; - return proxy.getNumberOfMatchesInLogFile(pattern, excludeExpList); - } - - /** - * Gets number of times ERROR log messages where logged in Daemon logs. - *
- * Pattern used for searching is ERROR.
- * @param excludeExpList list of exception to exclude - * @return number of occurrence of error message. - * @throws IOException is thrown on RPC error. - */ - public int getNumberOfErrorStatementsInLog(String[] excludeExpList) - throws IOException { - DaemonProtocol proxy = getProxy(); - String pattern = "ERROR"; - return proxy.getNumberOfMatchesInLogFile(pattern, excludeExpList); - } - - /** - * Gets number of times Warning log messages where logged in Daemon logs. - *
- * Pattern used for searching is WARN.
- * @param excludeExpList list of exception to exclude - * @return number of occurrence of warning message. - * @throws IOException thrown on RPC error. - */ - public int getNumberOfWarnStatementsInLog(String[] excludeExpList) - throws IOException { - DaemonProtocol proxy = getProxy(); - String pattern = "WARN"; - return proxy.getNumberOfMatchesInLogFile(pattern, excludeExpList); - } - - /** - * Gets number of time given Exception were present in log file.
- * - * @param e exception class. - * @param excludeExpList list of exceptions to exclude. - * @return number of exceptions in log - * @throws IOException is thrown on RPC error. - */ - public int getNumberOfExceptionsInLog(Exception e, - String[] excludeExpList) throws IOException { - DaemonProtocol proxy = getProxy(); - String pattern = e.getClass().getSimpleName(); - return proxy.getNumberOfMatchesInLogFile(pattern, excludeExpList); - } - - /** - * Number of times ConcurrentModificationException present in log file. - *
- * @param excludeExpList list of exceptions to exclude. - * @return number of times exception in log file. - * @throws IOException is thrown on RPC error. - */ - public int getNumberOfConcurrentModificationExceptionsInLog( - String[] excludeExpList) throws IOException { - return getNumberOfExceptionsInLog(new ConcurrentModificationException(), - excludeExpList); - } - - private int errorCount; - private int fatalCount; - private int concurrentExceptionCount; - - /** - * Populate the initial exception counts to be used to assert once a testcase - * is done there was no exception in the daemon when testcase was run. - * @param excludeExpList list of exceptions to exclude - * @throws IOException is thrown on RPC error. - */ - protected void populateExceptionCount(String [] excludeExpList) - throws IOException { - errorCount = getNumberOfErrorStatementsInLog(excludeExpList); - LOG.info("Number of error messages in logs : " + errorCount); - fatalCount = getNumberOfFatalStatementsInLog(excludeExpList); - LOG.info("Number of fatal statement in logs : " + fatalCount); - concurrentExceptionCount = - getNumberOfConcurrentModificationExceptionsInLog(excludeExpList); - LOG.info("Number of concurrent modification in logs : " - + concurrentExceptionCount); - } - - /** - * Assert if the new exceptions were logged into the log file. - *
- * - * Pre-req for the method is that populateExceptionCount() has - * to be called before calling this method. - * @param excludeExpList list of exceptions to exclude - * @throws IOException is thrown on RPC error. - */ - protected void assertNoExceptionsOccurred(String [] excludeExpList) - throws IOException { - int newerrorCount = getNumberOfErrorStatementsInLog(excludeExpList); - LOG.info("Number of error messages while asserting :" + newerrorCount); - int newfatalCount = getNumberOfFatalStatementsInLog(excludeExpList); - LOG.info("Number of fatal messages while asserting : " + newfatalCount); - int newconcurrentExceptionCount = - getNumberOfConcurrentModificationExceptionsInLog(excludeExpList); - LOG.info("Number of concurrentmodification exception while asserting :" - + newconcurrentExceptionCount); - Assert.assertEquals( - "New Error Messages logged in the log file", errorCount, newerrorCount); - Assert.assertEquals( - "New Fatal messages logged in the log file", fatalCount, newfatalCount); - Assert.assertEquals( - "New ConcurrentModificationException in log file", - concurrentExceptionCount, newconcurrentExceptionCount); - } - - /** - * Builds correct name of JMX object name from given domain, service name, type - * @param domain JMX domain name - * @param serviceName of the service where MBean is registered (NameNode) - * @param typeName of the MXBean class - * @return ObjectName for requested MXBean of null if one wasn't - * found - * @throws java.io.IOException in if object name is malformed - */ - protected ObjectName getJmxBeanName(String domain, String serviceName, - String typeName) throws IOException { - if (domain == null) - domain = HADOOP_JMX_DOMAIN; - - ObjectName jmxBean; - try { - jmxBean = new ObjectName(domain + ":service=" + serviceName + - ",name=" + typeName); - } catch (MalformedObjectNameException e) { - LOG.debug(e.getStackTrace()); - throw new IOException(e); - } - return jmxBean; - } - - /** - * Create connection with the remote JMX server at given host and port - * @param host name of the remote JMX server host - * @param port port number of the remote JXM server host - * @return instance of MBeanServerConnection or null if one - * hasn't been established - * @throws IOException in case of comminication errors - */ - protected MBeanServerConnection establishJmxConnection(String host, int port) - throws IOException { - if (connection != null) return connection; - String urlPattern = null; - try { - urlPattern = "service:jmx:rmi:///jndi/rmi://" + - host + ":" + port + - "/jmxrmi"; - JMXServiceURL url = new JMXServiceURL(urlPattern); - JMXConnector connector = JMXConnectorFactory.connect(url, null); - connection = connector.getMBeanServerConnection(); - } catch (java.net.MalformedURLException badURLExc) { - LOG.debug("bad url: " + urlPattern, badURLExc); - throw new IOException(badURLExc); - } - return connection; - } - - Hashtable jmxObjectNames = - new Hashtable(); - - /** - * Method implements all logic for receiving a bean's attribute. - * If any initializations such as establishing bean server connections, etc. - * are need it will do it. - * @param serviceName name of the service where MBean is registered (NameNode) - * @param type name of the MXBean class - * @param attributeName name of the attribute to be retrieved - * @return Object value of the attribute or null if not found - * @throws IOException is thrown in case of any errors - */ - protected Object getJmxAttribute (String serviceName, - String type, - String attributeName) - throws IOException { - Object retAttribute = null; - String domain = null; - if (isJmxEnabled()) { - try { - MBeanServerConnection conn = - establishJmxConnection(getHostName(), - getJmxPortNumber(HADOOP_OPTS_ENV)); - for (String d : conn.getDomains()) { - if (d != null && d.startsWith(HADOOP_JMX_DOMAIN)) - domain = d; - } - if (!jmxObjectNames.containsKey(type)) - jmxObjectNames.put(type, getJmxBeanName(domain, serviceName, type)); - retAttribute = - conn.getAttribute(jmxObjectNames.get(type), attributeName); - } catch (MBeanException e) { - LOG.debug(e.getStackTrace()); - throw new IOException(e); - } catch (AttributeNotFoundException e) { - LOG.warn(e.getStackTrace()); - throw new IOException(e); - } catch (InstanceNotFoundException e) { - LOG.warn(e.getStackTrace()); - throw new IOException(e); - } catch (ReflectionException e) { - LOG.debug(e.getStackTrace()); - throw new IOException(e); - } - } - return retAttribute; - } - - /** - * This method has to be implemented by appropriate concrete daemon client - * e.g. DNClient, NNClient, etc. - * Concrete implementation has to provide names of the service and bean type - * @param attributeName name of the attribute to be retrieved - * @return Object value of the given attribute - * @throws IOException is thrown in case of communication errors - */ - public abstract Object getDaemonAttribute (String attributeName) - throws IOException; -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonCluster.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonCluster.java deleted file mode 100644 index b1277a0ea3a..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/AbstractDaemonCluster.java +++ /dev/null @@ -1,537 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.IOException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileInputStream; -import java.io.DataInputStream; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Iterator; -import java.util.Enumeration; -import java.util.Arrays; -import java.util.Hashtable; -import java.net.URI; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.test.system.process.ClusterProcessManager; -import org.apache.hadoop.test.system.process.RemoteProcess; - -/** - * Abstract class which represent the cluster having multiple daemons. - */ -@SuppressWarnings("unchecked") -public abstract class AbstractDaemonCluster { - - private static final Log LOG = LogFactory.getLog(AbstractDaemonCluster.class); - private String [] excludeExpList ; - private Configuration conf; - protected ClusterProcessManager clusterManager; - private Map, List> daemons = - new LinkedHashMap, List>(); - private String newConfDir = null; - private static final String CONF_HADOOP_LOCAL_DIR = - "test.system.hdrc.hadoop.local.confdir"; - private final static Object waitLock = new Object(); - - /** - * Constructor to create a cluster client.
- * - * @param conf - * Configuration to be used while constructing the cluster. - * @param rcluster - * process manger instance to be used for managing the daemons. - * - * @throws IOException - */ - public AbstractDaemonCluster(Configuration conf, - ClusterProcessManager rcluster) throws IOException { - this.conf = conf; - this.clusterManager = rcluster; - createAllClients(); - } - - /** - * The method returns the cluster manager. The system test cases require an - * instance of HadoopDaemonRemoteCluster to invoke certain operation on the - * daemon. - * - * @return instance of clusterManager - */ - public ClusterProcessManager getClusterManager() { - return clusterManager; - } - - protected void createAllClients() throws IOException { - for (RemoteProcess p : clusterManager.getAllProcesses()) { - List dms = daemons.get(p.getRole()); - if (dms == null) { - dms = new ArrayList(); - daemons.put(p.getRole(), dms); - } - dms.add(createClient(p)); - } - } - - /** - * Method to create the daemon client.
- * - * @param process - * to manage the daemon. - * @return instance of the daemon client - * - * @throws IOException - */ - protected abstract AbstractDaemonClient - createClient(RemoteProcess process) throws IOException; - - /** - * Get the global cluster configuration which was used to create the - * cluster.
- * - * @return global configuration of the cluster. - */ - public Configuration getConf() { - return conf; - } - - /** - * - - /** - * Return the client handle of all the Daemons.
- * - * @return map of role to daemon clients' list. - */ - public Map, List> getDaemons() { - return daemons; - } - - /** - * Checks if the cluster is ready for testing.
- * Algorithm for checking is as follows :
- *
    - *
  • Wait for Daemon to come up
  • - *
  • Check if daemon is ready
  • - *
  • If one of the daemon is not ready, return false
  • - *
- * - * @return true if whole cluster is ready. - * - * @throws IOException - */ - public boolean isReady() throws IOException { - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - waitForDaemon(daemon); - if (!daemon.isReady()) { - return false; - } - } - } - return true; - } - - protected void waitForDaemon(AbstractDaemonClient d) { - final int TEN_SEC = 10000; - while(true) { - try { - LOG.info("Waiting for daemon at " + d.getHostName() + " to come up."); - LOG.info("Daemon might not be " + - "ready or the call to setReady() method hasn't been " + - "injected to " + d.getClass() + " "); - d.connect(); - break; - } catch (IOException e) { - try { - Thread.sleep(TEN_SEC); - } catch (InterruptedException ie) { - } - } - } - } - - /** - * Starts the cluster daemons. - * @throws IOException - */ - public void start() throws IOException { - clusterManager.start(); - } - - /** - * Stops the cluster daemons. - * @throws IOException - */ - public void stop() throws IOException { - clusterManager.stop(); - } - - /** - * Connect to daemon RPC ports. - * @throws IOException - */ - public void connect() throws IOException { - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - daemon.connect(); - } - } - } - - /** - * Disconnect to daemon RPC ports. - * @throws IOException - */ - public void disconnect() throws IOException { - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - daemon.disconnect(); - } - } - } - - /** - * Ping all the daemons of the cluster. - * @throws IOException - */ - public void ping() throws IOException { - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - LOG.info("Daemon is : " + daemon.getHostName() + " pinging...."); - daemon.ping(); - } - } - } - - /** - * Connect to the cluster and ensure that it is clean to run tests. - * @throws Exception - */ - public void setUp() throws Exception { - while (!isReady()) { - Thread.sleep(1000); - } - connect(); - ping(); - clearAllControlActions(); - ensureClean(); - populateExceptionCounts(); - } - - /** - * This is mainly used for the test cases to set the list of exceptions - * that will be excluded. - * @param excludeExpList list of exceptions to exclude - */ - public void setExcludeExpList(String [] excludeExpList) { - this.excludeExpList = excludeExpList; - } - - public void clearAllControlActions() throws IOException { - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - LOG.info("Daemon is : " + daemon.getHostName() + " pinging...."); - daemon.getProxy().clearActions(); - } - } - } - - /** - * Ensure that the cluster is clean to run tests. - * @throws IOException - */ - public void ensureClean() throws IOException { - } - - /** - * Ensure that cluster is clean. Disconnect from the RPC ports of the daemons. - * @throws IOException - */ - public void tearDown() throws IOException { - ensureClean(); - clearAllControlActions(); - assertNoExceptionMessages(); - disconnect(); - } - - /** - * Populate the exception counts in all the daemons so that it can be checked when - * the testcase has finished running.
- * @throws IOException - */ - protected void populateExceptionCounts() throws IOException { - for(List lst : daemons.values()) { - for(AbstractDaemonClient d : lst) { - d.populateExceptionCount(excludeExpList); - } - } - } - - /** - * Assert no exception has been thrown during the sequence of the actions. - *
- * @throws IOException - */ - protected void assertNoExceptionMessages() throws IOException { - for(List lst : daemons.values()) { - for(AbstractDaemonClient d : lst) { - d.assertNoExceptionsOccurred(excludeExpList); - } - } - } - - /** - * Get the proxy user definitions from cluster from configuration. - * @return ProxyUserDefinitions - proxy users data like groups and hosts. - * @throws Exception - if no proxy users found in config. - */ - public ProxyUserDefinitions getHadoopProxyUsers() throws - Exception { - Iterator itr = conf.iterator(); - ArrayList proxyUsers = new ArrayList(); - while (itr.hasNext()) { - if (itr.next().toString().indexOf("hadoop.proxyuser") >= 0 && - itr.next().toString().indexOf("groups=") >= 0) { - proxyUsers.add(itr.next().toString().split("\\.")[2]); - } - } - if (proxyUsers.size() == 0) { - LOG.error("No proxy users found in the configuration."); - throw new Exception("No proxy users found in the configuration."); - } - - ProxyUserDefinitions pud = new ProxyUserDefinitions() { - @Override - public boolean writeToFile(URI filePath) throws IOException { - throw new UnsupportedOperationException("No such method exists."); - }; - }; - - for (String userName : proxyUsers) { - List groups = Arrays.asList(conf.get("hadoop.proxyuser." + - userName + ".groups").split("//,")); - List hosts = Arrays.asList(conf.get("hadoop.proxyuser." + - userName + ".hosts").split("//,")); - ProxyUserDefinitions.GroupsAndHost definitions = - pud.new GroupsAndHost(); - definitions.setGroups(groups); - definitions.setHosts(hosts); - pud.addProxyUser(userName, definitions); - } - return pud; - } - - /** - * It's a local folder where the config file stores temporarily - * while serializing the object. - * @return String temporary local folder path for configuration. - */ - private String getHadoopLocalConfDir() { - String hadoopLocalConfDir = conf.get(CONF_HADOOP_LOCAL_DIR); - if (hadoopLocalConfDir == null || hadoopLocalConfDir.isEmpty()) { - LOG.error("No configuration " - + "for the CONF_HADOOP_LOCAL_DIR passed"); - throw new IllegalArgumentException( - "No Configuration passed for hadoop conf local directory"); - } - return hadoopLocalConfDir; - } - - /** - * It uses to restart the cluster with new configuration at runtime.
- * @param props attributes for new configuration. - * @param configFile configuration file. - * @throws IOException if an I/O error occurs. - */ - public void restartClusterWithNewConfig(Hashtable props, - String configFile) throws IOException { - - String mapredConf = null; - String localDirPath = null; - File localFolderObj = null; - File xmlFileObj = null; - String confXMLFile = null; - Configuration initConf = new Configuration(getConf()); - Enumeration e = props.keys(); - while (e.hasMoreElements()) { - String propKey = e.nextElement(); - Object propValue = props.get(propKey); - initConf.set(propKey,propValue.toString()); - } - - localDirPath = getHadoopLocalConfDir(); - localFolderObj = new File(localDirPath); - if (!localFolderObj.exists()) { - localFolderObj.mkdir(); - } - confXMLFile = localDirPath + File.separator + configFile; - xmlFileObj = new File(confXMLFile); - initConf.writeXml(new FileOutputStream(xmlFileObj)); - newConfDir = clusterManager.pushConfig(localDirPath); - stop(); - waitForClusterToStop(); - clusterManager.start(newConfDir); - waitForClusterToStart(); - localFolderObj.delete(); - } - - /** - * It uses to restart the cluster with default configuration.
- * @throws IOException if an I/O error occurs. - */ - public void restart() throws - IOException { - stop(); - waitForClusterToStop(); - start(); - waitForClusterToStart(); - cleanupNewConf(newConfDir); - } - - /** - * It uses to delete the new configuration folder. - * @param path - configuration directory path. - * @throws IOException if an I/O error occurs. - */ - public void cleanupNewConf(String path) throws IOException { - File file = new File(path); - file.delete(); - } - - /** - * It uses to wait until the cluster is stopped.
- * @throws IOException if an I/O error occurs. - */ - public void waitForClusterToStop() throws - IOException { - List chkDaemonStop = new ArrayList(); - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - DaemonStopThread dmStop = new DaemonStopThread(daemon); - chkDaemonStop.add(dmStop); - dmStop.start(); - } - } - - for (Thread daemonThread : chkDaemonStop){ - try { - daemonThread.join(); - } catch(InterruptedException intExp) { - LOG.warn("Interrupted while thread is joining." + intExp.getMessage()); - } - } - } - - /** - * It uses to wait until the cluster is started.
- * @throws IOException if an I/O error occurs. - */ - public void waitForClusterToStart() throws - IOException { - List chkDaemonStart = new ArrayList(); - for (List set : daemons.values()) { - for (AbstractDaemonClient daemon : set) { - DaemonStartThread dmStart = new DaemonStartThread(daemon); - chkDaemonStart.add(dmStart);; - dmStart.start(); - } - } - - for (Thread daemonThread : chkDaemonStart){ - try { - daemonThread.join(); - } catch(InterruptedException intExp) { - LOG.warn("Interrupted while thread is joining" + intExp.getMessage()); - } - } - } - - /** - * It waits for specified amount of time. - * @param duration time in milliseconds. - * @throws InterruptedException if any thread interrupted the current - * thread while it is waiting for a notification. - */ - public void waitFor(long duration) { - try { - synchronized (waitLock) { - waitLock.wait(duration); - } - } catch (InterruptedException intExp) { - LOG.warn("Interrrupeted while thread is waiting" + intExp.getMessage()); - } - } - - class DaemonStartThread extends Thread { - private AbstractDaemonClient daemon; - - public DaemonStartThread(AbstractDaemonClient daemon) { - this.daemon = daemon; - } - - public void run(){ - LOG.info("Waiting for Daemon " + daemon.getHostName() - + " to come up....."); - while (true) { - try { - daemon.ping(); - LOG.info("Daemon is : " + daemon.getHostName() + " pinging..."); - break; - } catch (Exception exp) { - if(LOG.isDebugEnabled()) { - LOG.debug(daemon.getHostName() + " is waiting to come up."); - } - waitFor(60000); - } - } - } - } - - class DaemonStopThread extends Thread { - private AbstractDaemonClient daemon; - - public DaemonStopThread(AbstractDaemonClient daemon) { - this.daemon = daemon; - } - - public void run() { - LOG.info("Waiting for Daemon " + daemon.getHostName() - + " to stop....."); - while (true) { - try { - daemon.ping(); - if(LOG.isDebugEnabled()) { - LOG.debug(daemon.getHostName() +" is waiting state to stop."); - } - waitFor(60000); - } catch (Exception exp) { - LOG.info("Daemon is : " + daemon.getHostName() + " stopped..."); - break; - } - } - } - } -} - diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ControlAction.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ControlAction.java deleted file mode 100644 index de1b7998e67..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ControlAction.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import org.apache.hadoop.io.Writable; - -/** - * Class to represent a control action which can be performed on Daemon.
- * - */ - -public abstract class ControlAction implements Writable { - - private T target; - - /** - * Default constructor of the Control Action, sets the Action type to zero.
- */ - public ControlAction() { - } - - /** - * Constructor which sets the type of the Control action to a specific type.
- * - * @param target - * of the control action. - */ - public ControlAction(T target) { - this.target = target; - } - - /** - * Gets the id of the control action
- * - * @return target of action - */ - public T getTarget() { - return target; - } - - @Override - public void readFields(DataInput in) throws IOException { - target.readFields(in); - } - - @Override - public void write(DataOutput out) throws IOException { - target.write(out); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof ControlAction) { - ControlAction other = (ControlAction) obj; - return (this.target.equals(other.getTarget())); - } else { - return false; - } - } - - - @Override - public String toString() { - return "Action Target : " + this.target; - } -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/DaemonProtocol.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/DaemonProtocol.java deleted file mode 100644 index 6cdccc3b113..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/DaemonProtocol.java +++ /dev/null @@ -1,204 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.FileNotFoundException; -import java.io.IOException; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.io.Writable; -import org.apache.hadoop.ipc.VersionedProtocol; -import org.apache.hadoop.fs.permission.FsPermission; - -/** - * RPC interface of a given Daemon. - */ -public interface DaemonProtocol extends VersionedProtocol{ - long versionID = 1L; - - /** - * Returns the Daemon configuration. - * @return Configuration - * @throws IOException in case of errors - */ - Configuration getDaemonConf() throws IOException; - - /** - * Check if the Daemon is alive. - * - * @throws IOException - * if Daemon is unreachable. - */ - void ping() throws IOException; - - /** - * Check if the Daemon is ready to accept RPC connections. - * - * @return true if Daemon is ready to accept RPC connection. - * @throws IOException in case of errors - */ - boolean isReady() throws IOException; - - /** - * Get system level view of the Daemon process. - * - * @return returns system level view of the Daemon process. - * - * @throws IOException in case of errors - */ - ProcessInfo getProcessInfo() throws IOException; - - /** - * Return a file status object that represents the path. - * @param path - * given path - * @param local - * whether the path is local or not - * @return a FileStatus object - * @throws FileNotFoundException when the path does not exist; - * IOException see specific implementation - */ - FileStatus getFileStatus(String path, boolean local) throws IOException; - - /** - * Create a file with given permissions in a file system. - * @param path - source path where the file has to create. - * @param fileName - file name. - * @param permission - file permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - void createFile(String path, String fileName, - FsPermission permission, boolean local) throws IOException; - - /** - * Create a folder with given permissions in a file system. - * @param path - source path where the file has to be creating. - * @param folderName - folder name. - * @param permission - folder permissions. - * @param local - identifying the path whether its local or not. - * @throws IOException - if an I/O error occurs. - */ - public void createFolder(String path, String folderName, - FsPermission permission, boolean local) throws IOException; - /** - * List the statuses of the files/directories in the given path if the path is - * a directory. - * - * @param path - * given path - * @param local - * whether the path is local or not - * @return the statuses of the files/directories in the given patch - * @throws IOException in case of errors - */ - FileStatus[] listStatus(String path, boolean local) throws IOException; - - /** - * Enables a particular control action to be performed on the Daemon
- * - * @param action is a control action to be enabled. - * - * @throws IOException in case of errors - */ - @SuppressWarnings("unchecked") - void sendAction(ControlAction action) throws IOException; - - /** - * Checks if the particular control action has be delivered to the Daemon - * component
- * - * @param action to be checked. - * - * @return true if action is still in waiting queue of - * actions to be delivered. - * @throws IOException in case of errors - */ - @SuppressWarnings("unchecked") - boolean isActionPending(ControlAction action) throws IOException; - - /** - * Removes a particular control action from the list of the actions which the - * daemon maintains.
- * Not to be directly called by Test Case or clients. - * @param action to be removed - * @throws IOException in case of errors - */ - - @SuppressWarnings("unchecked") - void removeAction(ControlAction action) throws IOException; - - /** - * Clears out the list of control actions on the particular daemon. - *
- * @throws IOException in case of errors - */ - void clearActions() throws IOException; - - /** - * Gets a list of pending actions which are targeted on the specified key. - *
- * Not to be directly used by clients - * @param key target - * @return list of actions. - * @throws IOException in case of errors - */ - @SuppressWarnings("unchecked") - ControlAction[] getActions(Writable key) throws IOException; - - /** - * Gets the number of times a particular pattern has been found in the - * daemons log file.
- * Please note that search spans across all previous messages of - * Daemon, so better practice is to get previous counts before an operation - * and then re-check if the sequence of action has caused any problems - * @param pattern to look for in the damon's log file - * @param list of exceptions to ignore - * @return number of times the pattern if found in log file. - * @throws IOException in case of errors - */ - int getNumberOfMatchesInLogFile(String pattern, String[] list) - throws IOException; - - /** - * Gets the user who started the particular daemon initially.
- * - * @return user who started the particular daemon. - * @throws IOException in case of errors - */ - String getDaemonUser() throws IOException; - - /** - * It uses for suspending the process. - * @param pid process id. - * @return true if the process is suspended otherwise false. - * @throws IOException if an I/O error occurs. - */ - boolean suspendProcess(String pid) throws IOException; - - /** - * It uses for resuming the suspended process. - * @param pid process id - * @return true if suspended process is resumed otherwise false. - * @throws IOException if an I/O error occurs. - */ - boolean resumeProcess(String pid) throws IOException; -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfo.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfo.java deleted file mode 100644 index 22b385529f1..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfo.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.util.Map; - -import org.apache.hadoop.io.Writable; - -/** - * Daemon system level process information. - */ -public interface ProcessInfo extends Writable { - /** - * Get the current time in the millisecond.
- * - * @return current time on daemon clock in millisecond. - */ - public long currentTimeMillis(); - - /** - * Get the environment that was used to start the Daemon process.
- * - * @return the environment variable list. - */ - public Map getEnv(); - - /** - * Get the System properties of the Daemon process.
- * - * @return the properties list. - */ - public Map getSystemProperties(); - - /** - * Get the number of active threads in Daemon VM.
- * - * @return number of active threads in Daemon VM. - */ - public int activeThreadCount(); - - /** - * Get the maximum heap size that is configured for the Daemon VM.
- * - * @return maximum heap size. - */ - public long maxMemory(); - - /** - * Get the free memory in Daemon VM.
- * - * @return free memory. - */ - public long freeMemory(); - - /** - * Get the total used memory in Demon VM.
- * - * @return total used memory. - */ - public long totalMemory(); -} \ No newline at end of file diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfoImpl.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfoImpl.java deleted file mode 100644 index c32666dc45a..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProcessInfoImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - - -public class ProcessInfoImpl implements ProcessInfo { - - private int threadCount; - private long currentTime; - private long freemem; - private long maxmem; - private long totmem; - private Map env; - private Map props; - - public ProcessInfoImpl() { - env = new HashMap(); - props = new HashMap(); - } - - /** - * Construct a concrete process information object.
- * - * @param threadCount - * count of threads. - * @param currentTime - * @param freemem - * @param maxmem - * @param totmem - * @param env environment list. - * @param props - */ - public ProcessInfoImpl(int threadCount, long currentTime, long freemem, - long maxmem, long totmem, Map env, - Map props) { - this.threadCount = threadCount; - this.currentTime = currentTime; - this.freemem = freemem; - this.maxmem = maxmem; - this.totmem = totmem; - this.env = env; - this.props = props; - } - - @Override - public int activeThreadCount() { - return threadCount; - } - - @Override - public long currentTimeMillis() { - return currentTime; - } - - @Override - public long freeMemory() { - return freemem; - } - - @Override - public Map getEnv() { - return env; - } - - @Override - public Map getSystemProperties() { - return props; - } - - @Override - public long maxMemory() { - return maxmem; - } - - @Override - public long totalMemory() { - return totmem; - } - - @Override - public void readFields(DataInput in) throws IOException { - this.threadCount = in.readInt(); - this.currentTime = in.readLong(); - this.freemem = in.readLong(); - this.maxmem = in.readLong(); - this.totmem = in.readLong(); - read(in, env); - read(in, props); - } - - @Override - public void write(DataOutput out) throws IOException { - out.writeInt(threadCount); - out.writeLong(currentTime); - out.writeLong(freemem); - out.writeLong(maxmem); - out.writeLong(totmem); - write(out, env); - write(out, props); - } - - private void read(DataInput in, Map map) throws IOException { - int size = in.readInt(); - for (int i = 0; i < size; i = i + 2) { - String key = in.readUTF(); - String value = in.readUTF(); - map.put(key, value); - } - } - - private void write(DataOutput out, Map map) - throws IOException { - int size = (map.size() * 2); - out.writeInt(size); - for (Map.Entry entry : map.entrySet()) { - out.writeUTF(entry.getKey()); - out.writeUTF(entry.getValue()); - } - } - - @Override - public String toString() { - StringBuffer strBuf = new StringBuffer(); - strBuf.append(String.format("active threads : %d\n", threadCount)); - strBuf.append(String.format("current time : %d\n", currentTime)); - strBuf.append(String.format("free memory : %d\n", freemem)); - strBuf.append(String.format("total memory : %d\n", totmem)); - strBuf.append(String.format("max memory : %d\n", maxmem)); - strBuf.append("Environment Variables : \n"); - for (Map.Entry entry : env.entrySet()) { - strBuf.append(String.format("key : %s value : %s \n", entry.getKey(), - entry.getValue())); - } - return strBuf.toString(); - } - -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProxyUserDefinitions.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProxyUserDefinitions.java deleted file mode 100644 index c9d6be441e0..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/ProxyUserDefinitions.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * 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.hadoop.test.system; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.io.IOException; -import java.net.URI; - -/** - * Its the data container which contains host names and - * groups against each proxy user. - */ -public abstract class ProxyUserDefinitions { - - /** - * Groups and host names container - */ - public class GroupsAndHost { - private List groups; - private List hosts; - public List getGroups() { - return groups; - } - public void setGroups(List groups) { - this.groups = groups; - } - public List getHosts() { - return hosts; - } - public void setHosts(List hosts) { - this.hosts = hosts; - } - } - - protected Map proxyUsers; - protected ProxyUserDefinitions () { - proxyUsers = new HashMap(); - } - - /** - * Add proxy user data to a container. - * @param userName - proxy user name. - * @param definitions - groups and host names. - */ - public void addProxyUser (String userName, GroupsAndHost definitions) { - proxyUsers.put(userName, definitions); - } - - /** - * Get the host names and groups against given proxy user. - * @return - GroupsAndHost object. - */ - public GroupsAndHost getProxyUser (String userName) { - return proxyUsers.get(userName); - } - - /** - * Get the Proxy users data which contains the host names - * and groups against each user. - * @return - the proxy users data as hash map. - */ - public Map getProxyUsers () { - return proxyUsers; - } - - /** - * The implementation of this method has to be provided by a child of the class - * @param filePath - * @return - * @throws IOException - */ - public abstract boolean writeToFile(URI filePath) throws IOException; -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/ClusterProcessManager.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/ClusterProcessManager.java deleted file mode 100644 index 70dd4146157..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/ClusterProcessManager.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * 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.hadoop.test.system.process; - -import java.io.IOException; -import java.util.List; -import java.util.Set; - -import org.apache.hadoop.conf.Configuration; - -/** - * Interface to manage the remote processes in the cluster. - */ -public interface ClusterProcessManager { - - /** - * Initialization method to pass the configuration object which is required - * by the ClusterProcessManager to manage the cluster.
- * Configuration object should typically contain all the parameters which are - * required by the implementations.
- * - * @param conf configuration containing values of the specific keys which - * are required by the implementation of the cluster process manger. - * - * @throws IOException when initialization fails. - */ - void init(Configuration conf) throws IOException; - - /** - * Get the list of RemoteProcess handles of all the remote processes. - */ - List getAllProcesses(); - - /** - * Get all the roles this cluster's daemon processes have. - */ - Set> getRoles(); - - /** - * Method to start all the remote daemons.
- * - * @throws IOException if startup procedure fails. - */ - void start() throws IOException; - - /** - * Starts the daemon from the user specified conf dir. - * @param newConfLocation the dir where the new conf files reside. - * @throws IOException if start from new conf fails. - */ - void start(String newConfLocation) throws IOException; - - /** - * Stops the daemon running from user specified conf dir. - * - * @param newConfLocation the dir where the new conf files reside. - * @throws IOException if stop from new conf fails. - */ - void stop(String newConfLocation) throws IOException; - - /** - * Method to shutdown all the remote daemons.
- * - * @throws IOException if shutdown procedure fails. - */ - void stop() throws IOException; - - /** - * Gets if multi-user support is enabled for this cluster. - *
- * @return true if multi-user support is enabled. - * @throws IOException if RPC returns error. - */ - boolean isMultiUserSupported() throws IOException; - - /** - * The pushConfig is used to push a new config to the daemons. - * @param localDir - * @return is the remoteDir location where config will be pushed - * @throws IOException if pushConfig fails. - */ - String pushConfig(String localDir) throws IOException; -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/HadoopDaemonRemoteCluster.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/HadoopDaemonRemoteCluster.java deleted file mode 100644 index d3e5d630a37..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/HadoopDaemonRemoteCluster.java +++ /dev/null @@ -1,404 +0,0 @@ -/** - * 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.hadoop.test.system.process; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.util.Shell.ShellCommandExecutor; - -/** - * The concrete class which implements the start up and shut down based routines - * based on the hadoop-daemon.sh.
- * - * Class requires two keys to be present in the Configuration objects passed to - * it. Look at CONF_HADOOPHOME and - * CONF_HADOOPCONFDIR for the names of the - * configuration keys. - * - * Following will be the format which the final command execution would look : - *
- * - * ssh host 'hadoop-home/bin/hadoop-daemon.sh --script scriptName - * --config HADOOP_CONF_DIR (start|stop) command' - * - */ -public abstract class HadoopDaemonRemoteCluster - implements ClusterProcessManager { - - private static final Log LOG = LogFactory - .getLog(HadoopDaemonRemoteCluster.class.getName()); - - public static final String CONF_HADOOPNEWCONFDIR = - "test.system.hdrc.hadoopnewconfdir"; - /** - * Key used to configure the HADOOP_PREFIX to be used by the - * HadoopDaemonRemoteCluster. - */ - public final static String CONF_HADOOPHOME = - "test.system.hdrc.hadoophome"; - - public final static String CONF_SCRIPTDIR = - "test.system.hdrc.deployed.scripts.dir"; - /** - * Key used to configure the HADOOP_CONF_DIR to be used by the - * HadoopDaemonRemoteCluster. - */ - public final static String CONF_HADOOPCONFDIR = - "test.system.hdrc.hadoopconfdir"; - - public final static String CONF_DEPLOYED_HADOOPCONFDIR = - "test.system.hdrc.deployed.hadoopconfdir"; - - private String hadoopHome; - protected String hadoopConfDir; - protected String scriptsDir; - protected String hadoopNewConfDir; - private final Set> roles; - private final List daemonInfos; - private List processes; - protected Configuration conf; - - public static class HadoopDaemonInfo { - public final String cmd; - public final Enum role; - public final List hostNames; - public HadoopDaemonInfo(String cmd, Enum role, List hostNames) { - super(); - this.cmd = cmd; - this.role = role; - this.hostNames = hostNames; - } - - public HadoopDaemonInfo(String cmd, Enum role, String hostFile) - throws IOException { - super(); - this.cmd = cmd; - this.role = role; - File file = new File(getDeployedHadoopConfDir(), hostFile); - BufferedReader reader = null; - hostNames = new ArrayList(); - try { - reader = new BufferedReader(new FileReader(file)); - String host = null; - while ((host = reader.readLine()) != null) { - if (host.trim().isEmpty() || host.startsWith("#")) { - // Skip empty and possible comment lines - // throw new IllegalArgumentException( - // "Hostname could not be found in file " + hostFile); - continue; - } - hostNames.add(host.trim()); - } - if (hostNames.size() < 1) { - throw new IllegalArgumentException("At least one hostname " - + - "is required to be present in file - " + hostFile); - } - } finally { - try { - reader.close(); - } catch (IOException e) { - LOG.warn("Could not close reader"); - } - } - LOG.info("Created HadoopDaemonInfo for " + cmd + " " + role + " from " - + hostFile); - } - } - - @Override - public String pushConfig(String localDir) throws IOException { - for (RemoteProcess process : processes){ - process.pushConfig(localDir); - } - return hadoopNewConfDir; - } - - public HadoopDaemonRemoteCluster(List daemonInfos) { - this.daemonInfos = daemonInfos; - this.roles = new HashSet>(); - for (HadoopDaemonInfo info : daemonInfos) { - this.roles.add(info.role); - } - } - - @Override - public void init(Configuration conf) throws IOException { - this.conf = conf; - populateDirectories(conf); - this.processes = new ArrayList(); - populateDaemons(); - } - - @Override - public List getAllProcesses() { - return processes; - } - - @Override - public Set> getRoles() { - return roles; - } - - /** - * Method to populate the hadoop home and hadoop configuration directories. - * - * @param conf - * Configuration object containing values for - * CONF_HADOOPHOME and - * CONF_HADOOPCONFDIR - * - * @throws IllegalArgumentException - * if the configuration or system property set does not contain - * values for the required keys. - */ - protected void populateDirectories(Configuration conf) { - hadoopHome = conf.get(CONF_HADOOPHOME); - hadoopConfDir = conf.get(CONF_HADOOPCONFDIR); - scriptsDir = conf.get(CONF_SCRIPTDIR); - hadoopNewConfDir = conf.get(CONF_HADOOPNEWCONFDIR); - if (hadoopHome == null || hadoopConfDir == null || hadoopHome.isEmpty() - || hadoopConfDir.isEmpty()) { - LOG.error("No configuration " - + "for the HADOOP_PREFIX and HADOOP_CONF_DIR passed"); - throw new IllegalArgumentException( - "No Configuration passed for hadoop home " + - "and hadoop conf directories"); - } - } - - public static String getDeployedHadoopConfDir() { - String dir = System.getProperty(CONF_DEPLOYED_HADOOPCONFDIR); - if (dir == null || dir.isEmpty()) { - LOG.error("No configuration " - + "for the CONF_DEPLOYED_HADOOPCONFDIR passed"); - throw new IllegalArgumentException( - "No Configuration passed for hadoop deployed conf directory"); - } - return dir; - } - - @Override - public void start() throws IOException { - for (RemoteProcess process : processes) { - process.start(); - } - } - - @Override - public void start(String newConfLocation)throws IOException { - for (RemoteProcess process : processes) { - process.start(newConfLocation); - } - } - - @Override - public void stop() throws IOException { - for (RemoteProcess process : processes) { - process.kill(); - } - } - - @Override - public void stop(String newConfLocation) throws IOException { - for (RemoteProcess process : processes) { - process.kill(newConfLocation); - } - } - - protected void populateDaemon(HadoopDaemonInfo info) throws IOException { - for (String host : info.hostNames) { - InetAddress addr = InetAddress.getByName(host); - RemoteProcess process = getProcessManager(info, - addr.getCanonicalHostName()); - processes.add(process); - } - } - - protected void populateDaemons() throws IOException { - for (HadoopDaemonInfo info : daemonInfos) { - populateDaemon(info); - } - } - - @Override - public boolean isMultiUserSupported() throws IOException { - return false; - } - - protected RemoteProcess getProcessManager( - HadoopDaemonInfo info, String hostName) { - RemoteProcess process = new ScriptDaemon(info.cmd, hostName, info.role); - return process; - } - - /** - * The core daemon class which actually implements the remote process - * management of actual daemon processes in the cluster. - * - */ - class ScriptDaemon implements RemoteProcess { - - private static final String STOP_COMMAND = "stop"; - private static final String START_COMMAND = "start"; - private static final String SCRIPT_NAME = "hadoop-daemon.sh"; - private static final String PUSH_CONFIG ="pushConfig.sh"; - protected final String daemonName; - protected final String hostName; - private final Enum role; - - public ScriptDaemon(String daemonName, String hostName, Enum role) { - this.daemonName = daemonName; - this.hostName = hostName; - this.role = role; - } - - @Override - public String getHostName() { - return hostName; - } - - private String[] getPushConfigCommand(String localDir, String remoteDir, - File scriptDir) throws IOException{ - ArrayList cmdArgs = new ArrayList(); - cmdArgs.add(scriptDir.getAbsolutePath() + File.separator + PUSH_CONFIG); - cmdArgs.add(localDir); - cmdArgs.add(hostName); - cmdArgs.add(remoteDir); - cmdArgs.add(hadoopConfDir); - return (String[]) cmdArgs.toArray(new String[cmdArgs.size()]); - } - - private ShellCommandExecutor buildPushConfig(String local, String remote ) - throws IOException { - File scriptDir = new File(scriptsDir); - String[] commandArgs = getPushConfigCommand(local, remote, scriptDir); - HashMap env = new HashMap(); - ShellCommandExecutor executor = new ShellCommandExecutor(commandArgs, - scriptDir, env); - LOG.info(executor.toString()); - return executor; - } - - private ShellCommandExecutor createNewConfDir() throws IOException { - ArrayList cmdArgs = new ArrayList(); - cmdArgs.add("ssh"); - cmdArgs.add(hostName); - cmdArgs.add("if [ -d "+ hadoopNewConfDir+ - " ];\n then echo Will remove existing directory; rm -rf "+ - hadoopNewConfDir+";\nmkdir "+ hadoopNewConfDir+"; else \n"+ - "echo " + hadoopNewConfDir + " doesnt exist hence creating" + - "; mkdir " + hadoopNewConfDir + ";\n fi"); - String[] cmd = (String[]) cmdArgs.toArray(new String[cmdArgs.size()]); - ShellCommandExecutor executor = new ShellCommandExecutor(cmd); - LOG.info(executor.toString()); - return executor; - } - - @Override - public void pushConfig(String localDir) throws IOException { - createNewConfDir().execute(); - buildPushConfig(localDir, hadoopNewConfDir).execute(); - } - - private ShellCommandExecutor buildCommandExecutor(String command, - String confDir) { - String[] commandArgs = getCommand(command, confDir); - File cwd = new File("."); - HashMap env = new HashMap(); - env.put("HADOOP_CONF_DIR", confDir); - ShellCommandExecutor executor - = new ShellCommandExecutor(commandArgs, cwd, env); - LOG.info(executor.toString()); - return executor; - } - - private File getBinDir() { - File binDir = new File(hadoopHome, "bin"); - return binDir; - } - - protected String[] getCommand(String command, String confDir) { - ArrayList cmdArgs = new ArrayList(); - File binDir = getBinDir(); - cmdArgs.add("ssh"); - cmdArgs.add(hostName); - cmdArgs.add(binDir.getAbsolutePath() + File.separator + SCRIPT_NAME); - cmdArgs.add("--config"); - cmdArgs.add(confDir); - // XXX Twenty internal version does not support --script option. - cmdArgs.add(command); - cmdArgs.add(daemonName); - return (String[]) cmdArgs.toArray(new String[cmdArgs.size()]); - } - - @Override - public void kill() throws IOException { - kill(hadoopConfDir); - } - - @Override - public void start() throws IOException { - start(hadoopConfDir); - } - - public void start(String newConfLocation) throws IOException { - ShellCommandExecutor cme = buildCommandExecutor(START_COMMAND, - newConfLocation); - cme.execute(); - String output = cme.getOutput(); - if (!output.isEmpty()) { //getOutput() never returns null value - if (output.toLowerCase().contains("error")) { - LOG.warn("Error is detected."); - throw new IOException("Start error\n" + output); - } - } - } - - public void kill(String newConfLocation) throws IOException { - ShellCommandExecutor cme - = buildCommandExecutor(STOP_COMMAND, newConfLocation); - cme.execute(); - String output = cme.getOutput(); - if (!output.isEmpty()) { //getOutput() never returns null value - if (output.toLowerCase().contains("error")) { - LOG.info("Error is detected."); - throw new IOException("Kill error\n" + output); - } - } - } - - @Override - public Enum getRole() { - return role; - } - } -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/MultiUserHadoopDaemonRemoteCluster.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/MultiUserHadoopDaemonRemoteCluster.java deleted file mode 100644 index 2f9e215ffde..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/MultiUserHadoopDaemonRemoteCluster.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * 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.hadoop.test.system.process; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.hadoop.test.system.process.HadoopDaemonRemoteCluster.HadoopDaemonInfo; - -public abstract class MultiUserHadoopDaemonRemoteCluster - extends HadoopDaemonRemoteCluster { - - public MultiUserHadoopDaemonRemoteCluster(List daemonInfos) { - super(daemonInfos); - } - - @Override - protected RemoteProcess getProcessManager( - HadoopDaemonInfo info, String hostName) { - return new MultiUserScriptDaemon(info.cmd, hostName, info.role); - } - - @Override - public boolean isMultiUserSupported() throws IOException { - return true; - } - - class MultiUserScriptDaemon extends ScriptDaemon { - - private static final String MULTI_USER_BINARY_PATH_KEY = - "test.system.hdrc.multi-user.binary.path"; - private static final String MULTI_USER_MANAGING_USER = - "test.system.hdrc.multi-user.managinguser."; - private String binaryPath; - /** - * Manging user for a particular daemon is gotten by - * MULTI_USER_MANAGING_USER + daemonname - */ - private String mangingUser; - - public MultiUserScriptDaemon( - String daemonName, String hostName, Enum role) { - super(daemonName, hostName, role); - initialize(daemonName); - } - - private void initialize(String daemonName) { - binaryPath = conf.get(MULTI_USER_BINARY_PATH_KEY); - if (binaryPath == null || binaryPath.trim().isEmpty()) { - throw new IllegalArgumentException( - "Binary path for multi-user path is not present. Please set " - + MULTI_USER_BINARY_PATH_KEY + " correctly"); - } - File binaryFile = new File(binaryPath); - if (!binaryFile.exists() || !binaryFile.canExecute()) { - throw new IllegalArgumentException( - "Binary file path is not configured correctly. Please set " - + MULTI_USER_BINARY_PATH_KEY - + " to properly configured binary file."); - } - mangingUser = conf.get(MULTI_USER_MANAGING_USER + daemonName); - if (mangingUser == null || mangingUser.trim().isEmpty()) { - throw new IllegalArgumentException( - "Manging user for daemon not present please set : " - + MULTI_USER_MANAGING_USER + daemonName + " to correct value."); - } - } - - @Override - protected String[] getCommand(String command,String confDir) { - ArrayList commandList = new ArrayList(); - commandList.add(binaryPath); - commandList.add(mangingUser); - commandList.add(hostName); - commandList.add("--config " - + confDir + " " + command + " " + daemonName); - return (String[]) commandList.toArray(new String[commandList.size()]); - } - } -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/RemoteProcess.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/RemoteProcess.java deleted file mode 100644 index d0afe16b260..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/test/system/process/RemoteProcess.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * 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.hadoop.test.system.process; - -import java.io.IOException; - -/** - * Interface to manage the remote process. - */ -public interface RemoteProcess { - /** - * Get the host on which the daemon process is running/stopped.
- * - * @return hostname on which process is running/stopped. - */ - String getHostName(); - - /** - * Start a given daemon process.
- * - * @throws IOException if startup fails. - */ - void start() throws IOException; - /** - * Starts a daemon from user specified conf dir. - * @param newConfLocation is dir where new conf resides. - * @throws IOException if start of process fails from new location. - */ - void start(String newConfLocation) throws IOException; - /** - * Stop a given daemon process.
- * - * @throws IOException if shutdown fails. - */ - void kill() throws IOException; - - /** - * Stops a given daemon running from user specified - * conf dir.
- * @param newConfLocation dir location where new conf resides. - * @throws IOException if kill fails from new conf location. - */ - void kill(String newConfLocation) throws IOException; - /** - * Get the role of the Daemon in the cluster. - * - * @return Enum - */ - Enum getRole(); - - /** - * Pushed the configuration to new configuration directory - * @param localDir The local directory which has config files that will be - * pushed to the remote location - * @throws IOException is thrown if the pushConfig results in a error. - */ - void pushConfig(String localDir) throws IOException; -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/RemoteExecution.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/RemoteExecution.java deleted file mode 100644 index 6177c7909a8..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/RemoteExecution.java +++ /dev/null @@ -1,27 +0,0 @@ -/** - * 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.hadoop.util; - -public interface RemoteExecution { - public void executeCommand (String remoteHostName, String user, - String command) throws Exception; - public int getExitCode(); - public String getOutput(); - public String getCommandString(); -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/SSHRemoteExecution.java b/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/SSHRemoteExecution.java deleted file mode 100644 index 704c97d745b..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/java/org/apache/hadoop/util/SSHRemoteExecution.java +++ /dev/null @@ -1,203 +0,0 @@ -/** - * 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.hadoop.util; - -import com.jcraft.jsch.*; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Properties; - -/** - * Remote Execution of commands on a remote machine. - */ - -public class SSHRemoteExecution implements RemoteExecution { - - static final Log LOG = LogFactory.getLog(SSHRemoteExecution.class); - static final int SSH_PORT = 22; - static final String DEFAULT_IDENTITY="id_dsa"; - static final String DEFAULT_KNOWNHOSTS="known_hosts"; - static final String FS = System.getProperty("file.separator"); - static final String LS = System.getProperty("line.separator"); - private int exitCode; - private StringBuffer output; - private String commandString; - - final StringBuffer errorMessage = new StringBuffer(); - public SSHRemoteExecution() throws Exception { - } - - protected String getHomeDir() { - String currentUser=System.getProperty("user.name"); - String userHome=System.getProperty("user.home"); - - return userHome.substring(0, userHome.indexOf(currentUser)-1); - } - - /** - * Execute command at remote host under given user - * @param remoteHostName remote host name - * @param user is the name of the user to be login under; - * current user will be used if this is set to null - * @param command to be executed remotely - * @param identityFile is the name of alternative identity file; default - * is ~user/.ssh/id_dsa - * @param portNumber remote SSH daemon port number, default is 22 - * @throws Exception in case of errors - */ - public void executeCommand (String remoteHostName, String user, - String command, String identityFile, int portNumber) throws Exception { - commandString = command; - String sessionUser = System.getProperty("user.name"); - String userHome=System.getProperty("user.home"); - if (user != null) { - sessionUser = user; - userHome = getHomeDir() + FS + user; - } - String dotSSHDir = userHome + FS + ".ssh"; - String sessionIdentity = dotSSHDir + FS + DEFAULT_IDENTITY; - if (identityFile != null) { - sessionIdentity = identityFile; - } - - JSch jsch = new JSch(); - - Session session = jsch.getSession(sessionUser, remoteHostName, portNumber); - jsch.setKnownHosts(dotSSHDir + FS + DEFAULT_KNOWNHOSTS); - jsch.addIdentity(sessionIdentity); - - Properties config = new Properties(); - config.put("StrictHostKeyChecking", "no"); - session.setConfig(config); - - session.connect(30000); // making a connection with timeout. - - Channel channel=session.openChannel("exec"); - ((ChannelExec)channel).setCommand(command); - channel.setInputStream(null); - - final BufferedReader errReader = - new BufferedReader( - new InputStreamReader(((ChannelExec)channel).getErrStream())); - BufferedReader inReader = - new BufferedReader(new InputStreamReader(channel.getInputStream())); - - channel.connect(); - Thread errorThread = new Thread() { - @Override - public void run() { - try { - String line = errReader.readLine(); - while((line != null) && !isInterrupted()) { - errorMessage.append(line); - errorMessage.append(LS); - line = errReader.readLine(); - } - } catch(IOException ioe) { - LOG.warn("Error reading the error stream", ioe); - } - } - }; - - try { - errorThread.start(); - } catch (IllegalStateException e) { - LOG.debug(e); - } - try { - parseExecResult(inReader); - String line = inReader.readLine(); - while (line != null) { - line = inReader.readLine(); - } - - if(channel.isClosed()) { - exitCode = channel.getExitStatus(); - LOG.debug("exit-status: " + exitCode); - } - try { - // make sure that the error thread exits - errorThread.join(); - } catch (InterruptedException ie) { - LOG.warn("Interrupted while reading the error stream", ie); - } - } catch (Exception ie) { - throw new IOException(ie.toString()); - } - finally { - try { - inReader.close(); - } catch (IOException ioe) { - LOG.warn("Error while closing the input stream", ioe); - } - try { - errReader.close(); - } catch (IOException ioe) { - LOG.warn("Error while closing the error stream", ioe); - } - channel.disconnect(); - session.disconnect(); - } - } - - /** - * Execute command at remote host under given username - * Default identity is ~/.ssh/id_dsa key will be used - * Default known_hosts file is ~/.ssh/known_hosts will be used - * @param remoteHostName remote host name - * @param user is the name of the user to be login under; - * if equals to null then current user name will be used - * @param command to be executed remotely - */ - @Override - public void executeCommand (String remoteHostName, String user, - String command) throws Exception { - executeCommand(remoteHostName, user, command, null, SSH_PORT); - } - - @Override - public int getExitCode() { - return exitCode; - } - - protected void parseExecResult(BufferedReader lines) throws IOException { - output = new StringBuffer(); - char[] buf = new char[512]; - int nRead; - while ( (nRead = lines.read(buf, 0, buf.length)) > 0 ) { - output.append(buf, 0, nRead); - } - } - - /** Get the output of the ssh command.*/ - @Override - public String getOutput() { - return (output == null) ? "" : output.toString(); - } - - /** Get the String representation of ssh command */ - @Override - public String getCommandString() { - return commandString; - } -} diff --git a/hadoop-common-project/hadoop-common/src/test/system/scripts/pushConfig.sh b/hadoop-common-project/hadoop-common/src/test/system/scripts/pushConfig.sh deleted file mode 100644 index 1230f0e0d35..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/scripts/pushConfig.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -# 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. - -# local folder with new configuration file -LOCAL_DIR=$1 -# remote daemon host -HOST=$2 -#remote dir points to the location of new config files -REMOTE_DIR=$3 -# remote daemon HADOOP_CONF_DIR location -DAEMON_HADOOP_CONF_DIR=$4 - -if [ $# -ne 4 ]; then - echo "Wrong number of parameters" >&2 - exit 2 -fi - -ret_value=0 - -echo The script makes a remote copy of existing ${DAEMON_HADOOP_CONF_DIR} to ${REMOTE_DIR} -echo and populates it with new configs prepared in $LOCAL_DIR - -ssh ${HOST} cp -r ${DAEMON_HADOOP_CONF_DIR}/* ${REMOTE_DIR} -ret_value=$? - -# make sure files are writeble -ssh ${HOST} chmod u+w ${REMOTE_DIR}/* - -# copy new files over -scp -r ${LOCAL_DIR}/* ${HOST}:${REMOTE_DIR} - -err_code=`echo $? + $ret_value | bc` -echo Copying of files from local to remote returned ${err_code} - diff --git a/hadoop-common-project/hadoop-common/src/test/system/validation/org/apache/hadoop/util/TestSSHRemoteExecution.java b/hadoop-common-project/hadoop-common/src/test/system/validation/org/apache/hadoop/util/TestSSHRemoteExecution.java deleted file mode 100644 index 15eb00cfe33..00000000000 --- a/hadoop-common-project/hadoop-common/src/test/system/validation/org/apache/hadoop/util/TestSSHRemoteExecution.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * 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.hadoop.util; - -import static org.junit.Assert.assertEquals; -import org.junit.Test; - -public class TestSSHRemoteExecution { - - @Test - /** - * Method: executeCommand(String remoteHostName, String user, String command) - */ - public void testExecuteCommandForRemoteHostNameUserCommand() throws Exception { - String command = "ls -l /bin"; - SSHRemoteExecution sshRE = new SSHRemoteExecution(); - sshRE.executeCommand("localhost", null, "ls -l /bin"); - System.out.println(sshRE.getOutput()); - assertEquals("Exit code should is expected to be 0", sshRE.getExitCode(), 0); - assertEquals("Mismatched command string", sshRE.getCommandString(), command); - } - - @Test - /** - * Method: getHomeDir() - */ - public void testGetHomeDir() throws Exception { - SSHRemoteExecution sshRE = new SSHRemoteExecution(); - String ret = sshRE.getHomeDir(); - assertEquals(System.getProperty("user.home"), - ret + System.getProperty("file.separator") + - System.getProperty("user.name")); - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/HDFSPolicyProviderAspect.aj b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/HDFSPolicyProviderAspect.aj deleted file mode 100644 index 4738c254b2b..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/HDFSPolicyProviderAspect.aj +++ /dev/null @@ -1,63 +0,0 @@ -/** - * 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.hadoop.hdfs; - -import java.util.ArrayList; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.test.system.DaemonProtocol; -import org.apache.hadoop.hdfs.test.system.DNProtocol; -import org.apache.hadoop.hdfs.test.system.NNProtocol; -import org.apache.hadoop.security.authorize.Service; -import org.apache.hadoop.security.authorize.ServiceAuthorizationManager; - -/** - * This aspect adds two HDFS Herriot specific protocols tp the list of 'authorized' - * Herriot protocols. - * Protocol descriptors i.e. 'security.nn.protocol.acl' have to be added to - * hadoop-policy.xml if present - */ -public privileged aspect HDFSPolicyProviderAspect { - private static final Log LOG = LogFactory - .getLog(HDFSPolicyProviderAspect.class); - - ArrayList herriotHDFSServices = null; - - pointcut updateHDFSServices() : - execution (public Service[] HDFSPolicyProvider.getServices()); - - Service[] around() : updateHDFSServices () { - herriotHDFSServices = new ArrayList(); - for (Service s : HDFSPolicyProvider.hdfsServices) { - LOG.debug("Copying configured protocol to " - + s.getProtocol().getCanonicalName()); - herriotHDFSServices.add(s); - } - herriotHDFSServices.add(new Service("security.daemon.protocol.acl", - DaemonProtocol.class)); - herriotHDFSServices.add(new Service("security.nn.protocol.acl", - NNProtocol.class)); - herriotHDFSServices.add(new Service("security.dn.protocol.acl", - DNProtocol.class)); - final Service[] retArray = herriotHDFSServices - .toArray(new Service[herriotHDFSServices.size()]); - LOG.debug("Number of configured protocols to return: " + retArray.length); - return retArray; - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/datanode/DataNodeAspect.aj b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/datanode/DataNodeAspect.aj deleted file mode 100644 index e2f3ec32710..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/datanode/DataNodeAspect.aj +++ /dev/null @@ -1,70 +0,0 @@ -/** - * 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.hadoop.hdfs.server.datanode; - -import java.io.File; -import java.io.IOException; -import java.util.AbstractList; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.test.system.DNProtocol; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.test.system.DaemonProtocol; -import org.apache.hadoop.hdfs.server.datanode.SecureDataNodeStarter.SecureResources; - -public privileged aspect DataNodeAspect { - declare parents : DataNode implements DNProtocol; - - public Configuration DataNode.getDaemonConf() { - return super.getConf(); - } - - pointcut dnConstructorPointcut(Configuration conf, AbstractList dirs, - SecureResources resources) : - call(DataNode.new(Configuration, AbstractList, SecureResources)) - && args(conf, dirs, resources); - - after(Configuration conf, AbstractList dirs, SecureResources resources) - returning (DataNode datanode): - dnConstructorPointcut(conf, dirs, resources) { - try { - UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - datanode.setUser(ugi.getShortUserName()); - } catch (IOException e) { - datanode.LOG.warn("Unable to get the user information for the " + - "DataNode"); - } - datanode.setReady(true); - } - - pointcut getVersionAspect(String protocol, long clientVersion) : - execution(public long DataNode.getProtocolVersion(String , - long) throws IOException) && args(protocol, clientVersion); - - long around(String protocol, long clientVersion) : - getVersionAspect(protocol, clientVersion) { - if(protocol.equals(DaemonProtocol.class.getName())) { - return DaemonProtocol.versionID; - } else if(protocol.equals(DNProtocol.class.getName())) { - return DNProtocol.versionID; - } else { - return proceed(protocol, clientVersion); - } - } -} \ No newline at end of file diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/namenode/NameNodeAspect.aj b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/namenode/NameNodeAspect.aj deleted file mode 100644 index 068382d4351..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/aop/org/apache/hadoop/hdfs/server/namenode/NameNodeAspect.aj +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 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.hadoop.hdfs.server.namenode; - -import java.io.IOException; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.test.system.NNProtocol; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.test.system.DaemonProtocol; - -public privileged aspect NameNodeAspect { - declare parents : NameNode implements NNProtocol; - - // Namename doesn't store a copy of its configuration - // because it can be changed through the life cycle of the object - // So, the an exposed reference needs to be added and updated after - // new NameNode(Configuration conf) is complete - Configuration NameNode.configRef = null; - - // Method simply assign a reference to the NameNode configuration object - void NameNode.setRef (Configuration conf) { - if (configRef == null) - configRef = conf; - } - - public Configuration NameNode.getDaemonConf() { - return configRef; - } - - pointcut nnConstructorPointcut(Configuration conf) : - call(NameNode.new(Configuration)) && args(conf); - - after(Configuration conf) returning (NameNode namenode): - nnConstructorPointcut(conf) { - try { - UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - namenode.setUser(ugi.getShortUserName()); - } catch (IOException e) { - namenode.LOG.warn("Unable to get the user information for the " + - "Jobtracker"); - } - namenode.setRef(conf); - namenode.setReady(true); - } - - pointcut getVersionAspect(String protocol, long clientVersion) : - execution(public long NameNode.getProtocolVersion(String , - long) throws IOException) && args(protocol, clientVersion); - - long around(String protocol, long clientVersion) : - getVersionAspect(protocol, clientVersion) { - if(protocol.equals(DaemonProtocol.class.getName())) { - return DaemonProtocol.versionID; - } else if(protocol.equals(NNProtocol.class.getName())) { - return NNProtocol.versionID; - } else { - return proceed(protocol, clientVersion); - } - } -} \ No newline at end of file diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/conf/system-test-hdfs.xml b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/conf/system-test-hdfs.xml deleted file mode 100644 index 4e540623641..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/conf/system-test-hdfs.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - test.system.hdrc.hadoophome - $(TO_DO_HADOOP_INSTALL)/share/hadoop-current - This is the path to the home directory of the hadoop deployment. - - - - test.system.hdrc.hadoopconfdir - $(TO_DO_HADOOP_INSTALL)/conf/hadoop - This is the path to the configuration directory of the hadoop - cluster that is deployed. - - - - - test.system.hdrc.dn.hostfile - slaves.localcopy.txt - File name containing the hostnames where the DataNodes are running. - - - - - test.system.hdfs.clusterprocess.impl.class - org.apache.hadoop.hdfs.test.system.HDFSCluster$HDFSProcessManager - - Cluster process manager for the Hdfs subsystem of the cluster. The value - org.apache.hadoop.hdfs.test.system.HDFSCluster$MultiUserHDFSProcessManager can - be used to enable multi user support. - - - - - test.system.hdrc.deployed.scripts.dir - ./src/test/system/scripts - - This directory hosts the scripts in the deployed location where - the system test client runs. - - - - - test.system.hdrc.hadoopnewconfdir - $(TO_DO_GLOBAL_TMP_DIR)/newconf - - The directory where the new config files will be copied to in all - the clusters is pointed out this directory. - - - - - test.system.hdrc.suspend.cmd - kill -SIGSTOP - - Command for suspending the given process. - - - - - test.system.hdrc.resume.cmd - kill -SIGCONT - - Command for resuming the given suspended process. - - - - test.system.hdrc.hadoop.local.confdir - $(TO_DO_GLOBAL_TMP_DIR)/localconf - - A local directory where a new config file is placed before - being pushed into new config location on the cluster. - - - - - - - test.system.hdfs.clusterprocess.impl.class - org.apache.hadoop.hdfs.test.system.HDFSCluster$MultiUserHDFSProcessManager - - Enabling multi user based cluster process manger. - - - - test.system.hdrc.multi-user.list.path - $(TO_DO_HADOOP_INSTALL)/conf/hadoop/proxyusers - - Multi user list for creating the proxy users. - - - - test.system.hdrc.multi-user.binary.path - $(TO_DO_HADOOP_INSTALL)/conf/hadoop/runAs - - Local file system path on gate way to cluster-controller binary including the binary name. - To build the binary the following commands need to be executed: - % ant run-as -Drun-as.hadoop.home.dir=(HADOOP_PREFIX of setup cluster) - % cp build-fi/system/c++-build/runAs test.system.hdrc.multi-user.binary.path - Location of the cluster is important security precaution. - The binary should be owned by root and test user group permission should be set such a - way that it can be executed by binary. Example usage would be: - % sudo chown root binary - % sudo chmod 6511 binary - Change permission appropriately to make it more secure. - - - - test.system.hdrc.multi-user.managinguser.namenode - * - - User value for managing the particular daemon, please note that these user should be - present on gateways also, an example configuration for the above would be - key name = test.system.hdrc.multi-user.managinguser.namenode - key value = guest - Please note the daemon names are all lower case, corresponding to hadoop-daemon.sh command. - - - - test.system.hdrc.multi-user.managinguser.datanode - * - - - diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNClient.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNClient.java deleted file mode 100644 index 2376892c53b..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNClient.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * 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.hadoop.hdfs.test.system; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.test.system.process.RemoteProcess; - -/** - * Datanode client for system tests. Assumption of the class is that the - * configuration key is set for the configuration key : {@code - * DFSConfigKeys.DFS_DATANODE_IPC_ADDRESS_KEY} is set, only the port portion of - * the address is used. - */ -public class DNClient extends HDFSDaemonClient { - - DNProtocol proxy; - private static final String HADOOP_DATANODE_OPTS_ENV = "HADOOP_DATANODE_OPTS"; - - public DNClient(Configuration conf, RemoteProcess process) throws IOException { - super(conf, process); - } - - @Override - public void connect() throws IOException { - if (isConnected()) { - return; - } - String sockAddrStr = getConf().get(DFSConfigKeys.DFS_DATANODE_IPC_ADDRESS_KEY); - if (sockAddrStr == null) { - throw new IllegalArgumentException("Datenode IPC address is not set." - + "Check if " + DFSConfigKeys.DFS_DATANODE_IPC_ADDRESS_KEY - + " is configured."); - } - String[] splits = sockAddrStr.split(":"); - if (splits.length != 2) { - throw new IllegalArgumentException( - "Datanode IPC address is not correctly configured"); - } - String port = splits[1]; - String sockAddr = getHostName() + ":" + port; - InetSocketAddress bindAddr = NetUtils.createSocketAddr(sockAddr); - proxy = (DNProtocol) RPC.getProxy(DNProtocol.class, DNProtocol.versionID, - bindAddr, getConf()); - setConnected(true); - } - - @Override - public void disconnect() throws IOException { - RPC.stopProxy(proxy); - setConnected(false); - } - - @Override - protected DNProtocol getProxy() { - return proxy; - } - - public Configuration getDatanodeConfig() throws IOException { - return getProxy().getDaemonConf(); - } - - @Override - public String getHadoopOptsEnvName() { - return HADOOP_DATANODE_OPTS_ENV; - } - - /** - * Concrete implementation of abstract super class method - * @param attributeName name of the attribute to be retrieved - * @return Object value of the given attribute - * @throws IOException is thrown in case of communication errors - */ - @Override - public Object getDaemonAttribute (String attributeName) throws IOException { - return getJmxAttribute("DataNode", "DataNodeInfo", attributeName); - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNProtocol.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNProtocol.java deleted file mode 100644 index 31bdd7f0aa9..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/DNProtocol.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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.hadoop.hdfs.test.system; - -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.security.KerberosInfo; -import org.apache.hadoop.test.system.DaemonProtocol; - -/** - * Client side API exposed from Datanode. - * Actual implementations are likely to be injected - * - * The protocol has to be annotated so KerberosInfo can be filled in during - * creation of a ipc.Client connection - */ -@KerberosInfo( - serverPrincipal = DFSConfigKeys.DFS_DATANODE_USER_NAME_KEY) -public interface DNProtocol extends DaemonProtocol { - public static final long versionID = 1L; -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSCluster.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSCluster.java deleted file mode 100644 index d9504f8faec..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSCluster.java +++ /dev/null @@ -1,149 +0,0 @@ -/** - * 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.hadoop.hdfs.test.system; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.test.system.AbstractDaemonClient; -import org.apache.hadoop.test.system.AbstractDaemonCluster; -import org.apache.hadoop.test.system.process.ClusterProcessManager; -import org.apache.hadoop.test.system.process.HadoopDaemonRemoteCluster; -import org.apache.hadoop.test.system.process.MultiUserHadoopDaemonRemoteCluster; -import org.apache.hadoop.test.system.process.RemoteProcess; -import org.apache.hadoop.test.system.process.HadoopDaemonRemoteCluster.HadoopDaemonInfo; - -public class HDFSCluster extends AbstractDaemonCluster { - - static { - Configuration.addDefaultResource("hdfs-site.xml"); - } - - private static final Log LOG = LogFactory.getLog(HDFSCluster.class); - public static final String CLUSTER_PROCESS_MGR_IMPL = - "test.system.hdfs.clusterprocess.impl.class"; - - private HDFSCluster(Configuration conf, ClusterProcessManager rCluster) - throws IOException { - super(conf, rCluster); - } - - /** - * Key is used to to point to the file containing hostnames of tasktrackers - */ - public static final String CONF_HADOOP_DN_HOSTFILE_NAME = - "test.system.hdrc.dn.hostfile"; - - private static List hdfsDaemonInfos; - - private static String nnHostName; - private static String DN_hostFileName; - - protected enum Role {NN, DN} - - @Override - protected AbstractDaemonClient - createClient(RemoteProcess process) throws IOException { - Enum pRole = process.getRole(); - if (Role.NN.equals(pRole)) { - return createNNClient(process); - } else if (Role.DN.equals(pRole)) { - return createDNClient(process); - } else throw new IOException("Role " + pRole + - " is not supported by HDFSCluster"); - } - - protected DNClient createDNClient(RemoteProcess dnDaemon) throws IOException { - return new DNClient(getConf(), dnDaemon); - } - - protected NNClient createNNClient(RemoteProcess nnDaemon) throws IOException { - return new NNClient(getConf(), nnDaemon); - } - - public NNClient getNNClient () { - Iterator iter = getDaemons().get(Role.NN).iterator(); - return (NNClient) iter.next(); - } - - public List getDNClients () { - return (List) getDaemons().get(Role.DN); - } - - public DNClient getDNClient (String hostname) { - for (DNClient dnC : getDNClients()) { - if (dnC.getHostName().equals(hostname)) - return dnC; - } - return null; - } - - public static class HDFSProcessManager extends HadoopDaemonRemoteCluster { - public HDFSProcessManager() { - super(hdfsDaemonInfos); - } - } - - public static class MultiUserHDFSProcessManager - extends MultiUserHadoopDaemonRemoteCluster { - public MultiUserHDFSProcessManager() { - super(hdfsDaemonInfos); - } - } - - - public static HDFSCluster createCluster(Configuration conf) throws Exception { - conf.addResource("system-test.xml"); - String sockAddrStr = FileSystem.getDefaultUri(conf).getAuthority(); - if (sockAddrStr == null) { - throw new IllegalArgumentException("Namenode IPC address is not set"); - } - String[] splits = sockAddrStr.split(":"); - if (splits.length != 2) { - throw new IllegalArgumentException( - "Namenode report IPC is not correctly configured"); - } - nnHostName = splits[0]; - DN_hostFileName = conf.get(CONF_HADOOP_DN_HOSTFILE_NAME, "slaves"); - - hdfsDaemonInfos = new ArrayList(); - hdfsDaemonInfos.add(new HadoopDaemonInfo("namenode", - Role.NN, Arrays.asList(new String[]{nnHostName}))); - hdfsDaemonInfos.add(new HadoopDaemonInfo("datanode", - Role.DN, DN_hostFileName)); - - String implKlass = conf.get(CLUSTER_PROCESS_MGR_IMPL); - if (implKlass == null || implKlass.isEmpty()) { - implKlass = HDFSCluster.HDFSProcessManager.class.getName(); - } - Class klass = - (Class) Class.forName(implKlass); - ClusterProcessManager clusterProcessMgr = klass.newInstance(); - LOG.info("Created ClusterProcessManager as " + implKlass); - clusterProcessMgr.init(conf); - return new HDFSCluster(conf, clusterProcessMgr); - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSDaemonClient.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSDaemonClient.java deleted file mode 100644 index 4316b36ac3b..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/HDFSDaemonClient.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * 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.hadoop.hdfs.test.system; - -import java.io.IOException; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.test.system.AbstractDaemonClient; -import org.apache.hadoop.test.system.DaemonProtocol; -import org.apache.hadoop.test.system.process.RemoteProcess; - -public abstract class HDFSDaemonClient - extends AbstractDaemonClient { - - public HDFSDaemonClient(Configuration conf, RemoteProcess process) - throws IOException { - super(conf, process); - } - - public String[] getHDFSDataDirs() throws IOException { - return getProxy().getDaemonConf().getStrings( - DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY); - } - - public String getHDFSNameDirs() throws IOException { - return getProxy().getDaemonConf().getStrings( - DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY)[0]; - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNClient.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNClient.java deleted file mode 100644 index 79be0e18f8e..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNClient.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * 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.hadoop.hdfs.test.system; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.ipc.RPC; -import org.apache.hadoop.net.NetUtils; -import org.apache.hadoop.test.system.process.RemoteProcess; - -public class NNClient extends HDFSDaemonClient { - - NNProtocol proxy; - private static final String HADOOP_NAMENODE_OPTS_ENV = "HADOOP_NAMENODE_OPTS"; - - public NNClient(Configuration conf, RemoteProcess process) throws IOException { - super(conf, process); - } - - @Override - public void connect() throws IOException { - if (isConnected()) - return; - String sockAddrStr = FileSystem.getDefaultUri(getConf()).getAuthority(); - if (sockAddrStr == null) { - throw new IllegalArgumentException("Namenode IPC address is not set"); - } - String[] splits = sockAddrStr.split(":"); - if (splits.length != 2) { - throw new IllegalArgumentException( - "Namenode report IPC is not correctly configured"); - } - String port = splits[1]; - String sockAddr = getHostName() + ":" + port; - - InetSocketAddress bindAddr = NetUtils.createSocketAddr(sockAddr); - proxy = (NNProtocol) RPC.getProxy(NNProtocol.class, NNProtocol.versionID, - bindAddr, getConf()); - setConnected(true); - } - - @Override - public void disconnect() throws IOException { - RPC.stopProxy(proxy); - setConnected(false); - } - - @Override - protected NNProtocol getProxy() { - return proxy; - } - - @Override - public String getHadoopOptsEnvName() { - return HADOOP_NAMENODE_OPTS_ENV; - } - - /** - * Concrete implementation of abstract super class method - * @param attributeName name of the attribute to be retrieved - * @return Object value of the given attribute - * @throws IOException is thrown in case of communication errors - */ - @Override - public Object getDaemonAttribute (String attributeName) throws IOException { - return getJmxAttribute("NameNode", "NameNodeInfo", attributeName); - } -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNProtocol.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNProtocol.java deleted file mode 100644 index 2665d23d4ba..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/java/org/apache/hadoop/hdfs/test/system/NNProtocol.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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.hadoop.hdfs.test.system; - -import org.apache.hadoop.hdfs.DFSConfigKeys; -import org.apache.hadoop.security.KerberosInfo; -import org.apache.hadoop.test.system.DaemonProtocol; - -/** - * Client side API exposed from Namenode. - * Actual implementations are likely to be injected - * - * The protocol has to be annotated so KerberosInfo can be filled in during - * creation of a ipc.Client connection - */ -@KerberosInfo( - serverPrincipal = DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY) -public interface NNProtocol extends DaemonProtocol { - public static final long versionID = 1L; -} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/test/org/apache/hadoop/hdfs/TestHL040.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/system/test/org/apache/hadoop/hdfs/TestHL040.java deleted file mode 100644 index 43dcae541d2..00000000000 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/system/test/org/apache/hadoop/hdfs/TestHL040.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * 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.hadoop.hdfs; - -import java.io.IOException; -import java.util.Collection; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hdfs.test.system.DNClient; -import org.apache.hadoop.hdfs.test.system.HDFSCluster; -import org.apache.hadoop.hdfs.test.system.NNClient; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mortbay.util.ajax.JSON; - -public class TestHL040 { - private HDFSCluster cluster = null; - private static final Log LOG = LogFactory.getLog(TestHL040.class); - - public TestHL040() throws Exception { - } - - @Before - public void setupUp() throws Exception { - cluster = HDFSCluster.createCluster(new Configuration()); - cluster.setUp(); - } - - @After - public void tearDown() throws Exception { - cluster.tearDown(); - } - - @Test - public void testConnect() throws IOException { - LOG.info("Staring TestHL040: connecting to the HDFSCluster "); - LOG.info("================ Getting namenode info ================"); - NNClient dfsMaster = cluster.getNNClient(); - LOG.info("Process info of namenode " + dfsMaster.getHostName() + " is: " + - dfsMaster.getProcessInfo()); - LOG.info("================ Getting datanode info ================"); - Collection clients = cluster.getDNClients(); - for (DNClient dnC : clients) { - LOG.info("Process info of datanode " + dnC.getHostName() + " is: " + - dnC.getProcessInfo()); - Assert.assertNotNull("Datanode process info isn't suppose to be null", - dnC.getProcessInfo()); - LOG.info("Free space " + getFreeSpace(dnC)); - } - } - - private long getFreeSpace(DNClient dnC) throws IOException { - Object volObj = dnC.getDaemonAttribute("VolumeInfo"); - Assert.assertNotNull("Attribute value is expected to be not null", volObj); - LOG.debug("Got object: " + volObj); - Map volInfoMap = (Map) JSON.parse(volObj.toString()); - long totalFreeSpace = 0L; - for (Object key : volInfoMap.keySet()) { - Map attrMap = (Map) volInfoMap.get(key); - long freeSpace = (Long) attrMap.get("freeSpace"); - totalFreeSpace += freeSpace; - } - return totalFreeSpace; - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/GridmixSystemTestCase.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/GridmixSystemTestCase.java deleted file mode 100644 index b70fb9aeffb..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/GridmixSystemTestCase.java +++ /dev/null @@ -1,231 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.mapreduce.test.system.MRCluster; -import org.apache.hadoop.mapreduce.test.system.JTProtocol; -import org.apache.hadoop.mapreduce.test.system.JTClient; -import org.apache.hadoop.mapred.JobConf; -import org.apache.hadoop.mapred.gridmix.test.system.GridmixJobSubmission; -import org.apache.hadoop.mapred.gridmix.test.system.GridmixJobVerification; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridmixJobStory; -import org.apache.hadoop.tools.rumen.ZombieJob; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.mapreduce.JobID; -import org.junit.AfterClass; -import org.junit.BeforeClass; - -import java.util.Iterator; -import java.util.Map; -import java.util.List; -import java.util.Set; -import java.io.IOException; -import org.junit.Assert; - -/** - * Run and verify the Gridmix jobs for given a trace. - */ -public class GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(GridmixSystemTestCase.class); - protected static Configuration conf = new Configuration(); - protected static MRCluster cluster; - protected static int cSize; - protected static JTClient jtClient; - protected static JTProtocol rtClient; - protected static Path gridmixDir; - protected static Map map; - protected static GridmixJobSubmission gridmixJS; - protected static GridmixJobVerification gridmixJV; - protected static List jobids; - - @BeforeClass - public static void before() throws Exception { - String [] excludeExpList = {"java.net.ConnectException", - "java.io.IOException"}; - cluster = MRCluster.createCluster(conf); - cluster.setExcludeExpList(excludeExpList); - cluster.setUp(); - cSize = cluster.getTTClients().size(); - jtClient = cluster.getJTClient(); - rtClient = jtClient.getProxy(); - gridmixDir = new Path("herriot-gridmix"); - UtilsForGridmix.createDirs(gridmixDir, rtClient.getDaemonConf()); - map = UtilsForGridmix.getMRTraces(rtClient.getDaemonConf()); - } - - @AfterClass - public static void after() throws Exception { - UtilsForGridmix.cleanup(gridmixDir, rtClient.getDaemonConf()); - org.apache.hadoop.fs.FileUtil.fullyDelete(new java.io.File(System. - getProperty("java.io.tmpdir") + "/gridmix-st/")); - cluster.tearDown(); - - /* Clean up the proxy user directories if gridmix run with - RoundRobinUserResovler mode.*/ - if (gridmixJV != null - && gridmixJV.getJobUserResolver().contains("RoundRobin")) { - List proxyUsers = - UtilsForGridmix.listProxyUsers(gridmixJS.getJobConf(), - UserGroupInformation.getLoginUser().getShortUserName()); - for(int index = 0; index < proxyUsers.size(); index++){ - UtilsForGridmix.cleanup(new Path("hdfs:///user/" + - proxyUsers.get(index)), - rtClient.getDaemonConf()); - } - } - } - - /** - * Run the gridmix with specified runtime parameters and - * verify the jobs the after completion of execution. - * @param runtimeValues - common runtime arguments for gridmix. - * @param otherValues - test specific runtime arguments for gridmix. - * @param tracePath - path of a trace file. - * @throws Exception - if an exception occurs. - */ - public static void runGridmixAndVerify(String[] runtimeValues, - String [] otherValues, String tracePath) throws Exception { - runGridmixAndVerify(runtimeValues, otherValues, tracePath , - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Run the gridmix with specified runtime parameters and - * verify the jobs the after completion of execution. - * @param runtimeValues - common runtime arguments for gridmix. - * @param otherValues - test specific runtime arguments for gridmix. - * @param tracePath - path of a trace file. - * @param mode - 1 for data generation, 2 for run the gridmix and 3 for - * data generation and run the gridmix. - * @throws Exception - if an exception occurs. - */ - public static void runGridmixAndVerify(String [] runtimeValues, - String [] otherValues, String tracePath, int mode) throws Exception { - List jobids = runGridmix(runtimeValues, otherValues, mode); - gridmixJV = new GridmixJobVerification(new Path(tracePath), - gridmixJS.getJobConf(), jtClient); - gridmixJV.verifyGridmixJobsWithJobStories(jobids); - } - - /** - * Run the gridmix with user specified mode. - * @param runtimeValues - common runtime parameters for gridmix. - * @param otherValues - test specifix runtime parameters for gridmix. - * @param mode - 1 for data generation, 2 for run the gridmix and 3 for - * data generation and run the gridmix. - * @return - list of gridmix job ids. - * @throws Exception - if an exception occurs. - */ - public static List runGridmix(String[] runtimeValues, - String[] otherValues, int mode) throws Exception { - gridmixJS = new GridmixJobSubmission(rtClient.getDaemonConf(), - jtClient, gridmixDir); - gridmixJS.submitJobs(runtimeValues, otherValues, mode); - List jobids = - UtilsForGridmix.listGridmixJobIDs(jtClient.getClient(), - gridmixJS.getGridmixJobCount()); - return jobids; - } - - /** - * get the trace file based on given regular expression. - * @param regExp - trace file file pattern. - * @return - trace file as string. - * @throws IOException - if an I/O error occurs. - */ - public static String getTraceFile(String regExp) throws IOException { - List listTraces = UtilsForGridmix.listMRTraces( - rtClient.getDaemonConf()); - Iterator ite = listTraces.iterator(); - while(ite.hasNext()) { - String traceFile = ite.next(); - if (traceFile.indexOf(regExp)>=0) { - return traceFile; - } - } - return null; - } - - /** - * Validate the task memory parameters. - * @param tracePath - trace file. - * @param isTraceHasHighRamJobs - true if trace has high ram job(s) - * otherwise its false - */ - @SuppressWarnings("deprecation") - public static void validateTaskMemoryParamters(String tracePath, - boolean isTraceHasHighRamJobs) throws IOException { - if (isTraceHasHighRamJobs) { - GridmixJobStory gjs = new GridmixJobStory(new Path(tracePath), - rtClient.getDaemonConf()); - Set jobids = gjs.getZombieJobs().keySet(); - boolean isHighRamFlag = false; - for (JobID jobid :jobids) { - ZombieJob zombieJob = gjs.getZombieJobs().get(jobid); - JobConf origJobConf = zombieJob.getJobConf(); - int origMapFactor = - GridmixJobVerification.getMapFactor(origJobConf); - int origReduceFactor = - GridmixJobVerification.getReduceFactor(origJobConf); - if (origMapFactor >= 2 || origReduceFactor >= 2) { - isHighRamFlag = true; - long TaskMapMemInMB = - GridmixJobVerification.getScaledTaskMemInMB( - GridMixConfig.JOB_MAP_MEMORY_MB, - GridMixConfig.CLUSTER_MAP_MEMORY, - origJobConf, rtClient.getDaemonConf()); - - long TaskReduceMemInMB = - GridmixJobVerification.getScaledTaskMemInMB( - GridMixConfig.JOB_REDUCE_MEMORY_MB, - GridMixConfig.CLUSTER_REDUCE_MEMORY, - origJobConf, rtClient.getDaemonConf()); - long taskMapLimitInMB = - conf.getLong(GridMixConfig.CLUSTER_MAX_MAP_MEMORY, - JobConf.DISABLED_MEMORY_LIMIT); - - long taskReduceLimitInMB = - conf.getLong(GridMixConfig.CLUSTER_MAX_REDUCE_MEMORY, - JobConf.DISABLED_MEMORY_LIMIT); - - GridmixJobVerification.verifyMemoryLimits(TaskMapMemInMB, - taskMapLimitInMB); - GridmixJobVerification.verifyMemoryLimits(TaskReduceMemInMB, - taskReduceLimitInMB); - } - } - Assert.assertTrue("Trace doesn't have atleast one high ram job.", - isHighRamFlag); - } - } - - public static boolean isLocalDistCache(String fileName, String userName, - boolean visibility) { - return DistributedCacheEmulator.isLocalDistCacheFile(fileName, - userName, visibility); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithCustomInterval.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithCustomInterval.java deleted file mode 100644 index dd8e51edfd7..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithCustomInterval.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test cpu emulation with default interval for gridmix jobs - * against different input data, submission policies and user resolvers. - * Verify the cpu resource metrics of both maps and reduces phase of - * Gridmix jobs with their corresponding original job in the input trace. - */ -public class TestCPUEmulationForMapsAndReducesWithCustomInterval - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestCPUEmulationWithUncompressedInput.class"); - int execMode = GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue(); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * cpu emulation feature with default setting. The {@link Gridmix} - * should use the following runtime parameters. - * Submission Policy : STRESS, UserResovler: RoundRobinUserResolver. - * Once the {@link Gridmix} run is complete, verify cpu resource metrics of - * {@link Gridmix} jobs with their corresponding original job in a trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulationForMapsAndReducesWithCompressedInputCase7() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("cpu_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_CUSTOM_INTERVAL + "=0.35F", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * cpu emulation feature with default setting. The {@link Gridmix} - * should use the following runtime parameters. - * Submission Policy : SERIAL, UserResovler: SubmitterUserResolver - * Once the {@link Gridmix} run is complete, verify cpu resource metrics of - * {@link Gridmix} jobs with their corresponding original job in a trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsAndReducesWithUncompressedInputCase8() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("cpu_emul_case2"); - Assert.assertNotNull("Trace file not found.", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_CUSTOM_INTERVAL + "=0.4F", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } -} - - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithDefaultInterval.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithDefaultInterval.java deleted file mode 100644 index edd14a6bcbf..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsAndReducesWithDefaultInterval.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.JobContext; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test cpu emulation with default interval for gridmix jobs - * against different input data, submission policies and user resolvers. - * Verify the cpu resource metrics for both maps and reduces of - * Gridmix jobs with their corresponding original job in the input trace. - */ -public class TestCPUEmulationForMapsAndReducesWithDefaultInterval - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestCPUEmulationForMapsAndReducesWithDefaultInterval.class"); - int execMode = GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue(); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * cpu emulation feature with default setting. The {@link Gridmix} - * should use the following runtime parameters. - * Submission Policy : REPLAY, UserResovler: RoundRobinUserResolver. - * Once the {@link Gridmix} run is complete, verify cpu resource metrics of - * {@link Gridmix} jobs with their corresponding original jobs in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulationForMapsAndReducesWithCompressedInputCase5() - throws Exception { - final long inputSizeInMB = 7168; - String tracePath = getTraceFile("cpu_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", JobContext.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * cpu emulation feature with default settings. The {@link Gridmix} - * should use the following runtime parameters. - * Submission Policy : STRESS, UserResovler: SubmitterUserResolver - * Once the Gridmix run is complete, verify cpu resource metrics of - * {@link Gridmix} jobs with their corresponding original jobs in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsAndReducesWithUncompressedInputCase6() - throws Exception { - final long inputSizeInMB = cSize * 400; - String tracePath = getTraceFile("cpu_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", JobContext.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithCustomInterval.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithCustomInterval.java deleted file mode 100644 index ac5205818cc..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithCustomInterval.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} cpu emulation with custom interval for - * gridmix jobs against different input data, submission policies and - * user resolvers. Verify the map phase cpu metrics of gridmix jobs - * against their original job in the trace. - */ -public class TestCPUEmulationForMapsWithCustomInterval - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestCPUEmulationForMapsWithCustomInterval.class"); - int execMode = GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue(); - - /** - * Generate compressed input and run {@link Gridmix} by turning on - * cpu emulation feature with custom setting. The {@link Gridmix} should - * use the following runtime parameters while running gridmix jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Once {@link Gridmix} run is complete, verify maps phase cpu resource - * metrics of {@link Gridmix} jobs with their corresponding original - * in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsWithCompressedInputCase3() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("cpu_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_CUSTOM_INTERVAL + "=0.25F"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on - * cpu emulation feature with custom settings. The {@link Gridmix} - * should use the following runtime paramters while running gridmix jobs. - * Submission Policy: REPLAY User Resolver Mode: RoundRobinUserResolver - * Once {@link Gridmix} run is complete, verify the map phase cpu resource - * metrics of {@link Gridmix} jobs with their corresponding jobs - * in the original trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsUnCompressedInputCase4() - throws Exception { - final long inputSizeInMB = cSize * 200; - String tracePath = getTraceFile("cpu_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN, - "-D", GridMixConfig.GRIDMIX_CPU_CUSTOM_INTERVAL + "=0.35F"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithDefaultInterval.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithDefaultInterval.java deleted file mode 100644 index 6eabc53838c..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCPUEmulationForMapsWithDefaultInterval.java +++ /dev/null @@ -1,103 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} cpu emulation with default settings for - * gridmix jobs against different input data, submission policies and - * user resolvers. Verify the map phase cpu metrics of gridmix jobs - * against their original jobs in the trace. - */ -public class TestCPUEmulationForMapsWithDefaultInterval - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestCPUEmulationForMapsWithDefaultInterval.class"); - int execMode = GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue(); - - /** - * Generate compressed input and run {@link Gridmix} by turning on cpu - * emulation feature with default settings. The {@link Gridmix} should - * use the following runtime parameters while running the gridmix jobs. - * Submission Policy: STRESS, UserResolver: SubmitterUserResolver. - * Once the {@link Gridmix} run is complete, verify map phase cpu metrics of - * {@link Gridmix} jobs with their corresponding original job in a trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsWithCompressedInputCase1() - throws Exception { - final long inputSizeInMB = 1024 * 6; - String tracePath = getTraceFile("cpu_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_HIGH_RAM_JOB_ENABLE + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, execMode); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on - * cpu emulation feature with default settings. The {@link Gridmix} - * should use the following runtime parameters while running Gridmix jobs. - * Submission Policy: REPLAY, UserResolver: RoundRobinUserResolver - * Once the Gridmix run is complete, verify cpu resource metrics of - * {@link Gridmix} jobs with their corresponding original job in a trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testCPUEmulatonForMapsWithUnCompressedInputCase2() - throws Exception { - final long inputSizeInMB = cSize * 200; - String tracePath = getTraceFile("cpu_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_HIGH_RAM_JOB_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_CPU_EMULATON + "=" + - GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationEnableForAllTypesOfJobs.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationEnableForAllTypesOfJobs.java deleted file mode 100644 index 3ade9e34e68..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationEnableForAllTypesOfJobs.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the compression emulation for all the jobs in the trace - * irrespective of compressed inputs. - */ -public class TestCompressionEmulationEnableForAllTypesOfJobs - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestCompressionEmulationEnableForAllTypesOfJobs.class"); - - /** - * Generate compressed input data and verify the compression emulation - * for all the jobs in the trace irrespective of whether the original - * job uses the compressed input or not.Also use the custom compression - * ratios for map input, map output and reduce output. - * @throws Exception - if an error occurs. - */ - @Test - public void testInputCompressionEmualtionEnableForAllJobsWithDefaultRatios() - throws Exception { - final long inputSizeInMB = 1024 * 6; - final String tracePath = getTraceFile("compression_case4_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_INPUT_DECOMPRESS_ENABLE + "=true", - "-D", GridMixConfig.GRIDMIX_INPUT_COMPRESS_RATIO + "=0.46", - "-D", GridMixConfig.GRIDMIX_INTERMEDIATE_COMPRESSION_RATIO + "=0.35", - "-D", GridMixConfig.GRIDMIX_OUTPUT_COMPRESSION_RATIO + "=0.36" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Use existing compressed input data and turn off the compression - * emulation. Verify the compression emulation whether it uses - * by the jobs or not. - * @throws Exception - if an error occurs. - */ - @Test - public void testInputCompressionEmulationEnableForAllJobsWithCustomRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case4_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForCompressInAndUncompressOut.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForCompressInAndUncompressOut.java deleted file mode 100644 index 4b7fc3a15aa..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForCompressInAndUncompressOut.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Assert; -import org.junit.Test; -/** - * Verify the gridmix jobs compression ratio's of input, - * intermediate input and with default/custom ratios.Also verify - * the compressed output file format is enabled or not. - * - */ -public class TestCompressionEmulationForCompressInAndUncompressOut - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestCompressionEmulationForCompressInAndUncompressOut.class"); - final long inputSizeInMB = 1024 * 6; - - /** - * Generate a compressed input data and verify the compression ratios - * of map input and map output against default compression ratios - * and also verify the whether the compressed output file output format - * is enabled or not. - * @throws Exception -if an error occurs. - */ - @Test - public void testCompressionEmulationOfCompressedInputWithDefaultRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case2_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Use existing compressed input data and verify the compression ratios - * of input and intermediate input against custom compression ratios - * and also verify the compressed output file output format is enabled or not. - * @throws Exception -if an error occurs. - */ - @Test - public void testCompressionEmulationOfCompressedInputWithCustomRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case2_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - UtilsForGridmix.cleanup(gridmixDir, rtClient.getDaemonConf()); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true", - "-D", GridMixConfig.GRIDMIX_INPUT_DECOMPRESS_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_INPUT_COMPRESS_RATIO + "=0.58", - "-D", GridMixConfig.GRIDMIX_INTERMEDIATE_COMPRESSION_RATIO + "=0.42" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForUncompressInAndCompressOut.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForUncompressInAndCompressOut.java deleted file mode 100644 index 383fc83de4b..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestCompressionEmulationForUncompressInAndCompressOut.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Assert; -import org.junit.Test; -/** - * Verify the gridmix jobs compression ratio's of reduce output and - * with default and custom ratios. - */ -public class TestCompressionEmulationForUncompressInAndCompressOut - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestCompressionEmulationForUncompressInAndCompressOut.class"); - final long inputSizeInMB = 1024 * 6; - - /** - * Generate a uncompressed input data and verify the compression ratios - * of reduce output against default output compression ratio. - * @throws Exception -if an error occurs. - */ - @Test - public void testCompressionEmulationOfCompressedOuputWithDefaultRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case3_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Use existing uncompressed input data and verify the compression ratio - * of reduce output against custom output compression ratio and also verify - * the compression output file output format. - * @throws Exception -if an error occurs. - */ - @Test - public void testCompressionEmulationOfCompressedOutputWithCustomRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case3_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - UtilsForGridmix.cleanup(gridmixDir, rtClient.getDaemonConf()); - final String [] runtimeValues = { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath }; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_OUTPUT_COMPRESSION_RATIO + "=0.38" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestDisableGridmixEmulationOfHighRam.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestDisableGridmixEmulationOfHighRam.java deleted file mode 100644 index bb77016e120..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestDisableGridmixEmulationOfHighRam.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.GridmixJob; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the {@link Gridmix} with a high ram jobs trace by disabling the - * emulation of high ram and verify each {@link Gridmix} job - * whether it honors the high ram or not. In disable mode it should - * should not honor the high ram and run it as a normal job. - */ -public class TestDisableGridmixEmulationOfHighRam - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestDisableGridmixEmulationOfHighRam.class"); - - /** - * Generate input data and run {@link Gridmix} with a high ram jobs trace - * as a load job and STRESS submission policy in a SubmitterUserResolver - * mode. Verify each {@link Gridmix} job whether it honors the - * high ram or not after completion of execution. In disable mode the - * jobs should not honor the high ram. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHighRamForReducersOfMRJobs() - throws Exception { - final long inputSizeInMB = cSize * 250; - String tracePath = getTraceFile("highram_mr_jobs_case3"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSAndLocalFSDCFiles.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSAndLocalFSDCFiles.java deleted file mode 100644 index a1ae1e9dfaf..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSAndLocalFSDCFiles.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the emulation of HDFS and Local FS distributed cache files against - * the given input trace file. - */ -public class TestEmulationOfHDFSAndLocalFSDCFiles extends - GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestEmulationOfLocalFSDCFiles.class"); - - /** - * Generate the input data and distributed cache files for HDFS and - * local FS. Verify the gridmix emulation of HDFS and Local FS - * distributed cache files in RoundRobinUserResolver mode with STRESS - * submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateDataEmulateHDFSAndLocalFSDCFiles() - throws Exception { - final long inputSizeInMB = 1024 * 6; - final String tracePath = getTraceFile("distcache_case8_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Use existing input and distributed cache files for HDFS and - * local FS. Verify the gridmix emulation of HDFS and Local FS - * distributed cache files in SubmitterUserResolver mode with REPLAY - * submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHDFSAndLocalFSDCFiles() - throws Exception { - final String tracePath = getTraceFile("distcache_case8_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues ={"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFileUsesMultipleJobs.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFileUsesMultipleJobs.java deleted file mode 100644 index 7f8938f88a7..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFileUsesMultipleJobs.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix emulation of HDFS distributed cache file which uses - * different jobs that are submitted with different users. - */ -public class TestEmulationOfHDFSDCFileUsesMultipleJobs extends - GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestEmulationOfHDFSDCFileUsesMultipleJobs.class"); - - /** - * Generate the input data and HDFS distributed cache file based - * on given input trace. Verify the Gridmix emulation of HDFS - * distributed cache file in RoundRobinResolver mode with - * STRESS submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulationOfHDFSDCFile() - throws Exception { - final long inputSizeInMB = 1024 * 6; - final String tracePath = getTraceFile("distcache_case9_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Verify the Gridmix emulation of HDFS distributed cache - * file in SubmitterUserResolver mode with STRESS submission policy - * by using the existing input data and HDFS distributed cache file. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixEmulationOfHDFSPublicDCFile() - throws Exception { - final String tracePath = getTraceFile("distcache_case9_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - tracePath}; - - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFilesWithDifferentVisibilities.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFilesWithDifferentVisibilities.java deleted file mode 100644 index 453e5b99081..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHDFSDCFilesWithDifferentVisibilities.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix emulation of HDFS distributed cache files of - * different visibilities. - */ - -public class TestEmulationOfHDFSDCFilesWithDifferentVisibilities - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestEmulationOfHDFSDCFilesWithDifferentVisibilities.class"); - - /** - * Generate input data and HDFS distributed cache files of different - * visibilities based on given input trace. Verify the Gridmix emulation - * of HDFS distributed cache files of different visibilities in - * RoundRobinUserResolver mode with SERIAL submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulateOfHDFSDCFilesWithDiffVisibilities() - throws Exception { - final long INPUT_SIZE = 1024 * 9; - final String tracePath = getTraceFile("distcache_case5_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - INPUT_SIZE+"m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Disable the distributed cache emulation and verify the Gridmix jobs - * whether it emulates or not. - * @throws Exception - */ - @Test - public void testHDFSDCFilesWithoutEnableDCEmulation() - throws Exception { - final String tracePath = getTraceFile("distcache_case6_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues ={ "LOADJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - tracePath}; - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHighRamAndNormalMRJobs.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHighRamAndNormalMRJobs.java deleted file mode 100644 index cb3a35f4270..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfHighRamAndNormalMRJobs.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the {@link Gridmix} with combination of high ram and normal jobs of - * trace and verify whether high ram jobs{@link Gridmix} are honoring or not. - * Normal MR jobs should not honors the high ram emulation. - */ -public class TestEmulationOfHighRamAndNormalMRJobs - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestEmulationOfHighRamAndNormalMRJobs.class"); - - /** - * Generate input data and run the combination normal and high ram - * {@link Gridmix} jobs as load job and STRESS submission policy - * in a SubmitterUserResolver mode. Verify whether each {@link Gridmix} - * job honors the high ram or not after completion of execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHighRamForReducersOfMRJobs() - throws Exception { - final long inputSizeInMB = cSize * 250; - String tracePath = getTraceFile("highram_mr_jobs_case4"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeArgs = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - tracePath}; - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_HIGH_RAM_JOB_ENABLE + "=true"}; - - validateTaskMemoryParamters(tracePath, true); - runGridmixAndVerify(runtimeArgs, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfLocalFSDCFiles.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfLocalFSDCFiles.java deleted file mode 100644 index eff47f2d641..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestEmulationOfLocalFSDCFiles.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the emulation of local FS distributed cache files. - * - */ -public class TestEmulationOfLocalFSDCFiles extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestEmulationOfLocalFSDCFiles.class"); - - /** - * Generate the input data and distributer cache files.Verify the - * gridmix emulation of local file system distributed cache files - * in RoundRobinUserResolver mode with REPLAY submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateInputAndEmulateLocalFSDCFile() - throws Exception { - final long inputSizeInMB = 1024 * 6; - final String tracePath = getTraceFile("distcache_case7_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Use existing input and local distributed cache files and verify - * the gridmix emulation of local file system distributed cache - * files in SubmitterUserResolver mode with STRESS - * Submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfLocalFSDCFile() - throws Exception { - final String tracePath = getTraceFile("distcache_case7_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixDataGeneration.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixDataGeneration.java deleted file mode 100644 index ef273b5fd25..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixDataGeneration.java +++ /dev/null @@ -1,229 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapreduce.test.system.MRCluster; -import org.apache.hadoop.mapreduce.test.system.JTProtocol; -import org.apache.hadoop.mapreduce.test.system.JTClient; -import org.apache.hadoop.mapred.JobClient; -import org.apache.hadoop.mapred.JobStatus; -import org.apache.hadoop.mapred.gridmix.RoundRobinUserResolver; -import org.apache.hadoop.mapred.gridmix.EchoUserResolver; -import org.apache.hadoop.mapred.gridmix.SubmitterUserResolver; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.ContentSummary; -import org.junit.BeforeClass; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.Assert; -import java.io.IOException; - -/** - * Verify the Gridmix data generation with various submission policies and - * user resolver modes. - */ -public class TestGridMixDataGeneration { - private static final Log LOG = - LogFactory.getLog(TestGridMixDataGeneration.class); - private static Configuration conf = new Configuration(); - private static MRCluster cluster; - private static JTClient jtClient; - private static JTProtocol rtClient; - private static Path gridmixDir; - private static int cSize; - - @BeforeClass - public static void before() throws Exception { - String [] excludeExpList = {"java.net.ConnectException", - "java.io.IOException"}; - cluster = MRCluster.createCluster(conf); - cluster.setExcludeExpList(excludeExpList); - cluster.setUp(); - cSize = cluster.getTTClients().size(); - jtClient = cluster.getJTClient(); - rtClient = jtClient.getProxy(); - gridmixDir = new Path("herriot-gridmix"); - UtilsForGridmix.createDirs(gridmixDir, rtClient.getDaemonConf()); - } - - @AfterClass - public static void after() throws Exception { - UtilsForGridmix.cleanup(gridmixDir,conf); - cluster.tearDown(); - } - - /** - * Generate the data in a STRESS submission policy with SubmitterUserResolver - * mode and verify whether the generated data matches with given - * input size or not. - * @throws IOException - */ - @Test - public void testGenerateDataWithSTRESSSubmission() throws Exception { - conf = rtClient.getDaemonConf(); - final long inputSizeInMB = cSize * 128; - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file:///dev/null"}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - int exitCode = - UtilsForGridmix.runGridmixJob(gridmixDir, conf, - GridMixRunMode.DATA_GENERATION.getValue(), - runtimeValues, otherArgs); - Assert.assertEquals("Data generation has failed.", 0 , exitCode); - checkGeneratedDataAndJobStatus(inputSizeInMB); - } - - /** - * Generate the data in a REPLAY submission policy with RoundRobinUserResolver - * mode and verify whether the generated data matches with the given - * input size or not. - * @throws Exception - */ - @Test - public void testGenerateDataWithREPLAYSubmission() throws Exception { - conf = rtClient.getDaemonConf(); - final long inputSizeInMB = cSize * 300; - String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB +"m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - "file:///dev/null"}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - int exitCode = - UtilsForGridmix.runGridmixJob(gridmixDir, conf, - GridMixRunMode.DATA_GENERATION.getValue(), - runtimeValues, otherArgs); - Assert.assertEquals("Data generation has failed.", 0 , exitCode); - checkGeneratedDataAndJobStatus(inputSizeInMB); - } - - /** - * Generate the data in a SERIAL submission policy with EchoUserResolver - * mode and also set the no.of bytes per file in the data.Verify whether each - * file size matches with given per file size or not and also - * verify the overall size of generated data. - * @throws Exception - */ - @Test - public void testGenerateDataWithSERIALSubmission() throws Exception { - conf = rtClient.getDaemonConf(); - long perNodeSizeInMB = 500; // 500 mb per node data - final long inputSizeInMB = cSize * perNodeSizeInMB; - String [] runtimeValues ={"LOADJOB", - EchoUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - "file:///dev/null"}; - long bytesPerFile = 200 * 1024 * 1024; // 200 mb per file of data - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_BYTES_PER_FILE + "=" + bytesPerFile, - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - int exitCode = - UtilsForGridmix.runGridmixJob(gridmixDir, conf, - GridMixRunMode.DATA_GENERATION.getValue(), - runtimeValues, otherArgs); - Assert.assertEquals("Data generation has failed.", 0 , exitCode); - LOG.info("Verify the eache file size in a generate data."); - verifyEachNodeSize(new Path(gridmixDir, "input"), perNodeSizeInMB); - verifyNumOfFilesGeneratedInEachNode(new Path(gridmixDir, "input"), - perNodeSizeInMB, bytesPerFile); - checkGeneratedDataAndJobStatus(inputSizeInMB); - } - - private void checkGeneratedDataAndJobStatus(long inputSize) - throws IOException { - LOG.info("Verify the generated data size."); - long dataSizeInMB = getDataSizeInMB(new Path(gridmixDir,"input")); - Assert.assertTrue("Generate data has not matched with given size", - dataSizeInMB + 0.1 > inputSize || dataSizeInMB - 0.1 < inputSize); - - JobClient jobClient = jtClient.getClient(); - int len = jobClient.getAllJobs().length; - LOG.info("Verify the job status after completion of job."); - Assert.assertEquals("Job has not succeeded.", JobStatus.SUCCEEDED, - jobClient.getAllJobs()[len-1].getRunState()); - } - - private void verifyEachNodeSize(Path inputDir, long dataSizePerNode) - throws IOException { - FileSystem fs = inputDir.getFileSystem(conf); - FileStatus [] fstatus = fs.listStatus(inputDir); - for (FileStatus fstat : fstatus) { - if ( fstat.isDirectory()) { - long fileSize = getDataSizeInMB(fstat.getPath()); - Assert.assertTrue("The Size has not matched with given " - + "per node file size(" + dataSizePerNode +"MB)", - fileSize + 0.1 > dataSizePerNode - || fileSize - 0.1 < dataSizePerNode); - } - } - } - - private void verifyNumOfFilesGeneratedInEachNode(Path inputDir, - long nodeSize, long fileSize) throws IOException { - long fileCount = nodeSize/fileSize; - long expFileCount = Math.round(fileCount); - expFileCount = expFileCount + ((nodeSize%fileSize != 0)? 1:0); - FileSystem fs = inputDir.getFileSystem(conf); - FileStatus [] fstatus = fs.listStatus(inputDir); - for (FileStatus fstat : fstatus) { - if ( fstat.isDirectory()) { - FileSystem nodeFs = fstat.getPath().getFileSystem(conf); - long actFileCount = nodeFs.getContentSummary( - fstat.getPath()).getFileCount(); - Assert.assertEquals("File count has not matched.", expFileCount, - actFileCount); - } - } - } - - private static long getDataSizeInMB(Path inputDir) throws IOException { - FileSystem fs = inputDir.getFileSystem(conf); - ContentSummary csmry = fs.getContentSummary(inputDir); - long dataSize = csmry.getLength(); - dataSize = dataSize/(1024 * 1024); - return dataSize; - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixFilePool.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixFilePool.java deleted file mode 100644 index 883feec88fc..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridMixFilePool.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.mapreduce.test.system.MRCluster; -import org.apache.hadoop.mapreduce.test.system.JTClient; -import org.apache.hadoop.mapreduce.test.system.JTProtocol; -import org.apache.hadoop.mapred.gridmix.FilePool; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.FileStatus; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.AfterClass; -import org.junit.Test; -import java.io.IOException; -import java.util.ArrayList; - -public class TestGridMixFilePool { - private static final Log LOG = - LogFactory.getLog(TestGridMixFilePool.class); - private static Configuration conf = new Configuration(); - private static MRCluster cluster; - private static JTProtocol remoteClient; - private static JTClient jtClient; - private static Path gridmixDir; - private static int clusterSize; - - @BeforeClass - public static void before() throws Exception { - String [] excludeExpList = {"java.net.ConnectException", - "java.io.IOException"}; - cluster = MRCluster.createCluster(conf); - cluster.setExcludeExpList(excludeExpList); - cluster.setUp(); - jtClient = cluster.getJTClient(); - remoteClient = jtClient.getProxy(); - clusterSize = cluster.getTTClients().size(); - gridmixDir = new Path("herriot-gridmix"); - UtilsForGridmix.createDirs(gridmixDir, remoteClient.getDaemonConf()); - } - - @AfterClass - public static void after() throws Exception { - UtilsForGridmix.cleanup(gridmixDir, conf); - cluster.tearDown(); - } - - @Test - public void testFilesCountAndSizesForSpecifiedFilePool() throws Exception { - conf = remoteClient.getDaemonConf(); - final long inputSizeInMB = clusterSize * 200; - int [] fileSizesInMB = {50, 100, 400, 50, 300, 10, 60, 40, 20 ,10 , 500}; - long targetSize = Long.MAX_VALUE; - final int expFileCount = clusterSize + 4; - String [] runtimeValues ={"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file:///dev/null"}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - // Generate the input data by using gridmix framework. - int exitCode = - UtilsForGridmix.runGridmixJob(gridmixDir, conf, - GridMixRunMode.DATA_GENERATION.getValue(), - runtimeValues, otherArgs); - Assert.assertEquals("Data generation has failed.", 0 , exitCode); - // Create the files without using gridmix input generation with - // above mentioned sizes in a array. - createFiles(new Path(gridmixDir, "input"), fileSizesInMB); - conf.setLong(FilePool.GRIDMIX_MIN_FILE, 100 * 1024 * 1024); - FilePool fpool = new FilePool(conf, new Path(gridmixDir, "input")); - fpool.refresh(); - verifyFilesSizeAndCountForSpecifiedPool(expFileCount, targetSize, fpool); - } - - private void createFiles(Path inputDir, int [] fileSizes) - throws Exception { - for (int size : fileSizes) { - UtilsForGridmix.createFile(size, inputDir, conf); - } - } - - private void verifyFilesSizeAndCountForSpecifiedPool(int expFileCount, - long minFileSize, FilePool pool) throws IOException { - final ArrayList files = new ArrayList(); - long filesSizeInBytes = pool.getInputFiles(minFileSize, files); - long actFilesSizeInMB = filesSizeInBytes / (1024 * 1024); - long expFilesSizeInMB = (clusterSize * 200) + 1300; - Assert.assertEquals("Files Size has not matched for specified pool.", - expFilesSizeInMB, actFilesSizeInMB); - int actFileCount = files.size(); - Assert.assertEquals("File count has not matched.", expFileCount, - actFileCount); - int count = 0; - for (FileStatus fstat : files) { - String fp = fstat.getPath().toString(); - count = count + ((fp.indexOf("datafile_") > 0)? 0 : 1); - } - Assert.assertEquals("Total folders are not matched with cluster size", - clusterSize, count); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressedInputGeneration.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressedInputGeneration.java deleted file mode 100644 index 1dfc8970e61..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressedInputGeneration.java +++ /dev/null @@ -1,173 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.JobClient; -import org.apache.hadoop.mapred.JobStatus; -import org.apache.hadoop.mapred.gridmix.Gridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.ContentSummary; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.Path; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix generated input if compression emulation turn on. - */ -public class TestGridmixCompressedInputGeneration - extends GridmixSystemTestCase { - - private static final Log LOG = - LogFactory.getLog("TestGridmixCompressedInputGeneration.class"); - - /** - * Generate input data and verify whether input files are compressed - * or not. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixCompressionInputGeneration() throws Exception { - final long inputSizeInMB = 1024 * 7; - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file:///dev/null"}; - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true" - }; - LOG.info("Verify the generated compressed input data."); - runAndVerify(true, inputSizeInMB, runtimeValues, otherArgs); - } - - /** - * Disable compression emulation and verify whether input files are - * compressed or not. - * @throws Exception - */ - @Test - public void testGridmixInputGenerationWithoutCompressionEnable() - throws Exception { - UtilsForGridmix.cleanup(gridmixDir, rtClient.getDaemonConf()); - final long inputSizeInMB = 1024 * 6; - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file:///dev/null"}; - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - LOG.info("Verify the generated uncompressed input data."); - runAndVerify(false, inputSizeInMB, runtimeValues, otherArgs); - } - - private void runAndVerify(boolean isCompressed, long INPUT_SIZE, - String [] runtimeValues, String [] otherArgs) throws Exception { - int exitCode = - UtilsForGridmix.runGridmixJob(gridmixDir, conf, - GridMixRunMode.DATA_GENERATION.getValue(), - runtimeValues,otherArgs); - Assert.assertEquals("Data generation has failed.", 0, exitCode); - verifyJobStatus(); - verifyInputDataSize(INPUT_SIZE); - verifyInputFiles(isCompressed); - } - - private void verifyInputFiles(boolean isCompressed) throws IOException { - List inputFiles = - getInputFiles(conf, Gridmix.getGridmixInputDataPath(gridmixDir)); - for (String inputFile: inputFiles) { - boolean fileStatus = (inputFile.contains(".gz") - || inputFile.contains(".tgz"))? true : false; - if (isCompressed) { - Assert.assertTrue("Compressed input split file was not found.", - fileStatus); - } else { - Assert.assertFalse("Uncompressed input split file was not found.", - fileStatus); - } - } - } - - private void verifyInputDataSize(long INPUT_SIZE) throws IOException { - long actDataSize = - getInputDataSizeInMB(conf, Gridmix.getGridmixInputDataPath(gridmixDir)); - double ratio = ((double)actDataSize)/INPUT_SIZE; - long expDataSize = (long)(INPUT_SIZE * ratio); - Assert.assertEquals("Generated data has not matched with given size.", - expDataSize, actDataSize); - } - - private void verifyJobStatus() throws IOException { - JobClient jobClient = jtClient.getClient(); - int len = jobClient.getAllJobs().length; - LOG.info("Verify the job status after completion of job..."); - Assert.assertEquals("Job has not succeeded.", JobStatus.SUCCEEDED, - jobClient.getAllJobs()[len -1].getRunState()); - } - - private long getInputDataSizeInMB(Configuration conf, Path inputDir) - throws IOException { - FileSystem fs = inputDir.getFileSystem(conf); - ContentSummary csmry = fs.getContentSummary(inputDir); - long dataSize = csmry.getLength(); - dataSize = dataSize/(1024 * 1024); - return dataSize; - } - - private List getInputFiles(Configuration conf, Path inputDir) - throws IOException { - FileSystem fs = inputDir.getFileSystem(conf); - FileStatus [] listStatus = fs.listStatus(inputDir); - List files = new ArrayList(); - for (FileStatus fileStat : listStatus) { - files.add(getInputFile(fileStat, conf)); - } - return files; - } - - private String getInputFile(FileStatus fstatus, Configuration conf) - throws IOException { - String fileName = null; - if (!fstatus.isDirectory()) { - fileName = fstatus.getPath().getName(); - } else { - FileSystem fs = fstatus.getPath().getFileSystem(conf); - FileStatus [] listStatus = fs.listStatus(fstatus.getPath()); - for (FileStatus fileStat : listStatus) { - return getInputFile(fileStat, conf); - } - } - return fileName; - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressionEmulationWithCompressInput.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressionEmulationWithCompressInput.java deleted file mode 100644 index 3fdd16d7f6f..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixCompressionEmulationWithCompressInput.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the gridmix jobs compression ratios of map input, - * map output and reduce output with default and user specified - * compression ratios. - * - */ -public class TestGridmixCompressionEmulationWithCompressInput - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestGridmixCompressionEmulationWithCompressInput.class"); - final long inputSizeInMB = 1024 * 6; - - /** - * Generate compressed input data and verify the map input, - * map output and reduce output compression ratios of gridmix jobs - * against the default compression ratios. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixCompressionRatiosAgainstDefaultCompressionRatio() - throws Exception { - final String tracePath = getTraceFile("compression_case1_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Verify map input, map output and reduce output compression ratios of - * gridmix jobs against user specified compression ratios. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixOuputCompressionRatiosAgainstCustomRatios() - throws Exception { - final String tracePath = getTraceFile("compression_case1_trace"); - Assert.assertNotNull("Trace file has not found.", tracePath); - UtilsForGridmix.cleanup(gridmixDir, rtClient.getDaemonConf()); - - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=true", - "-D", GridMixConfig.GRIDMIX_INPUT_DECOMPRESS_ENABLE + "=true", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_INPUT_COMPRESS_RATIO + "=0.68", - "-D", GridMixConfig.GRIDMIX_INTERMEDIATE_COMPRESSION_RATIO + "=0.35", - "-D", GridMixConfig.GRIDMIX_OUTPUT_COMPRESSION_RATIO + "=0.40" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPrivateDCFile.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPrivateDCFile.java deleted file mode 100644 index e6c7e6af46b..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPrivateDCFile.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix emulation of HDFS private distributed cache file. - */ -public class TestGridmixEmulationOfHDFSPrivateDCFile - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixEmulationOfHDFSPrivateDCFile.class"); - /** - * Generate input data and single HDFS private distributed cache - * file based on given input trace.Verify the Gridmix emulation of - * single private HDFS distributed cache file in RoundRobinUserResolver - * mode with STRESS submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulateOfHDFSPrivateDCFile() - throws Exception { - final long inputSizeInMB = 8192; - final String tracePath = getTraceFile("distcache_case3_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - /** - * Verify the Gridmix emulation of single HDFS private distributed - * cache file in SubmitterUserResolver mode with REPLAY submission - * policy by using the existing input data and HDFS private - * distributed cache file. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixEmulationOfHDFSPrivateDCFile() - throws Exception { - final String tracePath = getTraceFile("distcache_case3_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues ={"LOADJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - tracePath}; - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPublicDCFile.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPublicDCFile.java deleted file mode 100644 index 0bf07fdf4d2..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHDFSPublicDCFile.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix emulation of HDFS public distributed cache file. - */ -public class TestGridmixEmulationOfHDFSPublicDCFile - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixEmulationOfHDFSPublicDCFile.class"); - - /** - * Generate the input data and HDFS distributed cache file based - * on given input trace. Verify the Gridmix emulation of single HDFS - * public distributed cache file in SubmitterUserResolver mode with - * STRESS submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulationOfSingleHDFSDCFile() - throws Exception { - final long inputSizeInMB = 7168; - final String tracePath = getTraceFile("distcache_case1_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Verify the Gridmix emulation of Single HDFS public distributed cache - * file in RoundRobinUserResolver mode with REPLAY submission policy - * by using the existing input data and HDFS public distributed cache file. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixEmulationOfSingleHDFSPublicDCFile() - throws Exception { - final String tracePath = getTraceFile("distcache_case1_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase1.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase1.java deleted file mode 100644 index b5d821f5009..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase1.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.GridmixJob; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the {@link Gridmix} with a high ram jobs trace and - * verify each {@link Gridmix} job whether it honors the high ram or not. - * In the trace the jobs should use the high ram for both maps and reduces. - */ -public class TestGridmixEmulationOfHighRamJobsCase1 - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixEmulationOfHighRamJobsCase1.class"); - - /** - * Generate input data and run {@link Gridmix} with a high ram jobs trace - * as a load job and STRESS submission policy in a SubmitterUserResolver - * mode. Verify each {@link Gridmix} job whether it honors the high ram or not - * after completion of execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHighRamForMapsAndReducesOfMRJobs() - throws Exception { - final long inputSizeInMB = cSize * 400; - String tracePath = getTraceFile("highram_mr_jobs_case1"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=true"}; - - validateTaskMemoryParamters(tracePath, true); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase2.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase2.java deleted file mode 100644 index bfca1f20dc3..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase2.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.GridmixJob; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the {@link Gridmix} with a high ram jobs trace and - * verify each {@link Gridmix} job whether it honors the high ram or not. - * In the trace the jobs should use the high ram only for maps. - */ -public class TestGridmixEmulationOfHighRamJobsCase2 - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixEmulationOfHighRamJobsCase2.class"); - - /** - * Generate input data and run {@link Gridmix} with a high ram jobs trace - * as a load job and REPALY submission policy in a RoundRobinUserResolver - * mode. Verify each {@link Gridmix} job whether it honors the high ram or not - * after completion of execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHighRamForMapsOfMRJobs() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("highram_mr_jobs_case2"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=true"}; - - validateTaskMemoryParamters(tracePath, true); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase3.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase3.java deleted file mode 100644 index bc5e3aafd12..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfHighRamJobsCase3.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.GridmixJob; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the {@link Gridmix} with a high ram jobs trace and - * verify each {@link Gridmix} job whether it honors the high ram or not. - * In the trace the jobs should use the high ram only for reducers. - */ -public class TestGridmixEmulationOfHighRamJobsCase3 - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixEmulationOfHighRamJobsCase3.class); - - /** - * Generate input data and run {@link Gridmix} with a high ram jobs trace - * as a load job and SERIAL submission policy in a SubmitterUserResolver - * mode. Verify each {@link Gridmix} job whether it honors the - * high ram or not after completion of execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testEmulationOfHighRamForReducersOfMRJobs() - throws Exception { - final long inputSizeInMB = cSize * 250; - String tracePath = getTraceFile("highram_mr_jobs_case3"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=true"}; - - validateTaskMemoryParamters(tracePath, true); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPrivateDCFiles.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPrivateDCFiles.java deleted file mode 100644 index 5f464ce39be..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPrivateDCFiles.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; - -/** - * Verify the Gridmix emulation of Multiple HDFS private distributed - * cache files. - */ -public class TestGridmixEmulationOfMultipleHDFSPrivateDCFiles - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestGridmixEmulationOfMultipleHDFSPrivateDCFiles.class"); - - /** - * Generate input data and multiple HDFS private distributed cache - * files based on given input trace.Verify the Gridmix emulation of - * multiple private HDFS distributed cache files in RoundRobinUserResolver - * mode with SERIAL submission policy. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulationOfMultipleHDFSPrivateDCFiles() - throws Exception { - final long inputSize = 6144; - final String tracePath = getTraceFile("distcache_case4_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "SERIAL", - inputSize+"m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Verify the Gridmix emulation of multiple HDFS private distributed - * cache files in SubmitterUserResolver mode with STRESS submission - * policy by using the existing input data and HDFS private - * distributed cache files. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixEmulationOfMultipleHDFSPrivateDCFiles() - throws Exception { - final String tracePath = getTraceFile("distcache_case4_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - tracePath}; - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPublicDCFiles.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPublicDCFiles.java deleted file mode 100644 index cca5da83ecb..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixEmulationOfMultipleHDFSPublicDCFiles.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Assert; -import org.junit.Test; -import java.io.IOException; - -/** - * Verify the Gridmix emulation of Multiple HDFS public distributed - * cache files. - */ -public class TestGridmixEmulationOfMultipleHDFSPublicDCFiles - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog( - "TestGridmixEmulationOfMultipleHDFSPublicDCFiles.class"); - - /** - * Generate the compressed input data and dist cache files based - * on input trace. Verify the Gridmix emulation of - * multiple HDFS public distributed cache file. - * @throws Exception - if an error occurs. - */ - @Test - public void testGenerateAndEmulationOfMultipleHDFSDCFiles() - throws Exception { - final long inputSizeInMB = 7168; - final String tracePath = getTraceFile("distcache_case2_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - final String [] otherArgs = { - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Verify the Gridmix emulation of Single HDFS public distributed cache file - * by using an existing input compressed data and HDFS dist cache file. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixEmulationOfMulitpleHDFSPublicDCFile() - throws Exception { - final String tracePath = getTraceFile("distcache_case2_trace"); - Assert.assertNotNull("Trace file was not found.", tracePath); - final String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - tracePath}; - - final String [] otherArgs = { - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=true" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.RUN_GRIDMIX.getValue()); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith10minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith10minTrace.java deleted file mode 100644 index ec11a2b36e6..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith10minTrace.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; - -/** - * Run the Gridmix with 10 minutes MR jobs trace and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith10minTrace extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixWith10minTrace.class); - - /** - * Generate data and run gridmix by sleep jobs with STRESS submission - * policy in a RoundRobinUserResolver mode against 10 minutes trace file. - * Verify each Gridmix job history with a corresponding job story - * in a trace file after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith10minTrace() throws Exception { - final long inputSizeInMB = cSize * 250; - final long minFileSize = 200 * 1024 * 1024; - String [] runtimeValues = - {"SLEEPJOB", - RoundRobinUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - map.get("10m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_MINIMUM_FILE_SIZE + "=" + minFileSize, - "-D", GridMixConfig.GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE + "=false", - "-D", GridMixConfig.GRIDMIX_SLEEPJOB_MAPTASK_ONLY + "=true", - "-D", GridMixConfig.GRIDMIX_SLEEP_MAP_MAX_TIME + "=10" - }; - String tracePath = map.get("10m"); - runGridmixAndVerify(runtimeValues, otherArgs,tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith12minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith12minTrace.java deleted file mode 100644 index 9bcb45a3fbb..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith12minTrace.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; - -/** - * Run the Gridmix with 12 minutes MR job traces and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith12minTrace extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixWith12minTrace.class); - - /** - * Generate data and run gridmix sleep jobs with REPLAY submission - * policy in a SubmitterUserResolver mode against 12 minutes trace file. - * Verify each Gridmix job history with a corresponding job story - * in a trace file after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith12minTrace() throws Exception { - final long inputSizeInMB = cSize * 150; - String [] runtimeValues = {"SLEEPJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - map.get("12m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_SLEEP_MAP_MAX_TIME + "=10", - "-D", GridMixConfig.GRIDMIX_SLEEP_REDUCE_MAX_TIME + "=5" - }; - - String tracePath = map.get("12m"); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith1minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith1minTrace.java deleted file mode 100644 index c583e6d3a29..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith1minTrace.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.junit.Test; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; - -/** - * Run the Gridmix with 1 minute MR jobs trace and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith1minTrace extends GridmixSystemTestCase{ - private static final Log LOG = - LogFactory.getLog(TestGridmixWith1minTrace.class); - - /** - * Generate data and run gridmix by load job with STRESS submission policy - * in a SubmitterUserResolver mode against 1 minute trace file. - * Verify each Gridmix job history with a corresponding job story in the - * trace after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith1minTrace() throws Exception { - final long inputSizeInMB = cSize * 400; - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - map.get("1m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - String tracePath = map.get("1m"); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith2minStreamingJobTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith2minStreamingJobTrace.java deleted file mode 100644 index d9fb7c70f7f..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith2minStreamingJobTrace.java +++ /dev/null @@ -1,64 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the Gridmix with 2 minutes job trace which has been generated with - * streaming jobs histories and verify each job history against - * the corresponding job story in a given trace file. - */ -public class TestGridmixWith2minStreamingJobTrace - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixWith2minStreamingJobTrace.class"); - - /** - * Generate input data and run Gridmix by load job with STRESS submission - * policy in a SubmitterUserResolver mode against 2 minutes job - * trace file of streaming jobs. Verify each Gridmix job history with - * a corresponding job story in a trace file after completion of all - * the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith2minStreamJobTrace() throws Exception { - final long inputSizeInMB = cSize * 250; - final long minFileSize = 150 * 1024 * 1024; - String tracePath = getTraceFile("2m_stream"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE + "=true", - "-D", GridMixConfig.GRIDMIX_MINIMUM_FILE_SIZE + "=" + minFileSize, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minStreamingJobTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minStreamingJobTrace.java deleted file mode 100644 index 85dedf6675f..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minStreamingJobTrace.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.junit.Assert; -import org.junit.Test; - -/** - * Run the Gridmix with 3 minutes job trace which has been generated with - * streaming jobs histories and verify each job history against - * corresponding job story in a given trace file. - */ -public class TestGridmixWith3minStreamingJobTrace - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixWith3minStreamingJobTrace.class"); - - /** - * Generate input data and run gridmix by load job with REPLAY submission - * policy in a RoundRobinUserResolver mode against 3 minutes job trace file - * of streaming job. Verify each gridmix job history with a corresponding - * job story in a trace file after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith3minStreamJobTrace() throws Exception { - final long inputSizeInMB = cSize * 200; - final long bytesPerFile = 150 * 1024 * 1024; - String tracePath = getTraceFile("3m_stream"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE + "=true", - "-D", GridMixConfig.GRIDMIX_BYTES_PER_FILE + "=" + bytesPerFile, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minTrace.java deleted file mode 100644 index 5f2171fb401..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith3minTrace.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; - -/** - * Run the Gridmix with 3 minutes MR jobs trace and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith3minTrace extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixWith3minTrace.class); - - /** - * Generate data and run gridmix by load job with REPLAY submission - * policy in a RoundRobinUserResolver mode by using 3 minutes trace file. - * Verify each Gridmix job history with a corresponding job story in - * a trace after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith3minTrace() throws Exception { - final long inputSizeInMB = cSize * 200; - String [] runtimeValues = - {"LOADJOB", - RoundRobinUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - map.get("3m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - String tracePath = map.get("3m"); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minStreamingJobTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minStreamingJobTrace.java deleted file mode 100644 index ef1878c0855..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minStreamingJobTrace.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Run the Gridmix with 5 minutes job trace which has been generated with - * streaming jobs histories and verify each job history against - * corresponding job story in a given trace file. - */ -public class TestGridmixWith5minStreamingJobTrace - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestGridmixWith5minStreamingJobTrace.class"); - - /** - * Generate input data and run gridmix by load job with SERIAL submission - * policy in a SubmitterUserResolver mode against 5 minutes job trace file - * of streaming job. Verify each gridmix job history with a corresponding - * job story in a trace file after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith5minStreamJobTrace() throws Exception { - String tracePath = getTraceFile("5m_stream"); - Assert.assertNotNull("Trace file has not found.", tracePath); - final long inputSizeInMB = cSize * 200; - final long bytesPerFile = 150 * 1024 * 1024; - String [] runtimeValues = {"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_KEY_FRC + "=0.5f", - "-D", GridMixConfig.GRIDMIX_BYTES_PER_FILE + "=" + bytesPerFile, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false" - }; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minTrace.java deleted file mode 100644 index c55167e3b4f..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith5minTrace.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; - -/** - * Run the Gridmix with 5 minutes MR jobs trace and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith5minTrace extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixWith5minTrace.class); - - /** - * Generate data and run gridmix by load job with SERIAL submission - * policy in a SubmitterUserResolver mode against 5 minutes trace file. - * Verify each Gridmix job history with a corresponding job story - * in a trace file after completion of all the jobs. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith5minTrace() throws Exception { - final long inputSizeInMB = cSize * 300; - final long minFileSize = 100 * 1024 * 1024; - String [] runtimeValues ={"LOADJOB", - SubmitterUserResolver.class.getName(), - "SERIAL", - inputSizeInMB + "m", - map.get("5m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_MINIMUM_FILE_SIZE + "=" + minFileSize - }; - - String tracePath = map.get("5m"); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith7minTrace.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith7minTrace.java deleted file mode 100644 index 55be37b17dd..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestGridmixWith7minTrace.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.LogFactory; -import org.apache.commons.logging.Log; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.junit.Test; - -/** - * Run the Gridmix with 7 minutes MR jobs trace and - * verify each job history against the corresponding job story - * in a given trace file. - */ -public class TestGridmixWith7minTrace extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog(TestGridmixWith7minTrace.class); - - /** - * Generate data and run gridmix by sleep job with STRESS submission - * policy in a SubmitterUserResolver mode against 7 minute trace file. - * Verify each Gridmix job history with a corresponding job story - * in a trace file after completion of all the jobs execution. - * @throws Exception - if an error occurs. - */ - @Test - public void testGridmixWith7minTrace() throws Exception { - final long inputSizeInMB = cSize * 400; - final long minFileSize = 200 * 1024 * 1024; - String [] runtimeValues ={"SLEEPJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - map.get("7m")}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridmixJob.GRIDMIX_HIGHRAM_EMULATION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_MINIMUM_FILE_SIZE + "=" + minFileSize, - "-D", GridMixConfig.GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE + "=false" - }; - String tracePath = map.get("7m"); - runGridmixAndVerify(runtimeValues, otherArgs, tracePath); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithCustomIntrvl.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithCustomIntrvl.java deleted file mode 100644 index a82e806059b..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithCustomIntrvl.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} memory emulation feature for the jobs with - * custom progress interval, different input data, submission policies - * and user resolver modes. Verify the total heap usage of map and reduce - * tasks of the jobs with corresponding original job in the trace. - */ -public class TestMemEmulForMapsAndReducesWithCustomIntrvl - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestMemEmulForMapsAndReducesWithCustomIntrvl.class"); - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * memory emulation with custom progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps and reduces total heap memory usage of {@link Gridmix} jobs - * with corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForReducesWithCompressedInputCase7() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_HEAP_MEMORY_CUSTOM_INTRVL + "=0.3F", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * memory emulation with custom progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps and reduces total heap memory usage of {@link Gridmix} jobs - * with corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForReducesWithUncompressedInputCase8() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_HEAP_MEMORY_CUSTOM_INTRVL + "=0.2F", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithDefaultIntrvl.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithDefaultIntrvl.java deleted file mode 100644 index e1f211a11f3..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsAndReducesWithDefaultIntrvl.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} memory emulation feature for gridmix jobs - * with default progress interval, different input data, submission - * policies and user resolver modes. Verify the total heap usage of - * map and reduce tasks of the jobs with corresponding original - * job in the trace. - */ -public class TestMemEmulForMapsAndReducesWithDefaultIntrvl - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestMemEmulForMapsAndReducesWithDefaultIntrvl.class"); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * memory emulation with default progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps and reduces total heap memory usage of {@link Gridmix} jobs - * with corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForReducesWithCompressedInputCase5() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * memory emulation with default progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps and reduces total heap memory usage of {@link Gridmix} jobs - * with corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForReducesWithUncompressedInputCase6() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "REPLAY", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomHeapMemoryRatio.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomHeapMemoryRatio.java deleted file mode 100644 index da48ad4538e..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomHeapMemoryRatio.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} memory emulation feature for {@link Gridmix} jobs - * with default progress interval, custom heap memory ratio, different input - * data, submission policies and user resolver modes. Verify the total heap - * usage of map and reduce tasks of the jobs with corresponding the original job - * in the trace. - */ -public class TestMemEmulForMapsWithCustomHeapMemoryRatio - extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestMemEmulForMapsWithCustomHeapMemoryRatio.class"); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * memory emulation. The {@link Gridmix} should use the following runtime - * parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify total heap memory usage of the tasks of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithCompressedInputCase1() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_HEAP_FREE_MEMORY_RATIO + "=0.5F"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * memory emulation. The {@link Gridmix} should use the following runtime - * parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : RoundRobinUserResolver - * Verify total heap memory usage of tasks of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithUncompressedInputCase2() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("mem_emul_case2"); - Assert.assertNotNull("Trace file has not found.", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false", - "-D", GridMixConfig.GRIDMIX_HEAP_FREE_MEMORY_RATIO + "=0.4F"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomIntrvl.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomIntrvl.java deleted file mode 100644 index 5d1d452b8d6..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithCustomIntrvl.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} memory emulation feature for {@link Gridmix} jobs - * with custom progress interval, different input data, submission policies - * and user resolver modes. Verify the total heap usage of map tasks of - * the jobs with corresponding the original job in the trace. - */ -public class TestMemEmulForMapsWithCustomIntrvl extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestMemEmulForMapsWithCustomIntrvl.class"); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * memory emulation with custom progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps total heap memory usage of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithCompressedInputCase3() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("mem_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_HEAP_MEMORY_CUSTOM_INTRVL + "=0.2F", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * memory emulation with custom progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : RoundRobinUserResolver - * Verify maps total heap memory usage of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithUncompressedInputCase4() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("mem_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_HEAP_MEMORY_CUSTOM_INTRVL + "=0.3F", - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithDefaultIntrvl.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithDefaultIntrvl.java deleted file mode 100644 index ff136b89c7d..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/TestMemEmulForMapsWithDefaultIntrvl.java +++ /dev/null @@ -1,104 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixConfig; -import org.apache.hadoop.mapred.gridmix.test.system.GridMixRunMode; -import org.apache.hadoop.mapred.gridmix.test.system.UtilsForGridmix; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.junit.Test; -import org.junit.Assert; - -/** - * Test the {@link Gridmix} memory emulation feature for {@link Gridmix} jobs - * with default progress interval, different input data, submission policies - * and user resolver modes. Verify the total heap usage of map tasks of the - * jobs with corresponding original job in the trace. - */ -public class TestMemEmulForMapsWithDefaultIntrvl extends GridmixSystemTestCase { - private static final Log LOG = - LogFactory.getLog("TestMemEmulForMapsWithDefaultIntrvl.class"); - - /** - * Generate compressed input and run {@link Gridmix} by turning on the - * memory emulation with default progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : SumitterUserResolver - * Verify maps total heap memory usage of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithCompressedInputCase1() - throws Exception { - final long inputSizeInMB = 1024 * 7; - String tracePath = getTraceFile("mem_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - SubmitterUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } - - /** - * Generate uncompressed input and run {@link Gridmix} by turning on the - * memory emulation with default progress interval. The {@link Gridmix} - * should use the following runtime parameters while running the jobs. - * Submission Policy : STRESS, User Resolver Mode : RoundRobinUserResolver - * Verify maps total heap memory usage of {@link Gridmix} jobs with - * corresponding original job in the trace. - * @throws Exception - if an error occurs. - */ - @Test - public void testMemoryEmulationForMapsWithUncompressedInputCase2() - throws Exception { - final long inputSizeInMB = cSize * 300; - String tracePath = getTraceFile("mem_emul_case1"); - Assert.assertNotNull("Trace file not found!", tracePath); - String [] runtimeValues = - { "LOADJOB", - RoundRobinUserResolver.class.getName(), - "STRESS", - inputSizeInMB + "m", - "file://" + UtilsForGridmix.getProxyUsersFile(conf), - tracePath}; - - String [] otherArgs = { - "-D", GridMixConfig.GRIDMIX_MEMORY_EMULATON + "=" + - GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN, - "-D", GridMixConfig.GRIDMIX_DISTCACHE_ENABLE + "=false", - "-D", GridMixConfig.GRIDMIX_COMPRESSION_ENABLE + "=false", - "-D", MRJobConfig.JOB_CANCEL_DELEGATION_TOKEN + "=false"}; - - runGridmixAndVerify(runtimeValues, otherArgs, tracePath, - GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixConfig.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixConfig.java deleted file mode 100644 index fc99162bd86..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixConfig.java +++ /dev/null @@ -1,285 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; - -import org.apache.hadoop.mapred.gridmix.Gridmix; -import org.apache.hadoop.mapred.gridmix.JobCreator; -import org.apache.hadoop.mapred.gridmix.SleepJob; -import org.apache.hadoop.mapreduce.MRConfig; -import org.apache.hadoop.mapreduce.MRJobConfig; -import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig; -import org.apache.hadoop.mapred.gridmix.emulators.resourceusage.*; - -/** - * Gridmix system tests configurations. - */ -public class GridMixConfig { - - /** - * Gridmix original job id. - */ - public static final String GRIDMIX_ORIGINAL_JOB_ID = Gridmix.ORIGINAL_JOB_ID; - - /** - * Gridmix output directory. - */ - public static final String GRIDMIX_OUTPUT_DIR = Gridmix.GRIDMIX_OUT_DIR; - - /** - * Gridmix job type (LOADJOB/SLEEPJOB). - */ - public static final String GRIDMIX_JOB_TYPE = JobCreator.GRIDMIX_JOB_TYPE; - - /** - * Gridmix submission use queue. - */ - /* In Gridmix package the visibility of below mentioned - properties are protected and it have not visible outside - the package. However,it should required for system tests, - so it's re-defining in system tests config file.*/ - public static final String GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE = - "gridmix.job-submission.use-queue-in-trace"; - - /** - * Gridmix user resolver(RoundRobinUserResolver/ - * SubmitterUserResolver/EchoUserResolver). - */ - public static final String GRIDMIX_USER_RESOLVER = Gridmix.GRIDMIX_USR_RSV; - - /** - * Gridmix queue depth. - */ - public static final String GRIDMIX_QUEUE_DEPTH = Gridmix.GRIDMIX_QUE_DEP; - - /* In Gridmix package the visibility of below mentioned - property is protected and it should not available for - outside the package. However,it should required for - system tests, so it's re-defining in system tests config file.*/ - /** - * Gridmix generate bytes per file. - */ - public static final String GRIDMIX_BYTES_PER_FILE = - "gridmix.gen.bytes.per.file"; - - /** - * Gridmix job submission policy(STRESS/REPLAY/SERIAL). - */ - - public static final String GRIDMIX_SUBMISSION_POLICY = - "gridmix.job-submission.policy"; - - /** - * Gridmix minimum file size. - */ - public static final String GRIDMIX_MINIMUM_FILE_SIZE = - "gridmix.min.file.size"; - - /** - * Gridmix key fraction. - */ - public static final String GRIDMIX_KEY_FRC = - "gridmix.key.fraction"; - - /** - * Gridmix compression enable - */ - public static final String GRIDMIX_COMPRESSION_ENABLE = - "gridmix.compression-emulation.enable"; - /** - * Gridmix distcache enable - */ - public static final String GRIDMIX_DISTCACHE_ENABLE = - "gridmix.distributed-cache-emulation.enable"; - - /** - * Gridmix input decompression enable. - */ - public static final String GRIDMIX_INPUT_DECOMPRESS_ENABLE = - "gridmix.compression-emulation.input-decompression.enable"; - - /** - * Gridmix input compression ratio. - */ - public static final String GRIDMIX_INPUT_COMPRESS_RATIO = - "gridmix.compression-emulation.map-input.decompression-ratio"; - - /** - * Gridmix intermediate compression ratio. - */ - public static final String GRIDMIX_INTERMEDIATE_COMPRESSION_RATIO = - "gridmix.compression-emulation.map-output.compression-ratio"; - - /** - * Gridmix output compression ratio. - */ - public static final String GRIDMIX_OUTPUT_COMPRESSION_RATIO = - "gridmix.compression-emulation.reduce-output.compression-ratio"; - - /** - * Gridmix distributed cache visibilities. - */ - public static final String GRIDMIX_DISTCACHE_VISIBILITIES = - MRJobConfig.CACHE_FILE_VISIBILITIES; - - /** - * Gridmix distributed cache files. - */ - public static final String GRIDMIX_DISTCACHE_FILES = - MRJobConfig.CACHE_FILES; - - /** - * Gridmix distributed cache files size. - */ - public static final String GRIDMIX_DISTCACHE_FILESSIZE = - MRJobConfig.CACHE_FILES_SIZES; - - /** - * Gridmix distributed cache files time stamp. - */ - public static final String GRIDMIX_DISTCACHE_TIMESTAMP = - MRJobConfig.CACHE_FILE_TIMESTAMPS; - - /** - * Gridmix logger mode. - */ - public static final String GRIDMIX_LOG_MODE = - "log4j.logger.org.apache.hadoop.mapred.gridmix"; - - /** - * Gridmix sleep job map task only. - */ - public static final String GRIDMIX_SLEEPJOB_MAPTASK_ONLY = - SleepJob.SLEEPJOB_MAPTASK_ONLY; - - /** - * Gridmix sleep map maximum time. - */ - public static final String GRIDMIX_SLEEP_MAP_MAX_TIME = - SleepJob.GRIDMIX_SLEEP_MAX_MAP_TIME; - - /** - * Gridmix sleep reduce maximum time. - */ - public static final String GRIDMIX_SLEEP_REDUCE_MAX_TIME = - SleepJob.GRIDMIX_SLEEP_MAX_REDUCE_TIME; - - /** - * Gridmix high ram job emulation enable. - */ - public static final String GRIDMIX_HIGH_RAM_JOB_ENABLE = - "gridmix.highram-emulation.enable"; - - /** - * Job map memory in mb. - */ - public static final String JOB_MAP_MEMORY_MB = - MRJobConfig.MAP_MEMORY_MB; - - /** - * Job reduce memory in mb. - */ - public static final String JOB_REDUCE_MEMORY_MB = - MRJobConfig.REDUCE_MEMORY_MB; - - /** - * Cluster map memory in mb. - */ - public static final String CLUSTER_MAP_MEMORY = - MRConfig.MAPMEMORY_MB; - - /** - * Cluster reduce memory in mb. - */ - public static final String CLUSTER_REDUCE_MEMORY = - MRConfig.REDUCEMEMORY_MB; - - /** - * Cluster maximum map memory. - */ - public static final String CLUSTER_MAX_MAP_MEMORY = - JTConfig.JT_MAX_MAPMEMORY_MB; - - /** - * Cluster maximum reduce memory. - */ - public static final String CLUSTER_MAX_REDUCE_MEMORY = - JTConfig.JT_MAX_REDUCEMEMORY_MB; - - /** - * Gridmix cpu emulation. - */ - public static final String GRIDMIX_CPU_EMULATON = - ResourceUsageMatcher.RESOURCE_USAGE_EMULATION_PLUGINS; - - /** - * Gridmix cpu usage emulation plugin. - */ - public static final String GRIDMIX_CPU_USAGE_PLUGIN = - CumulativeCpuUsageEmulatorPlugin.class.getName(); - - /** - * Gridmix cpu emulation custom interval. - */ - public static final String GRIDMIX_CPU_CUSTOM_INTERVAL = - CumulativeCpuUsageEmulatorPlugin.CPU_EMULATION_PROGRESS_INTERVAL; - - /** - * Gridmix cpu emulation lower limit. - */ - public static int GRIDMIX_CPU_EMULATION_LOWER_LIMIT = 55; - - /** - * Gridmix cpu emulation upper limit. - */ - public static int GRIDMIX_CPU_EMULATION_UPPER_LIMIT = 130; - - /** - * Gridmix heap memory custom interval - */ - public static final String GRIDMIX_HEAP_MEMORY_CUSTOM_INTRVL = - TotalHeapUsageEmulatorPlugin.HEAP_EMULATION_PROGRESS_INTERVAL; - - /** - * Gridmix heap free memory ratio - */ - public static final String GRIDMIX_HEAP_FREE_MEMORY_RATIO = - TotalHeapUsageEmulatorPlugin.MIN_HEAP_FREE_RATIO; - - /** - * Gridmix memory emulation plugin - */ - public static final String GRIDMIX_MEMORY_EMULATION_PLUGIN = - TotalHeapUsageEmulatorPlugin.class.getName(); - - /** - * Gridmix memory emulation - */ - public static final String GRIDMIX_MEMORY_EMULATON = - ResourceUsageMatcher.RESOURCE_USAGE_EMULATION_PLUGINS; - - /** - * Gridmix memory emulation lower limit. - */ - public static int GRIDMIX_MEMORY_EMULATION_LOWER_LIMIT = 55; - - /** - * Gridmix memory emulation upper limit. - */ - public static int GRIDMIX_MEMORY_EMULATION_UPPER_LIMIT = 130; - -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixRunMode.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixRunMode.java deleted file mode 100644 index 0abfc5ce00a..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridMixRunMode.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; -/** - * Gridmix run modes. - * - */ -public enum GridMixRunMode { - DATA_GENERATION(1), RUN_GRIDMIX(2), DATA_GENERATION_AND_RUN_GRIDMIX(3); - private int mode; - - GridMixRunMode (int mode) { - this.mode = mode; - } - - public int getValue() { - return mode; - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobStory.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobStory.java deleted file mode 100644 index ad00f0d9a16..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobStory.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.mapreduce.JobID; -import org.apache.hadoop.tools.rumen.ZombieJobProducer; -import org.apache.hadoop.tools.rumen.ZombieJob; -import org.apache.hadoop.conf.Configuration; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Build the job stories with a given trace file. - */ -public class GridmixJobStory { - private static Log LOG = LogFactory.getLog(GridmixJobStory.class); - private Path path; - private Map zombieJobs; - private Configuration conf; - - public GridmixJobStory(Path path, Configuration conf) { - this.path = path; - this.conf = conf; - try { - zombieJobs = buildJobStories(); - if(zombieJobs == null) { - throw new NullPointerException("No jobs found in a " - + " given trace file."); - } - } catch (IOException ioe) { - LOG.warn("Error:" + ioe.getMessage()); - } catch (NullPointerException npe) { - LOG.warn("Error:" + npe.getMessage()); - } - } - - /** - * Get the zombie jobs as a map. - * @return the zombie jobs map. - */ - public Map getZombieJobs() { - return zombieJobs; - } - - /** - * Get the zombie job of a given job id. - * @param jobId - gridmix job id. - * @return - the zombie job object. - */ - public ZombieJob getZombieJob(JobID jobId) { - return zombieJobs.get(jobId); - } - - private Map buildJobStories() throws IOException { - ZombieJobProducer zjp = new ZombieJobProducer(path,null, conf); - Map hm = new HashMap(); - ZombieJob zj = zjp.getNextJob(); - while (zj != null) { - hm.put(zj.getJobID(),zj); - zj = zjp.getNextJob(); - } - if (hm.size() == 0) { - return null; - } else { - return hm; - } - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobSubmission.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobSubmission.java deleted file mode 100644 index 6a5699eb048..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobSubmission.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.mapreduce.test.system.JTClient; -import org.junit.Assert; - -/** - * Submit the gridmix jobs. - */ -public class GridmixJobSubmission { - private static final Log LOG = - LogFactory.getLog(GridmixJobSubmission.class); - private int gridmixJobCount; - private Configuration conf; - private Path gridmixDir; - private JTClient jtClient; - - public GridmixJobSubmission(Configuration conf, JTClient jtClient , - Path gridmixDir) { - this.conf = conf; - this.jtClient = jtClient; - this.gridmixDir = gridmixDir; - } - - /** - * Submit the gridmix jobs. - * @param runtimeArgs - gridmix common runtime arguments. - * @param otherArgs - gridmix other runtime arguments. - * @param traceInterval - trace time interval. - * @throws Exception - */ - public void submitJobs(String [] runtimeArgs, - String [] otherArgs, int mode) throws Exception { - int prvJobCount = jtClient.getClient().getAllJobs().length; - int exitCode = -1; - if (otherArgs == null) { - exitCode = UtilsForGridmix.runGridmixJob(gridmixDir, conf, - mode, runtimeArgs); - } else { - exitCode = UtilsForGridmix.runGridmixJob(gridmixDir, conf, mode, - runtimeArgs, otherArgs); - } - Assert.assertEquals("Gridmix jobs have failed.", 0 , exitCode); - gridmixJobCount = jtClient.getClient().getAllJobs().length - prvJobCount; - } - - /** - * Get the submitted jobs count. - * @return count of no. of jobs submitted for a trace. - */ - public int getGridmixJobCount() { - return gridmixJobCount; - } - - /** - * Get the job configuration. - * @return Configuration of a submitted job. - */ - public Configuration getJobConf() { - return conf; - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobVerification.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobVerification.java deleted file mode 100644 index e448412a39f..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/GridmixJobVerification.java +++ /dev/null @@ -1,1166 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; - -import java.io.IOException; -import java.io.File; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.Collections; -import java.util.Set; -import java.util.ArrayList; -import java.util.Arrays; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.permission.FsPermission; -import org.apache.hadoop.fs.permission.FsAction; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.mapreduce.TaskCounter; -import org.apache.hadoop.mapreduce.Counters; -import org.apache.hadoop.mapreduce.Counter; -import org.apache.hadoop.mapreduce.CounterGroup; -import org.apache.hadoop.mapreduce.jobhistory.JobHistoryParser; -import org.apache.hadoop.mapreduce.JobID; -import org.apache.hadoop.mapreduce.TaskType; -import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; -import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; -import org.apache.hadoop.mapreduce.test.system.JTClient; -import org.apache.hadoop.mapred.JobConf; -import org.apache.hadoop.tools.rumen.LoggedJob; -import org.apache.hadoop.tools.rumen.ZombieJob; -import org.apache.hadoop.tools.rumen.TaskInfo; -import org.junit.Assert; -import java.text.ParseException; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.mapred.gridmix.GridmixSystemTestCase; - -/** - * Verifying each Gridmix job with corresponding job story in a trace file. - */ -public class GridmixJobVerification { - - private static Log LOG = LogFactory.getLog(GridmixJobVerification.class); - private Path path; - private Configuration conf; - private JTClient jtClient; - private String userResolverVal; - static final String origJobIdKey = GridMixConfig.GRIDMIX_ORIGINAL_JOB_ID; - static final String jobSubKey = GridMixConfig.GRIDMIX_SUBMISSION_POLICY; - static final String jobTypeKey = GridMixConfig.GRIDMIX_JOB_TYPE; - static final String mapTaskKey = GridMixConfig.GRIDMIX_SLEEPJOB_MAPTASK_ONLY; - static final String usrResolver = GridMixConfig.GRIDMIX_USER_RESOLVER; - static final String fileOutputFormatKey = FileOutputFormat.COMPRESS; - static final String fileInputFormatKey = FileInputFormat.INPUT_DIR; - static final String compEmulKey = GridMixConfig.GRIDMIX_COMPRESSION_ENABLE; - static final String inputDecompKey = - GridMixConfig.GRIDMIX_INPUT_DECOMPRESS_ENABLE; - static final String mapInputCompRatio = - GridMixConfig.GRIDMIX_INPUT_COMPRESS_RATIO; - static final String mapOutputCompRatio = - GridMixConfig.GRIDMIX_INTERMEDIATE_COMPRESSION_RATIO; - static final String reduceOutputCompRatio = - GridMixConfig.GRIDMIX_OUTPUT_COMPRESSION_RATIO; - private Map> simuAndOrigJobsInfo = - new HashMap>(); - - /** - * Gridmix job verification constructor - * @param path - path of the gridmix output directory. - * @param conf - cluster configuration. - * @param jtClient - jobtracker client. - */ - public GridmixJobVerification(Path path, Configuration conf, - JTClient jtClient) { - this.path = path; - this.conf = conf; - this.jtClient = jtClient; - } - - /** - * It verifies the Gridmix jobs with corresponding job story in a trace file. - * @param jobids - gridmix job ids. - * @throws IOException - if an I/O error occurs. - * @throws ParseException - if an parse error occurs. - */ - public void verifyGridmixJobsWithJobStories(List jobids) - throws Exception { - - SortedMap origSubmissionTime = new TreeMap (); - SortedMap simuSubmissionTime = new TreeMap(); - GridmixJobStory gjs = new GridmixJobStory(path, conf); - final Iterator ite = jobids.iterator(); - File destFolder = new File(System.getProperty("java.io.tmpdir") - + "/gridmix-st/"); - destFolder.mkdir(); - while (ite.hasNext()) { - JobID simuJobId = ite.next(); - JobHistoryParser.JobInfo jhInfo = getSimulatedJobHistory(simuJobId); - Assert.assertNotNull("Job history not found.", jhInfo); - Counters counters = jhInfo.getTotalCounters(); - JobConf simuJobConf = getSimulatedJobConf(simuJobId, destFolder); - String origJobId = simuJobConf.get(origJobIdKey); - LOG.info("OriginalJobID<->CurrentJobID:" - + origJobId + "<->" + simuJobId); - - if (userResolverVal == null) { - userResolverVal = simuJobConf.get(usrResolver); - } - ZombieJob zombieJob = gjs.getZombieJob(JobID.forName(origJobId)); - Map mapJobCounters = getJobMapCounters(zombieJob); - Map reduceJobCounters = getJobReduceCounters(zombieJob); - if (simuJobConf.get(jobSubKey).contains("REPLAY")) { - origSubmissionTime.put(zombieJob.getSubmissionTime(), - origJobId.toString() + "^" + simuJobId); - simuSubmissionTime.put(jhInfo.getSubmitTime() , - origJobId.toString() + "^" + simuJobId); ; - } - - LOG.info("Verifying the job <" + simuJobId + "> and wait for a while..."); - verifySimulatedJobSummary(zombieJob, jhInfo, simuJobConf); - verifyJobMapCounters(counters, mapJobCounters, simuJobConf); - verifyJobReduceCounters(counters, reduceJobCounters, simuJobConf); - verifyCompressionEmulation(zombieJob.getJobConf(), simuJobConf, counters, - reduceJobCounters, mapJobCounters); - verifyDistributeCache(zombieJob,simuJobConf); - setJobDistributedCacheInfo(simuJobId.toString(), simuJobConf, - zombieJob.getJobConf()); - verifyHighRamMemoryJobs(zombieJob, simuJobConf); - verifyCPUEmulationOfJobs(zombieJob, jhInfo, simuJobConf); - verifyMemoryEmulationOfJobs(zombieJob, jhInfo, simuJobConf); - LOG.info("Done."); - } - verifyDistributedCacheBetweenJobs(simuAndOrigJobsInfo); - } - - /** - * Verify the job submission order between the jobs in replay mode. - * @param origSubmissionTime - sorted map of original jobs submission times. - * @param simuSubmissionTime - sorted map of simulated jobs submission times. - */ - public void verifyJobSumissionTime(SortedMap origSubmissionTime, - SortedMap simuSubmissionTime) { - Assert.assertEquals("Simulated job's submission time count has " - + "not match with Original job's submission time count.", - origSubmissionTime.size(), simuSubmissionTime.size()); - for ( int index = 0; index < origSubmissionTime.size(); index ++) { - String origAndSimuJobID = origSubmissionTime.get(index); - String simuAndorigJobID = simuSubmissionTime.get(index); - Assert.assertEquals("Simulated jobs have not submitted in same " - + "order as original jobs submitted in REPLAY mode.", - origAndSimuJobID, simuAndorigJobID); - } - } - - /** - * It verifies the simulated job map counters. - * @param counters - Original job map counters. - * @param mapJobCounters - Simulated job map counters. - * @param jobConf - Simulated job configuration. - * @throws ParseException - If an parser error occurs. - */ - public void verifyJobMapCounters(Counters counters, - Map mapCounters, JobConf jobConf) throws ParseException { - if (!jobConf.get(jobTypeKey, "LOADJOB").equals("SLEEPJOB")) { - Assert.assertEquals("Map input records have not matched.", - mapCounters.get("MAP_INPUT_RECS").longValue(), - getCounterValue(counters, "MAP_INPUT_RECORDS")); - } else { - Assert.assertTrue("Map Input Bytes are zero", - getCounterValue(counters,"HDFS_BYTES_READ") != 0); - Assert.assertNotNull("Map Input Records are zero", - getCounterValue(counters, "MAP_INPUT_RECORDS")!=0); - } - } - - /** - * It verifies the simulated job reduce counters. - * @param counters - Original job reduce counters. - * @param reduceCounters - Simulated job reduce counters. - * @param jobConf - simulated job configuration. - * @throws ParseException - if an parser error occurs. - */ - public void verifyJobReduceCounters(Counters counters, - Map reduceCounters, JobConf jobConf) throws ParseException { - if (jobConf.get(jobTypeKey, "LOADJOB").equals("SLEEPJOB")) { - Assert.assertTrue("Reduce output records are not zero for sleep job.", - getCounterValue(counters, "REDUCE_OUTPUT_RECORDS") == 0); - Assert.assertTrue("Reduce output bytes are not zero for sleep job.", - getCounterValue(counters,"HDFS_BYTES_WRITTEN") == 0); - } - } - - /** - * It verifies the gridmix simulated job summary. - * @param zombieJob - Original job summary. - * @param jhInfo - Simulated job history info. - * @param jobConf - simulated job configuration. - * @throws IOException - if an I/O error occurs. - */ - public void verifySimulatedJobSummary(ZombieJob zombieJob, - JobHistoryParser.JobInfo jhInfo, JobConf jobConf) throws IOException { - Assert.assertEquals("Job id has not matched", zombieJob.getJobID(), - JobID.forName(jobConf.get(origJobIdKey))); - - Assert.assertEquals("Job maps have not matched", zombieJob.getNumberMaps(), - jhInfo.getTotalMaps()); - - if (!jobConf.getBoolean(mapTaskKey, false)) { - Assert.assertEquals("Job reducers have not matched", - zombieJob.getNumberReduces(), jhInfo.getTotalReduces()); - } else { - Assert.assertEquals("Job reducers have not matched", - 0, jhInfo.getTotalReduces()); - } - - Assert.assertEquals("Job status has not matched.", - zombieJob.getOutcome().name(), - convertJobStatus(jhInfo.getJobStatus())); - - LoggedJob loggedJob = zombieJob.getLoggedJob(); - Assert.assertEquals("Job priority has not matched.", - loggedJob.getPriority().toString(), - jhInfo.getPriority()); - - if (jobConf.get(usrResolver).contains("RoundRobin")) { - String user = UserGroupInformation.getLoginUser().getShortUserName(); - Assert.assertTrue(jhInfo.getJobId().toString() - + " has not impersonate with other user.", - !jhInfo.getUsername().equals(user)); - } - } - - /** - * Get the original job map counters from a trace. - * @param zombieJob - Original job story. - * @return - map counters as a map. - */ - public Map getJobMapCounters(ZombieJob zombieJob) { - long expMapInputBytes = 0; - long expMapOutputBytes = 0; - long expMapInputRecs = 0; - long expMapOutputRecs = 0; - Map mapCounters = new HashMap(); - for (int index = 0; index < zombieJob.getNumberMaps(); index ++) { - TaskInfo mapTask = zombieJob.getTaskInfo(TaskType.MAP, index); - expMapInputBytes += mapTask.getInputBytes(); - expMapOutputBytes += mapTask.getOutputBytes(); - expMapInputRecs += mapTask.getInputRecords(); - expMapOutputRecs += mapTask.getOutputRecords(); - } - mapCounters.put("MAP_INPUT_BYTES", expMapInputBytes); - mapCounters.put("MAP_OUTPUT_BYTES", expMapOutputBytes); - mapCounters.put("MAP_INPUT_RECS", expMapInputRecs); - mapCounters.put("MAP_OUTPUT_RECS", expMapOutputRecs); - return mapCounters; - } - - /** - * Get the original job reduce counters from a trace. - * @param zombieJob - Original job story. - * @return - reduce counters as a map. - */ - public Map getJobReduceCounters(ZombieJob zombieJob) { - long expReduceInputBytes = 0; - long expReduceOutputBytes = 0; - long expReduceInputRecs = 0; - long expReduceOutputRecs = 0; - Map reduceCounters = new HashMap(); - for (int index = 0; index < zombieJob.getNumberReduces(); index ++) { - TaskInfo reduceTask = zombieJob.getTaskInfo(TaskType.REDUCE, index); - expReduceInputBytes += reduceTask.getInputBytes(); - expReduceOutputBytes += reduceTask.getOutputBytes(); - expReduceInputRecs += reduceTask.getInputRecords(); - expReduceOutputRecs += reduceTask.getOutputRecords(); - } - reduceCounters.put("REDUCE_INPUT_BYTES", expReduceInputBytes); - reduceCounters.put("REDUCE_OUTPUT_BYTES", expReduceOutputBytes); - reduceCounters.put("REDUCE_INPUT_RECS", expReduceInputRecs); - reduceCounters.put("REDUCE_OUTPUT_RECS", expReduceOutputRecs); - return reduceCounters; - } - - /** - * Get the simulated job configuration of a job. - * @param simulatedJobID - Simulated job id. - * @param tmpJHFolder - temporary job history folder location. - * @return - simulated job configuration. - * @throws IOException - If an I/O error occurs. - */ - public JobConf getSimulatedJobConf(JobID simulatedJobID, File tmpJHFolder) - throws IOException{ - FileSystem fs = null; - try { - - String historyFilePath = - jtClient.getProxy().getJobHistoryLocationForRetiredJob(simulatedJobID); - Path jhpath = new Path(historyFilePath); - fs = jhpath.getFileSystem(conf); - fs.copyToLocalFile(jhpath,new Path(tmpJHFolder.toString())); - String historyPath = - historyFilePath.substring(0,historyFilePath.lastIndexOf("_")); - fs.copyToLocalFile(new Path(historyPath + "_conf.xml"), - new Path(tmpJHFolder.toString())); - JobConf jobConf = new JobConf(); - jobConf.addResource(new Path(tmpJHFolder.toString() - + "/" + simulatedJobID + "_conf.xml")); - jobConf.reloadConfiguration(); - return jobConf; - - }finally { - fs.close(); - } - } - - /** - * Get the simulated job history of a job. - * @param simulatedJobID - simulated job id. - * @return - simulated job information. - * @throws IOException - if an I/O error occurs. - */ - public JobHistoryParser.JobInfo getSimulatedJobHistory(JobID simulatedJobID) - throws IOException { - FileSystem fs = null; - try { - String historyFilePath = jtClient.getProxy(). - getJobHistoryLocationForRetiredJob(simulatedJobID); - Path jhpath = new Path(historyFilePath); - fs = jhpath.getFileSystem(conf); - JobHistoryParser jhparser = new JobHistoryParser(fs, jhpath); - JobHistoryParser.JobInfo jhInfo = jhparser.parse(); - return jhInfo; - - } finally { - fs.close(); - } - } - - /** - * It verifies the heap memory resource usage of gridmix jobs with - * corresponding original job in the trace. - * @param zombieJob - Original job history. - * @param jhInfo - Simulated job history. - * @param simuJobConf - simulated job configuration. - */ - public void verifyMemoryEmulationOfJobs(ZombieJob zombieJob, - JobHistoryParser.JobInfo jhInfo, - JobConf simuJobConf) throws Exception { - long origJobMapsTHU = 0; - long origJobReducesTHU = 0; - long simuJobMapsTHU = 0; - long simuJobReducesTHU = 0; - boolean isMemEmulOn = false; - if (simuJobConf.get(GridMixConfig.GRIDMIX_MEMORY_EMULATON) != null) { - isMemEmulOn = - simuJobConf.get(GridMixConfig.GRIDMIX_MEMORY_EMULATON). - contains(GridMixConfig.GRIDMIX_MEMORY_EMULATION_PLUGIN); - } - - if (isMemEmulOn) { - for (int index = 0; index < zombieJob.getNumberMaps(); index ++) { - TaskInfo mapTask = zombieJob.getTaskInfo(TaskType.MAP, index); - if (mapTask.getResourceUsageMetrics().getHeapUsage() > 0) { - origJobMapsTHU += - mapTask.getResourceUsageMetrics().getHeapUsage(); - } - } - LOG.info("Original Job Maps Total Heap Usage: " + origJobMapsTHU); - - for (int index = 0; index < zombieJob.getNumberReduces(); index ++) { - TaskInfo reduceTask = zombieJob.getTaskInfo(TaskType.REDUCE, index); - if (reduceTask.getResourceUsageMetrics().getHeapUsage() > 0) { - origJobReducesTHU += - reduceTask.getResourceUsageMetrics().getHeapUsage(); - } - } - LOG.info("Original Job Reduces Total Heap Usage: " + origJobReducesTHU); - - simuJobMapsTHU = - getCounterValue(jhInfo.getMapCounters(), - TaskCounter.COMMITTED_HEAP_BYTES.toString()); - LOG.info("Simulated Job Maps Total Heap Usage: " + simuJobMapsTHU); - - simuJobReducesTHU = - getCounterValue(jhInfo.getReduceCounters(), - TaskCounter.COMMITTED_HEAP_BYTES.toString()); - LOG.info("Simulated Jobs Reduces Total Heap Usage: " + simuJobReducesTHU); - - long mapCount = jhInfo.getTotalMaps(); - long reduceCount = jhInfo.getTotalReduces(); - - String strHeapRatio = - simuJobConf.get(GridMixConfig.GRIDMIX_HEAP_FREE_MEMORY_RATIO); - if (strHeapRatio == null) { - strHeapRatio = "0.3F"; - } - - if (mapCount > 0) { - double mapEmulFactor = (simuJobMapsTHU * 100) / origJobMapsTHU; - long mapEmulAccuracy = Math.round(mapEmulFactor); - LOG.info("Maps memory emulation accuracy of a job:" - + mapEmulAccuracy + "%"); - Assert.assertTrue("Map phase total memory emulation had crossed the " - + "configured max limit.", mapEmulAccuracy - <= GridMixConfig.GRIDMIX_MEMORY_EMULATION_UPPER_LIMIT); - Assert.assertTrue("Map phase total memory emulation had not crossed " - + "the configured min limit.", mapEmulAccuracy - >= GridMixConfig.GRIDMIX_MEMORY_EMULATION_LOWER_LIMIT); - double expHeapRatio = Double.parseDouble(strHeapRatio); - LOG.info("expHeapRatio for maps:" + expHeapRatio); - double actHeapRatio = - ((double)Math.abs(origJobMapsTHU - simuJobMapsTHU)) ; - actHeapRatio /= origJobMapsTHU; - LOG.info("actHeapRatio for maps:" + actHeapRatio); - Assert.assertTrue("Simulate job maps heap ratio not matched.", - actHeapRatio <= expHeapRatio); - } - - if (reduceCount >0) { - double reduceEmulFactor = (simuJobReducesTHU * 100) / origJobReducesTHU; - long reduceEmulAccuracy = Math.round(reduceEmulFactor); - LOG.info("Reduces memory emulation accuracy of a job:" - + reduceEmulAccuracy + "%"); - Assert.assertTrue("Reduce phase total memory emulation had crossed " - + "configured max limit.", reduceEmulAccuracy - <= GridMixConfig.GRIDMIX_MEMORY_EMULATION_UPPER_LIMIT); - Assert.assertTrue("Reduce phase total memory emulation had not " - + "crosssed configured min limit.", reduceEmulAccuracy - >= GridMixConfig.GRIDMIX_MEMORY_EMULATION_LOWER_LIMIT); - double expHeapRatio = Double.parseDouble(strHeapRatio); - LOG.info("expHeapRatio for reduces:" + expHeapRatio); - double actHeapRatio = - ((double)Math.abs(origJobReducesTHU - simuJobReducesTHU)); - actHeapRatio /= origJobReducesTHU; - LOG.info("actHeapRatio for reduces:" + actHeapRatio); - Assert.assertTrue("Simulate job reduces heap ratio not matched.", - actHeapRatio <= expHeapRatio); - } - } - } - - /** - * It verifies the cpu resource usage of a gridmix job against - * their original job. - * @param origJobHistory - Original job history. - * @param simuJobHistoryInfo - Simulated job history. - * @param simuJobConf - simulated job configuration. - */ - public void verifyCPUEmulationOfJobs(ZombieJob origJobHistory, - JobHistoryParser.JobInfo simuJobHistoryInfo, - JobConf simuJobConf) throws Exception { - - boolean isCpuEmulOn = false; - if (simuJobConf.get(GridMixConfig.GRIDMIX_CPU_EMULATON) != null) { - isCpuEmulOn = - simuJobConf.get(GridMixConfig.GRIDMIX_CPU_EMULATON). - contains(GridMixConfig.GRIDMIX_CPU_USAGE_PLUGIN); - } - - if (isCpuEmulOn) { - Map origJobMetrics = - getOriginalJobCPUMetrics(origJobHistory); - Map simuJobMetrics = - getSimulatedJobCPUMetrics(simuJobHistoryInfo); - - long origMapUsage = origJobMetrics.get("MAP"); - LOG.info("Maps cpu usage of original job:" + origMapUsage); - - long origReduceUsage = origJobMetrics.get("REDUCE"); - LOG.info("Reduces cpu usage of original job:" + origReduceUsage); - - long simuMapUsage = simuJobMetrics.get("MAP"); - LOG.info("Maps cpu usage of simulated job:" + simuMapUsage); - - long simuReduceUsage = simuJobMetrics.get("REDUCE"); - LOG.info("Reduces cpu usage of simulated job:"+ simuReduceUsage); - - long mapCount = simuJobHistoryInfo.getTotalMaps(); - long reduceCount = simuJobHistoryInfo.getTotalReduces(); - - if (mapCount > 0) { - double mapEmulFactor = (simuMapUsage * 100) / origMapUsage; - long mapEmulAccuracy = Math.round(mapEmulFactor); - LOG.info("CPU emulation accuracy for maps in job " + - simuJobHistoryInfo.getJobId() + - ":"+ mapEmulAccuracy + "%"); - Assert.assertTrue("Map-side cpu emulaiton inaccurate!" + - " Actual cpu usage: " + simuMapUsage + - " Expected cpu usage: " + origMapUsage, mapEmulAccuracy - >= GridMixConfig.GRIDMIX_CPU_EMULATION_LOWER_LIMIT - && mapEmulAccuracy - <= GridMixConfig.GRIDMIX_CPU_EMULATION_UPPER_LIMIT); - } - - if (reduceCount >0) { - double reduceEmulFactor = (simuReduceUsage * 100) / origReduceUsage; - long reduceEmulAccuracy = Math.round(reduceEmulFactor); - LOG.info("CPU emulation accuracy for reduces in job " + - simuJobHistoryInfo.getJobId() + - ": " + reduceEmulAccuracy + "%"); - Assert.assertTrue("Reduce side cpu emulaiton inaccurate!" + - " Actual cpu usage:" + simuReduceUsage + - "Expected cpu usage: " + origReduceUsage, - reduceEmulAccuracy - >= GridMixConfig.GRIDMIX_CPU_EMULATION_LOWER_LIMIT - && reduceEmulAccuracy - <= GridMixConfig.GRIDMIX_CPU_EMULATION_UPPER_LIMIT); - } - } - } - - /** - * Get the simulated job cpu metrics. - * @param jhInfo - Simulated job history - * @return - cpu metrics as a map. - * @throws Exception - if an error occurs. - */ - private Map getSimulatedJobCPUMetrics( - JobHistoryParser.JobInfo jhInfo) throws Exception { - Map resourceMetrics = new HashMap(); - long mapCPUUsage = - getCounterValue(jhInfo.getMapCounters(), - TaskCounter.CPU_MILLISECONDS.toString()); - resourceMetrics.put("MAP", mapCPUUsage); - long reduceCPUUsage = - getCounterValue(jhInfo.getReduceCounters(), - TaskCounter.CPU_MILLISECONDS.toString()); - resourceMetrics.put("REDUCE", reduceCPUUsage); - return resourceMetrics; - } - - /** - * Get the original job cpu metrics. - * @param zombieJob - original job history. - * @return - cpu metrics as map. - */ - private Map getOriginalJobCPUMetrics(ZombieJob zombieJob) { - long mapTotalCPUUsage = 0; - long reduceTotalCPUUsage = 0; - Map resourceMetrics = new HashMap(); - - for (int index = 0; index < zombieJob.getNumberMaps(); index ++) { - TaskInfo mapTask = zombieJob.getTaskInfo(TaskType.MAP, index); - if (mapTask.getResourceUsageMetrics().getCumulativeCpuUsage() > 0) { - mapTotalCPUUsage += - mapTask.getResourceUsageMetrics().getCumulativeCpuUsage(); - } - } - resourceMetrics.put("MAP", mapTotalCPUUsage); - - for (int index = 0; index < zombieJob.getNumberReduces(); index ++) { - TaskInfo reduceTask = zombieJob.getTaskInfo(TaskType.REDUCE, index); - if (reduceTask.getResourceUsageMetrics().getCumulativeCpuUsage() > 0) { - reduceTotalCPUUsage += - reduceTask.getResourceUsageMetrics().getCumulativeCpuUsage(); - } - } - resourceMetrics.put("REDUCE", reduceTotalCPUUsage); - return resourceMetrics; - } - - /** - * Get the user resolver of a job. - */ - public String getJobUserResolver() { - return userResolverVal; - } - - /** - * It verifies the compression ratios of mapreduce jobs. - * @param origJobConf - original job configuration. - * @param simuJobConf - simulated job configuration. - * @param counters - simulated job counters. - * @param origReduceCounters - original job reduce counters. - * @param origMapCounters - original job map counters. - * @throws ParseException - if a parser error occurs. - * @throws IOException - if an I/O error occurs. - */ - public void verifyCompressionEmulation(JobConf origJobConf, - JobConf simuJobConf,Counters counters, - Map origReduceCounters, - Map origMapJobCounters) - throws ParseException,IOException { - if (simuJobConf.getBoolean(compEmulKey, false)) { - String inputDir = origJobConf.get(fileInputFormatKey); - Assert.assertNotNull(fileInputFormatKey + " is Null",inputDir); - long simMapInputBytes = getCounterValue(counters, "HDFS_BYTES_READ"); - long uncompressedInputSize = origMapJobCounters.get("MAP_INPUT_BYTES"); - long simReduceInputBytes = - getCounterValue(counters, "REDUCE_SHUFFLE_BYTES"); - long simMapOutputBytes = getCounterValue(counters, "MAP_OUTPUT_BYTES"); - - // Verify input compression whether it's enable or not. - if (inputDir.contains(".gz") || inputDir.contains(".tgz") - || inputDir.contains(".bz")) { - Assert.assertTrue("Input decompression attribute has been not set for " - + "for compressed input", - simuJobConf.getBoolean(inputDecompKey, false)); - - float INPUT_COMP_RATIO = - getExpectedCompressionRatio(simuJobConf, mapInputCompRatio); - float INTERMEDIATE_COMP_RATIO = - getExpectedCompressionRatio(simuJobConf, mapOutputCompRatio); - - // Verify Map Input Compression Ratio. - assertMapInputCompressionRatio(simMapInputBytes, uncompressedInputSize, - INPUT_COMP_RATIO); - - // Verify Map Output Compression Ratio. - assertMapOuputCompressionRatio(simReduceInputBytes, simMapOutputBytes, - INTERMEDIATE_COMP_RATIO); - } else { - Assert.assertEquals("MAP input bytes has not matched.", - convertBytes(uncompressedInputSize), - convertBytes(simMapInputBytes)); - } - - Assert.assertEquals("Simulated job output format has not matched with " - + "original job output format.", - origJobConf.getBoolean(fileOutputFormatKey,false), - simuJobConf.getBoolean(fileOutputFormatKey,false)); - - if (simuJobConf.getBoolean(fileOutputFormatKey,false)) { - float OUTPUT_COMP_RATIO = - getExpectedCompressionRatio(simuJobConf, reduceOutputCompRatio); - - //Verify reduce output compression ratio. - long simReduceOutputBytes = - getCounterValue(counters, "HDFS_BYTES_WRITTEN"); - long origReduceOutputBytes = - origReduceCounters.get("REDUCE_OUTPUT_BYTES"); - assertReduceOutputCompressionRatio(simReduceOutputBytes, - origReduceOutputBytes, - OUTPUT_COMP_RATIO); - } - } - } - - private void assertMapInputCompressionRatio(long simMapInputBytes, - long origMapInputBytes, - float expInputCompRatio) { - LOG.info("***Verify the map input bytes compression ratio****"); - LOG.info("Simulated job's map input bytes(REDUCE_SHUFFLE_BYTES): " - + simMapInputBytes); - LOG.info("Original job's map input bytes: " + origMapInputBytes); - - final float actInputCompRatio = - getActualCompressionRatio(simMapInputBytes, origMapInputBytes); - LOG.info("Expected Map Input Compression Ratio:" + expInputCompRatio); - LOG.info("Actual Map Input Compression Ratio:" + actInputCompRatio); - - float diffVal = (float)(expInputCompRatio * 0.06); - LOG.info("Expected Difference of Map Input Compression Ratio is <= " + - + diffVal); - float delta = Math.abs(expInputCompRatio - actInputCompRatio); - LOG.info("Actual Difference of Map Iput Compression Ratio:" + delta); - Assert.assertTrue("Simulated job input compression ratio has mismatched.", - delta <= diffVal); - LOG.info("******Done******"); - } - - private void assertMapOuputCompressionRatio(long simReduceInputBytes, - long simMapoutputBytes, - float expMapOuputCompRatio) { - LOG.info("***Verify the map output bytes compression ratio***"); - LOG.info("Simulated job reduce input bytes:" + simReduceInputBytes); - LOG.info("Simulated job map output bytes:" + simMapoutputBytes); - - final float actMapOutputCompRatio = - getActualCompressionRatio(simReduceInputBytes, simMapoutputBytes); - LOG.info("Expected Map Output Compression Ratio:" + expMapOuputCompRatio); - LOG.info("Actual Map Output Compression Ratio:" + actMapOutputCompRatio); - - float diffVal = 0.05f; - LOG.info("Expected Difference Of Map Output Compression Ratio is <= " - + diffVal); - float delta = Math.abs(expMapOuputCompRatio - actMapOutputCompRatio); - LOG.info("Actual Difference Of Map Ouput Compression Ratio :" + delta); - - Assert.assertTrue("Simulated job map output compression ratio " - + "has not been matched.", delta <= diffVal); - LOG.info("******Done******"); - } - - private void assertReduceOutputCompressionRatio(long simReduceOutputBytes, - long origReduceOutputBytes , float expOutputCompRatio ) { - LOG.info("***Verify the reduce output bytes compression ratio***"); - final float actOuputputCompRatio = - getActualCompressionRatio(simReduceOutputBytes, origReduceOutputBytes); - LOG.info("Simulated job's reduce output bytes:" + simReduceOutputBytes); - LOG.info("Original job's reduce output bytes:" + origReduceOutputBytes); - LOG.info("Expected output compression ratio:" + expOutputCompRatio); - LOG.info("Actual output compression ratio:" + actOuputputCompRatio); - long diffVal = (long)(origReduceOutputBytes * 0.15); - long delta = Math.abs(origReduceOutputBytes - simReduceOutputBytes); - LOG.info("Expected difference of output compressed bytes is <= " - + diffVal); - LOG.info("Actual difference of compressed ouput bytes:" + delta); - Assert.assertTrue("Simulated job reduce output compression ratio " + - "has not been matched.", delta <= diffVal); - LOG.info("******Done******"); - } - - private float getExpectedCompressionRatio(JobConf simuJobConf, - String RATIO_TYPE) { - // Default decompression ratio is 0.50f irrespective of original - //job compression ratio. - if (simuJobConf.get(RATIO_TYPE) != null) { - return Float.parseFloat(simuJobConf.get(RATIO_TYPE)); - } else { - return 0.50f; - } - } - - private float getActualCompressionRatio(long compressBytes, - long uncompessBytes) { - double ratio = ((double)compressBytes) / uncompessBytes; - int significant = (int)Math.round(ratio * 100); - return ((float)significant)/100; - } - - /** - * Verify the distributed cache files between the jobs in a gridmix run. - * @param jobsInfo - jobConfs of simulated and original jobs as a map. - */ - public void verifyDistributedCacheBetweenJobs( - Map> jobsInfo) { - if (jobsInfo.size() > 1) { - Map simJobfilesOccurBtnJobs = - getDistcacheFilesOccurenceBetweenJobs(jobsInfo, 0); - Map origJobfilesOccurBtnJobs = - getDistcacheFilesOccurenceBetweenJobs(jobsInfo, 1); - List simuOccurList = - getMapValuesAsList(simJobfilesOccurBtnJobs); - Collections.sort(simuOccurList); - List origOccurList = - getMapValuesAsList(origJobfilesOccurBtnJobs); - Collections.sort(origOccurList); - Assert.assertEquals("The unique count of distibuted cache files in " - + "simulated jobs have not matched with the unique " - + "count of original jobs distributed files ", - simuOccurList.size(), origOccurList.size()); - int index = 0; - for (Integer origDistFileCount : origOccurList) { - Assert.assertEquals("Distributed cache file reused in simulated " - + "jobs has not matched with reused of distributed" - + "cache file in original jobs.", - origDistFileCount, simuOccurList.get(index)); - index ++; - } - } - } - - /** - * Get the unique distributed cache files and occurrence between the jobs. - * @param jobsInfo - job's configurations as a map. - * @param jobConfIndex - 0 for simulated job configuration and - * 1 for original jobs configuration. - * @return - unique distributed cache files and occurrences as map. - */ - private Map getDistcacheFilesOccurenceBetweenJobs( - Map> jobsInfo, int jobConfIndex) { - Map filesOccurBtnJobs = new HashMap (); - Set jobIds = jobsInfo.keySet(); - Iterator ite = jobIds.iterator(); - while (ite.hasNext()) { - String jobId = ite.next(); - List jobconfs = jobsInfo.get(jobId); - String [] distCacheFiles = jobconfs.get(jobConfIndex).get( - GridMixConfig.GRIDMIX_DISTCACHE_FILES).split(","); - String [] distCacheFileTimeStamps = jobconfs.get(jobConfIndex).get( - GridMixConfig.GRIDMIX_DISTCACHE_TIMESTAMP).split(","); - String [] distCacheFileVisib = jobconfs.get(jobConfIndex).get( - GridMixConfig.GRIDMIX_DISTCACHE_VISIBILITIES).split(","); - int indx = 0; - for (String distCacheFile : distCacheFiles) { - String fileAndSize = distCacheFile + "^" - + distCacheFileTimeStamps[indx] + "^" - + jobconfs.get(jobConfIndex).getUser(); - if (filesOccurBtnJobs.get(fileAndSize) != null) { - int count = filesOccurBtnJobs.get(fileAndSize); - count ++; - filesOccurBtnJobs.put(fileAndSize, count); - } else { - filesOccurBtnJobs.put(fileAndSize, 1); - } - } - } - return filesOccurBtnJobs; - } - - /** - * It verifies the distributed cache emulation of a job. - * @param zombieJob - Original job story. - * @param simuJobConf - Simulated job configuration. - */ - public void verifyDistributeCache(ZombieJob zombieJob, - JobConf simuJobConf) throws IOException { - if (simuJobConf.getBoolean(GridMixConfig.GRIDMIX_DISTCACHE_ENABLE, false)) { - JobConf origJobConf = zombieJob.getJobConf(); - assertFileVisibility(simuJobConf); - assertDistcacheFiles(simuJobConf,origJobConf); - assertFileSizes(simuJobConf,origJobConf); - assertFileStamps(simuJobConf,origJobConf); - } else { - Assert.assertNull("Configuration has distributed cache visibilites" - + "without enabled distributed cache emulation.", - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_VISIBILITIES)); - Assert.assertNull("Configuration has distributed cache files time " - + "stamps without enabled distributed cache emulation.", - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_TIMESTAMP)); - Assert.assertNull("Configuration has distributed cache files paths" - + "without enabled distributed cache emulation.", - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_FILES)); - Assert.assertNull("Configuration has distributed cache files sizes" - + "without enabled distributed cache emulation.", - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_FILESSIZE)); - } - } - - private void assertFileStamps(JobConf simuJobConf, JobConf origJobConf) { - //Verify simulated jobs against distributed cache files time stamps. - String [] origDCFTS = - origJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_TIMESTAMP).split(","); - String [] simuDCFTS = - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_TIMESTAMP).split(","); - for (int index = 0; index < origDCFTS.length; index++) { - Assert.assertTrue("Invalid time stamps between original " - +"and simulated job", Long.parseLong(origDCFTS[index]) - < Long.parseLong(simuDCFTS[index])); - } - } - - private void assertFileVisibility(JobConf simuJobConf ) { - // Verify simulated jobs against distributed cache files visibilities. - String [] distFiles = - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_FILES).split(","); - String [] simuDistVisibilities = - simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_VISIBILITIES).split(","); - List expFileVisibility = new ArrayList(); - int index = 0; - for (String distFile : distFiles) { - boolean isLocalDistCache = GridmixSystemTestCase.isLocalDistCache( - distFile, - simuJobConf.getUser(), - Boolean.valueOf(simuDistVisibilities[index])); - if (!isLocalDistCache) { - expFileVisibility.add(true); - } else { - expFileVisibility.add(false); - } - index ++; - } - index = 0; - for (String actFileVisibility : simuDistVisibilities) { - Assert.assertEquals("Simulated job distributed cache file " - + "visibilities has not matched.", - expFileVisibility.get(index), - Boolean.valueOf(actFileVisibility)); - index ++; - } - } - - private void assertDistcacheFiles(JobConf simuJobConf, JobConf origJobConf) - throws IOException { - //Verify simulated jobs against distributed cache files. - String [] origDistFiles = origJobConf.get( - GridMixConfig.GRIDMIX_DISTCACHE_FILES).split(","); - String [] simuDistFiles = simuJobConf.get( - GridMixConfig.GRIDMIX_DISTCACHE_FILES).split(","); - String [] simuDistVisibilities = simuJobConf.get( - GridMixConfig.GRIDMIX_DISTCACHE_VISIBILITIES).split(","); - Assert.assertEquals("No. of simulatued job's distcache files mismacted" - + "with no.of original job's distcache files", - origDistFiles.length, simuDistFiles.length); - - int index = 0; - for (String simDistFile : simuDistFiles) { - Path distPath = new Path(simDistFile); - boolean isLocalDistCache = - GridmixSystemTestCase.isLocalDistCache(simDistFile, - simuJobConf.getUser(), - Boolean.valueOf(simuDistVisibilities[index])); - if (!isLocalDistCache) { - FileSystem fs = distPath.getFileSystem(conf); - FileStatus fstat = fs.getFileStatus(distPath); - FsPermission permission = fstat.getPermission(); - Assert.assertTrue("HDFS distributed cache file has wrong " - + "permissions for users.", - FsAction.READ_WRITE.SYMBOL - == permission.getUserAction().SYMBOL); - Assert.assertTrue("HDFS distributed cache file has wrong " - + "permissions for groups.", - FsAction.READ.SYMBOL - == permission.getGroupAction().SYMBOL); - Assert.assertTrue("HDSFS distributed cache file has wrong " - + "permissions for others.", - FsAction.READ.SYMBOL - == permission.getOtherAction().SYMBOL); - } - index++; - } - } - - private void assertFileSizes(JobConf simuJobConf, JobConf origJobConf) { - // Verify simulated jobs against distributed cache files size. - List origDistFilesSize = - Arrays.asList(origJobConf.get( - GridMixConfig.GRIDMIX_DISTCACHE_FILESSIZE).split(",")); - Collections.sort(origDistFilesSize); - - List simuDistFilesSize = - Arrays.asList(simuJobConf.get( - GridMixConfig.GRIDMIX_DISTCACHE_FILESSIZE).split(",")); - Collections.sort(simuDistFilesSize); - - Assert.assertEquals("Simulated job's file size list has not " - + "matched with the Original job's file size list.", - origDistFilesSize.size(), - simuDistFilesSize.size()); - - for (int index = 0; index < origDistFilesSize.size(); index ++) { - Assert.assertEquals("Simulated job distcache file size has not " - + "matched with original job distcache file size.", - origDistFilesSize.get(index), - simuDistFilesSize.get(index)); - } - } - - private void setJobDistributedCacheInfo(String jobId, JobConf simuJobConf, - JobConf origJobConf) { - if (simuJobConf.get(GridMixConfig.GRIDMIX_DISTCACHE_FILES) != null) { - List jobConfs = new ArrayList(); - jobConfs.add(simuJobConf); - jobConfs.add(origJobConf); - simuAndOrigJobsInfo.put(jobId,jobConfs); - } - } - - private List getMapValuesAsList(Map jobOccurs) { - List occursList = new ArrayList(); - Set files = jobOccurs.keySet(); - Iterator ite = files.iterator(); - while (ite.hasNext()) { - String file = ite.next(); - occursList.add(jobOccurs.get(file)); - } - return occursList; - } - - /** - * It verifies the high ram gridmix jobs. - * @param zombieJob - Original job story. - * @param simuJobConf - Simulated job configuration. - */ - @SuppressWarnings("deprecation") - public void verifyHighRamMemoryJobs(ZombieJob zombieJob, - JobConf simuJobConf) { - JobConf origJobConf = zombieJob.getJobConf(); - int origMapFactor = getMapFactor(origJobConf); - int origReduceFactor = getReduceFactor(origJobConf); - boolean isHighRamEnable = - simuJobConf.getBoolean(GridMixConfig.GRIDMIX_HIGH_RAM_JOB_ENABLE, - false); - if (isHighRamEnable) { - if (origMapFactor >= 2 && origReduceFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 1); - } else if(origMapFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 2); - } else if(origReduceFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 3); - } - } else { - if (origMapFactor >= 2 && origReduceFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 4); - } else if(origMapFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 5); - } else if(origReduceFactor >= 2) { - assertGridMixHighRamJob(simuJobConf, origJobConf, 6); - } - } - } - - /** - * Get the value for identifying the slots used by the map. - * @param jobConf - job configuration - * @return - map factor value. - */ - public static int getMapFactor(Configuration jobConf) { - long clusterMapMem = - Long.parseLong(jobConf.get(GridMixConfig.CLUSTER_MAP_MEMORY)); - long jobMapMem = - Long.parseLong(jobConf.get(GridMixConfig.JOB_MAP_MEMORY_MB)); - return (int)Math.ceil((double)jobMapMem / clusterMapMem); - } - - /** - * Get the value for identifying the slots used by the reduce. - * @param jobConf - job configuration. - * @return - reduce factor value. - */ - public static int getReduceFactor(Configuration jobConf) { - long clusterReduceMem = - Long.parseLong(jobConf.get(GridMixConfig.CLUSTER_REDUCE_MEMORY)); - long jobReduceMem = - Long.parseLong(jobConf.get(GridMixConfig.JOB_REDUCE_MEMORY_MB)); - return (int)Math.ceil((double)jobReduceMem / clusterReduceMem); - } - - @SuppressWarnings("deprecation") - private void assertGridMixHighRamJob(JobConf simuJobConf, - Configuration origConf, int option) { - int simuMapFactor = getMapFactor(simuJobConf); - int simuReduceFactor = getReduceFactor(simuJobConf); - /** - * option 1 : Both map and reduce honors the high ram. - * option 2 : Map only honors the high ram. - * option 3 : Reduce only honors the high ram. - * option 4 : Both map and reduce should not honors the high ram - * in disable state. - * option 5 : Map should not honors the high ram in disable state. - * option 6 : Reduce should not honors the high ram in disable state. - */ - switch (option) { - case 1 : - Assert.assertTrue("Gridmix job has not honored the high " - + "ram for map.", simuMapFactor >= 2 - && simuMapFactor == getMapFactor(origConf)); - Assert.assertTrue("Gridmix job has not honored the high " - + "ram for reduce.", simuReduceFactor >= 2 - && simuReduceFactor - == getReduceFactor(origConf)); - break; - case 2 : - Assert.assertTrue("Gridmix job has not honored the high " - + "ram for map.", simuMapFactor >= 2 - && simuMapFactor == getMapFactor(origConf)); - break; - case 3 : - Assert.assertTrue("Girdmix job has not honored the high " - + "ram for reduce.", simuReduceFactor >= 2 - && simuReduceFactor - == getReduceFactor(origConf)); - break; - case 4 : - Assert.assertTrue("Gridmix job has honored the high " - + "ram for map in emulation disable state.", - simuMapFactor < 2 - && simuMapFactor != getMapFactor(origConf)); - Assert.assertTrue("Gridmix job has honored the high " - + "ram for reduce in emulation disable state.", - simuReduceFactor < 2 - && simuReduceFactor - != getReduceFactor(origConf)); - break; - case 5 : - Assert.assertTrue("Gridmix job has honored the high " - + "ram for map in emulation disable state.", - simuMapFactor < 2 - && simuMapFactor != getMapFactor(origConf)); - break; - case 6 : - Assert.assertTrue("Girdmix job has honored the high " - + "ram for reduce in emulation disable state.", - simuReduceFactor < 2 - && simuReduceFactor - != getReduceFactor(origConf)); - break; - } - } - - /** - * Get task memory after scaling based on cluster configuration. - * @param jobTaskKey - Job task key attribute. - * @param clusterTaskKey - Cluster task key attribute. - * @param origConf - Original job configuration. - * @param simuConf - Simulated job configuration. - * @return scaled task memory value. - */ - @SuppressWarnings("deprecation") - public static long getScaledTaskMemInMB(String jobTaskKey, - String clusterTaskKey, - Configuration origConf, - Configuration simuConf) { - long simuClusterTaskValue = - simuConf.getLong(clusterTaskKey, JobConf.DISABLED_MEMORY_LIMIT); - long origClusterTaskValue = - origConf.getLong(clusterTaskKey, JobConf.DISABLED_MEMORY_LIMIT); - long origJobTaskValue = - origConf.getLong(jobTaskKey, JobConf.DISABLED_MEMORY_LIMIT); - double scaleFactor = - Math.ceil((double)origJobTaskValue / origClusterTaskValue); - long simulatedJobValue = (long)(scaleFactor * simuClusterTaskValue); - return simulatedJobValue; - } - - /** - * It Verifies the memory limit of a task. - * @param TaskMemInMB - task memory limit. - * @param taskLimitInMB - task upper limit. - */ - public static void verifyMemoryLimits(long TaskMemInMB, long taskLimitInMB) { - if (TaskMemInMB > taskLimitInMB) { - Assert.fail("Simulated job's task memory exceeds the " - + "upper limit of task virtual memory."); - } - } - - private String convertJobStatus(String jobStatus) { - if (jobStatus.equals("SUCCEEDED")) { - return "SUCCESS"; - } else { - return jobStatus; - } - } - - private String convertBytes(long bytesValue) { - int units = 1024; - if( bytesValue < units ) { - return String.valueOf(bytesValue)+ "B"; - } else { - // it converts the bytes into either KB or MB or GB or TB etc. - int exp = (int)(Math.log(bytesValue) / Math.log(units)); - return String.format("%1d%sB",(long)(bytesValue / Math.pow(units, exp)), - "KMGTPE".charAt(exp -1)); - } - } - - - private long getCounterValue(Counters counters, String key) - throws ParseException { - for (String groupName : counters.getGroupNames()) { - CounterGroup totalGroup = counters.getGroup(groupName); - Iterator itrCounter = totalGroup.iterator(); - while (itrCounter.hasNext()) { - Counter counter = itrCounter.next(); - if (counter.getName().equals(key)) { - return counter.getValue(); - } - } - } - return 0; - } -} - diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/UtilsForGridmix.java b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/UtilsForGridmix.java deleted file mode 100644 index 723adbc23c3..00000000000 --- a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/org/apache/hadoop/mapred/gridmix/test/system/UtilsForGridmix.java +++ /dev/null @@ -1,513 +0,0 @@ -/** - * 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.hadoop.mapred.gridmix.test.system; - -import java.io.IOException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.fs.FileSystem; -import org.apache.hadoop.fs.FileStatus; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.security.UserGroupInformation; -import org.apache.hadoop.util.ToolRunner; -import org.apache.hadoop.mapred.gridmix.Gridmix; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.mapred.JobClient; -import org.apache.hadoop.mapred.JobStatus; -import org.apache.hadoop.mapreduce.JobID; -import java.util.Date; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Arrays; -import java.net.URI; -import java.text.SimpleDateFormat; -import java.io.OutputStream; -import java.util.Set; -import java.util.List; -import java.util.Iterator; -import java.util.Map; -import java.io.File; -import java.io.FileOutputStream; -import org.apache.hadoop.test.system.ProxyUserDefinitions; -import org.apache.hadoop.test.system.ProxyUserDefinitions.GroupsAndHost; - -/** - * Gridmix utilities. - */ -public class UtilsForGridmix { - private static final Log LOG = LogFactory.getLog(UtilsForGridmix.class); - private static final Path DEFAULT_TRACES_PATH = - new Path(System.getProperty("user.dir") + "/src/test/system/resources/"); - - /** - * cleanup the folder or file. - * @param path - folder or file path. - * @param conf - cluster configuration - * @throws IOException - If an I/O error occurs. - */ - public static void cleanup(Path path, Configuration conf) - throws IOException { - FileSystem fs = path.getFileSystem(conf); - fs.delete(path, true); - fs.close(); - } - - /** - * Get the login user. - * @return - login user as string.. - * @throws IOException - if an I/O error occurs. - */ - public static String getUserName() throws IOException { - return UserGroupInformation.getLoginUser().getUserName(); - } - - /** - * Get the argument list for gridmix job. - * @param gridmixDir - gridmix parent directory. - * @param gridmixRunMode - gridmix modes either 1,2,3. - * @param values - gridmix runtime values. - * @param otherArgs - gridmix other generic args. - * @return - argument list as string array. - */ - public static String [] getArgsList(Path gridmixDir, int gridmixRunMode, - String [] values, String [] otherArgs) { - String [] runtimeArgs = { - "-D", GridMixConfig.GRIDMIX_LOG_MODE + "=DEBUG", - "-D", GridMixConfig.GRIDMIX_OUTPUT_DIR + "=gridmix", - "-D", GridMixConfig.GRIDMIX_JOB_SUBMISSION_QUEUE_IN_TRACE + "=true", - "-D", GridMixConfig.GRIDMIX_JOB_TYPE + "=" + values[0], - "-D", GridMixConfig.GRIDMIX_USER_RESOLVER + "=" + values[1], - "-D", GridMixConfig.GRIDMIX_SUBMISSION_POLICY + "=" + values[2] - }; - - String [] classArgs; - if ((gridmixRunMode == GridMixRunMode.DATA_GENERATION.getValue() - || gridmixRunMode - == GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()) - && values[1].indexOf("RoundRobinUserResolver") > 0) { - classArgs = new String[] { - "-generate", values[3], - "-users", values[4], - gridmixDir.toString(), - values[5] - }; - } else if (gridmixRunMode == GridMixRunMode.DATA_GENERATION.getValue() - || gridmixRunMode - == GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.getValue()) { - classArgs = new String[] { - "-generate", values[3], - gridmixDir.toString(), - values[4] - }; - } else if (gridmixRunMode == GridMixRunMode.RUN_GRIDMIX.getValue() - && values[1].indexOf("RoundRobinUserResolver") > 0) { - classArgs = new String[] { - "-users", values[3], - gridmixDir.toString(), - values[4] - }; - } else { - classArgs = new String[] { - gridmixDir.toString(),values[3] - }; - } - - String [] args = new String [runtimeArgs.length + - classArgs.length + ((otherArgs != null)?otherArgs.length:0)]; - System.arraycopy(runtimeArgs, 0, args, 0, runtimeArgs.length); - - if (otherArgs != null) { - System.arraycopy(otherArgs, 0, args, runtimeArgs.length, - otherArgs.length); - System.arraycopy(classArgs, 0, args, (runtimeArgs.length + - otherArgs.length), classArgs.length); - } else { - System.arraycopy(classArgs, 0, args, runtimeArgs.length, - classArgs.length); - } - return args; - } - - /** - * Create a file with specified size in mb. - * @param sizeInMB - file size in mb. - * @param inputDir - input directory. - * @param conf - cluster configuration. - * @throws Exception - if an exception occurs. - */ - public static void createFile(int sizeInMB, Path inputDir, - Configuration conf) throws Exception { - Date d = new Date(); - SimpleDateFormat sdf = new SimpleDateFormat("ddMMyy_HHmmssS"); - String formatDate = sdf.format(d); - FileSystem fs = inputDir.getFileSystem(conf); - OutputStream out = fs.create(new Path(inputDir,"datafile_" + formatDate)); - final byte[] b = new byte[1024 * 1024]; - for (int index = 0; index < sizeInMB; index++) { - out.write(b); - } - out.close(); - fs.close(); - } - - /** - * Create directories for a path. - * @param path - directories path. - * @param conf - cluster configuration. - * @throws IOException - if an I/O error occurs. - */ - public static void createDirs(Path path,Configuration conf) - throws IOException { - FileSystem fs = path.getFileSystem(conf); - if (!fs.exists(path)) { - fs.mkdirs(path); - } - } - - /** - * Run the Gridmix job with given runtime arguments. - * @param gridmixDir - Gridmix parent directory. - * @param conf - cluster configuration. - * @param gridmixRunMode - gridmix run mode either 1,2,3 - * @param runtimeValues -gridmix runtime values. - * @return - gridmix status either 0 or 1. - * @throws Exception - */ - public static int runGridmixJob(Path gridmixDir, Configuration conf, - int gridmixRunMode, String [] runtimeValues) throws Exception { - return runGridmixJob(gridmixDir, conf, gridmixRunMode, runtimeValues, null); - } - /** - * Run the Gridmix job with given runtime arguments. - * @param gridmixDir - Gridmix parent directory - * @param conf - cluster configuration. - * @param gridmixRunMode - gridmix run mode. - * @param runtimeValues - gridmix runtime values. - * @param otherArgs - gridmix other generic args. - * @return - gridmix status either 0 or 1. - * @throws Exception - */ - - public static int runGridmixJob(Path gridmixDir, Configuration conf, - int gridmixRunMode, String [] runtimeValues, - String [] otherArgs) throws Exception { - Path outputDir = new Path(gridmixDir, "gridmix"); - Path inputDir = new Path(gridmixDir, "input"); - LOG.info("Cleanup the data if data already exists."); - String modeName = new String(); - switch (gridmixRunMode) { - case 1 : - cleanup(inputDir, conf); - cleanup(outputDir, conf); - modeName = GridMixRunMode.DATA_GENERATION.name(); - break; - case 2 : - cleanup(outputDir, conf); - modeName = GridMixRunMode.RUN_GRIDMIX.name(); - break; - case 3 : - cleanup(inputDir, conf); - cleanup(outputDir, conf); - modeName = GridMixRunMode.DATA_GENERATION_AND_RUN_GRIDMIX.name(); - break; - } - - final String [] args = - UtilsForGridmix.getArgsList(gridmixDir, gridmixRunMode, - runtimeValues, otherArgs); - Gridmix gridmix = new Gridmix(); - LOG.info("Submit a Gridmix job in " + runtimeValues[1] - + " mode for " + modeName); - int exitCode = ToolRunner.run(conf, gridmix, args); - return exitCode; - } - - /** - * Get the proxy users file. - * @param conf - cluster configuration. - * @return String - proxy users file. - * @Exception - if no proxy users found in configuration. - */ - public static String getProxyUsersFile(Configuration conf) - throws Exception { - ProxyUserDefinitions pud = getProxyUsersData(conf); - String fileName = buildProxyUsersFile(pud.getProxyUsers()); - if (fileName == null) { - LOG.error("Proxy users file not found."); - throw new Exception("Proxy users file not found."); - } else { - return fileName; - } - } - - /** - * List the current gridmix jobid's. - * @param client - job client. - * @param execJobCount - number of executed jobs. - * @return - list of gridmix jobid's. - */ - public static List listGridmixJobIDs(JobClient client, - int execJobCount) throws IOException { - List jobids = new ArrayList(); - JobStatus [] jobStatus = client.getAllJobs(); - int numJobs = jobStatus.length; - for (int index = 1; index <= execJobCount; index++) { - JobStatus js = jobStatus[numJobs - index]; - JobID jobid = js.getJobID(); - String jobName = js.getJobName(); - if (!jobName.equals("GRIDMIX_GENERATE_INPUT_DATA") && - !jobName.equals("GRIDMIX_GENERATE_DISTCACHE_DATA")) { - jobids.add(jobid); - } - } - return (jobids.size() == 0)? null : jobids; - } - - /** - * List the proxy users. - * @param conf - * @return - * @throws Exception - */ - public static List listProxyUsers(Configuration conf, - String loginUser) throws Exception { - List proxyUsers = new ArrayList(); - ProxyUserDefinitions pud = getProxyUsersData(conf); - Map usersData = pud.getProxyUsers(); - Collection users = usersData.keySet(); - Iterator itr = users.iterator(); - while (itr.hasNext()) { - String user = itr.next(); - if (!user.equals(loginUser)){ proxyUsers.add(user); }; - } - return proxyUsers; - } - - private static String buildProxyUsersFile(final Map - proxyUserData) throws Exception { - FileOutputStream fos = null; - File file = null; - StringBuffer input = new StringBuffer(); - Set users = proxyUserData.keySet(); - Iterator itr = users.iterator(); - while (itr.hasNext()) { - String user = itr.next().toString(); - if (!user.equals( - UserGroupInformation.getLoginUser().getShortUserName())) { - input.append(user); - final GroupsAndHost gah = proxyUserData.get(user); - final List groups = gah.getGroups(); - for (String group : groups) { - input.append(","); - input.append(group); - } - input.append("\n"); - } - } - if (input.length() > 0) { - try { - file = File.createTempFile("proxyusers", null); - fos = new FileOutputStream(file); - fos.write(input.toString().getBytes()); - } catch(IOException ioexp) { - LOG.warn(ioexp.getMessage()); - return null; - } finally { - fos.close(); - file.deleteOnExit(); - } - LOG.info("file.toString():" + file.toString()); - return file.toString(); - } else { - return null; - } - } - - private static ProxyUserDefinitions getProxyUsersData(Configuration conf) - throws Exception { - Iterator itr = conf.iterator(); - List proxyUsersData = new ArrayList(); - while (itr.hasNext()) { - String property = itr.next().toString(); - if (property.indexOf("hadoop.proxyuser") >= 0 - && property.indexOf("groups=") >= 0) { - proxyUsersData.add(property.split("\\.")[2]); - } - } - - if (proxyUsersData.size() == 0) { - LOG.error("No proxy users found in the configuration."); - throw new Exception("No proxy users found in the configuration."); - } - - ProxyUserDefinitions pud = new ProxyUserDefinitions() { - public boolean writeToFile(URI filePath) throws IOException { - throw new UnsupportedOperationException("No such methood exists."); - }; - }; - - for (String userName : proxyUsersData) { - List groups = Arrays.asList(conf.get("hadoop.proxyuser." + - userName + ".groups").split("//,")); - List hosts = Arrays.asList(conf.get("hadoop.proxyuser." + - userName + ".hosts").split("//,")); - ProxyUserDefinitions.GroupsAndHost definitions = - pud.new GroupsAndHost(); - definitions.setGroups(groups); - definitions.setHosts(hosts); - pud.addProxyUser(userName, definitions); - } - return pud; - } - - /** - * Gives the list of paths for MR traces against different time - * intervals.It fetches only the paths which followed the below - * file convention. - * Syntax : <FileName>_<TimeIntervals>.json.gz - * There is a restriction in a file and user has to - * follow the below convention for time interval. - * Syntax: <numeric>[m|h|d] - * e.g : for 10 minutes trace should specify 10m, - * same way for 1 hour traces should specify 1h, - * for 1 day traces should specify 1d. - * - * @param conf - cluster configuration. - * @return - list of MR paths as key/value pair based on time interval. - * @throws IOException - if an I/O error occurs. - */ - public static Map getMRTraces(Configuration conf) - throws IOException { - return getMRTraces(conf, DEFAULT_TRACES_PATH); - } - - /** - * It gives the list of paths for MR traces against different time - * intervals. It fetches only the paths which followed the below - * file convention. - * Syntax : <FileNames>_<TimeInterval>.json.gz - * There is a restriction in a file and user has to follow the - * below convention for time interval. - * Syntax: <numeric>[m|h|d] - * e.g : for 10 minutes trace should specify 10m, - * same way for 1 hour traces should specify 1h, - * for 1 day traces should specify 1d. - * - * @param conf - cluster configuration object. - * @param tracesPath - MR traces path. - * @return - list of MR paths as key/value pair based on time interval. - * @throws IOException - If an I/O error occurs. - */ - public static Map getMRTraces(Configuration conf, - Path tracesPath) throws IOException { - Map jobTraces = new HashMap (); - final FileSystem fs = FileSystem.getLocal(conf); - final FileStatus fstat[] = fs.listStatus(tracesPath); - for (FileStatus fst : fstat) { - final String fileName = fst.getPath().getName(); - if (fileName.endsWith("m.json.gz") - || fileName.endsWith("h.json.gz") - || fileName.endsWith("d.json.gz")) { - jobTraces.put(fileName.substring(fileName.indexOf("_") + 1, - fileName.indexOf(".json.gz")), fst.getPath().toString()); - } - } - if (jobTraces.size() == 0) { - LOG.error("No traces found in " + tracesPath.toString() + " path."); - throw new IOException("No traces found in " - + tracesPath.toString() + " path."); - } - return jobTraces; - } - - /** - * It list the all the MR traces path irrespective of time. - * @param conf - cluster configuration. - * @param tracesPath - MR traces path - * @return - MR paths as a list. - * @throws IOException - if an I/O error occurs. - */ - public static List listMRTraces(Configuration conf, - Path tracesPath) throws IOException { - List jobTraces = new ArrayList(); - final FileSystem fs = FileSystem.getLocal(conf); - final FileStatus fstat[] = fs.listStatus(tracesPath); - for (FileStatus fst : fstat) { - jobTraces.add(fst.getPath().toString()); - } - if (jobTraces.size() == 0) { - LOG.error("No traces found in " + tracesPath.toString() + " path."); - throw new IOException("No traces found in " - + tracesPath.toString() + " path."); - } - return jobTraces; - } - - /** - * It list the all the MR traces path irrespective of time. - * @param conf - cluster configuration. - * @param tracesPath - MR traces path - * @return - MR paths as a list. - * @throws IOException - if an I/O error occurs. - */ - public static List listMRTraces(Configuration conf) - throws IOException { - return listMRTraces(conf, DEFAULT_TRACES_PATH); - } - - /** - * Gives the list of MR traces for given time interval. - * The time interval should be following convention. - * Syntax : <numeric>[m|h|d] - * e.g : 10m or 1h or 2d etc. - * @param conf - cluster configuration - * @param timeInterval - trace time interval. - * @param tracesPath - MR traces Path. - * @return - MR paths as a list for a given time interval. - * @throws IOException - If an I/O error occurs. - */ - public static List listMRTracesByTime(Configuration conf, - String timeInterval, Path tracesPath) throws IOException { - List jobTraces = new ArrayList(); - final FileSystem fs = FileSystem.getLocal(conf); - final FileStatus fstat[] = fs.listStatus(tracesPath); - for (FileStatus fst : fstat) { - final String fileName = fst.getPath().getName(); - if (fileName.indexOf(timeInterval) >= 0) { - jobTraces.add(fst.getPath().toString()); - } - } - return jobTraces; - } - - /** - * Gives the list of MR traces for given time interval. - * The time interval should be following convention. - * Syntax : <numeric>[m|h|d] - * e.g : 10m or 1h or 2d etc. - * @param conf - cluster configuration - * @param timeInterval - trace time interval. - * @return - MR paths as a list for a given time interval. - * @throws IOException - If an I/O error occurs. - */ - public static List listMRTracesByTime(Configuration conf, - String timeInterval) throws IOException { - return listMRTracesByTime(conf, timeInterval, DEFAULT_TRACES_PATH); - } -} diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/2m_stream_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/2m_stream_trace.json.gz deleted file mode 100644 index c1458361904566d9fe3e2861120047f75f56c53b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 62467 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 diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/3m_stream_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/3m_stream_trace.json.gz deleted file mode 100644 index 7bf17a06d211710a567f6cc1409d7521e1e96796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87384 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

xI-BsI&$;W8#MmN0%* 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 diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/5m_stream_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/5m_stream_trace.json.gz deleted file mode 100644 index a72e41f44017e65fb9060c4c8f81687ed3d4e6cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 191702 zcmV)JK)b&miwFo;P}@xa12t`5b98cLVQpV@a$#d-E^2dcZUF3^S##tzl7Qd+D-?=- z+K|||55IXl_N;f^ZAYse^RO}Dpj4Dp?z)C#b+^Vb|9vwPtSVFyJgRh9j##@@2MK}z znD{c0NT7cI>g?=%RZf@Xw0<~0`}*ws-B0h|e)Hq`1)lhAdHus*=_q{qRWQz(fIrLm zugr5E60NJEq%@zVi~OP9UimJc7j*n@<#aNiez~g4BA-tecUQ}@F3PN$=d)QzJvm=v7Ji;$p(OPb>0$9DOCo&U<{zw_vd4-czQ zthe9%yg8oNbunMnd-sRKv*k@*PnQckyjag>7n>9J%c|a1?+wrBe=pwPaiR73HeqKS z%r;3`RO?wyIbHqo?YG}uUF|Nvoi3);ed~H-nct>q%HA|Y^R1^Xer3D-Z=i-BuU50^ zrs|R#dvV5%IR54AAG>T<>tCw;u4ppl0`nB^;^P@Cn!GDm5Nhz@a zRtUi_&V+(G`-?Nly!Vikw9YxmOet%vxj56@7z5X7r?r+BXGTLdaJ?0f4}*6P+4$(b ztNVxQ?f$K~vz|cOJm?G*PKiIZk@qYf*B|gyi2Jaem5Wk`0kv> zbkOiju;{+k{rdKHR(wwqP)zX7mwa~?x=_cd`^jzf7cA`iBByg&IuHiYPVjf=^L0Ve z%_5PT6?>N_PDK}L<+yQjn+AIF4~x~heqY=y%Lz4@a)!s}e_Gd&;4ho@gyK01kEoTR zD~p@u{Cc`54sXMv9yM9tg!6wZm+Mt^&_dDq==xTItMCN21#Km06*GQ7tLbc3OnRDu z?jL1Nr~bW>fUd4@ncm=URTj5J2}Sv_!Bh)h`9o1Q2hX>VI==|~655}i{UhA4XOj}KvyeNGuonJvqD+TQO!tDNBwHXa!e_>(vX4F zR>Sq0F%b4Mqa-RZ&@HI0z3`S}8LhCW5(U>5l_+Q$hsQPJ4v!lsoqHw~14Xf>o#1Iy zjP+Q-UKPUzR17qYY^UhT;!mq$*yB|U^mXN*O2xRxX^WHe(upc2lHi1jVVx=_63� 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�A-k~T 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 z zBmctTL;c*S&F78LGZ0^dO%DGj*y&SFXLV!3d?gbd?U}U1($IHeS)~WX;2KyYwU@|B zGVCEho9(;rR*SWhNl8&0r*=`RPE4M!jp8^~AkI~m6 zaJ$uM5U{wevAF4CBZYA-*Wsl*yfC{9%PwcWRzGKyQ`24Si@S%M_M%^Yb z7q~uqhZB8lj04in)GQ&O+fY#wpe$0_ z?e2gSiR@NU9 zv0#6WsKER%;K`CRpEz9;RXcj8k79#G=`la{+lx~rf0I>Om+)dD&I?y|-3HNTIfg6p zq)JiGeEMEQ1?FTD%0A9}ENvJqZD%bs)#H`vCkE6NQvjyCgfqoC8pg+0U@8-WNthJU_-5EhM zOfLXCxT0=4&W+kASFf0;{1d%DEkhPvNs{#$ugP+pzKsCiccGzs1ui7BH z7gBT+rK@Rx6qP-0u6Gf(!TzOFRb<`yIK`HxMwHwO7gVunU;)*|;zQ`A=C#Y1W*EEw z5_IFx3?42`!JgO5P1dlV(gj@~&r<{WS+r^s((ZA&k`*U28p-@xAB{6*XoI|Bh=|PX z7m0<(nyA|p`Bo=#NhYwdD=8CDt0u5@N(c^_uExBAA42@dQ^_rCGM$RKISsD6%4lT+ zJwC#0M=Wm$ib%B?BB1s7rmPhACtCGfx~pI$FCey=fJw^htCb=pTfV@Xw@Cnl!|tm* zRn6wT)s7kHFja4&8xOTtTo=vNRbFhD&SFOl*&w?L&onIq`x)QxLG8lJg%~m|&gZlG zsm6fIgVFb(uT?5am^J{nWWcAd-<>F*FL40)XV-<9i1{9|sC{0ZOBo_C(4hx}Xzf`3 zeOOmIgSB28g+gi4gdYAS0=W$8$7m*gd@SjkzkqKjS%2dRN1d6&zPaqsJ_eZwv+v=# zB=&&5vj{iq<(EetG3pOgoS2?80HnK)*O7$wM$*@)yi~_x1=46ecSnx|yT}@ToXkG} zva9AtBlM+uWMMV~UzPKy@f|5J(dWAT>)#QP&)v2D$h978#Te^Y7YYepfiLW4`(D$^ zoD0%x8A1Y;R9r5IyK)(~g%U~vfOdUgD5peC{+>E*FOdD+T7B;X9X4;e$y97Mw-|dz zgZR7^9eNeXbVjDnqbrPGowJfTb=M`XjPVa9hN3i?cbDf_$>uu9B~HNnH>L*B%}%Ga z;4F(;Mz}1}o5krH29dtEn!vwklU#n#BUp2iZql0i6Ti&Cv(c%VVgC|$%i@}>(Lcl< zvoALgDnc-m!OE_$EdeG2p_xA{v5;7EJ*+|IR&vnsUmwsIY50_u54zy2ljMXDlMvYH z19EYGtz+cOc%962jrM>%v_P7RC2BP2y$rZ-@KIF+eH%=iJ9RnlAl0Ao*7Sp@-$4dkE%|791RMX6yucW=Zo*i-KVukun^QD%_l-^J%a)3QDB5 zd$qT+m1NWj0R0UulZeBrg6}!8=K23mdLyHr?}$x&Y8kbrD0$Ust!W}tX%f{AG_R{1k*0-w>Ae(j<}`H9J$elA z5%b*ve*Q*7c=riS{QiTI@dpB(mVqS$uh9*muHDA)2(Kwq7n5T0QEIHLb*@X4eajod ziI4!Yn1U|=4*!!heTW^FL9l28%_dC*22H5QlZMTu!Q?$4^0US;+7Jq#E_k4GqPl2W zBiO2R{J`~B_t^iQd&y>mY)T*OWR1qnf*P z{$Me?Zp&ZR1PH2+Dx&pSqhE+=Wht+NK!4uEI7ExSyTsiRNe+zyZ6is^_AQ1VQ-R${ z19~L=D9pE~-t_pJs_I|i`7JXKi&6QV?g)hJ3FOtHim-W_1J6MZ&)KhgWP)+JuIfc6 z6I}APw?r<|P#%0`o5HDHiKmc^)Hq|0YvO0h_U!jLsP_)vT`&9nw0{_h@=%jJG@ z>zAqcbCs~QLD=j2FNTXWZ}HurzsNsMJ@%K8+LTZw38zR|?PH#05e;=%u^b)f=xU-B zel^RI*C@Zb6~sBMDLLEnU(&IAklpMr?e$jKX8Vy}iGfVsm+VH)2j*+@fxup9PsFjH zQ^?1azHqO-GYpNf_oYl;iF=Se1v`%q_B=SBP@38zQ4i8(!Y~rsiy&2}PWv!wU!zZx zC_g#DM*E$7t5d-g!pAJEru>)PCyesz%9$?;b|u5=P`7}<0ThCRje#25+qmy|vktXA zymt25(W7G9xPj>?!L?xN%-4oyu&bEUevh5I?=PiTjgdbXaMRQ(_)1DmSsLcwIIjV? z2nl+BlIwumAvM@D%Yt?e95{%Hof-pv*k9*`+EwoGrJK@aogReex`4U#VB|V!Yh|}f zE**HvIqtUdCJJGhI)2ZW62E!E7*Lv~1AVBuq3R(QA>`AkLn_4H+H>TaCsK#Hbw`@du3i$^uJs&J7m zcsNhTHZd=}ZjynwL57#JW!8A_@iGoO&yj8UGf1jIxSm_qM|10q;_fUH$1^^2y7hO$ zT2dRD3=<@8C;xa6U--83^GcXYG#MDt3qfnv*cz(4w=n!l1S9YLPN2f#p%LkDRJgz6{e zd8pFvEMBs)x${Es;^?2mPerrg5>I|{(R#9ukf(JMWw4sjY3i`gI4O5H(#4HvFpdlG4yOGb;VNcy3;eES~BB|FV#(ob~*yNjCjlBQ!^#SGDgCg9CuVjY4Z2 z%*2b;ROvg#l1FfwQ5LVX!y{Ml2+qdJOtD2X?fF;QQ4+!@Jw)z|c4fA4D0u2q23|P% z347`Gg_|8nAD{gqxUU!yjL2zY8GW>xV9Z}LXRT~hdK;&{TKx|$g@V!k&=I(-F>`#!zq!Ll@JF(EqTZ^U+xFJMZve=R< zfF%wJ2ERQ&!x2Da4LSscWajwtE@ZSM?w;o1vpSr34->_`?xCv6#GdPX1{$(f#sWNJ z;rR!DALbXIS=7fSLsj)*3!deg^i75Z4d(o!cPi3=lJ(>o{W|4X)uxOo{U;2>>1y|< z@>4gQ>cBScjH8bTkBe-%N=rnlr&_Q#OhqE7;Ar5-z&DlosHX##&+1WbGmq@<@oC~j zS!lH`pQcls5FA&vRh-I&n$163K=Nc~WoB;o*WH*z=t5c}N}&5~k8W&`o@{CM9pUFG zln49*;}Cm_z2oU*esEO5FYu(V!hJ3eC8$u}0|vOe7+`=FWw$h;S)xrSzz(qpOM-}} zyvb1waT?W~)EcpFY=cKg$xqV?Vp9BJL)MMJ^NVaS;13A{xx-JV?VpDi>BMklIl6&w z>|4{@>hxYTbuPE{P#z5&CTH>wE5Eq1h|Bnd*=%=wlrbwXKD6{~07qrTTQBfVx8Sfc z1SrL1BZ(hxVzuwNp7?v_0c-*{zY*R@2$im^+M3N+bF!6kT?NAVK$&iYoY6t~^g|WS zgp15+t{}KznINNV+L(!!eq^m58taZCbLuGwh8BS-N<;t-%EV&Dl%^;BPjsOP7Q!7c zd@aWe9#JN#emH**(CtTpE>uB}k9W&JWmlMb>|K1P3MxiDd&B%4EZwt2-0|dCIHw8M za{*OY1VYabPcp9gGhaD+3_%U~a(Kz!WSkZeWZ1y;p?`Y2@pdYJ0)BP$t6NR`K}JF( z)=y~(XRf%b4_I1V3Xb-g?m|A1)B-UQHNEG^4&wyt0v+%OR3NGYSRzU?2k*R6E6a|N z;2(h&S>M;Rr7eko&fS3yP+}46NI|cArzm`PP(qVZzy_UA_$rMOn6M%G8zpwsi^xlo zt$}g;SK{Y2PWQvfcbeJ!dm-(hh=0~7=A$B_HD zc;YVl9CA@fM>LgzeE{Hs@VVb6HDtylrH0=Z$b=MZ{7UwFKTUUsG!sx zdn4D0_YrDuLf*tyKJX$fjkTlVGB7<;*G1ta7T-y`1EuG+Vc8<{$G(8*YDW733fa09 z!eC(&go)9+n?#yK5zS=tT>8Wvf=DU*j=Kj5hPQJ0`x~9y)*00u0@0=?)y16F1^?UU z*02vyOojR*F2MY2{st=r6lxc6>Xg8HA!qPfLE%Zi^8ueB_+>IBqV;wGr_v5IA;*&cET+`;TfY<8 zwB^&F$zyks9ttIRZiC6WtNTP09#P~Brf^LI@-|k(6=?4ya5ZM4^7mbGMm$KhwF4h> zx>27O6xkQTW(XhQ-qPcbIPwIek$hK00L3dG#Xk<;fqd*U>9bd!2I8Q7G;mV*n`ji2 zqM#28_8T0tr&vzsO~pcfu7E7~QGCQA7+tZ|!l_%_4*bn6Jk3owBZjAA7>$DAi)zHf zJ2&J$y|>b{;wdxv4>@V#giQv`{=Jg29SG)=PjW~CJ6IdqQX4?5@@*byPGkkg)KE~1 zl-r*w-Q!ERo2UPUHO!r@%#^O!1+~Ti&f5G^9Cd%{L)AR*IL;TlI>Y8ZuuKteKJ;)0 zq8KS@ZtI!9>KP|xI{_QI8aMe~uoF_Oj6k&$KG0Mi&rI6<@&Lhj>~|L#_4^xgxyV8P z=-VE0#0Pg;DwtAkpP0oc%2q9~r++G^P7hTnGg1Vt@Gz>Qq=*L3Q(hUF@L;k z>`l`Ee`?EvAUE#Ur^OcWdb0GSu_46G?;OS?7x5QAPQw#w`Mvn1j#|47|;Y%2a1*2LOt)VIAR zB5zWR#V)%(L^utaTXY*$TUR16_cSI(+xFiH)SEq1XAO##i4(`;~tf(k9hfw zZ;1PdcS&2DNqO$Tj@H>^Tq zG5wyU%f49OX-Z+M>{nl_Ct9Eg*M4h>4G{H=tn!-y5qT3BP_r-tZ@ovBiyVbXEgb7t zXHeMy;nU~|SM4=*fr~{Elfco5RuIJP8<|Ug3@75zbewOzzh79u#KGi7_+@b_l)`0_r6z)9(Mf`O2d zzBm>J#1{C%?=rq9$OI$1pz@-+HT02eghiDAqoe81w&Gq%U%Bs<@#0S}>&l5bm32P` zhY|O+jQfr7@X(Xiei^h-!V07@scj&2A(Z%9Elfcvv_Hk4TWV6zKUQC& zig#-`%R1z9(Y=D`(0dnVW@`JsAH5#}^uceX`r|ty2|Og1d2Gg2;cVZ&n%NVlvg!N{ z{k%jNW7FUJSy@jTs(A#*@NXoBJW$C)@(iH+ao&V>;J2wn<;4xc;JKNpEw zKXNEK=1c%o#eY!}Y3}WQ_H^TylVXR1F*V~X34~rYBi>jEFE7PpySfWJ=34TGkf^T> zKphh=An`zw`A0N6*GZ=7^PmI`X}3IE!EwDCCVSKVYf-^boRtU%`UW=Ty;IX@!C zQpnykL+^Pzxn5Om9rwi8s)869sgb9<}omY(f2>@Rp zrDUDk{&C#ADgs82Z*%B$wUzPkEIG^_!9O5-{HD~Slw)oT0uSlU6?mT(*{eU zPk}(PEW_s4W9I;G3a$w{kMb9!)DX^`6}QoZsw-5OBMzl^q!&F06ycd^+3v)OC@$59 zfni!WvWK?FF^y6jLon3`)fjXlZ=3@ZGtuN@5*#=UxufrovYTpdqxbicC>8Ocb7BY( zRfSVIWAj>L_2mk)qie#Y30%S@Nlpj)kjbor+m_X@b?<~!%kSS6YJkRI^~*qi(la3* z#T36aTC%aPJ6inf9(D*=&9nVC8KZP-bOgz4W?6g0tBSmNl!Ck3IO$SEc(d4rh(9T_ zFnA9b8UR3KLZKk-5tjlVk9a<)nMH-ajDe>fOp_zVB*?2;92l50HcdoXIYT1`Ytc>J zQ%)I+X`KMNMx1Qn7d8ycO_x_UH`g!*Z46ajfkngnb0ZYJB1Rf1#_gG9TybF5W-eA= z9>m<<4Vq>LnS)iSaXffTp$eG5kNtlFpHPeiG7o@ zSzA+0$WF~Omz26Fd=;Ysvr98b4jO&t@7H}Pvca|vve-@d@2AkX$Hi!j=#sWRG1&h( zNMevz5Gl%88}6Yo7K&#)LnVZ(D+47Fl8tAyf1wJ9MuM3Dt9yGjEfFie>8pd@AK5rc zxEr8}4Z{M;O?BLQ5%y04vc{T;l@)xeND15qxxmo|u^PfJbs5g%+v* z&F@Q#mV$+bhhTFpM|v~ET~qR z^+GW6LP{|O)m0fn?QjXhn265}A!qh$jZd z=P)XgX0ql(gU~g%-cTbio?w>h8T(Fb8EjM!i1_HK}q=RS%*+$z7BL@js z7*_Kp9MD&iMI~9?c_nlglB6xujA(ARL}EJPslC{#iVmsz8=8c8l=j^~6|v&po>V-` zR}q*se^?k-xs4^~P1JJ6z*KijM3~!Rqn1-AQi+QuUm`5GwE9wi8fjVAHl~dO@K3tt zhswY6tt9wU+)u7%Od&V#>AejAh4Q@?UHd?N{XUd+sJt|5G>^Sps`=z0`J(n|3S~_1y3e90M~33yEVMw-S&x%R0NX7h%|?o$(raZF4c``Zc{7*u#? z8wsgcTJfn^9865isi|FOLAfu66KA4)(l;ZlvvQ-}rOd(^z>}ud6XITpF~;Oza54s^ zz(oV5&J|iB;KmJ(ocMH3LwNO85mNh#5&te#`!)DN8hNhFlKkr9mgt2 z5yqrVxdzK+SW|~&##F%K%i2E}Rcp^@!SuV1wLgguFFovAstcB!DXamjymhbJHdlhl zkJ@O>cF;$F+XB~u31pg>29m&+Rgh?lpGg~e(zX~R2dfMYaxEhFH~X9)r;|{~1XAWF z=Rz2e;n}N8BbFS+SjIn%Sj03yBNh_DgFDHs9ef0!U+K@RZo^w<8A}KQZIGwQDdea0 z6ED-@!i5cS<}3!T9Z1RQ(wR5Ue65WgP^i zq+;NrY9w;KL7?LR4dJJp9o7|kaODoFn;tG2*ZqwzZYlkWcn*Fw?g$JDyEfJ+HD?%5 zkE>CYQ>o#85D}c{4;yyv)v%E%Z_0OAgh{b56^OzwS3kok0BsDlnO&zg;c#r&v2}2< zgZ}6`Cq06LpA9RhtJ9>o54UF(pxx8#u+L5Zhpya?8MKY|{FRyfLWtJXEyAvj2u|%( z#7tEzNgJU#1YsgHRG_ZQ_>wxyfqwnmv}TfA{N$S>dfP1Q1wdfPZS`c*YsMo zMUWg+W00kr8AV2^HDdipnxKR``@s2LA)P5{>?GyCI0# zf^Vk>7(G~xvZfg;v1gZcC5g^;N_Jxy0bTNVN+~r;wt9=bqQ@gO=*68wf1*KUWyEuO zRI=W^@$+YXabJvxuQcZ9A%jtYIisz^1WhdEM?OkmCcU;iD3%GaQhe=@!|$#pO?(B4 zJ@iGm_$iHH`iBXz$SZsd@)knQG7Q35?&1~BA`VS8+2BH3>H2CNd)!pZH>&*iqzZ#x zT$zB{r@u=Kg>PFyX1imI%L^9-yJM@ihf6M>ZheW5CUd%LSlkSnt(h71{fYTz2n^~0 zZiZx%jYe3BOKTw-8YOA`MQm~tP-ZkrR+D$A z-7^wPFm#tOrRyE%+^?|rL0uw44|aw}Xy-I`dKQ_-#g-TZh(ImHx zJEdLO6DAQ*@E$QDFGor^usn1@PPi7j=b?QD-WbkO7RNM6(shdpVb+r!2W9nfKz`0BA~G$k(R%oa1|tnJf~-;Ef?7HSqfIln>hcc?*!U!%hQUgt6$2>4`g9~Y z6jG>UwLZx5@d}&xd63FFQCMXaLIAEc^GMlSoSZFyH>OGP4~;9M)3E6|w!8A74Xf?X z9lPu?Uc_L?fB@x+%EeqS6U|>tE>_Ni1rX@Jl05*uuze`wq*VLRP)s8Ekyu*9tyD>! z`R~M43DQQu7f%SK0un=t!kj}%ogq~!%7zd`Hc$|y=ydK_=D}MB4Ax z2Sd*InxbFH`Oc1B0_sbKd54&6Hsn;OEj02?g`^tk%JO)%x)DtO90T-641Ntwo{2@qnDi08KJ04O3+Ja}4Y{_jK$8r=@k`w?cQ z-|=!DEOEJ{{Y)&W(37$O=m}q3-xE)tOSZ~6n6y)atwfjY6Qbs>!T%fsIv>DxgX=W- z8;~)-$}<(Ac89R?#pdr+2_Ay({nLhBZNP#fzz<8jVZI9c#xkeT%#qqoWdwhblxB59 zTJ!To>;*&RcP93rXGa0p978w`TBhZuAqmPIxdTOuItx6&x83dw#G$e1iVnQS!l#nJEy46LHFW+JS?xUAo-|HfAhhRY?a z2!5qOTsz?GuDP8-(X9mr?zexD9PiH(w`a`j{eD#kt`S79;is2smZ?auC*Ar?13?#rYUn z5XV3(0_zu5Lxz^uBxhS-5BLL&qn5t|KiXR``SKhxoc{J9f9x2tVfp^7BzqofK9hHF zlmQDy$VOv)sQNJGqst6~2wsi>te6z!{R^Kq?*vgpD!nF$2pZ?m37*d66u{ub*k14O zWu!H!(Uh?xr1MVCQ{CM>k5yr+(J}6A*5w<8EWbR??iPdNf$_tFW0}!D*=X9BmD)Xe zBkvbRZ*rO|9aMPmoUCuY{^ts2q+$wx5aVtc+T*F>O6Sqvs;_)u%77^4Q?FA8 zXo+QcW3T_{|0>pi-oAB1KU=RgMbI`JYifTR)-qco?w_m{05;Ra(-=i>yw@dJgg)0K zBMfP9G_y%kKX*0!jPU{fIz6(v{mdsDSiwv&E-C#r1N$5-hn(LZV_ZVZn*-<{n6k`B z?QK%{;TZgk0ZDT7Q4(N4ldc-&62|0dJ>>B4i0~G`zRLZN@3lfqvk|#VrUD9r(!#lh z8#=!J_$D#aOVtnc_@`Z=X?cDu>_rT0wFZ zeI@*Zcbx^8dOgEYElrKND#Z9ct%JdW7HekL3*~DCn6Ne5k>y%YQHcnRw39;7(i3_rgiXl*L^zQWDpQ3^{}T(25^ajlB>LyzIbl&< zQBRUo%rXxeP={LW|9O2JCN=&3+}fxsX1!|({Q!)XNbV3wHAv%`(nt7yt|GS@nGcS? zjA*B%)e~IxUL9UMb55~FCw9`4%3mgB`Y49m?}Q-FB3hOFn=jQN=c|Ph@j=%xKU1;B zVXJ~fK-Q)9D)#R%%Ibrmz!m4N?2sJRs1~>UNL>^I%RxF-t^QLqieM1irw`EMbTFJ0h;Ve`Q1{e@3PtBd?B$pE+v3Jb*W^U8g<2^_}N6H%!QYO3vu!fYSTF zM!@s}IB%?D8L}Mn-j#(8L6^z`;J{*fp{u9{$nX;~5EV-F10gJGd*3HEd0gK7EX{q2 z{iHvv@D^q0y8omX9SgeE{5c;3;95^%*uk)nEvcHSAvW6r)$0YMfLn#w>+25SCSEox z!ofO|@kI@T&?;G*ol`itU{ccsKPI#u70QlKAD zR`IJXyJJO}V?x!*)c{_1&a=x2DK{VKWY@6$mV6T;U+sXE7rdiYy zxrTZ|_l5&T>6#DZ)@}!B$;7aR*40x6>|YM8g_`%s@LQzq4d17kHqaY+C6db#$r38# zMatcWN2Ac0LS07>ElHbJNlq5-Bsiq*T^graE=Num6c7>;vP9jMWq>aC0&sVm-fkXG?601KWR8a zX**>d!4V``Q#@8W& zlntgH$NYY#^{9x^{Gg?AJXXlYFkLR2^IKu>b(qst=Y2U(LDU)T9X=sx6)nXGUCKOl zA2wzWLnI(cjKf&>Ih^h{t)9iIq_AOl2NZ3r%TnaznlMY7Eqiu4cUq8K9u@+K280rO zT~N$2&m!E^cIqci(gv4>m#uzI0VS~XpjQd#@Ivoo)g)vu!lXN^hQt(=Xp*s*Kh&=V zzT!97orSIkKo&?|)JwKuWEmKjdUI*2r|uh5=*dL_uzj5vtogPPfgW_Tc;<0#%`ne7 zt`vz4U1NQn%fS~RG8k940!lku`o22gS9Z)bux4;qT*G5MUdPX^wg?Kdi_8gXw%e`a zyc;%jU69Y2uL*u08&0Sj%`{pf{a(COUn#aaKc0p8Y&HsoP~?*^7%){}Dha!=i(`II}D=v+7Gw8u6V|}Y(zBLNg^_k9}eotyul&Z+ru*t;ue8uj?6V9@k}$uHpa>PYXZuN-ZBGJb>B-CDO|xJ z;Mp&qgg6*+ER$?n)s?u{45SlXgAnM1bD#y|88Z$@x}OLyQVt8!8JF+SONUdc2cghr z=+m%AG#vvYqsYowCEU>Xt&yWH;u>@JW7jGt?tV@FT6?EXm1@PbW)&wVFec$sR5F+2 zYm7XXrk!dA6n;MAsQ z)BU?f2_#s(I40G5?SR(7do6cn=E`&I%}f+51o>w8pidOor%U#Y!LK{+0HPV`iSb;Q ztmCv55>ULyKU7C*<2_j43Js@@YexQU55mTi65%NQ{Ae{uR*Z14lWE#a^|Xb-oE=x= zn3On#MY4;IsoN||r*oV!8^WC{Rm)+GxL-9Hi2df4V<4EhahU&7%pWYs@l*VLj0ecIKrs{>_j&z`$>j_ zUvzM@B&}V{df(QGAms((RTAbbFY*7GzS4giIX4T@mWx^2FmK-YQYTu@4G19ULd>kj(9 zwHcVY>H8)v+=Cc;sQiJg!90M{56!1$ zye=t|@3ACAJOh0T-NmRw8x>orV(`BZX3n@Kq^?TBP=%Y3Yvr$Y!ll`au00Wjl}w}A zgsC7vi(6fazap8)QFT}w144PD;Id)}D<|C?&thw$+w3=O$wH2ay#lP?g7=5#Rl?}| zFY-Ar_hhWouFjV(N5Bfsa71X20)4$T8-y!6oDbu(KrOnpi@u<9g<_PZi*CS*s#6O& zFc+eGh@Jz4X~umg{X7B4tlkW;u6eKqBZ#9V8}G?GtX21UwnLNnF6!i_%Y z1)}lgVc7|x8keZv_7hdS5X#{Whh=XWi4-C9D}Olh9vZ&UPla7C9(0s>w&of1byoFx zp?W+-@*8AkTTM`?P~VZp(6@bJz!3b=owgE^A?+^zrE2FNmowsI1D>qeD9<5XW1ogn z@smuI0(EqDO^`%|SmGVEBA?@6i#6E8!m#k5>_>vGk>a{(GYG%JsBtx_e=0#2zyJh##Lhp+E*6Yda+At?B#m+_4w1N=h)~|%{hBb zHg+X30bgj7b*l`O$7Jl~rsa4iHQ6lZ;ABy}PtilG;kW=+%GsZLfIn9vBHn7?i7EUn zlI3`83scYu6#Q&$n4lxMxxDz-rAtn?+n2Zi#hm^6D44)cEe-c)#1ZS(*p z;ETj5)rWRUf06nXlwc36^E$7KAD3RM_~ou8T4;n8)pU?1McvcMmkc*An00`qspj#i zYirDzefRXn(3@&(0gnv_pgziKG%t(Rn*;)kq$Sm)OA1lLFv!cJ-c@`(%)>+m;Q$_L zt|n@2Dp7?V2C8i?apPn!BZnwI@nO4JFESUUe$!xcBgW#TIdenrCCHu!m8IBMECx$G zr%66%H9$clvLKbWciZ|?b874BAuw<5QxO08GHola!M8LUp}|zFXpk2h@ZgZ>c=mWP zVQJzY!#s-D^(0fIHLk~5DV>z2IVTH#R*!%hst$i<$L@`;IZUZ@-G23o?#VE>m`m+_ z8Pz)Szl9uppYj}o*pEiJ&QDS27vS|4xrEY)+RlGtUh~?w?4UDQ0O6G{l-`6`z3#yI z$V~_mejK-_GYq5nP!IGjZ29G9aN?q5rQ9`IfpgX67?g-zg6qQ^PzR|A!AQaqQw%|**WDUlUq^wZat|N~m5ri%y zAg2Pxz~D9?oml@i|NfrD>w(2phdMJKbi^c8bHlo*a&Y3PIO3z~s^PMD#+cDcAQ`q@ zyuDR&J#2mnx6iCx{qt}pwFz*7j8-9;O@Jk7ycT7@re0Yjax_AgVrKEkOTr}(4`W_6 zubjkW1so~suVV0>2y!z^c`Z(z^<=H727X7Zs|N18CZCB-UEWjZ;5g9ZNm;JjTH&t* zP$H}(DA{T%_gc`FBT^PRz!s{BOO-0*n8$YWyFX~*2<(0n-sIEU2o|_QXSE4?P@3I? zWML1T2~mL-w*u=$hq+2=PRU%`>*E?TW*-gf0Vw&wCnLi$ZIwpa;zZ9>2}hHj4b{Ik?W0kd zo^(bn{zzSV{Z|by)kIhqbky={>52>|=R=PRPR9Jjl-L^ZU>Y&D-jd3F$2aGuuI z<-Uww*T-%z;gC<)pB1>I!VETRS;}w_r^>9#dX^6p`e^)c<-X(d&a+x9tEcg1hItjR zSFG=Mq6}?PM8v9}){%`ey|CWys1zx23AQ`Z0~)Aws*&;cgBX^Z@a~;Q;+&nZQu8zLmn|f-TB_Zn^Ph8F zzV2d8b={#KIox701p<#VTfGM zHa5*L==VO^+EQ8BF3T119hKgvrKmN>?2^L$CdA^Yu+zUeKk{oVcFDZnlhMnvJtw*f zd5;j4bhpyNy_{&(Yz|(bk)9^E@CnsJmcd)4pybeAf0B?l3H$GCb!+{%O1Z?W=p2z6 z$RtcMN(qgAUNZ7m4T&cu)F4CsUv&O1nm@BON3_F>-gt*Fdpn*Dz`Z57%lEo|ydP{q ztk%vNf_?oh+%(6N{VCxtv$mjsurfedqU1*)LY&waY}@Tn0ej`*ogMiO5)TwjbW`lI zI{bM#_`KNyIKLgcVq2YSl$swc*##F;1E2O+m1JyY2n&$2-l$g! zjfS+=8D3aljh1I-mIn*bc(#0uSM`%R#9v5P3V#{W+&zD7uw~h8yG|D2L*EV`;c0#i zu`Bd?QC@^pR*#hC)OZs?eHbz@#xav#OpZi>Q4SHbxJHv*gZ9`LZ1wzRi_Orh=&`ZH z1^@8)W!%dGq4acOPcJIG19=yDOQEt9tIyWKyFc6Lgu@ph64MTx#SvXa^ZYwBm3{fN zr<+E@P1O(3BxHy#!>_#ndcVh$H6&K=A9E{)J3b%O8)cC`=_EWbFLEuLVUQ?(-5EjS z!Wcs$XT$pERDITqT@hcZ0v^&6VMYHw86&#lfW*kp$c^ zOY|ysU$yOkFb`A;zlTwb#*XmqwaOHhEGum(FO7o2exUdxQt&%p^s#LNpvI$WX)N zImMGxwbJ|N|AZCrHPiw1uqhRUreaw$2&-HQqb#GC-b6*?fG#NhQja@xgxH-OM+8sw z4v!6U)Hm!qxxt(8uFU6gw$7kigS6yPfL~Hn+|K*CHhj}?UfM{*CXv^6pk9+{S0#uSOjWWU5Gdh3oJs&_WZ-{3xIr;FT>byl9LX(s@G6y0-ein5L# zXyZ@ZAs#IMci%KNW;Qb_AU{oNTf80ThX%!YtTUxPP$oQ;5phh zrvS7OzFFIQr`)|2TutA1hS@aQFdoh3o`zb}zTqRWTxH&Q4J?NC*VDdE%-uF8;yji} zJ7b~OiK$w9+iZm((*Dl1U@81IqNOKVCfn=ad=|h04DethRd+z&;PZyJt{i}`km|1f z;bT25sB~&>A?~^~+P!xyzelsU0&Aswc@mB0Lla^uk7Cbkh82}EK#6`(y(rasP}E!5 z6C*{PEXnXDCwEfh09`Jb-_1%M*Hc)T_y?jzFuZ+fq5O|rOKj3X6N`V}4IJcQzfiF& z9)_4tji0+dmJHf0%Mwq%GPyJNTJa|{#OziG&kR1Q4GN=b7Swa^Ynm+rCo)u;j9N=b zh$_qB-z<TSJOBDN%klRc)I zb?mC!c$J{vQ1~Eq?uv`0!gkoBQEsXbKFA-$U!Re^!kGQL1TSO4jAd7m*W+0XyW4?` z*@p6q#7bC}i#$Y9h_a3@hy^8rgBXM<^Zs4vARO^G#ZQ8S98)E<>&~S;iv7+oCBDl3 zC>FF11jPz-*e$Z*u|2Q5cl^0d4hdc3V_FASf_4T##oN5}1RQ|Pzww?gwdCI7^FFe| zyMD}ar5pUWE8Nl--G$G(-g`&wz#zNV4r}r-mkuwaEZG6c;ovf-8SJvCI)ikbW}%t= zr2KK6c?g{rWxJ)PhX)<^pooEDC!s`Xs?SLmWDw_xkH$JB?}=$ul9S$x{ehV&2tj&| zw>F4Nw(d@w5|QMIE6Bby!U?15Zy0!*bp|yl;z9ifRU%3q)1=a%P_xcu?9cXaHCezD z=ULn7)|3_us%gnJHYv0r>oVKVNgC7Q!? zGR4|@BWL>klG@z(ma4k$o$alHxzEFPubjwa11v%eP7?L`eDWCAD%MHALXcGvu8F@r zgVew*wUl@?2Z{cUA+Ltle|XE1cs3wC8Rbup25trMkgq(puklAq)t8pK5F+19RMan5 zNLdz(lX)(GET?93Bb=WmQ%9(2ucrs1>^(SkSdpJejH@mp&9OAd5c4K+Bj2|O_>pV5 zh8y?;C_?{D!x4BJ!t4#{PzK^AGKm;ydjZB&-4d?39Q*)iI|0TN(5FCpVniXQ&bN-^ z?xgpEqyb)AAYE8;{0fv*Md(X%GS&5!%tiZ*X?jzsn>(^f$kwHAzx2sN)U3acx;-3E zvnt3_jBq#@MLB6xBp>et637sI;gvNgD-0qJoXLkAk}6pYCu^h1jn$7wU2VJ?qg(Tt zu&dHaDaz#QKOyQXN-`@2=aCj4hp06KW3w1cp)Hk8X#V;=08#ME;jd09yJLwA=)E~g zNUWyA&1t-qcQ;l=}ew&l=Ld01iU27L-EJ-fYqiCK@4`U9}>N%5OalD7vhdeQ{=nq_-71J0S5W1{rHELna!yM$d2(n!;f7L*V$yCk z#U^d{s7Np5h*-*;@|~EIU`iLU^{`~3^w|lK6QWKA7T0nzM@(~DO%di&6p%shcszmw z3bZffz@Vx6c4Y3jL{(MtYjkq0GaVJi47#C}LthzQ1h8V2jV2R^m&sq1YPJc<_>7t> zuZ$EPNxT-Bo=nE}EmA;;H<|$WK%Dp6yX1warK~8!fy)&m@o6(gHbr#yL~%v|0NUyC zE-r>N;`Mg7Vu9$6$LE54cd9EQ)%W4(WVLsvQNqmOj7>7~VT@PQ3GUs_QOb9#P0$RA zy#b1SSbMGZeIj3!y(u){f^R(Sl?Mm9HyuXcjOh&idK)|5dNyhq-eJRqB0HV)6B?Bk zZ20LXlxO}m_U}->+_qwX6VPK}Cf#iaV$cGXhL^k)*-8o1Zu+TSO}n8w!`Y9#uBzZY z554jwPfWO!&_~%1K&4-Fyx3au{2e6KckWky`pYG?yvQJ=;uSD1s4OxVO`BeRyt~?+ zTpXlThYos@fBUq5we@Q9*anGrGSln$mm#n1-E4`^I8OR;i146$;xPs5`d^Iv7gBI; zz^htEFjLBpN3Lq`yr;U?h3fzEKP#d-CtpTq*bU27{Fyq>^1p1q%=_{oR0$>1{5z zPJTarS`*IxYW6c8wXSsxJ75?;DLa~7x;{9E#^Jz+4o^3k$sH%5s!j&Y!(}wc2={apq-n zUm)HB+l=&q#oU`>iAgl939f$dRbh+A1TP=k(AjnZ=LQF=c(~a(xu0}wHeEW~8&yls z7#%tRYqsCqzA!8Lw>J>1zU5jKRmnEASXA4zbl1x1;g^=)-P&1Rs+AZjIZmy<^K?^N)l^hxVAoO%eCdtL)_f(#?&*hI4nv~HW)odQU>KdAwz*{ss_*K_C zr!-sC-#$-W4Xu#}ruXeWLBDqq+ToEa-c$ZY)^HD>-*PQS4Q)j}o~Hnbi}{0tcmm53 zNA`bvG1a%>EN(6;Z32nQ!LJh|ie@h=$r$sxRaX0`XjS?IT+NpFWw>=}c4t|!rGH+yx5D|KS~sr@sknvOBCvrO z&ssNacW70ZlpmH4cBMs4PwrCJJcf_s;p6X^G`hY5TYr&8Y~LNRYAzeUyR&v@_OncH zO;od`uVY;VF*>mHkG8*=v%PTZR&H0Jzd#u`r!ST{wFj_yq{z{WH$mQCanMbc+!%St zb0DtF7Oc^HrC-4VV>qwPE$GnbEh)waeyLp7#Ou+!jO&!=)@SJ1l|2Y%?f%&5saK)T zO1JVFI5K^|)c0m8cZRY+;GL|t3#&eA-|Vps`MhcEzx7e?*k0}l@+bV!M=!JG~{=2O+Y11#6efyA!1Uu;sJj?hv z1f~3qaEU2%!g8W}KFLD6w7ADYb84<_gK<7ccUrvnyE|j6VJo*B{+tQ!VvFAw z0I%?rLHqszNU;ClvQkKEn5 zX7ozRV@g~B5%GnWaAndHZVtlNs$Lr;t%uQ!pfpI~yhifgbP+pzkR=6lmcGGzfQ=b@ zlq?#>1zkpyHUHZOLN{5J1WBxaosCczDckI_;@TSM!lpTW*|kE;Adj05>J?hU7A~Z@ zhDD+YT1PLzs4;JDEqFTu0+IDa_?aOT z%qn>MT1QqT`Zc=VmDlH{%C<@Ny**sB9VFQX0YtY?dE(Ef;>kl9y>1(f_scu;XO;^* z9nPs{Ew6qX3<6t_-NZ{)m-TYn{`SqYjuhUZ#JJG^Qukkg=Scv$$+J;gGF$_O*%dNJHSI6dQT;(w@q&yHQ zLcFKXN_eh}bMigIstV&9*f90BS!pZlMZGjhD!cnEiTfYK~ zgiH4p^~;q)CCtv!GXb&n3T}N4UY%OnIyK?vgY9ENZ7)F2&ED@!W*FhwNPKi#3uXG= zy1+zF_kZe8`g$?msW^MxUW{C7A-x=Lqke55JHzWdBdCkRaLc;FFdiA>D}!$_OW#qo zB$xZWLdaBaIX(&R@bDH-h7@?qs#BhVMPEY)w`e<^o~mi-JEZj=_NY8M4J^06IWfH- zEl>71#VkELyM<3bLO-biLI1XrKncz-ZiuEn-aKxAt;pu#3Y2cJB@{M>(s ze%Nq|%0541(*3?@uJJ`*?*Mt8wD)?(=ef!za2~3inxb$d_H?ejW+-TiV$S3lkT&ARl7;~rUIB5!(poxEHQI=no0 zwEiI38)hEJd@?>_w0QD*S*1P#5}uiqB9Spmf4tSd5Tr5ixH6LWvq^dW)Bi}6rSV*_ zG0;M`Io8-mT*hRX$Q^RgXT`O-L))@@6>NGWCKw|{F;1|6huNVrALCh(Cp zdCN-7bGtfz#L2>(>47szB@5Wrh75dAdkbcXzu$)lrZ6-9ZcUJ<~+~6m`%KPUb(5t`8F9JP%AB_@(rbP4RC2 zk@$B6-Ly91!|XWK=$VnSYS8NuoW}%T+jq(hsDv+x%9hC(Jz~V^gg;M^CW&2S;VK%3 zPe7VZAYn8Y-r;7x8>le=q0pbu;t$Wn%w-IeXJ3e=pRdn+-f{#7R@Rl#w?&s#P2(E$ zz(vXMySCwfADGfH%S4XVM_vU%Q~hyKRl4bvPJ zb~0|93|mcK!4|jb2PC8igf~7cvybCm@R@Vxs&P&Ss?qRaS3XGx)rwcjb*>OWgHts^ zKbJ``75}75f;$mAhIo#8zi8i;zRQ_$8TvzqaJxI4J+%JP^Yi)e%hH=^+j={zb8Bjw zX1+NZ|IKB5knSYC7?c}Fw)oG|)1!MrBc2%yAgW$#ck#g>7jf8y})=>V}NZ~ z7Oh1`XI+q{n={?K6;Ct}I1tDe{{@zE>vE8u@N;wr!BYpuLip~+5e3wG;lx{nQT`DS zRqx|$hqS(OeY75K+#d)Zrb#gt5`{F^+6paVmXC$s{1{lSn^4Yn^I^=sia@0dZJ|lc zTjWZK?d3J1pu`nw2hrDgJsMKKL8k}&txmVX2j=$#@@rJ3VRSi!h7+6aqc!t@>?O%r zZ0c!8HoJ4Z;;Kg-qytzr`amO{JEpxH=K-D&~0l(x_ zX@I!-`&z`9u(V8`{VEJVGZexFVH7diq`AnKd>oxVuq3ag{)iPF-*V>Yrc_a&=c-4j z*d&!(%-nBJnxwlAP??<8-+z1DZ;?CSUwpu<>2~tN;~AiIf9+S)E~9Ew%m zNEeGIlkfZ_g9)fh1OS7d_AKw)F5~6RbaI-5%;IiRjkKr8)~B?1T{-*w_Q){|;Vc4c z5CI_3Gr5&}?QQ|RM3FR(4$VQ|5RKFefGfAVO1H+iaNut_gnZm-CS2^wQtg>Ks-|RN zG;AhTN;U@*5=QVx^w^qv7W0dxTkGj@p;`1T_9jb2WD>3796nFzM;^;V2yksyKr$JKk>#VOx}OZd4>KYpeeti$;yq&;&moscTM zJvr^}Y#QxqTAOL@Z~NA}i1xQgzV~WCOuZV*fC*YtQ#bnJa@}WRS=Z8K zwbWyymCt2awbx6N)jdeqC+2MXsqep-`YxWpUP3zioFmHN6NdOI?HZ2$^0XJUAkI*U z0;oLJcvtpkzcOIZPl$Qo7{U#IUh$FpGwa2H-v~2hiC-Q$-cO0_Z)bzc+n%q&K9FgQ zj+Y~gJ^1Td+lv{jv6RI^*raiHDGgWZIC)~*tLx*x$g&M@LGc!1v|r2n7coKnW(XV< z%nr(GEMKVQF-K=zpP-i<4J(wmtmQa1cOuGuMo>*uUIuTdLpXM4*;MPyUFigMLYhKA z=M68;wOF1VVp{~{C-fH3uCQ+Jv?&k7ZC0jZUYu}~H|TEB&Q7dd#O+Gigy%}O4Ek6* zv!!cEGg)nWau0T-+nJfJAm1N2go}0~b_sX;_>~>p-N9QH z_6d%>CdNsRe1(;Q8UiBfab-I|pw-~|h3Ww$FdPg0cXZ2$m{XtRAZ()sW3p~E2rXaE&S*1y%Wf^Q=HUK&5#9<-kL z(o}PMGcX#nHoGScq(Di-^Kl;G^Kjwsx8=nLUHJIw=6OzK*Vaatn&os~cG9feFdl4; zQD&lsK3DlFbJ*Q4wI9=!9GViKKaLJIiOhz?Lxh#@TG%OmVp4qU#_Yhlapqv8G)Qaa zGR+dq_oMWYWQUYNRln3h(77q{hMbRpTTlz{z9UbI2VyXRT_x9D#Dh3v9=V|Ao^R zD{?@s<7$5WK=D|UoPv)>ENukhd`BD;!g20Myu8%loy>kt&lcRkxq9Bu?tZ_X%-P z)%ga1;QY{wJ4d^=3evvA?|+BC_r|NWKVH+b_uRO*-mG34^Ici^N2J+RS(>}tISM4; zD((^c6^G$euyP}vdjJXdFYA9izU}I_C#`ue=<@&pK__p5b*e%sMf=0p!Ul0)SR}|1 z53sPo+CSYAN0)K(eA-Wq#ikqUZogJ}9SV(QipZgW zB26=(tXpX;zi%gYlwMWD_slj;w?W}Ce{qr(z%Ry$tEnIR2S+r4;uIUa2Jp`2wdzT+B86c!^a&`Oc^{79{aW)_()PWUNr2W)UPvE<8Xz7hGjs-C2z;N3uVnLnHLg`h z+WtCzyz?sYn$z3T2%P1IzLHgyIn0bA(MhxYPi-s-C2@#VJgvp)Gp2Tn~}!eV7E zjq&eE`Bj-yb$r2oDKPmRA)G=crX9Ma^GSSzAKJ>>o_Gvzqd{G8rJ)6+3);&I_J8}i zM;vt2!n;33<5M1|PxVQL`7Hz0CwlJW=}2S&VMrM#z__AQOD1iLU>;t`2Q^9orz_hE&AkA0Hl z4=UP?Xj>~QuaJ9c(9|xunCb6av9iZ1>)t3=HEcax3J*~?t;1D(x6uOWZuC-YPB!M@ zGHRZLaMzJnTI%{OxV2dxIsTMm!wwpJUq5t~D@MOWUem$d5v)Z6e$a5=qQ(fdZ!|ZF zDCBX#ORQroRBtN?6?{&YOi=!*!8hRA+G=`OM)FLnac zFJS-j$SvgNrj0_-!Z&_uNYSdN5$~`yi^^pDpYFn(QpMmWiX49OXzPcq5)eEWwHsiz zF@s_H@smvr@N-kN9U&Ec@R7_DFcCi*a7O&5Xo_=GHg|ijjpeWyW0fan)uk!cg={_{ zsLK0bjx>8-1>iqxR=jZ*DF?KEpLSo7hUiCuuK$m@y9$asSQiA2yF0<%1H<6%?j8v4 z?(Xgu+=IK5K+xds?(S~EVJGLDd-m+!x^MfiRr548HB(*P{qO0ofBk*0QfWFoDoga9 zELxS#n?dF4SgTN#nSM)3Ytrf>ycJFn^RNUM`-;r(7Qq`fk@s8fk={9i+%>kBb^x!Bk0eKnpR=C}*<}1Rpmvl_s zIEqg-Kp*VA^*(fSYj9ZSX=~X0`x2h|=hSEw%j9FsAAX5(V$xV%51tYQ8S>QwAK&!Seq!JwF7$do+EghQ5T^2r6i_zmYM8Pmbe#7 zXC|g^3}aGKn@3@rSxT5Vk(n4)V40R6)%l>M@1k7;#0Tt;=8h2G;B{vOZS}}~V7=~Y zCm&;6p#^N7=G`{>*ua}+F7LtS*TH+5#k>=%2~-g$8D=2j{+yE>>3O`m;uS408?bW{ zEK+m$;M&9Me;nkorBB*7k0Q5r9QAGbe(W|gcUs0=R?JG#|Ddar>7$$BQ2s`4_n}LM z=EJ0dt#)CN8I|o4_b4#hGnzU<9i$ndo`B_>deoW^m5-;zJQy# zi-hp{A-9m}5red}Gk@~g?C93MQoXu!uZu++3cM4l;f$swgJ_+zK&e;*zMopj+0N4A zn;GBV84z^djVSO+>vdw?77T7Z3S)Z}bTk5_db{+T^(^N4i<6d|qOENnjQEbkmg|&ME=7I)4KNGA;8sk+H za$bCYT))%lr8RdNH{80(wsjY{yw|fN+G#n6C+QHEbH|H2+1amVFa8XG{hsMxX2kX$ zmDq|+$S+vgIJbXm?tdzMF{AJ&J;$eUR+-;M8&u4G=zyheU4x@~c=^&inD@P8&JoE} zHnwutRJIjyFL*drWYKfmfYgY|#;F-#wr?1#n9TGjtn1gE9TdZb-)pI1o#E+!F$Cds0455n*G?$o_UkEa(2B!R^(?M>5TeTLy*a=;4Ry8|8y4Q#VJ8P{o2qK+s2a#+|wrWX$1 z(&qhO86RkBTEctmrbJZT_(R(GBfwU;LCeR+bJ*wunlhUIOT!cfGkZKq?86Qo*|q|v zq@+x$1q=;kG*K#J_;AKIMzA_6_^d_85_p{77BC*G+l@UasY&GA?wm1hTV`- zr6L`Yt13)eLSG>`Mak6UI~4lt)yf02QPl(dnN78c1_r=F|3Dn+1s4r)rWb>|e<|CS zP0K`mMyZGkfSr`n@2e9=$CRH)jxcoOo!E*d zm6a=tX)EhVU5d1_p|E~m#zWop!yc(Q6M+FN|DfNS(s+(%|Gz^W6 z;RzgFOYvP&SM$n^9|N!_ql|gqsc3Y>XR@?MNie<)!i6p%{|O1YbkLZ#n}#|Wg<7h$ za0P4O>{i+B<{vlbr)1j6Z^t`F98NyoHIQSAJ^hN z{d(|)Ketr+{p~k@HT&bRWgHCjt1t)Rht_kU_+#O5JiJckiRw~!9JJ>!x&1upkZh`x zZp{21HgG_4wzhPbp-@c(p$`^(Ray+z(~5MntTUK&GJ`Eg{<(q=Ddb`#XrupU++6t6 z!ldMGJ3xd#f|X?52=x#(ZDaAEPIxuQY!NWJ$^DCwgn%63RA^D6?WJq>9d=1o5r*yL?(I_ z_W$7su}ttd%j)aYg5vB8RddS~XV-8O=OitjR9)KM%ePMzCc&EYyOJjOw7snT^z+R_ ziaQ>xvYABzBvrEey8ERfj4Rn*FYVdemdqM|Ot&9AoX@z`)NFC*p^ju__yoJufp|d_$P$>!@WNe?G4|(&B+mJd71uB(hp+UPY`C8wm z@@7wm#WD&8wk^sV3MA(TbYuK&x_4{}!G}&}Qx>HOh~F)w`sEbmJ9OXS-oNX``Ln$# zGrlHn#}^9n_{_Da5JjSK&pc+x_hwQPVvl@KZ7q-683&SAE^`XuU?_qk;h1Gww^ zCAit3D23f4Z+;6Cymj{2{g5~$HPXJWw);gGSs+sg9(f~vY72a^6!dL{yR8h{t!g_( zP2f{os4t3ru1Wo_ldeU-5yMe5hdpn}S4eo7Gqfhtea(kDD`&bG2MFeR!FIuoB7K|1 zQooN>ncQo}zOKD=_RUzxQ6{8rty$cZ^WZGG@d3onAUs)t2Dzi*=WC+Stzb8QU}Zc8%~3$t!)ih`?xbzN8*E* zlvWoIN!2H5NCU z;av!~2jIi-2jWCh7()o6;!3UYN2DZ@)^2T?CTP+_Y#)=>CJ+76%DDgBKi@2@mkBlc z>LS#MxXqt%+3gOo*P*IQUy6D&9f(0n^5(@h)Z1QbjCqN_hswDG`vmj;Lh7F`1fRfp zZlx$ns$a?(3+wrCL~1`8)gE;^NLV;Tf^#F5;OMNY}> zpcqq_n91h3cNP&vQw5z+Ql;};DdBhFs}JE>Tb3M3@pGUt;ldhgndY(i{j68NLH4Q^ z*0uGorn>)> z`rgsdE_-n|Ex@A$aehf*xPg^I{>GoVW@adrc&X39=S~0%XlWoF9~ySxH8g zVCSeOePT@yo;(|t)1|gzscq=H7FpC{dKiSM@5}8H@x>bnhnx|`2HQ$|zmf)Er^33d z_CN>+x=s@-7B$nE_TC^JnL4CYFtvx0h)A7Rw(AK^Gx7@so~mL~M>m)IV=pLUkzPfF z1KxlKwt9U=%(a1c5$S8d_4kn@kts?o;EKTd_hC2TP0E2vqi4*xV7dXh0azJ>_SWz_ z8sn3)R_}qwBbXPw+OV0t9r)zm9_-|A@GKkhu`!47d8^uGZ2@jwJb)Gnh1xbHR7v99 zP;ChEAp}in!~m^S!f28{-xyg}gDr4AxiEfhtFzy@Fk!T5+R?iNY_Y zk*TLT1k6#_3*nPR+yM~ltBTm;9=cHZFSQAeCZan@J+Z>;--EKg2OHNZKQdHy z-9MOZIbXhz8wPhGz_*eDE^#u*83@gqwHeW({EG?{)f6WXE{-tG?;^=WA?XEeA&mJr zg!FEdYc%~tb}%7VS=IANB|P;cJe3f0Sx3@bAD!G7VtVnCC(W8Gyoc=gExaD$Zuo+4 zf|skOp=9!XxZBjZY)ekB;`7$E4faECXL3M^oO93W4U^gv)<@vH#ooK*gv>Aspx#TRAR?OhNg*gGN6Q<&fJ!Z zEoA5YxW9!@sF4kwi;E5gEj%ehJbRY0G|H@rKhCV6mE655DpLgg$gS&-(ggu#Dy_T1 z{CPuG>|tPWA88ES5{Zdw5Kb#?Hp76!N~5HF(h?Ol_%ES1%-`+(vw#d;S^Rgl^xkOwzq83w%M;*K#X1(s_i(2^NQs2;}A&yhx9`UGik`IrIm_6I`!IV7xoJ)}Ihp?hlh46EOZcDXD=jlI=3S^0)&*Sr^ zw56O2K0(qvsaHp4+R2Cf@e!$%NLvEtd@u(ehTW}vU(1z$O7C|jk@-rGG%dnc+S4C! zNbH*#aEP+YYuH-21#6)$mSBNy;du`JUat_)4Z#Xmi*QJ`Rms{pl`qbE7fS9>Admix z7+@Qy-S$IFS~?yteqCkS-bPHwHI#}_2=y9^&Qf^|lpWIe7?(;c8I~Ili_Qk3QBpI( zq~2LDzs9+@V7K%b_fS>pUTteF+R057eZrCO>#r6qoQXHz-@klGpQ$>##oT7mvIj9~ zQ`W^CHtxQ+w}1H~(}`FuLVa;N|7zzu&v0wwyRHK|N1m)-C1Y{ z>UT3~WajIPl(11-er;m&eA-v^_xs-S1Z~(us41|(QGzq!eiGuQ?`c@T7FwQF|H0}+ zHM~O7eGnX_NJZBDjWRx99}h92|Ay*@>6<4MznojcPz$YTa?u@_JlW%lw5;$I?bk9A zL{zMV-rqazjObykKk?KlV15OXk0+uD4?;lat0d5+GxzZT=mU_#ATTU46RT#!+Nr~` zRM>YYM)wYj2d1HKs$+V;5bG)wjcy3$H$2j)a*uUud&6Bj2oxRVHCtxBqwr@q=*49h zO?_N{dY7+3SUv=u>g=?Ii|mVVU~Pm826l7@y;!wI`2$OkGT4rO79EhQC3M_%28?>#R$ODGUv*VzTC`5Acv9;5cEO>0hED+1&B2@xL22{*adQ_yBdP2N!A~lE=p`3Mv zOl9d*2pOn<57X_ed#c=}6p7g6A}kn_e3tuT6!C(G*?-B-4tMp9^=#2av=bSUE11d5J*^J>>$y#Ru6_-KNM~lP zTlBM$PS$1fZDn)x`I*@}ac6i+*Ro&w`qvq~uu6%1Jv+0e&*l!#%kx?N^Q*cR)vsSk zd}_ie^s7^&@BMJ(qVW|jm)*cw+yib8!yQKJR%4z?CMz}u8=vM+eEeehv+KvNxxZTB zJ#Ef|kX{y(J=mq01L`ReU&r#kkMG;)jn~IPc>kaMov5GYZ_&Ne<(DtxMx85N`2<0V zqwLwI>ps|@l}^ewrJd%4THEz%^e2C2jr+NEAXO(Ym(e-7q@=;!IEWe`otwRkul9TW z)b7+it2};OBb1tWq-Uj#6h)yHfI2{1p_M&FR*o zrPBmvw^!D>1y4dQJfB+y#v8b`eW})N=JjX{$A?Zb@n$*6y`70c(Emx3Qdq+~{!dqD zhx;sIZ+TLi%3@t1J!8ew_-|H6N|3F59M0E^`8&|O)_{+5^*LgEx{U6=YK5$d|B2STZ?ql}XMwgx#8>E8C{H`TYFZ zyO4pt1GDZDENm~(Vxw~e6k2bBO~!ori{Cw~ITu^BG@}=riYh%jbgOW?vYQXE`EnM3 zA)>vu-Qv2;8}2yS4%7dmru%_{(vco&cJ`9#YGG`6YPWIr&>Xl&*GSpRDAfiCtR-~CjuZI^mbjO5U9UcP zcY972#LSfIRe!bJ#;#xe%pacM-e0$fd4Gr9-}}6f#UIrwi^IpqqhRrKE}1-(@E;b@ z!NK{Epq-g@!dOE7{`rL&T;3p~DSob}+*PZ@v&ky9f9F$7fCZkm;10p3*uA8|NZx3g z&sozSg1gEc`IP^IrAz;RVd+r9PHFxpOXuS7|F@-suOn6$8IF*6#Hsgg9;|gUp$X^- z=bXwqw8Xv~cU3NUMdvs!8{1|bnAjvqZH^Wip=nC?I16HhcL<&|g_YDni=A00opr`@ zvv9Cn+{~X5?S;~2##uasL-73-lVsCb3?6v8luw39N=B!sElHFcKW`>_i>`TbaC1re z&V#!#n2}rFN8w7z&+@|Qz;Dk{d3w8ADN{4CR9QZmpV8sjW`f8g;1lg!FEQgqe`~SA zIWWAfSq`P4;clr`^CNWr05=mo_O+|C{8fo{M8Db*L-wDl$qE`=6tW8Q_gd62%?8+5zawDmq`mPBbr zS8Gtw7nj?+xg8oS?!!;s-@AGGc7LwHy`%@-CWc(wd_JEn(q;6Mcy0Gkt&DmKgbrDn zWFA(4gVjH)J%T#iPFwFMzMJmn{pKLM#O<>#XhFqvCA7^nl%D0Oh3zrRHC(%;R|9iE zz}Mk5yNnz7@R-d(^6gpJvb+eBuag09$7{a0)Z8_4+!7@XQh$CCUH|fAar`VxpA&LX zSbKAIpGjbmVd)Zu7(mKpaizJsQB)a+QX#`~Z44*Fz{%d(Q@zf3>}4Rn(Op`j;vY6@ zi94AkfgeWKC}jQ7i(-QjwElFD*I8iy=*aSFa=}XAV>hnM@|7O1U~@M*=8|E`d6C<% zrgAdit#PvlLfhsRVU2V2e%<@7(cf>0%=?OzqUT&Jepsfm1+&72b7P{}nQQ#S%2~%T z>3bInq#^Vq(~+K}QjU)hGD1*6Q!cbMi-o!90-cmgyQ~Qq7zKp;7b2!~m|=LRt{~(l zVFd7!`APec3GgSs*k+ z1^Uc)W{NcR!o%h^D>6hom{e6h50*m1iH`7c#O8?8`b2SYo9dDm=<#?ftHp3D_{Hyb z6yxvTawlp;?@%f}>aOiPJC^(!;d2wokeOM^DZ{0_Ee^CLnJ>ykxCpe3XygSj$I)`# z0(KuieR|(^K!sGLf-4jvzAqUKy!|@v{{}{@6KH?a87!k?c4O@UQzS+QE;B5=eHOXg zYbTt$)j!oH( z>eio5aij`uJ}tk$U%>pzgsdD++MOAjWQpf##G*c$VkFv{W?*`lnz{BY>S0?^IDqHy z8uEW_ZKomvWkt|-;Se#UvjLuD`#<`R>P)KyY-wuO>*@u_R#6CCMI0pZmccBn7`uS$ z+=)VcK6!&V^4Cs{e)IX|7fSj3g8pe958KrruI>Hxg`}$t^@gK)VbEjNO%pUQ)4^^> zdh%#3db<5e3Xv%`UVTRcY{Z`TVNGx#YC`fp3+qrdm^6B}LGe2}Lqg(jo<$TBUSr@F zm~|4Fyy=+GlA7|h+*{d>&RI<$-|q5e=)|zyqN2GcFKh-@6Rlm`>nbC@5q5>@h>PEu zHp+%+mL)I>lO+6iO_!zi`P)Vd=%E6&7B`l24?mC!t+|JL+=+T9{Zfl@u`gv9!5;Nw z#l1Q1fIac2FPJ&ud{aE8Z`rN${l&?jqbtL{83dB-4=+=XS0z7Q+xB;G@5W}qbCGFh zsdQev_(vAvT%easqDro;{CS71*8=dp)Qw)08~2!YvWz1T)@o}{^W*e$!9y2V1#&(;*G{u|7bqE{bR;^6{5@mF|U=IMUz!}-(p^rv8%B|nf{ zHEJf`ILO7W210qoB5cr>f14g_{{)$@3t!<+Z&XUpCtSpMI=?6h9g-W>`Oik#fex46 zH(QJkvRc2p77+iS3TJnKao=Fu-rO5T$8{q5+tGN!cNP|y ze2E&gU`l8saLMTr*ru^=tPF2KUzw4phk)(+bTSZN(+!er0(2#Kd) zn9)>BJ@vnwumDsT6(89%*+q$^$@!;Do2kyv`Bc_IPQoOh5`k#=F{a=ud_AjJU zSrX+@iwyZMNO$@d()s@vq-&D8#naUUSuJD87}aQDL@`{Re?hvt{|nNg{2S8U{0q`) z{x?VmLqzePkS^-`zQkWhN0&ys_7~Ds{5MEP`5%z3{X4#W8;myL0+c1e7(AaycvIBn z0diOvTk6#KI?g-6T!RwiueMP0E{jp6B*c1r*{p{W?3|tX_8SvwbM@*JqEfQrTq$Ne zdOt>@*tTm?p-U#CIqzCNlMFgAP(sdl}mehx=Rpf|3 z)W$7>chg^8UZOJ@DEu+|Etj$lB_AxCOf_A|-YzA8vFZnsp>e!UG{f#GGJOixK;4EA zanCoupB^2p?fl+vqx&PkixbZGv#te?-{$jZdFo3m@7ikmqkk4Fp0%61IOZ3BzWu1| z{Ik9KvmcT6kFnTANpGz{h3Houf)zegE5i+&3bNk*OaPs*v6` z?!J=FD`FL2F)Y)iMvP}#t!*QAe9Y~clVW_n^`e?6iF)qWqG%e!L5kRq$rmS9_B3oa zN*Pje?k+QE%_i1soVSSYy95I(qL^z~ntu{FS>sQ=d3AR9Nw@i9{~`X4Pa8t4DZ5)& zo@QNz9H#=4)M~Km6MU+TF6q{6M_yNW`+X|NvrP1qBM>W1j zZYk0{tdli`*;#d7dhh`qqgVUYs0#kV2}j%QV*c}j`XkH3c}uYyX+?iRaIELjdWur- zvqs(UVIA>e^!(vCif(ArHGIug0H)?ws2c z1E&vFy%693#pwFy;67~D{)^F7{%=M%tUO4F>ExqEZqatPxgnnIA%rl_gQ7>Ym6hu{7-**l-zn1Kd#d%tPJ6>NXq zeGt?&NbMK*Eg@kcx6MW4I!CLggt~m-2CFI7aDMs#*Yt1n`Dpk_tQST}0};Up6Q3i^ z2Ta=d6T};Cd1;rbx%+Yjx%%^{ip%CoDC%dgLDo`ajPCF&sr+in5>r^+j0fFD$$o$% zqcqh)5a!SqrDU$0p`ThhJONXbGFsm;SBBa*eja(v;8 z3y^tpNB;a_@;{h-8J{FOKz?|+o&-e&mi7D1yY{<2m|j*t(%&u~>WtnGFLoXpH+8?N zEs(x4+YAiaE)bsA`fq;Ne!MI*+8}0W1a|fER@Hv|jB_V-wQ{(1XrZI|z3bbz>wmqk z$^8C0u6WHyZ2!V>wxV41iPVG!t144Rzk^Vv2xh@ELchW|tkPzRCyG&f%y2%ov!m&d zg!5(n?4TE=a9GGNu11hDO5DYg$E`}4joLC#8KYaO>$kxYm5OG@*AB9q<}9nQy{`n!2S=V%!6S60PcQQl{(*wfjhw6ilvgi-G!G$9nG-wg zPK~J90QgvIj08LWd7Wp9b5#-~xoESC9rbom$?n$^mQgPNVSa)z0~TBHg=XBEaAt@3 zDfHvJSmc(gbVqrN5T8huj2W(wd^0Nlve#~!Jx(Qd{kgv$^JaJ}4beu2I4*M0CJOYu zTIaD=Pq8KK*TBo#)M)n~nEk9qz&x;tfq|8R5^|8#WM zPk$Yqq{S_e70>*XRz&WZnYbjct`7xFG- z19EgLaIO{}Nr(S%bQ^yiUG_g59p+z0*ZJ4ciT~Ttfh~VHA|`FWx*t-Ky`OeX6vVf` zDN_==6Bhr5<^O+Ewjyt+XT{erK!a^ z9z<`A4Q<*{rIE(3S;;9H13H2@o*-RE)dA9VGNT|}S19TEr8XKO{;#gnYqS&9OnpR{ zZUO1K27B6(3X-dT={i(TP%&bVt|Ma6B`zz-ocwxbBR{-NuTdjF~G+CaMQQ^SAhIuoQI&A1H=^yal<C>ufyUc>%zjWPj!gIL>xNNxUaU5CvM(si-FLAtIY{=exu-3_(0CTCw7a zI-(TOKGsm=-J4QefB3tp+bx9;BgZx{N}bCOHSzk_A9NymgU!EnJK(0v^8ByWD@o68 z;Y2&oRJ6N`x>K1zxbC4$l&STfxUTart`q*LkTUoe*A3%aak4!>99L3UPs)Gz+$a&Y z_`a58Gc$%?l(bxvKl1$ttSdbqS6q22QjJb>6F8o`Daujg`N3m(n55vlGC^~0tMHf9 z4f^`od(TYJAPyG>Q(Ac;~;k^z@uYQ|Q** z6^wS?m0!-wS)J!DmS+*k;?uI$Wb6<`^OCY#KHwWb?}pBLr)~;T2>w!6!O8Vi2J)<|^`$Q@$bKVQ*FS7rFeSn3V>18p!r`3KTHb z6$ktIYQ<~cQvl|4{NNREasaWdL*6?C5eFZBh@Ap1`SJ(Vg_-Z22TA1=x2`xV*1DIV zGrBpX*8f)V)7WA2>OKs=xy#OF=g0Lb?j{?x=X@?@3IX4EZR}@=8qb*36I7W zy$$FdVo4Vhe`c=pBfCWMP1%E0T+qow$rALE!RTeLO2!)fH&4GM|F0zYfSP!u2L(&3 zUA(v1Uy~UMtV?zEUf1TT0%mO^v}Y4NpsdO(?TCS(64t9Y_scsmhLWEn$J^?DLp3Tyh<-FsX@_${C+&n?B>*-hqV4Oo{nN&88HUl~BRg zBFVM8l`)IsY^NtZV6`aWBEwA~XBMa`x1&7ym)TpVy3H~0h69p{i1;p}HG62e$;p!# z_m|h@O)r)9rX(&in#D60HO}k>q>CSY+(}9Uzg9r&&SS2&W%^0buA)KEE5VdtdtupCn~{0s*Pnhr;3s}H@px` zXmWHw234Byl_s!neA_pi)9Ioqiamt)WOIp7R9|rk+s3nmY?NB{PU5&>>joIocvmz< znmOpNut8>h;~3wQlOkAhjA;T7cByFER#aTco+3yx?l}b)qLv}ZP2o^5z%@|)aGrkI zJIsy{W)gTR2={~QG82yxVhQJMRL_$WW}+`{&K8ToTpGtK0!Tq&0Wx_{^cZ8+X^rYc zsiN@E9%!*z4r#Hgf`4fqC0Qc5c9dGXLFG0`#mI>$u*llyRP$r8^{I=L-XANBZ zy}ibz@pVb2kEQ?GU1?>l*JZR1dgQ4$60f`X+|XRsp6yp>1}!KlJ0gty-xl_PTF8YC z8Rk$Pcwn*hFenvWxHrQek!}VPJH z#bQy0%evJf#)^XUX+nC%BA!3x2jtUMIYT4)6KM#G$&^D0A`Egkkb(;K4}A8r$L^Fz zeI_j+U-~%!Dluk--8pW(5c)O-Nf;gj&NM~2Zx=p$YUm-*M(xiwE!$H725gD8#?J2q z97+_vkoLYv)a!DY>#D1X;u z5m`vAxwG`G5AX*IA=dNqJkTwj)=^DwN2%7!sekT6?ZR1M4A1Ec8*`!HfhW)j6+m~y zQ*98Jlzu%_7?@r!Ws?6Z;NlY+&_u|>E`+>L0%$Egw#6t8Fiu>B02JDGmw~TB{Sx8A zL_pbPLHfv8%v_TY;c~LKoDv>hYLH2SFJg=$3%r5qkNdNyhcSV7wm# z^FVFZG#s5VbU};;Ecl(%AO2|4FXxRHhYoDncpJn9k_^^?2Byf^9Ap+2@P1D&5}!;W z692L^3jeLeNFuFYjsecK)sW(RI`>l!HZWinV!Q5klCrb#(%A@R9C_d$vo8wYY4CTB z!@9gO5wkgaq3^h%IHMbWnVhxT3^de+aRBs7V~E(gceKk!xx}hw1&T=@z%&DYj>?|D*Y`@R%Q);`yM6y}J>4P!1sXT}Hp%X61b>a}omJSk9o6G!s1RMjxE68`xaUNP4 z`jbr%LsyBJbkds#NOFjGLBrONF=zZ`V^g|Is0ZuF`aT7mIV56X}$jO;NA z(>M@wmfXPz&o?GJy_nXtm+(msOCl7FMk6%d@QBmVNCo@txg~mskpGFaktGU=GN$;e zva|qpUG7&YSl6I4>=IvUPgR4yO*++sU z*<(cYwmpYKi4& z4+a}l#>rP<9AiUhinRRo3JPhMLbemXWe#nDk#AVmI0X}RFiCtq{33@2a`rQWeKuo% zqTzjTRr}v(+Xz9LlxB{e)zZ8ss6y#nQ8+~M%2P1S-rIqJBojO^haR^y$aA|=(` zp+|~C!?;9F$Bh2t8yHy!B0BpU&vaV*p>Co5<{M^X8-j3yQ(BVitIyYoaiJfkd(kMl zXddi)l8dQE{#5CV$vBopl6m1AsWwE9z398u(Ady+!|?Lv#a$IIzYJzsh9RiJZ?Hd8 z;)xU5;xRL7lmtF}GojSx+Gb@BWhK}b?QTXhn|gmWAeT6TMWWf&xUXyM_=Z@6clxD! zoP=a&78^j*W@J&l2pVqiG`#g&%hTi~8QpZ~Nsj%XxkG0p@ylp$Ps#LsXx?PRB?F6w zN>AI_B~&iAmby?ROfsIBXL`4v_25;wv5%n`_zm0gBrA&Ce0*odS zql`@O^n`}=n>Hx-#IcBqzjzuzqhu5-Gy&da1J9f;WGq4nO%i6gpc|&}3ep^Z+B7U2 zjn$GbG{F(Ww1*oZCv^=JvLQ23;Wzk%qyarXf}<*R0_#2f(2U2^N5h~a=bs*zKYGEm zdQ*nhfT_wBpUO0jq>z$`uW%wLH(`RG0g!%EX)A9K=VR49kZpj*&)79ZEM4VO`5D2d zYX(nEhb^Ju-+1Xv>`%Wa{&l*^-4h_%fO>{WVl}8#!XJSj8IuB)Z&Z#~!XEVPS@}a0 zP*|2sB}XKhqThs;iiC#bJ7^kC+&$=5Ayk;oeI2!y>Ecv3Qsje;|P=EiJbD(4C^ zSWvo4pZlgNfdnmN#D<@en@H+HtT4t^N?h~G>Rj;qTlu#^LF(%nBMIMU;t$Z$`K3DM z^b?05S^UQ_9SM&qhe%&Y7n+|5 z2m?qBeAQ7fq$@m1=KKH>9$L*=@Ns3VTD;0-l*z!z{M7H1~~S8ut;; zKV7m?jbsMONB&)D`j7~W$MLMiU8W1u8zes~YnY70xL%*}7r4dnWzvnN(e4Hf5#Q0v z`3_4HZY^TrA)tZv;L)Lu|&o+83BUq|yYINMZWPvimPXcbYZn$BN@nLN-dgpAwAs zO2`C|`sA)GEe}K#*(I@Ie%Ez3pLjih4{?M9P3Zxqvdm075U;sz{^tzVf zb9_r%WBcH+skpc6?@)gc9FgE2`P2&A3!2}U$XRAi#I{QT=^2C&S3}}}=rH89UU+4* zCD<84+oio|BLp=-p0dbDg#S0>X#6uu>5tdthzHMUBau8-@q;+z$a@GV6m3QfJ50UYBvDMnF7`$aKN5(RM)k zQc)Q11E30{Yhzm>7Ss6CGjbEj7Sj~sqiTyt{(BVVkWstCEk7y5~7EfOUJcS5oS1Fn% zcS6ooSI;V*JiPV%;J|j%{W}X*Ho|d(|Embnz{UQ)bUAGXJ9&No6q&#mPbV*BR_&#S z)HQ#j**(b=nsEH=1e%NjlfRd;XbPjgiF4N$?hjMocKKXwq%HZ}X?cEQ_Otw27OC>K zTl|18!Dyw;ajr||uneu)h1$W)p8<(bl|=85kq$s?Mz_*8!bUieFcU?_*ZC2dPY$DD z&<6k*orCSDUCLIJFyeXX=1EH%iGK-I2@T@hq9ucbfr>)xFDU1uJ|w#g3pNouMATeT zg%QUXXy(rzHX^RMpt@z$&l)R+lG5pW3{eJx_L>@fltCA92E7-P$2T5KMi*pcpg~ps zJi?9M8)lu<9k(ksHupU8T0S4|NHZVbO)BB%GGW^37n8h~48}ImZYGCw=kES-+~;0l z(Gb$^OYJkXd8qb+VFHhBmU`4t$TO0jp-3%zWC5QlUslLSr}CSWM&f=*WQOu-E!xnS z(hNHSCQ9MJrG6kZ6A-0MYwW_B!Lsm@0A>6GaeBBXVK`_{GeY5jj0eBdgDZ*3NuN(> zJRJjCBblcE$mETgR1w1#IW9s0ha?Sx7jXUIkyM=9O^3ipqbL^#K|rTSElDHjgz|xh zaK?5S72h*K&2xRr{kjy4-ef0ZOLF@#on%0(iNSG`zn_jprXgp+`h|<8p1l4Co|iTo z1&o}t{tv?2ugX>Fs$oX`RmjxQru}Sw{d7EEltxVm8qC{KjTE&o3zCpk^SQwLo8TV< z3zD$$K4aya4OgHW>?CkO{kjd99$w%pOCKJL%15MUHcMvWP!h1Y`sbeN*z)>fBm0p? zW5Zvqai1kv6*+me{Fw*$`L?LX^&8Ph@^-=N@QIyss#0p-&Ps_+gi z>Y3QwbLR$75M1X^l=zJC8VnguK&dkwaNK3|4SZXYN2Rssj2tGI_iN^E999?(WQ zVimig8Vw*f8ZVg98*n56m$A*{pykkjNvh8z+!{79kO!33VI#D}mg9TI{V|Asr{IIK zm(HIlzvK};e4`mxvq0+=xdkXt;+Nd<>Zv0YCYVIg_I;J5Qd1X+*%@Hb%20X6KKN<` z4k_;Emmm_FU?R7JD*cS71U7(n;KUQ^niGpgdnfeKt;KrSfhYoup@NkSkJ9TAPk@B! z5TyMkgdva}zo|95xwX-gC{8!oAeIiVGuHTuOFFj1k7ib3`SYDFGTobWEE7K)L2?4^ z?KqLmoOus=FKZ2+vN9E$%Rr(x#EbjzQ9?E7lnPt^CF#8lT zSr`y0jQP7F+(w7@dncDnk;5iXj^R zP?3DBXj+m+^FVaCu9oi^)8?f==J7%qB2{#R4|4;CPISAM)U*tUv_M@b#BBWod3^}# z#`2RY%`g+ikMB~fEnn#ahY9_{2EmhRhtiI>-kS3{@I61e;}ACdPe#VNg+zKIf_qGY z9yZlC{Ch=yHxzaEe1_e8l3BnQr+f6_2UP23$KPE*Gji#!pmZJwf3W z=UiSHi?)ABWEP#FZ7*x2Be}K1Zxx{adiCxcrYw{hO89_R z6;1FS2>oPjz}*udn4UhJ_`_k+2xgS>Q1!7|CWNxN4++O}lmIwQCZGU>{3U3#`LDZ98Gu*?6&X6{RG^bV` zGbA&YoQ6*|_LnoP^Tsc}1tNq6BQFKtce!W_d}j}K#b_`ZNJjVuP=#ZSM!g=6!gof6 z9!_q27|0+p9rvliNC*8pkHAl&lUe|+-06V*AQQN0d6#YrP@8@MDEeY}<;U>+o7h!P zs^wf0E{jR=*;NE~OpDle>8%Ge7Glb)@O8fcD;ms9>de&OSSd&Z%$~wq)7Z#@*;T2> zS%mc+t&(l{B!R;OxF>q_*cAhC3iS&Ms_dV@7uqPSB~+2v7r=yeZ7VMk`AiyIuh)5ZHD1lx0s2huJ#CVSP3(GIJN@{`aSjM34YuZ?%5%nfns?;;Bbr6 ztS`^KgUNo9==vSL`e<`bSNSDt93ei>4Cw>=wXTAIp&$UmC@d(xzCn=3wTWVz+LT2F z3s2kx#?YLS&7TcV%0s_L=?4JOjW&}8uQ!awRqc(DIgics(!th*_Sjy;+zdeiY`NEqglz{XFlnu zW?8Jb_N6Rn$!I@tMxa87+KK;UlZV>(O-y+PbX+<%$n?h+&CbX?X@qtsw+AI&jXh3i zMDpbyNtI&}x;ojgbqhs?@XE0CHK&6@RHD;^*Nie$zsj8M00xE0yXWx;vokq*#27oW zOo<&XCm}~HK0p1uy!`kHpUjxmT1JoRKb+7M)4ls-adzl*G3=ug{rS@6AZD+F6Sj_6 zz$0i>AxSq1EFsWp%VittFy8i$Y)cnXa1MxQBAP1_4huvH)0Ow|!Py37fN@^GXcdte z*J%ZdyeLC07&?H4bl#jnFWmaG4b)qzaJkDcL92h+TvZB|BJnQ3a;$y z`ve}_I6=p@ZQJNLIWammJGPCEt?oD-+cr98M;)7U`u{x7yl>Ua+|9*Y%*C!E zm9tC++LGwB!EMNM<*Oyd_?oCVpj%4mqO~s&P=9ppM3qyDPu5g(AVgvhBdrvB>8Eq? zEP26IF4BOOeil*(hS0|5FOnxgwiTWK;KcsIk))nQrj3cUK3=_=%^d5~V5`VAWKZg)28n)hGt+l!yA3sPhU(r( zY$*|(;WQbrx)}Yo{0}uzx=+tCkYjx!fJQevw4B!7BQu5>F(L?0Umk=N4FBR^*xj$Y&EL zP?@i;0R}jDcx(OdLbdY8z7Hbs@$R5QZOF*U9uAM*5=5$%{+Z!8TwkEj>Io=WudB|c z4G)!iG6O0vzk135nJLCeYojrrJx5gZj%9$;>2HpYF=B~*svm4w?MQw}S?ROH4S~YB zHks_^74L1DA!TB;CX19>80_c8>KfkwSl%|>;K@s-&jI(O2gut?CfOCKD;|)X9`JHs zMP16CRkA-_pFPjCEX{ES&&f4aL#eW6Su-#OX)cZuE0PL-o(ttyYF$N9SQZ<-gLKv7 zB6xOL87m3$m4fKFp2|?bLeu7yl043VwAWm+W_%m~GX#Kdu8|#}kQ>Jw+on2J{bD#c zSH5@xC)w7n2slr)U+ib3TCeOk;4IWhajuFxstg2Urn+H0);NkszNF?@>ap~ZC@S^l zxz6Gj$8FHq_Pyi`KA}sY%6m^bFpUr{v&u|>3af~!Rkx}SpJmIHoA<`s)y5sZRE|j# zEu;2D8q8)8z;pHK)0I{(>u+nQ?rCrleZrVi;ijs`3ULWT_~GJOYm!REf!Xuelc0KD zu7qXkX}+Y2O&5b-GIsG}q3SqbnQ9DTyx{pNPNM>A2m-l?Z#`c|a=uXlatVB@RMOu} zL(70gX(6BPnsvo2!%aDrPBQhtbT>~~#O;A3Zs8H2?v@hvnBfVaJf(@ zBNC>l#Ho+J0ACd3=Obdv^CM_0G^qw&tuY z)2As+`cnCZJjOd8=va2*Cj+Caw#G>=O;>7(9$i?$8D^U0VyLoKVIB6M(F(Yi_D#=L zO-e5TDv0}uq+CY4jj7Wk+3}#N@&ysJB!TLO#fqBTO{G0mJNKx!+e4~cX0uOs+Iund zp?%ZY7H4jcx7$yHJcze6XQQL)*Vd*!!~1ISGTWT~#bk-BzzB-${6*jh}$;mnn! z_0=lsD4$Y92~(gp6{P5T2_N?O%F*@vrY_rQ!2sX-?8M>TFU-4)ZhdDk4^;YBwpn3G z^sbC{H%0p$0L~6Io*b;nS_Suo@H4a6iGg|~AAz@Q4yg*I z;vtGn6B2f8ZADdaHA@jC!l#%nQJA6R@_`{R4acBx?-T8d2r&zaqwBpE5BSp0P&tq! z%y>;u0$EwJwT&1P@{rfKNGWsIdRJU9Rc(UC37~u~r3J&2dTzmlaJ!UG;2^^xX)*R$ zay}l+>xx9q*EhQ2S=7#3@E3EIB@;!f-;W#DdE;}}vsHWeA84;PV^vl&SzgB9X@kkv9?#nSkT>?J!oqAj-L2u`2p$oQD z-;r~Rk8d&7LvDUU-0Utf%yyBUg5!lZC!0Ciz;EO$G0?oM1vn8&4wxa0iFGmZdMCw0^?pW!M1>SY&Ud++ zggFYH9MND4Mb2F$BxLLk6sYJs!&)(AXzPkN$aIaGHPSz^C6a_C#;Qw|2&{KwURY$m zLKx^I1GCdUNu@UNmZ;#FN=r{4l~2x-^ze^k+-(odapWi0G9brqE{aW61}UClmhMRM zS}wM+DHcgG$iWs_>Zg@P`U`->S}G|HlC8`Q`-7R{mpwHV*LsTKYpmGt!G@U#vg zCcsN9FGls82A$=fu|@+}JhBD)Hs_sKgB;0EauqKs zWFZM^IciEt8Iu_zh;}sGF+?!ta(!e3ZD|exGESRI{q`i78f?v0s$AGLe3etx$~bb~ zIg9)~_Wh%}JQS(vp1RQ{c||$o2(lCkIlSvr8^O=P9xLD4s(aZz1SI=IozNXtU_Gk~ zz9Y`ELwtb{G>(!=;q*jPqYMa7w2}rD3JD3RL2U2kDT6&`!L%3!fciJ6m!SR)=I0`v z6fn;fC#as_KP-#WV|l>7N~ zTzI=B>Zq6`cpD}`p$~Rg@%Pads!^d2?nnc~2)VIgkHgB^jBUDh>uz_r5zDGxYmsPq z%G#V_MHgt`;~JpZ0(P`%S_;7{wTjN*ZVS@f@P)6^DpQ2>#rnZQR690Lky^=(TA&}C_FvJkUY(v6bEjBP>V%h`C13$hmY(1tAt+1*)p!>|D zj@PIDqBqbJ{<`7XIUK8)J8R6W2>ksjSsU@|XNbpSD^KK$IOs>Q3-8-dVlcsXOZ6?` zuZ?D!P+^*yK-|0FAO&hDkO4In*aBAqEpa}TGh1P9)CB5RuJS)n+) zNT=#bKrBzbL!|#hC9u)3G(?1dSIv3rfkX%|M*6f$V*Yl9Kk;h6=_Hpkth9Yzz_a=4GX^2StlnCO-qRThwkfTT9=>f{(AYjwr=zlL* zA-`wV(kKTDv9C}857i5zfiL;ZyI4G1Fbh}SqLGr(cb7`Z0XsnM6R4iZzQ=pbzCqv$ebn`JO3(+>QaETjKPxQ(cVZv=n z{$Gn(%GOO1lrGQ83l41;F5ny~$6f>SM2i)!eCmMlao`gkKx{h|sho+%Y?fAz7+P~~ z&mD|s36ql?+2)?4U8cRc{KUsZ!Bf^HJ?lCk!+VNuUd5@gJm{K-(Zn7?(l=JAqkHES=xxnc&=W#dtps&Yiv~eh2E2je+;aNov6IG`f+T zdTRK;N-T*z;n5+xCjGK67HlS9nWnCX0L!8ytB;GC=$h7q8S)&yEd2X^R$8VWExfRj zfEs|0C|7w&(~7l!=ZYmBwcajOMg^y;L=g3RfomiGTPj$ts;tZ~%WkQ*QB3HwiNFF* zzo(zPY7Se9q6*MiMN(E#(4`lxcCn(o3s)8t#l-@Vfokf7hhZ)m0DH5~QbhHehn2~f zNelxvJ8YmeFh&r_l#sPGr4S8c9^R7{6$ws`;ey9hjYj+qE-drwb6lMc6< z88BIBRuWYI3kB@r(Ja9Km0}4U%t2XgEjCHoNxvXoTidNp@^dVgY**3n&`c0Iy6&Z+rt49(WQWo<_;#2W}c$$HT=&3R}BX>^z+te zY1e4@_)20q+bB!bv7(dlNX3W~Z#q13B4L-NgcS*$L2AxD7cSlSc@=|wb}i&orLvxW z)sLtW_&CqeWgJBFK+eA#s%<-f~^h_qyt zXjeA1H4z%%6IX(^ts3qu7#s@KKke$QvxR3$vGFMr`hS*{bCE8m zvchRu02?NBE=^Mme}*N9EL7QC7ULm32||4z;7>9gUNT%`+R6#ejfwhWQldHrp*?Q&Kw-6Xf;DNJ}uUdT6T%$cG+$c z<%vgUz1@MAvs7FwKMEHRFE^z)r9b$CVs%0jwqIvvyEj5K`Ct^H12{Ob_*L@Z>tQ7% zxY5$~9yujH*Bz`)8%zx`l_6EvpvG{i`-*9!5l3_q;kOBz0B&_JysO8|s?c4N;@&(B zpP|(vQ!+_X7tRHDbkh%P!77WthtvUcQI+P4+dj(ro*)MmK=nf=*rT_>24X*`kVp;_ zH*}!mK1`RUm!9*n#~VBgY!kuYy4u8mAM6orH=-mAeY-9fppT6@z@M5A-dM)R4YW;S zC@7b&k~#3u)o9Di_RsknaKUIEw$8 zJg!$VmP@V5Ayr|zXD%V+pb4*;{t^2z3d*v==yfHb8xguP=;9E~56eLIszQLgOF*ot z^o2)o)TgZtYn*i3Lv}yDLRSK|J z@!*cs2lz}v4t{APcvD|K#K~dyV1L=Y3?<uW9 zZtIx~xLu5_*HMPsYsZ>Uozk4ZAw<7@$DPtNCxY7B)5|{87n~@>%&u~`F-i6Wor0`# zud)oW4JRvXmxT$fa^DN$<04b6AT<7YkTKNKORu+Uk$#hzhlZ0u`@T=mha2z+#`dYwVCS{CA5atlO z^~f}Bc|j5uLeW6o0jDGl-Cns_AdKv`*lcFNUB0PyB^)GVO1htQJ!P|HEVL=kIK*Z z%L$XB6@fk%+nt*bO^@ET9oDz8M04-3P*`0t&zv&L+qW6^d(p>-M*wCjIqY#J=sgjg zbX=h&m>@Oz>)!7wz%kzHXUMpnt$1W#oF`vRNd>kt+>1!&R@(TNoWOh2-%uTce`JPD#tl6I-s%9&X4D-t>p#Az|_>T{7QqYdL1g({;>o;(zO&Kz7{TqUZN zGo2T_wkN(DM@>om%n)&7)p!>Ky*1Im0eziBdq_op6`$9s8lipx8JD}u-y7?k{wiRg$NbaI$7=}~a4`Glr#5d((6-B67 zppA@FB~rkmt0D0mPtO+jta*eZ+x+6!v5AsCVZanM#Bvb5xb@vdx$U`~@#hh}Rt{^e zr?iIu!&4>uJ5l8nkg)?F>4JNfwrxPFT`b)E5z0sD zhmHQuqDM{UTL4QxR3J3J;ZJr&==ZS_sgy4pR&RoJ9}!Bx3q9R`jocK7UBn_QyIL%V zxK{zDX!TkkSXNpA))hA59Em+%Ar$x~k+)Tq0NdcDdy6RRNd2_tHUIAun@yeWhHZW({<4Y7e$L9uWLQ!(xib`CJ z8A;!t77|d3r!tYx>{rue+b_Y5z*vVmBmdIYTM*R+Qorsjfx}xI9(TST9$pP+yJY>h zE_^rtf}lDrVa7Rl)N?PmU!G3ZygZwCZ2CQf=P)C?H_x^hnuUAe8hZrcCp;kp4ZGIS z^2c0r7sr|XpKnl!2Lpg{{7zzEs4io*$Gas&u^l)hDXGU&YvX}5uL=oNmXKXL`ww1; zV!wyE)=3qTyem!A;>$*SW{$mRyo&T`yu_u@=$;CAAX=eS^2+)W%kR|p1(6hKuZg}< z1}sg>6erN@IPUs~AbS}g%zw+J#r^C|Z(0EsBVEe(FjYhoazSH`!;mLdFm_{1Me}T3 zcsa5lEc1%>$BOpPc2Q*X&5xwbM4aO-7uch*s7;vGsx!pMWWuJFm?v?wzFbt=kKd4$ zA5ZxjJj4Yz!TDdF;p2w(U7dobL8%IZ9>nme6|GhTr<^*+%Y0*;c@bkzComdh>0_Ip znZ3`3rF$*$3b8|%2Y$H_+6cqg>$6FV7R>36>GuIDj_?-+iaSjFsi9Dy zuxg{QYh~&1<1JHcJ(R;cX5v&8UR`_>y=h|8K1;8VE^=@~OAi#^OTQ_IA#^JK} z56+rP%L2=Fchy5s6PMm5*yiLm(GtI>cf??@ohc;o!9(RlOmtH-(-3E-8=o9wbRhp;nunzYuMZhFm)WZ!I!z|UE@%v(D zlG-BKCcRhg4MGT}v&NE&Zr#4>3M%-wnoVQse&Bgp_h)ffx-J)~65?wlWiZ&>&Y-Jx z+f#Bb=`{zOn{PTz;@Uo!)?Z`QeL1)Oz=ZLig-;X4ea!E^b-^&LvkQiF+crBmg?q>4 z7eAgAs_Cy-#=%SdUkYA4U@@Wd4s*0>VQeV}B|S_9@jpWBh=$YpD5d*-jdro||LS?3 zk;Z*F<0J&G6c_{>ZrIZhKE3>s<^O*li$e2>qWb^Ii~mdVqJ#7Q<60CsnE?-P-_MAR zcEPVr&S>4~?YdZ{}yoCx%2262MWCK3=GV$~L z3W7^*7Rt%(uN4oLZ+}NgCBmng@vdtTl2$nyH_tY^VMK=0A4WmW1cR6Ln&UgU^sVOl zloj9N%$@EJd$rtpDKvGfKuJ_VejK>k9eC>1pkt7?WvJ=wHe{&ihcbCKxkjlsbG4(F z9nG1vq@F1~-^Hqg(k(Y(T@Nc+9Xr<4T>I-)jJ+`NW0^aZ9!@e|>7qm1D6fY5<)F%Y zwqLUkZioW7(@bW)nC%H@2%To``--z@fwTP0O`r@+6Ct{~H|OGLT7GqT3ne|w+02v3 zHHJn+JPXjck&s0!?AKE`Nw0A@BeQYNEDCjRAskVB;;l74zWPdd)D}A{Orsx8dWy`D z5oZUA)0x+}vZ-6Flqli2o18lLJ*yDdY3|1UkMg!^OVN0hvyHkd4c_23{6DS0gdOvj#>rb zfKUB|y*|F!;~QM2<-qqsc1e^se<-ddOv9M!8Z_(yEv{eFc6(dRRL48H8n;;g79Jk?huQR{=!A+46CZj=X<%z2<59SZjpsi!ty2zEP_FCO9)}|(Bii~ zzKK_U(B9{K!_#hec(wlbdfFn~f=BN7P=D6!2{RRldx!W+1) zRU619L)z15xcOPct+VU#DSoT__4vWa_bDBuJopTDSAiDwaHk6v*y6n%g$E315K5>k7kWJsegJjD5wc%DK39jJZf2p z*Ef&iNMI!1FHCT546KAQ#u_Qwbmeu-t$L~<1~aF>RNVAXu^w0WiaZ^VLPIG+%S)3j z$m+AgID*-M>#Y^Z%=RLCP+gFJ2L-!YZbf-kWA7C3`3AMMDh>)uAiZ63DXyaWVqYI& zosWrY|LsQ_EID5j2Y#!8?CFGT6(I`6g;t~Tz+~v650TlmD1DSp_-A0V)U?C8z3R_3 zKq0`(d`B6JV+SZaKO2Vb@ZM!E!bSFW4atTGuGOcUp8p*~r+&4=ASkz`H83#7!F@n2 z&NC88m3<4P{+*ExD}jw@-MgvT+=laa*wasKlJ>5)!j&D=@ARB=Uyudn7G!-%Yf%LO(Mu~*ah?VFyU(SMS=TKa|6nfGDC zOSN6~d(EL#hxqf(;hLnHbm>lcuWU=S?~suKihSSYCT- zH-EmL75%VpeS|i+aSgD9{N*~j(gg}tYbG}b=gKUk>-e>$rc zIn$`3Le=GP0?np)TuYMmmt1|G@iz>>WzAjCn|OjHvq*xk$rF?q%AQXmcTZhpY`Td1=P-U{waSm9zs^obokN-%Rcm{C>%zuZN%UA2 zP_mSxDt{n<$!=kRG~^cj5`KypqoK2{Rm!IjgEfiyHP&J>K|V)=x){j4)gS()u z4qbFn-%dnBdX2WsP9AlY^oRLnfWDmn!1pME`veS4lbzsw-fH+CuKWBwr=K)PWU)RY zf}tkVGR{dzEie0RpR5EF+pAgy9*a#|!wx>j|3DEAKJK)JAH5YYgvCOd=aeMVh`u_R zbaq3wd2fHRRgd>Pp!ais_jlO*G-#ij<1hND8b_wU)M|HGxI>-!!IAu2!e3)MTaw0=zNS64RG z?{O3_U>-|~55|`iIdjKZ#k^;2F}--7tdVcXcq)?zA0iC7!OoJqU3ZDS>n7SgHm;Gu zE?<9jX$NP$GzMh%cQZU_ImqzM7lhXlJow2T-Vz_S58nMWj-TQPYrT7ie8TI;A!ESh z+y5d#RV$xXOH;Eo4XDvd|7ls{->UC5WbihW_qL3W`dE#>+kl|AW)yw$W%XTG)9Cbm zx%By0bGQ5AvXJi@mlycp*O-+J*A6Ts^1)4_LSO=bm&GO3=r%)Ei+Lq`M^o`NN;GGH zLJdsyn~XsAOV2`p-`C((un|;y(L9QMFSnmIVg<0;i*g@=EW$5x1b%nBrw(1Oh24;f zcx~>*Ho*8lKQ645zR9F2lObcudMW67d`DKzzc~A2o|L4V^caY2!&CFRxMPFlBytqj zTEXG0smCZtKs`XuA z?)Gn!Ol6tP4nnymo0Bb#>@$&;ySP$parT_mm;o%?GWL;P&aHz*MiHBZTiqg>&R$-y z&1yTO`|EPD#Ag133s{`ZE3$ zuJh=JTsbg4h`{wk0ND4gd+t~*s7mBAG_HT^w$itMoiXxO5v1AC7g{2w8uFr!muw9@ zPITw^abe#l9kX)b_+7^Hfb{#X-KxB=N6ckXua@G!{dM%G&JAJh?(PonCrx|+?~O5W zd}qJ_#?$I`j5VFfQq>gdQ8`cB$sIL(85Zgb6kc{EwfPAFCM5(oDHwkqG9K|8Yj7ha>-n56M2f zf00qK|3@AUoy(LaxbhZW`-~6f09uT{~@Eu$3!gul2Or; zG1h!vt7kc=X!BLcdS#Y-fJc<|TA99`r0+k!*@wOA(|`JhjPiyt=Oe#Ub3!Pu{tp@D zfxi0;GxteU=q801O@14G!IF03K;-N{WK|A&k^$7x&s4;h8^myD|W zZ)6lafgR*`5E->s<05vV@(&rsWHn;NKl2Y6g~j;m-(=J{HyaxYmXA>0Uowi$;a_AF z_P@y}OC+S%dEF z;I-w^a9|`v`YRg)401f;8axy^lDt-sRTWAn=ImvdI-RpL44Yd_Kco3jtdN8wr#cc?cHym$F&36-H{oKmy*YOj|g{zx;`fNgHXFQ$flCk8g@el{>=>mDe5SKM(r0A(|( zpH6H>{cMY*y60-mQ8XS=IA55=XsKA!UMC<#>1Kzu74*c<+C+Q?8ZAUofKOze|BOCG_-P*(6L&j0{!PEgU6? z(~;w)4_B(Y^&3ZCSuG3tX=ZjP!vuRzo$R}6{Dw(QtLo`kRTEQTYe5U6k@EBQ^L&c> z_^NzvO8R}9l#%Hhtt_g}yK^IRNYfGWRr2ft)J)%JL))h!fT`DJ|Zf@^nZAZ-|BiSt!uA} zqo^P#@5x5bky(>ijcIxF*b4?YNenmL?jpH<)F}p;~!%FObG%`qZ-4 zD%ukEXFj}>pbRy|@y1AYO}F>HNA{U~k~j-g>pb-x_^NF=jr3;8E@)btD1Ruqa4`jZ zp7+n}V$J$;@~OxgLZJVL!OEc&z6Hg7Bi0LLjcEh2J;Z)Ypd$XgQ+p-Z{rk31a9M>!W9XwMk2oB3z6U>V+|B(@V z+meyGNuRsF6LVU4dj(o}q@4#@ZM<|HPA8fcb<4$#ByzRt8GT^`3snm0%n^6b3li#3k$s`pO#}6osLq*%JM5CLKy>fn-LPq&pt^!1Q){8PSuRE1omeC=rNTTW$Z}9vIMi*f6C+u zTw*SHR22wmoeJ^R(|IO)s3@k4ovA2L&UoZ@ImCr@cU#J+olJh2whf@4^r$PQ@G#Lk zRf|5&zFH<^5(PkN(kK6=C21>s$l&jIPw0jl; zTD=feV$Eg(^T`OG1V-DLENd7pQazNv)JpLuYCSVhMZcMR+s<|HC_pcTvH74Ymr1Xh zuf>RJEX}vUd>Ea`?JZBPYkCx56PE2+Fg2EGbW=arLZSyZ&*&kSXgj+yhHHj+2ZUMe z<5*=J@|LWZEb@b>ht8p<(Zl`455N*z-wMLsH&bmUse!GBW+dAa)z7zuFGPpxK&Y2Y zo^S!8@+L7ZnBY-lkn5NhQ@sqjjAD-hO5cK6&D8|6ZNVp1?nN4!LexLY$~SxFCJ2dx z{3Y|~W7K)qRg*6di^uhYf?2k8W$fmlI<=8BZ=kxnJUg#?{osgG{h$Pnpj`9Oa4KV) z?az$lGXOm1h4yOUO}!*3L)*Q7^NpfXb4HkO(cj7M`q1&7NK(I<#et^bx}b1aH55pwVi9gMI2lW#IDD6DaKbm1pY>!z($|cPCXE_z zjG*(cA}ZsrD%C}Bd25EgM?C54R2B{L%^oBb*lTH}{n>dj$za?Gs7*>?lAWGf$Vv$m zEOhZOq@j{4OoK;TCSa4TV|kRdab2%xFPxDYi1?bVH>#Beg-0`^Imka$hEKZ(zU zL4b+;S|PDx@cPZkot4Ngm7F|eMX3UzO&VF!0G!v>VzI&MSEuW}L<0Ef02hF_i16}Z zP`JxLgIN^>3;_tUB$A>bRwM>Am_smhizo;Pk#m+O$GES)GN_bJ+SDx7${9}(#xTm| zXu1I6UG-F+9Ah4?#Ky>OhBO9a z+Hvx_D%R$c3jsIq$D&l&b^Knx3(2iMf^EgI3i!5D9Ep%2e{B^-7og7WZ4 z6RCqYwwT7(d;ij#$-Uv^)mmO0(%cw=D-yk!a^H8Zfn+BlGeosynGC#?@L#l%PUcd< z5pxn5yqLc4r4kuV$B8cLBq$@l9gwB-x@WQT^w_VX&sUP;3@3be|AR zumIf#5-jd|sALA~qAo zEMPVNue%f~flG*lV~EF8==_Yi1yzra45JV-OGnX1@@PsHgRJDAfJ}-$l_1QF#UWyOmBHT2wp^{)t63lafkdUppqy-ee-H;5^<&nZ=O2D>R? zxsETF`!{h{oU(zL1m$PMTD39oRMAyH1ym~2>mw0!BNknTHUzUf<&@3e1n*dmga43n z?LdWtASWy>s@ficHXxMuCgq{1x_+i*?(P@?Vr$wEJqBx*Gg0j4CD4bBK?Lu8 zlC&iv8uE|7+4Jqf~$-`npsPpZc6)!jO`%RY@uLmNwQflx+D_b2%0ybiIi~u zJTai~V#hN2*nW+>!WY*dN+<5`wU76W<)(BvwGM_$IPT3EtH2$V30Ls!_9r1`38e)H zlymO2Vpp0_h}8kaXQQgSKkK<+a1Uu~WSL}Tpg;NIewPU``xqYu#O&^384Fw)^mY;l zjfPnMvjY+cIGO&~9kRV_*G6E2TrHfj4m$T!dSXFfFH&u0L0^9X_F%QL7O!GG#I&%= z4O{^#6!(X0%dN?g*(}$Mq41ncQ^Fz16n37VvUvs=eg~a@55JHZ7@o`g8aF%T3n7JE9i-n>TClbr3MH3neoj`P@O~1p@b_esz zbNNplFANDDMA6zs9!4P(xCfM8524My?aX2pF>cR09WVLal0ZQGLyn7%jk4G=*p7B=tUyx7_SJ*b-^7 zJ+@SqY!S8^5EkmQJ_4%u`*MsvL|W>3N-2>=gE1rNx=VehV`@8zi)@eYSC}lqxf#bx zU9JW9lm?Bp1F6P;+^Grv(s-w*>SxSa2+5)) zh;9=ppI7j(DN1)!+>f!zl?5ZYB6sv>#7!gbPXpIh zfu-+5^O53Z&HjWyj!80l3AnA7|?C7SR}RPAqh;Wjc0q-3XT-R->i=T7ta zM}|)VeQnRh_oxq5rWed;b0WJg4t5^RL4WNZAhoVO>Vv0sE=BSaqZUzX)CX?bStH%M zcEP?(Yf{aw19F&-?6Wdb=jbRl)a>Q%bg3_cCs6yc=V%PFNb<5LpAn1;aTMJed2t%n ziG1V+qB*dX0GD*czfk9h5E2#POAm0Vn|1`7i8HLixEWarK|6XVSt~VE#Sv;mP?FHB1p^hQa$=%?@zgT+z;uMq2@HPK#8>PYiSRGO z7wH&rypYk_jlwFu${^ipcOHoU#ln$J!>h#*1lLiCr%ErLI&kD&)gK%$QZ( z=5?!ln=s`BEWX#gC{DGw$^PAbUuV`&f7TZEkCYB#t(_xZfrzuz6;VYC_SVdVJ& zf2g%7j<3KTtZtvK;OorJn{1!Xy6MMA{afq0OiR6W(eELmEq(aL_$g~_DE|e5)O)=< zJ43Vs`TKwxbANZ7Eh44@?uA%sNfW6?X2;PAAgr9#ysiejDRfp-4|h^r50`_qmN5pY zV60=^d4kObQQUc!N72r>ks2QfrHED|b9Lq?rZvc%;A;#8{}lGCk42L5l~A9gDHI&@ zbY}p`1ywqp_2RnZrH;hfaAKt}WA+2$HlqvHTS42$foejvU`%?nbbf;gq$Q!T^X<7? zgD}L2Bi7rD#jo`lUO|k*N@LAfV+4#A*Nnp{q>o+UBy7r~5t06*7dM5Jx6ElVyFrX) zwm4{vav@1$DRSiB-EcFY@4=Vs3Wvs-G>Bbjf{;kOM}l_xRJi3Y+*BJA=!w-S>(t`P zU`99TP7L8s@P`Opss%9V9@Kg90-*!MhFLMA^iA^cE78OU;fi~%Ls1WBhm~?ssdX{_ zDE*>u8HvMg0N!?k@u!u0uoyI!!LgThw(IO9G^M^ zIz}l~jB=dpftX(ESZkIA5ll0D>}9N}OxqTOa8`lkWF{=HT3(E4HKtgGu1&U z-d}0Y;=IJV9`KL`bK@ELT83%M-`>fW`8=-DjTD>vtT)u{)K98OQuA3mp@sbAj_TR0XP z#!TKS+f!Lq8paT+r%jlm-&>nV3DnngTTS)|X46;{>P}$J1FyTjRwU>n6g15W=RC%B zO-JIf@q=nT+TXBI?LSmL>qL-Ph`4Iy7%NznD7=kg0m>;@O+jjrt``QooGu1CTS!Xa zRe_v|l&U-~G$cKU#~Gt0=Ia7l;*wo8niQA`-$TIV7$c$P7>ga__E&@UN8ZqYbT1ZG z)5+i@izml}7K&35{20c2GXDP%P@sljM*d4CkVg0Gb!>lG! zFQX=hiSol(Z>)}})J=8|NAN7EMMcU%A;Z7{O>{jiEeX6k}$rY?^U zyAs>sAv*D%dzZQ~^pa0>k8&-0X!JW*`P&d7{AC<0LJxMv#mAfFT!{$?6 zWwie-4!+V{d80|{jb4}KU&R|4PQ5{-b%Cxp*vT3bD50qSCqMo2m0X?fYbV`#t z-NJeL0y`2iNmTyL3Sl*k1r2SODTff~M^F29M{x{|Y-Y2gmB+X^5(%uzXT%YB2_RjJ z;BNP}udoH2)l|0=;e0K~OQcXC6@k88?Ml8j4N)TVso5Ie@FHQS!ZKnaWO&#=+X+<%g`>?G+QN`jhMcf>Tw=qwUpN7G+W z)WH=%N$Xu0gaexv%g@Yr9_LHZD~-WJ8m+|wC+R@_fj4}*$u^J~7$}*YiJ_T~S26<> zoDcsZd8kmFzTQ26UNXm80vFKoJ{w?s!;A(#Llm}05!Zab$`RDYG0A@EUaHMfiRnA}(YAMD*zbY)T7Ht5*4Z95ekm84=< zY}>YN+qRR6ZQC{~R_}V>??35pj6Uemhkdrk+6P;6tvT1T=Y2gN$)(4`rZeit?50ye zUSo}8H!#)=pyn9krkd9>##8cKEXU9na~Z@!c~J|*VQY1IQ0k zC5}P1zR)19REVa65E_CNQkj2gON?C+7EEMSNwQvtu_fkwu;eH~gE+klXu%p+c|X}T z3{hAtwpKc!t!rtPOAAdNFW5S+VTTwRPkgHU@#3{SCJ0E&#Ll82WZgWz2N;bkj$wc%<683WR}Bih0?E)ib$-^?=0EA9Dv>7xu~pN@pu4a@?g};7jyGV zQdOblPi@1e^XQXn)%X)9@kVYyI`c*@%@|c+Ky<^W_UIEMd)Hyan=*}%Q?~Kq*Cfx+ zB?hrFlQDL!9P(D*Q{j*Sxpo!=>Da=JTs+=>%Mc?REQ71-xo29FCXYIsadiW_o6P!( z!_06)-T9*Qx4+)3fI0xcB#(;!NTZmPs8DoC>w}(`fqye87)vLaTEyCkLNaNvJq|C{ z-{;FZ%w*QVyUL_4)>ov_*G{DSJia?))(%cGM>mRWNw$K{W=Mxdz_yi%qo;7{DEa}E zM6Vhu#gc-@qR8bi3iOt$^dWNCQ1mr6{ky`coVuBiK`bFj0VL1zX3Ng zqZnLRiWtA9ldR%Ng~yp5ogF0CNGV5?j3XT=#Tb6uJ4O7VA{(WWl4~{m=JQyPHt1mL ziqhM1s1yeFEe^m8QHuX*nO$IzMkOCcjjG~?&92IUV~t=iUQ`fZ9Mz0f>D0#}r-QY> z8l^<#)a63lMfcZtF9SQ`W7vh~FnEq^_|{ZH2kWv>JlRObtgI^C`v+rG3gT!I^Y7dD zOvOGH6PWmkJHRZ$YJn0`Mj!saHF=^kry@HiNtbZ82DkDm$^4s@OqsB*N9XCHP zqv9f2ASG5o{iEiK5{$W><`0cNe*7X&4X*j%P*hY-Gr$-L#@Wx0E@&>fPlgDIjv}Do z!{$r=YlqdSWk#!nKG|f{3C+u#HKTMRJw*-D2Nj8Fj4rVf0}DUVl@DWu$H!&#w=Zyj zHuXo3yZa)q5ytbwRYZvi?R3Fvd`{B18uvm*A0G3Z)rBN=wNQ=t-0M$`U=}ri&6?GU zcZC1*zrquV)DZm2yfBP1{K{GpZHXQkuVr)FukniIctv-P^Ft@u@M0zoRD=<92vi842{c2aMK~u58zalEz-j1ozw}0h>{D zPwet74a@bM<`eeUa&>Vk{{pw2L)os}t?Ly|mUQ?j^qoNtmb9Dg#bpj`hqsj(ovB!&@Bx}Co%OF(W@`mq4&L{Sb^Y1>H0O^4KYDU!oI<~3zJG;#W(PUhzQ)c;AJea&r{#Y zA`&YBjxnA52a38!SHiYO#k}}#=F~&mIva^fkslVCxAlOwxk~J zWTNqtrW_R@+s2ftm#kW_7bZ$MoUc0@i+r?8dfSfd0P=ZQe@&x)AZKPN|8Khxf4;x! z{_oHcT}?vqtt3?UlMrJ3U<)*p24rG6kpLlKEyOfW3-G{EI-*OMuNmxe5gNq`$l{hN zUN&JH#WGlm4L{o=W9qA}%PTF}eMO61;Y!632X&CK zJ%IWEc^N8wLwi3*cMi&P4SA_-N@FCt4L%rC8>tb)88Nx6YJhAs4oP>dT{ zmll6L5|5*?CYOYa^u`g(B$LwXA}a+et2>N%3ZOv;EnzOmpmN98LpsWNRxVym;Osk< zHxW~OM1^F5x+9EXS9Fx{iv_5Ay@WH1P*b82VO(a{%UG(nG`*6vbGDUVPCz+hix~7r z^I_8z-cwsRmYoJf`RxGx!Th>ZVt06bi_h{JfFiIx_hGF7azt#;$jmiBw-Is>FHTeO zp#!EBuCR`T-Dr+%fL-UH?3g~a@;j1`b0T^G-Br%z z#U|wUbc_QSY`K;=fq6iQ@i)4OQ($SlZpze|Q0SExQv(~6%5t!Tcw=`-K<`EpSwTv| zr-Zu(w+Fz(OjRj=9G8OLbx2OH=AfO5@UCX`c;*H9@^CATJ5S2WVpC#Kwa3H;zMNv9 zPHS)^CE?E$Bsr!eCpIAOQx-8Rr=`e_`$&c{1_1*PTG|VTQAgN%vvDQPOt^^FR`L_G z#$+MWDTnf9elYClX)A`6H}F$kL-?cPR;f*Wmr+1bt)X3jo-@}UFe!N#xADlZGKu5J z@xoL&D{dB}1k-Vym8GGp5iC6LB4RI*Q3zt>tJZ+AKdNl+Q><6S#f_9Fch(8nmzD%0 z{C19!c-%Y9g<6`ri|7O?H)Qb_#1Sd(I<=j3sc(?2E~5-NZwNcz#-Mh^f<_g4fa_4V zPH}iH#WWd7-npfGzBJ(5H0U4V)_UX35TnMt2%A6gJ2#V*6Mb~re-J6~$fu)UK24#_ z?{ENcbDDg38p_X$@tIKeoX55hyX4NPc`kSh+vsW78qBP8Ost#WCLuMM(sZ?QlW;UM zQqo5ty{NxqC!>h`Fc%G>)3MQzMkm9B5r8FQWeftQ;dt@J(Y7i^Y#Y%q41t4C8tCv8v_#<(Jib^ zp2ou6RzyyOR}hJrK!^+1UzaNm2{la0d_2qn$z6^8PuRW%%fMt`BdN-YIU;?|r(r#3 zn*VDQs8%*Irs?hUbkqxkg{lK<^JL^}qFoIfoFV6zPik}`T=D0R(iXJS(o{6g1A1_c zalvlddPMn6y$DtWz79CL1!b*egJWh820Ss$GS_M<#Sy9`qyP`rJR)MQ z{W_e`(r0>q8*KxM8QhP3bZmN^8I&e3LNb*@}kCUpz30Kx%)@6hYQ zai|5TYr%IGNuH0pidfNiXNxq4Vh9*w~6ccTdwhU2Pd z!%6;7r0XhW*k&nG*PoF1fjB>fB^|;7ql%}AhEWM<#S<;U)5mk}93;d6ydfmDYYKNj zw`de?uvfSmt3~HkK)0=4AkK4w!YdPa7ZK*qJ3MfH7@h$m2YFzPnSqL))}bYfc%Yx@ z5^w}GJTgP4a!|Gde4e&CsyMV<$ixrGs-x#~3=mvl0_X&EVm_FIQd6#CB|8C@;f+LL zv!;8Ag_~D8Es3cD5d`^1&Ub#1#k_#1ilakU_kv+HVz$G&CMgA0@H%96bQHy;Y})$t zK=OiNy*Y6DqJ94|VFieY?>iC<6?hrx#%0BX&*w?^OZnPraFjII~A*ej+CSVXK{IEpMyiUoP$ z(+S8247E1$ONDLCiR*=rUoj$Fj!APN9A`?Z`yvMP-^E6zi{Sp>?>IDg!ThB%aH&k5 zBjAH$$s9DS;jVbwY4WvdM42OJ=sd{u{+1gKxD!1|bNiM2E|5gn$^aDGkMb$S8^VJqH`CV09~j-vq7V;|sgOiCxFV zCdZ5U+w-slT?LilcL^UL`%{~Q2FGRB1IZaTMgql7<;9qq@8W2rgiGjJ5@(|4_%+C- zg<~FBsa}lJMPtOIHfjJ=0Z)caQ0c;UPb4)DN1~&KS_L0h)m`2G4U2m|o|K4`$>QLIKNWG^}uU=sU9Xs0$7XVak0Ee#<3!aLmKV>hdp>os)!2`Nrb@ z;jz>`-3R7`f{1uFl_)Y;<^(D5A^bLvWDdDIhxOn=6 zRBmWVR2V;x@d}54jsvrZUf@UF#C_RjL3Ay&BXD_!YUIf{`FP3iz#O^!1Un5wbl0e6 zI@;^?_JeX)B+ku4G}o)W7ij3&hNzxp*>z-QTeSX8IrvonAWDCxq`hUqPbepdeQZs zG^+KH)VLmYq4=iy?j@`AnteCz(Qv@YZ zbSD^YLbTqj<3vd@qF@A`_MdAuZAu~CC+lOHRvx6QXVtn@4mkJEj-NhLgoC%RmrL`( ztihthhAf4zXPswNc&h!!JF&j;3+7;Yj^d5{3w!IC{zV!c0i1Tzr=cLPrKx=p<))NF zv+Bxjv0$%W5VWt;x%nkOA6wPWJ`FAJGJ;bWlwm=MIN5lSVQAN~6_)f2Jn=rn;znRx z!}`$fJHqg^5e}f z`}y;n2Mf*Y8S9)dBt``;2Tah+C{R?Y8!wBShjI5YRu;Jv#cLg1WV_ z0D|}Z_*g>L?Bb_J+Ja-CEDobUAr^yq99jwaiw7dXPQ8LmLhs=x`MRZ9lC;RAoa zT9q2}-cfrolE>e$Piadh(4m~q>{8uQB5%WvKQTc;_lOaEEP-0#E9JzuVeXp>6KduI ztXOQsqvSWZ#Jy$29!F+$@r8PFG2U#F`M518a{pL}{1N23*R8pQQ^aOTf=_#5n3)=t zcN-2-y@YWrh|io02*Vdr!AEBW0S9ggJnnn=X}rU1t)g(slj2Be6JpV9ScZtNe&wfjrC}Z8E|jU&cWP-b~DX1jc<}s zEDRh)t7Mi%OK*RawJvUN%7;z?)yJQo1Alsh7I-EsB1T$nRP^`o&rp-%%K7bv#Rk>`L5rX|S#F`X7Fv?-CF*?Ex=SiNtYGS%`$S6EkVH^u4Q%!jSRz7>31Gqw3 zx)}t``3C6nfI*Oc00<+kn_zB-`Aq8Wdj4#dCHoYeaWpf+TBvNEhX5YUk%o4rOth#4 z%{M&Bt4u4zCB!f%fHB)#r4=CRhEt9bRct7E++$lk<|u9SO)@hmM3of38#bA>{CXW> z0M!z8zL}`zjk4?ZxP|7dm@#2~4Kg)gspu40s(rUULf$gyk3J7=NCPaN9SYx&HDuCE z_}PD{@OHDQ)Nt_>>lFbF-Kuj|jFy&X#O=ss?^pa;d&cg^_pkfUJZ=K*dTtLnAmKKK z&mk|?uPtw^8-C7p&$9jFZym@jOA~n0e!d4O)f8F_lqMAlP2K|TzOkO3aXxO_{bH4T z@RvMHq?IAHUKd<3SU55|4WcC6F^D8(u3unhe-K4E9kP_7A|YB#&3rskY}PbXSnB1A z&94N*Vt=?nrB*$Q^nz%Seo+F^`Hivusl4$0DUw85;1 zaksd^FN#8Upo6tN$nhLdx0SoCb_lfQVNsvy`_cn<*1_^WgOJ0x0H>v>eWLArPE^Zo z?8ZqdAO3}0pJK7ONLWT%x6KRn6JYFA*emheGXDok9sXs4w)|c`R=Izds3uL{!qu$# zC8?e(r!!PFj+dF>?rtSaP{%IX8>$Gd3j4Rp0LR;GzOxt`ad(f!apS z2a1kYPEQN3UyL4_Twz(}vF{pDQLpPnh0j3n;1ju~jeTUg6&BF1O6|T)?a{IAfIPc+ zlu09K%$>b3?4ZwI$?UOwgQ{vpRD$^@Jn8J1pCFIy{1cvPIY~)&kuNBfIAe21xP@yu zO9$t&f*xOaRnMpyouZDnJ{eNy$1{a*{&hs+w_ylw@xu;Mm}X@cr` z%z)3(CqZ@+p46q~m+ZJYCuiWMb?bB)Twt zC7eZ54(hrSZ%W}y%_@|agzanZvla>(G2s?%XP@o+LLUSF%2y@hS2ZUEfk2^il!dR9 z&`+j&)We8*wr3h#-)H}z(6?=t!`5vJn%{0Y>K*YcJk#J(iuKom=9MMf*) zGRQFhOCziz&vK7_=*>&)x931cf1?0^>oLJH%VlMFhK(D?O1#xS$Wtaj0NGpqE ze+ZIz6M(roai?x8F}SWi603GKhM6KA81SytCI4Gd@974$hJMVm82XJ3;X-`w*&MG9 z#&ggoU^v{fgwhOe`NqIA%Ho?y9RQ#Q4C`B~^8Xuj)HtE-%<8s7MmQ&TiN7Q3Io_HO zh)!d;CQrfvBhMyzkwQ-1c=I|E`=6SraHRk#*P~}5f4$QPDlk%Jt@xhW9`;WU>ESCMgTg$N_MLq~YR< z7-OE74S64#@t}v;Qzw>HymH?3vnJU*Y1F|_o)InxpdrKfK0d`2z8s7+02NUFV{(=$ zPn*MPaXZMIk-)SKE#f>a_=IIKC<@jd&`tyDEppTg6fCmC2f+few@O3fxtp{wjm|{S zNhB~}C$4;`-3F@;W5!@-v1$q?)EyjIBu=eN3CTc&Mlm349CW7)8!f$zz&Wnhwd)|- z?gs2~qhC4p7yh64bb?;yUhG2zR8XT!|2(GGb%{)=nttRb+%VeFmQk z1W8bGZUnfWqsray+%GPD(_dd=|J?eK=m9m8O)bmA3>Jj*{sUKLV8r#CSM z+H$ZBt;1|xmD}LNRT>OTZA7MlMIeGw4{_><=Owrr2*8$%mi5SX2{C0LfAtBgChXt* z7$Z5s#>F)`i@#;0xvTy$cBY?FQ~#X^#30m5);SwAOUiGyHLY_kcJe+hSauP&3f1JW`AI$RQslRy@XDS#HXL&eX5?v98Vk zLD}x#?t@>wZ+(8pXeI-Euwr&_`rUC#ZW+kvRLBRhHwXr^aAO8t>_berm1~IzjsEd8 zdb|y@Vo?C=Dea&2#LWS)p7cHfMOB7dS8ELyv^)feIWoim$LkJkGdewbIy<{GT<#GHjuI(j#Z&DXv}y7AepkLONH^J;bkarkE-ax>^H++cqtsw z!1JG}AN;s$BFTGu!+4L_O?@*oy=cAMFeox$4YGQ{@*lj*)e_Kw3Xo)=Og<>(xPl%D zarwJU7Jqtnp?i;Hyu0r{`ms^$;A++Nf~D>e>Sp!Dl!ytd*n=}F3xu-}z!O!8c~%1# z$D~uCWIIX70pt_jSd#KT@(Jn*>4LU9mV#@#liO3msmON*KaZBf1NX3|fss+xWivow za#aKi>_nuc_tlTwj-QHXS|SaoPV(D9^gu}RuDmBm=3U_x%3ilFI9n=N71+P1exiBuaw1p4 zNqHVaeNEleXHKOE43?w7ope=lNgtb6^**6r4|GUa@DzU8a>n0gwxJWhCG z(OcwjZTsK;QIPBt zwM(S6S8{6Dot=mt#+AwY)W(oUi)N4JW#!q+Cf+p2?>}vudwak>s*$OLyT`WuFZ8xH z1J2ehwWbdnTv`v8Qy(6U?b&@gR8(rLSzVR2E`c+k%Wqc}{;_&4of_4etvqgxq1fPw zMxIPJIS=zuFuE<2=w|yQ8OohQz6)E#yZy4iGu|r6Co?P(X1~wzU0C3bZC)+eol;nt z;FaHqXKumlcGqaJW~N&B4IG<3U6}u*tMCLhL*^c@{1{Su*s{@U8}NDA+fs%@tVW6=N_C8M2W3y)1reAqLeE%!t(i&OWiC&fG8u{|M^uaOt z7h7%zyKnXqu&+$XHcIdDdp71SNGEW=d0XqiK$~7?A))5@(WPGJ!(lr^?bbxGU#z-$FpdDgYe0X0X_Gh*|>}<}$2Q=aE7bYvl8Zfp0&kvlTZD(029Z zN}%FyZD(^o^}EZDkHIb$UvJ>eqvtbD;_pgXLC}ZH{AlSX7jLtJv@gX8(cNv9elL-{n)`^_7H07)aiFF@G80L zPq6vhCwM6JK~qhhi%wji_l>J#b^^~MscD+G+Y z(6tYnZ;0Wml>yNhN^w(zIfr%cHeljM7Z>o8wNU1dI?0IEPHiMYZ~wqCy>QDvYVum! zI#W>Al9zqPmo`FyK^L{TyeeSMbg#Rv4{COOKR~ww&v$_QCK*-CCg>Z!T_n z-uU0MQZ3t}d4BADF}-~Lu12dDux9XudH3#IwM|v)tku7HnYZt`I>+_teDOnts`Q0|WWMChu=hE&5zS8!) z#|PF$RBi__nSfxbQ3I#?g_LbC#mZqJpY@L+_lR9?U)@#WuR-VC?!o^(cGn#8bkt6w z@(udMP2<=WRsZlDdUQoH`v6T(PSBYr1G2g6xYjp^F<8*_c=i`B1RqCh{n54T?<|x5 za^%n>SAeiC!vR^Qt-0VXw~N^*n55)*;<7^MiDC2Ftk+<2XZr_F*q`a(XZsRUnmbAS zpNNxR@LDsOQ|E6VPZbH3tWOr_j%Fsd+YD;~F^D_+T2=8)Ipe$;Pto=cFDf+t)nZyW z$(Gjo&9A{GqNLxowlr!;5d_)W?)5$VfZ1$9?Xe)VG6*>;{ZGHO*n9=o9bE}ju5QpL zL&X$B4d;cMEN}%HhDIRI&RlLPV0Ruq1N_nGE$=Cof?o(5y;&zQyMWJ|pID|^*<^lv z$ChpY)a8^9($A&Gnv~SWSDsmC+(KXZHUyDnTy-Y=jqAFelJfl}gG!ZfDf9Ep?5)>T zCHHx-Jz(Oe2k8dX{yxliTJApg z7h~6YNN=aR7_v?kb#oHN5faf>5fVZEZtqbKj0-*8;dGB3w(<=v`Qe6QKG5i~gg9f{Y zPiG}YL+^4Jc?pW?|Ia`DZ~jTBWrh^JWX^>}u5M1`>tN-G{tV0XV5y)HnMPVaQ{m)e z;QRM>L<$JlpZSQZdk`%H>~Mbxw%AP}_PS+)LfF*;LSj3G8&1LRg$Aw5lZi)Kvbmku z*|OoXvUd^nr<0xU7cuX+*7j!p;mnrKbq3o$urxJ{FHs>>geO*fYplEDo8J&dr1Ojd zM2$#xooD?nE(#%G&~a*YxKoLg6=3RbrgyH;fm;DheQOJ`k=2`&GL7Ns-sOB z;m+8mK~cJ|Ut3|*7lPH*u1oDrgy!kV3;iYyO#x%3HcMB3-L|9&BnVP4uoE4jK(y^? z{8QlgfwfM&b^C#8rY@2_kFe{qDb{Zat$4j6T!Adgt6r&>RMKc-RqEr)BQMSY;~yKS z$UTA`zL*LqrW>zsHxr+0A0|CpJ$#g$`}3GRIB zs+o!CV{9AINf*{a?EcmX6;x;O)JGge@v&^b+tqcq7teAP6QxnK~jg27bQ1 z9Y)N&5SyU&F{n~Ksgm>d!{o;rBCRTnr4}7u$qyPFXYWx3mG>}vi2m-IvEar{Mt$IK zO~zFLF!v`Aural!v6WDIZWzXo_UuE7mlPMt>8D+}-0qF4>t1z`E@0){8(NaWX2ENl zSy!0%pxmmd8UhjtGih9KSUfz-GCa@*aFMIL*P^oX^}6A3Sk_%<)Fzj^-@JGSit(3*q2T8{P2A_DKP*N}z$7Wy!eCtvs9=c@_moQ6gUZT`_ zLi}nH98fdHUf>&WR=Vve%pA#$SB<$+dsiUcbBDZP7a2 zUB1Ar>vV{MWAejwzi(x`HwU6WY8fPE?+aDkN*A)E(QM-rgN0Vc^M|&4+A}_HI**n% zQmJYTQi{4tG*g|RTb)v4bY`Pky+P?wECZV0pTG$62Q-IVA0P}xaFkAuZD7CQEi}sf zH@Es5b(@UK#)ej-j;1^pB4qC@blO=G8!MK_V;15R<%%%j(FIas#OH_cCbo7j*du{O;1x-p=X%I&wI| zc74S4ebTk$-EFi8o1w9?_NA|=HGa2L@vh#`%{;f<_*z%deZRHdI0Q#~XEtzMxKm_` zLi6+t3lP#g?44BcnKPu&?$&b*QDeWOg>Xhmlmr&FCb_e_22}!mdWAOuB@$=@_fCjA zS=y?A4kpl3q5XXB{kWvH|GN}f3&3|HzYy4rPuJrs{P|isdrG;iNmTg5*<{F$n9aAE zIYj+?8e3C;O7Z{PhvX>R>$+D9tz;eq&gVHUnIBcrU%S;PVoJ!pyF{-#8&$7#*(`AA z=)+b4$5KoCy#e3e40r0ox1;l?XzLG*C*mv|nn-MA@!jg;1p6|C1a;s~?K{GzCl#Rj*jqGrGi7_9BIkD<37=qMn-l&ikb4a>LhIikwB{=vSBqId@2KkOa-m53!rV*G+9K2mqcnyYqBCJFNsS(Uq(D%HZ zg?>3$4El07eWeZ^U0yrSs_NR>06=KdJ-La~vH=8$)rRSD`ugl8D;zQRgsPyCWjuyr ze=x`U>p0c}vd4|dgZ&~uJ)_%D(g4=OGd~@@d2ajQX;EL9SXro4FM^umtf`>1`iIn= z?w7qI!av_D}kKR+8KW|wMxxm9l z`)^mv2U(TQtQmV9(_XJlJlMYw1?sFL=ORQP5xdNI&|1QCN7GU!5m}nG^S4N#X^T@0 zY&7|?MiQ(H7zF)4z{T@n=R9o5Z+?#)O?R?+Sh-=jl)GRDVmIIr;}r*TCDG?S&iUd>I5MVrZrV2=BH8 z?-!=7&*T2g&Ij7e!QHW~NFBad6|ksFe_uuW4voDw|(QzlnwtSQvsaQ@#&jLgZf}v$-xNDFT(^79CDN>CwRCJ9TLyvu@&5X-_A3W z(V6CkyRS8V$6{0Y5>`b<^isd^w>7z)u2Vq}2TbA`TcU2{Lsq$T(0Z^OLGP4)Erh{q z!k*W!hwmsX9xSi>bo_*`1t;@vd@amlpM1|x<1S0y2i-@>J>(f?)D7$3EAKnWUFFwR ziM?|ivmH?QY+u}zMF>j?KQ%N@0z#r%K=DfrUjt?53c7Wz|6;x<)p?PU9thT-JcL6g zl@{Hr?pYT9fLEVuqX0fzR>Ch4nCE}&>uoVRX3!bp`HMbTi_lnwIgA{E-PA9n^yYIk zfp4_#xvb-NBbNlLle(BW4l_tPSYhM>ycqR9n^?{1^J-GBiM;o9@_6rE<~^Uk{X1$- z5awE5OYSHqhFmKnydVAL%c9*)t@F!$aibv>x(k=7Gij+hpWZ}xN^wo@Op`!l;1`@C zkr-|K~cTfZg?f>=d^Mdme<0y*k3&Wm(79J%9{aHIS8Kd&4*%O2ufpjDU=APXd;h=?_% z_UJHM9hxmlQ;R>{@IM z#Hwy|+SoMOh^VE!zyP=Zh^20`rJAiEd;pYnbb8)qV?FR4;y84hy_vKL%1djLN8Pn*Pf@XDn+QeR?d-fu5fAGe!u7bl2JQ}!$?4Wf1ePG9F zsJ#94z>kx}Y6KTx7_*In+`3sjQ1K>62PskWwBr*|VN*RwuX!nIO7~S68A%F_6;`T1_ltC1XbxoT8)oDNIMJHNcPUNWQSGl^_uPZv z*XLqTlAj-uwVLeuxe{3C!Ey626wwRn4-4$t=kk#?9NagyDwz9Q(<|yp)k%}XA{aiCm-A7jkTBl>2xJS>DQ0#wQOzu zg450I&4`a}iq=M2t=6$@&GG)=jmc?o%$(+_?Dh5j1BdkNY`RIiRIcWf0=pId)<(L` z=2}_4FxLd2S`mbnYYX?*u`FwL@|;qNcUKRQBc4 z29%Tx@Ql4es#@#w!6$>p3)){;_T^nPT5jT67RNAB!m?WDE}ezu`-;-4Kz&(li>rcn z>h|VsR99IW8%ci?quSWS(f?LtwXrQ@J^`So2{-eT$#VMC;GY@DsVS*BsNVWaPtfvV!DDNX3#5Mb z?BRFL0J8Vnplft8S|j)bT^Cs5{Rz>Dk@t%mPVoYhDJ?VF@&czPvNfpI_dyP4@}za+ z2x807Y5%6@`)&hsht0)xDTFK;6n#{#0M$H`DigW&y9TMLtuwtAq%sneyQUEHMELb> zFGX{>tU?S%+V$_-)6j@HW?=QeE41|vup)crI>Rv&MsP~}D%w!mo^RKeoDq(j!V3LF z1fwa_)!84JKUh=b>>7)U52xv~!+J^#<$M`idKpk5pIS`{A#eRywB^;s#*4c{&^COv zUlG?Q!hf(R>OqV3bJpFMYsg!o6x3y*-`%05yA6?4>)zoxO8Nj?0JfD3b+Adx7XXPO zEOLdTa-Nn@-S2jZn;Wk;xeFHCu&lhWs)>wBnZ}8?C12nkwC^Ss@L){8X2M%KfK_uZ zA6Wq|2XIe%0PacBHdq3{J$e0?drIhRO5`!2oC9!AEC0Bs-~ZvB)c$c#(*NO}e2j>+ zny@xvtAH1s1R5Yw8CuA+z^FJWp)hTLM`F+!UUiHT^cF2%Ou2oPcG9E#psNYR9{zDp z%-Ajr$1+ki<;>X6i<5BIiNsZ&v2}>3i_qs7&?F%^iP+ZV%;_Z%CgQZ=2K_M9x06K1 zX%Fr~1LW-JN}Gj}tlNf|?1;3$j5ru15!gulvIVnFSn;qcLtSEAv}7E45_g64(2|Vs zEybaYxWH=0%WiLbn;GK`+qJ^&8U(Qh9 zveX+>XdWUiK%+Vf8UFGOd`D)r`wh+B-JGE@mVvDL)Qa_=)Gtc3NNl~y^{+`hVXT=k8?Y zj~CW!(Zl^uhgl#)8czpl6M1F?SjQ@_^%&+rw$n$yOalKOA5(v3Mk$BFV=Q#UeJ95$ zPr|MgA>Q#FE78WW^OFQCMFZM|8zG~Rr5#kIqvu6ofAVHOB^15}_24Gys=@?Tr5XyK z1$dzl#9q>kv(^aq#=q>DEdmA1j&<9S;m-9dDlR~|qXcO>S}j*>9RzOZ*-HBGZeoSSTS4&)2p;Sj{wimxkr%3^74I9M}g8)1OH809fMN817a`ZU>13WdQ zF!_+yV@jRHvyHemM(9Aek44Ccvkhtw1k1yvY02yd_E;2l^yQZyIku4+Hf@pLWt2Jo z8kM(^sh&=I7kz&^=vrEF7e7q{&%)3ZK|^bRZQ^Lm!EPr?LG0z6KguY~@}?6qjq(BvP;YY$lo zEByr~+)ug?YxLAhr)Fs{43U>QsHH_&szH|+T%@yW(fUP=mLj7ux$3dp83@L?=7s#xA0e3p;(t)vZaAcy(GJ6%ZTub&`d6gdB9G9c71y zVu0EyrpN>T;3#VMTr3xIbS*Qm1jgwmmlY3gV^Al|y3MxRX5Q;!FuRsi?O2Qr06nF!^AQ`v4= zQxtKmCFi&TA*Py>2y96P{96uU+g-tNMH_f_Wm6wdG(9mKA!&BgS-{S!h42eH?-yX*4pQJ z;}5))WOSTwOawp?$MN`UK8u@U&Ttt#;LlWILSlZG5o~UyWcFKr?*Vc6qSW@1dF8Ca zE}i9^_!KPlS83al{5nxY`CHJ)P3!hE{V z^d_km4SQZlkaX@byYmEHijShMx)eJPB2%EbP6aa%b@noCQAS;g$%Yh?F;HJKA(cQ~ zRg)H@x%wbRbh0;4{JBxHkF{aWZ+p-m`eX`MjNlFegs<3>OqB6X4RocSg@&mJa3n4h*9dT(U{kn$0q^f5-4{JW z`W@j({77)lsb7X*6$2K&Uv$dzp(MXq3=|K;7(qU~6Tr1M+}|07l?vBYDXKN2K7`NkWBwgAqO*BA74Ye-L0WR)x+YK< z54<((TbCOf_OBZwJV_1?psX;9l|v5Do=+j(BRUC{Hw&SYt%qa%`9hehwb zXgJ8&kr0F!P$ok-Z=xU$P)kg~hUPLiC?d@;oVr2|kZJ)>7n9~>Zx(I3?XQuGeSk*s z{Pf`7_E&`a?89Mm7n4nLhy5DTDFC8BM?(JI!#r&)uN7n z$Yira7CO$^1dHt-DdInEmVe>D)HP8%YgM?lZ_K4TnV z13F-OK_1vyhIDuarF$LjvpH|*S(`au=-C=~KNl%m5VMohelV5n1P39NR(eX41oaVK zZAeT(0v!i9H-}LJ8xCQ)(rU?c#vO<=8Bn)TBl2GatWVBE|gl!k>yQkir~{tl~~{& z+@p~S#iIQ9L8U3aCdar{ofKGP^g5g5<#%5O^FcAa@8hGBZ6W4mk+)V)a!A-za{boA z773XMp}AIp!?t_y4Sk{s70Ve9j9ckq?DmM;=$6FVeR$c8&c`F?qDeY&v-{VyH`IV# zBQJ^OC*v;6Mwnp**1QeXH0oCRgf|o1FTw!FJ$UG}slBX|n#Qm~3&Ee^P$xArdz-F5vLJ^& zlwt!$ngruwrOO5Et;Ne?5FE8cMh?V57`mf#oW&nYm{oIGF!cS{^Bx85jMfg3s3|t& zh|fn#Yc_gTij>OsHe(BBMHjV!(nnxV>?zaL;ZHt23W>7@eu$bBFl0-DpIqz3AyA$p zzq7SR&x6wJcJ&+sO_KvF_O zk1ImzAtFbKoFbtrNR-BuZ=*Sj9nMQ}5UhAGUsnW`bDo|pZH&>PlLCIr80 z4dfv<@bv%H-a7?n_J#49aXNO#w$ZWEamO9ow)4eC$F^0(-xjo8F#Bj>+4TTHI&|SPEa<9>cF$a_Xf#(}FEo2`NK`;Z3s4CS zG9&QkXET?5aRP3%$4u=dMi`Gu!!Ck|5;}%Ln#cAULAvxhrO99hGEb0SvdZvZdUUj) zEYMA%0kvzl9X=dRtyjuW1IHxN2=HHd?VfqWEn{0*+i^Giks;ddJ)lkEH)cusWP-wG zA>MN_AJY|BM|a8TX-Oc$MglYBdw7xOuMUbsRA&KUK3ymEQ7vBbaa8Ls06@<6Q|{~RH_!~V_tdX>xZtcI zt;vQpxg`=`MEld3Yktu6%KJ6oQC2AA4dy4fnyS9r^N`kq*)cs7Aw4L~0A&L2_FT(9 zp(m6S%%eTRhOz-tFK`NSz>Bcf2!V2#3|oE{e*6@4Fd4i#->2`aNlL%j0`AY5%Q-o) z!`a{6#1Sw!7%d-iMjG)@@vB*(7Ye)~9d9V~0(-Zeay^JS_hf|O3fXS8a$^33ZCd#; zjQ{juPSKc9F3kCf+}no|;oK_`mB_`bO$gm%-`o;IO7BPZubGp0Pu_Vcc>vS!pJXRD z^~|_>i_Y8dJn&8fR=;-(aMvd9@6#e}FltS!yF6a|i+`Kvukkl+C@y!KhM=zS*qxzt z>H;5lv&0Q8y-#P!QN#xY_DuQM6$cie?8u;_gtO3l4t=%u+2!=_`$89;psk_|S4aQN zOcK%EVgpUEtTeJ_8e`)_Ku)sEr$laR#NXQpgr_3G86$A9BOZ(URz0=6e3Rm9srOIk z>OfnPlf+|HSM6!-Qmxe(&xbQb`SD?aKHG6%r6Nz*OayvW@yO-meQD&&D-_Ti+kdjjgccrwVx`yL#v+q81?HX2S# zyFzX^wdhxs59IOd}g(oRT6k4!Hvwvf!t zgO(lo+u5*-HEMcm!^Oik*#U$0<%`(X?U8ZaUYyN$(;z8U9lx&y*M08~m9G%)QLs+P zw#ErnPW7b|3>kCcCDAq+fpP9{*;nx$;?DfFnw?_#eHF*fx`g|TmXWE`T0Q=#5}V}~ zkD(6J?W{r;NU`r&Z>eJVRi@5DRS3gRm#o9KG8bPi+T)S*#cJpxF)Fzkk`?6VV~YK; z3(L4S7n~(ZWNUc{z27#B_2pi@z-xB;Q7D4K++*Ql%B@eDQq;B&(K^|tF{Lp7Vef=H z&39C*A6KU7476~yFcc8o@e&&tqJKePod%?;p}~5AwKR{XD3t3P2Skt)5MBy>uhERVZKjEfZe~ zCYd(V)9v{rIYmAV=OGep(7WW|+&gmboEiBp0J@gcPp!4QuP&DYWB&vq1j1^eUK0Mf z^_5EwkjHkC?moxFNH&K>8h{@?XUL1VS!9~bHf^Z6-1JW8g+A(*=15mtu>IRIY#kjI zUvJ)t(x$DTd3~CJstBAX5H~)Cu z0|uEe&JMnTtNKoE+&Ki1=Q9X6m#SjNS)xL|Cz6bNLh9C#(u-I8#oxc@kcfbCo@-zM|6G-4|F2NqcMztg@wUI}Kyb`tWZ@ssMn z0|i#xc=3$Zmt78dpH5uD-SHkJ2QuzFf|OI7%Oh^xYLoWD>GC8mz_Eu}fvRmXde6-c z)u=&aK_eAU+%m_IYQ43Naq>e! zNP8ek!iQHdFs?z_QD4dhK5GKd-D<|Jd!VUa1fmQd|LuGvJYEXo*tfl?%q7514#+}* zG?Oq8x)?I+dVd5Bzm+0$G%NVI0H(Ap_$ovm_NHwLN81WnwTAVPKkAHESEb)~Z`JPN zjW0GhXjEPrNF*a%U(Xl~KH9%^rW{*&_~@Cq35#a#jWpHV36MJ{@rr)t>aHry`w#ak zGZJzE698z?pMd@Pl;NuOjV@{~*kL&yM?#XLX@JZM^?|^zmwc}12@xaK?W?B~-$&Tg z*_d~q{2-Vrc}ZD3DiAfJbn}wJ+I3$n9aLO5a7=x4*_QVry#1&WI9x1`ei`;cK5HLw zdDcmuwneJOLdL^-ufzJ0$;l&+VY54iTtLCW*43A9&C*7g66^6?E_XU*&z)Ge&T51u zLLqAT)dlg5`EjVr+^E7M2tdON$hoE?@VgqJ!()O9-*B(Po^-y1I+zqFyF ztvLI~o{%9CNU#pCK*JD)JBMyxFkEod8@U^GqeuuSF(A`)DID^?-t39 zUIp6(RRpGN9mf6{RR=iy9=(Rst5xdv$ z+MDmkk15Fg5fTIzI1NNIsM+AE2*guK_q(v#*6a}byro=(8fM59iyom-h38HbSbD$t ztV~`Y6Fn!HSZy(GyS2PO4b%Q9u#-oqa2_y2qz?vw-nDIozGW8~Yml!zqGleuqG2td z|I=tRU!L;zeCyyJiL|Mb3oA+-BU$r+fAH0#M!9dV>QU_HD|~ccJ_$;vS)18AEZ7M8B{&NYvM&`vj_J!l$O|r%?3==E zi((v{F{@3ck6_QmiI(ND-np8c*cS<(s|UXG`yUjYq#ps}RB_Hp2|p))my-y%{oDNf zdn=KFIr7+C!7axwsj!}*i!owdW~ z9nes9dw-8iDx`D*pm@zcRTwn=a_3K`KVK_I;XuHEN9QXn!FQ*SxY~gT{YwfrwFc-X z!7v6OTuuGfw>721upb-Ui{TXQUj*(dIfr7ABWHEy{g72LX7UqQM0?b%n#}Si00_zG zG|{_zVtQX7{zL63Li}TXwBvNfu6xz1@{RJz%hBurkELTipoEL3LwqoTS676)P%N5EJMN<5l*Vq7 z@`*526On|ZhYp;ZbU??tWhy!d>``dESl+fKw71vNDeI5s_0sd8@qeM|cC|h*(zwNZ zowonr)>ra#mA-I@ouzkbi&3P<|L!WWvi^AD*WA>~X^YDwJLFnuErjHq)yeGWu`0&J zIexA|oNijr==pV@p>jK?WoRK`2xI*S`RXvWJ>SsAKrZtO?TWE*mb;@7I!v~?!DL2n(so=dYBeA_3oF2CV?!||meB4c zFjrBBn8i;!uD3vIL;YmIy_To@wMGrtgtkDqd*@?w6DT);oDFAnLEti|U+uAs8KVAV zM}!!%(I3l+cbBgnjwyd$xxcPlEY-{O_tZKaB0wj0k(shD5BNiyPv1E>8QF73kZ(9v z;zd|nz`)~TQ33q$1u7hLnokYn+uqo^UY#y|j8a^--Cem?jCy)JIG6mr9pXP1BoTg! z%ECETNaz==UllF+(9(Hr?_U|7^JT)RM~PVH zkj4eZ{U8m(o?_IOl^RMrRwLq?P{UZOu|sc$PB@);cjgJ}PDGFc--j3#0i?%E$pIH7wc) zNfxDxq65OwZx1ASLy?;ex&EqG;BYjQLFY(u^-_!Kb7R=Eh|`a(^O46g8K<87N*U$Y zPGT^f7ESScwukaEJ)lsp-dY+wmqlj9t<3yLQd#iAr|#lVKUi?h-9C$?;n*o)=ep+EtgrO#mNsd87lY`EiRxuL^67c^;C-DU^d3wIEmjDuTT zQDF08hU}m~3v;V2oCyh11efLxdaS}tj+LI%R&+7ArB*R%1(EzO1HXy=cTQe5zpdMd zt%>m_t))6sOaWdm$D5Dnt3x$o=IZKus9&?FL47Ahq141JWlkVkmftI&FDTdUkxK@P zvmJj-E)+pCX16jjE*!}=Y%H778p*h(kz(>OFLHNAPx&T;ls`bHwB7%4Rj1rk5JaH_Cvy(REspZ%jUW@fZnuU)jOAloEZ$zbn>TVWwTxw@ZklE^s6Id*E7fkB14NNxvGlt+dx zo7=ro(y!%nT1!V=19og=lao(CZpuD`@=+9<$R5!nH3o`w1YAUscHY?^#d40r_lxAT zT*oTKuqThFQGXNp#9y!4fx@7vuP^PYavm|hQE*vv9Di4ToUSOWfYpKV_gtC(u{ZB* z+v<9~SrH&}#fRsI9AEYKX{>Irfqn{d*2U87j%go_^WnPwA?FsI)^SV;aweLQ%8p}@1qo6D_@QN#vQ5s6oY71{Gj=w|?UoUD1b@SMPUaCFIEnj##cq$c1i;3re&xy$ z9b=utb!p+vP(qBmT1V*%(d8?*4s(RX+R!!xBd-{d_@APPdJ2q0Aim2()o-HeN>;%o z(?2sLA52N>OBs$ED?_Pi+zS;Xu3Xe(7uh5V{b@#91rvgM*+fFnHQEXi585;}iV%0d zPlsySxd(p5IKHRHCCU!2F=29z9cAWm98iVU{ikO1m}kD@roJ)LK7VtbsDRVf0AfxJ ziE-U{e=o%+K^(QRV9-BFq;QF4t#X@;b?56=a{NeM4j2ZTVYnU*R$M0qn z=-4TK$z|)VU&;Fz>Zv_LtztSLev28`iw?L5$ggJKFmUQDy$fFG5JtJ&;oX#?_~S?! zXcxGYg^3=;#H$cDKe0<~WDM5!byc;e=0Ke^4E!u`+RxllD}0V)5Ag7K_ht>D*W4`n zX6c1JeQ*1-rp(vFn8+z@3)D0?GC5(^_Ii?&8gx?2O>WFI%2T*r`nq}+RCb_$n)W;h zA$3ZIFU{r!F9%hlEZfdjy>iYT(r;9qNOvUO8ZoK5R`)X4svMw~XYOeP*}>M1H#Ojq zFeom&X?=d)n_d!d@9o?loiIR>t*Q86s?&9|(#9^m&|fRbedpZPA2D*5_hd<8;j~vB z1yx-@qTKbzh`Mx+AlI4An6Xf!k1-;*wHn?hQ$`s- zCGs_RDv-&XqJhwQ=_1K@`hf`iL1e6RFfQ&(wNvd`(eaU*+8qvgA#&~l^=LKM!dGvR$8Tj9ol-n_i=M14E7d#FiwbU;M?nN6LX7YfoVVyocS6SbaTkf2T`9kS!zF6 zvMnz7en3-XFJFnhR5g`@*;-0ZgEc%=9f&JTy&<>o{*DV1Gn`$z8_?M>+hw6aTdZA$ zq;2~#mjB`p4C8p=g|*ta=jspsoX#yipeso~f2_C-QUA6OewaP)F+0n6G#-{;(S%7$ zYy=@>Tcy$VV;&Q12>p<({d$*<&vP)#hd!r;2V=(7Z~Ev<>Nx`y2gW*X@7{GCKWWn= zXXSR+$NeQgL=I=z=o55~%&66yBGTRfYui=73tP`Ql*ye-j^!J;ITa(28G9yY+BztW zOkk18?smciiFUN)XA$^9ME+LrxF}ly^5zRBRn&}qWLm8xA>NH}wTV1mPy8UW>Mzhf zwoAN|wi1)P6n0X?evoEpD7L*F#Mtqh7xufB;VfYuardTZ3#ev}!Ve!1cX0$e{Ls}+#h?cPz?wlqrSca5t`kvzoi{d@X z(qhTfa!vZ|+2&x2|4anV&5!SEhvAwz3sk2uUr3&}@y8cF>9OsF+{`RSlsB8K$26@! zg!&WSOPVfk%Rat`_;?RzYeep?71;A)vIT?FfTIww%I+^4Ekl&(3#xdn>!P{Bx(wIA zSc$kZS&_^q=q*EhM~Gbi9qtL+S?!vs5h~o_Vdt>&R8nRR$LjXNWWz3r^}Wi4&wvk^ zhvEr_8bvT)JL+*6Mh^cS{ATB`k5(^dyd0=N6l6@Gwijq$;X6Ay&?JKcMCjBHuT^|E zXN&p(!2#NO+4+z}?qyclbKxlD6k7L}D5{M$oNquHkU4xW1>bp5`T zG`~j^j)!!WQ~ARBQYp{g1$mNc`k>1D$m|_CzX;2o)GVzBzByj8S6zXMXuM$~sG&vMir@{{ub@>(Gpb&dAxqnZ^ogc~2`789q0y95H{77J~tC#&bZoRUEvx5YL&fM=X#|4Qfl4QpQyKJv$*d`-rU-k;dN;gaPmZcRIT$W*WYX zfFeY9nP4q^DE|iqAG`X@UkIR`cMmh6vPpZzdS|nwh{&Ct55(HZfo4BWmhEwhpl4;| z`kb!n4c+znoIv6gd6`2`#61jn>5IY>2=2-8o`sJRa-SXSNWiRHFR{YFQp~m z_1+WT-qa3AQ5<0k4GZDHDshDs#&dS&Pi!AzZ#N-}eIf$8I~hFlVW{^xhwS=Ih74pn z3wJv-tN5Z1WCo!L65NmV5?u-K?-GDP^Fr?XIW+yc5sZ0iB)U@QqL|9s5m=rVaL#fa z1$7?sj_@fjzB_J%s?Cca%DH21)Ayb9fT)ob1b?iAV#D6l|gau@hqAJ97cu&7pjyIT^n&D6^WCDZTU|A0vbcbxH7|?p#*fy@a!!|rB3z> zLWm_?Wk`x1WkToP#ZtpPa&j~B<@rzY>^XH|kYHrG7EQnORMXBDk@9&2Ub-HR<~ecB zhS-#U^9t@Jg6>(1Xl6Is0O^qX{hjMcq|bulJDncG3ieiaPHSlHDP(!S$+wih5Kfzs zfQSX5FOL2OC5Lr4HG>}#(dxf{wCebV5`vn$kdkH=AOA9Lzf~fk`@7>r0A5X0f~cLI zdxU??8w`boY#jm7^JXY=1TK5DHxh-r#XJXyxTHD7Dw=(ne!!#n@7n@iBV?SixN^aI z2@qyID1b6}=_j68LrtlZKn?C{iA6rBLraT~8Ydn19^%Ys@skcRL0E1=x%|73H!J@s z#M_~BY!HAtYBUJo?HJ242O5ARw3(|UN;7ckgY)(Ks6K4+jPT}#*ymIzYh9|vodz24 zQ*nOoiSM#LH$xc&03^n2#r$=<;zm5{1M&jGM-6hz-?jw0&zIhDH$4Y(n}yK-MOI`+ zzYHRBWM4DGV{3@lzxV0EI5Y^kJ)5HHf3W2QPAnP%J|!lDGT=ffTL}rU{au40xT#9? zVifb#p>|delRvF`{lPFCAX+Z-@gCsCJ_?1udF53jr%|W zfaL+?NC>wV;NQk#?dFK}N(`dJsiAC$+ne6+_9vGZR~aHC2baG!3$7da0hPJ@qAb6c z!2hn9e>vH!!bZ?|i#!fv?rK)%4_;M58BFz5 zV9&UMxa?1X)&!+^NK-`*i9ttGM+d8lzVV80?U{ft)Bq64wcJrsIry4>^zhSBKzIUgwxCEV3QtOH$;QkP(+5mllYt}R0B3vQQObMd8#t?^d~;V-PRYI)!2x(z z47*5zw03S0_6AC50LOEPh+8u}4x%DNLy1eQoX=nqz3BB*d*t}N4H)^z7Et9PP$NU9 z@8tF4cJ@_1?|sEXL}X+<8Xz!0NJ2_3(5}6g)c=l1%&Q>4vBnbpGp*{0-{6vI?`o!} z)iR>$kIN8M##`>3>ni+?7I!Szq#PsckmQwD+Hu*vuP`TJdE3R07_do7^bN2K4#~#3 z9p2A#yUWyV-ntcY>Z|JtU>~3&$T6GdpVpEgNRbpJ z5`*mG>v%@U5)_M+8J`li`+EU;iGL|Fx0UEX7ra)&E%x3eOx!`{j zarn*9S*8x;dpP^=5<2VT=?Kx4=jXo#Y9b#T)8<0a9z<|}xNhxfJgzqQ?VbQDQFJ+U zDB?)q&=GRRFjL2=h;X)*AGhPhT0aGS zZpT|(OdGiiO^3*B1U`GU`(=vuus7*YVv%sQ#DJhcFhtCv z2sja;NpOV@aDpH8iSu-O0mY!wUE)WO*Fh!17;RUS=dW-CFUo&Es@5?Un~K29OhC9A zv&1J1y?s4h=s_Z|(grKOX>U0Sc{d+U4Rf1}*t^R}Rofqj;LSLFO9;MHoIyJr9{`<7 z?VSgVrwU0Rfp3dx)CXHb@1 zCngA889}gL1YH(^;&9w8idO%zC4LA&_D8WlN`Z!ppqL9V;#~HHpnH3b5`27Cql`2x z(SE4Kn@^%q#>f_M6-CPz9cBtXy)$wp1TYQBgKL<4!&a^Y%(Xv-^nPiWP}r5mu_AWF z0OeDGB8vb)=K0V;C{91R-S-+qvuRzj*G z3>d86UdMq&2khiIN&YT4oY8U;E~b8@T#pzdm!MRlq7jYp=ZLV(-W^gX(vmJu5zI<> zp(R&ostZ-8{w0~!azgiVitRLfd1WrnbP+Ugv2`xafAH9>wE5$iKbRM*hHfMQF+GdX z^p+0rjpa62)XOi&rudpqY4WB2?NQvDF7IM2_HSco7GA+Mkz%AsHKW~n%YgXIIeBiq zG*4|neg$*AGb}^lCW5eiabG}ubEc|7EaL`@K^-cu#tsM zhA-EnT6D2iED}U+P&_>QSBU{$AfAZ>hMnl;o zeZu4|XMFtF>xsB#$TkbTyltlReWUzipG;r}a;dLlH##kP)7JDd1d${LZn>EF>ByS} zi48!9xK0hH{bxXwh{q!Kd}$Fx9Qx)=h~l`8>tMD;n;y5er4{a#??o?pMlaKTxMaqExSiOVlf?=0mSe;gl0t5MN1JST*qhf( z7G^xgm{>D<-~WZ%H5q`GhiB@saC%xN3O|gRjQ;r%E6l7=^n6qvb=G9ycZEMFaA5!O zNQ*uXi5yK$xD|%ig~i{$O@-$in+~1@WZpUm|6Kwffi#5KU+nbZ+uBg4e$0(!+Na&+ z+lA`{!!RBR1*x;NclH+yaHuLCbZ}cZ#w$=DwT51Djh#3hom%$;8_TFAF7Mt)WTwT(3@^ew@u&EW z96+o47mTskD!~QsE{G7K*?}vteuUh%y#c6%#nV6o3S}@ueii5y z#`+ff4mso_%T!d!^og!V_xxh}vMUpNHJdl;)@?$#k54EFr=j)+$?DtQIBQ*}=BU>p zy=bhlWmODNCL2p{s9_($#|uf##(Y{d5$Xg3+PXOuMhJNQlJ>01MHKwxcjKkbMmZ7whuY(IO^R=~l&PZE(4!l=)CZy6B@f?eKR`9-F!adE|11IC^gZna$S ztT-H14(YmHmhp0Dhr{!|ZX#++RYyyGgu&0FsVZJM>x%9;2-d+m_qs|qA^!^e@YN=B zm$t^`#eD;?J`-Y14jWitX5IP=NT%?vr&>a?Dp8D5#`1y5r#<2t$RKgQge?(?95>0& zQV4{uALsv<3y0714@~zXj=lpVW4SHxW<2~gVq(RN$3n_!+Y#yWj|$c9Spl7RaC=2_ z?a*Df)KwWyOHHx+4}pEiOUBLN9~S?rkNgXlbqz_V!zQ#=g*@!y9FiHHJg4kl?pRjr zC7bac;!)t$2?ZPRUiBc#zl8CP{WigNRu5@2D$efz6*a`1k!%zZn&7wkH_rh=>@3{q zT1u7Om(uNQ$U4m!>VCCdtRNbfr8QpR@12t};vc}+!7k%va5p})pDSNj9UJH$nOBut zK&RCEXLXo=xa(O2-lEgTA^1hx{O(%sqG+`(w)X;?ff5Cw*nebcU&Zul>7?#Q-otDqa8NI`y=C2>|omjtDnMq%tE z_yIu(EL$!Y&#-e%4nSx9wKwJyepAZM!~6V(=RRI54zpaNO+NUYo?ac3cfBM|8Mlec zN?qN~as&wl>6gvrZyiT(h6~c*r6 zW}nmY1PwW8)!gtMuXoXFoxr0PWB2ut4zw!z-;}IlxcmQ4)`kDS$-1on4amA0r2h}H zj?er5ChHLX4_WuWgsi)M{eO^k`l!)o=@&!Vf644pA6T|vw#crR?1|8?*ZnRlAr?k4 zzq9j@3o8dJg(fG5Dio)WpA(KjK_a%hr0m&kaHt@EbV1@$iDQC=Iya#SHm*)?`F!mS zw%ca;Jk>v(1D9ByY}YM~_|S4?F6$QB9&VhMJ(u_lzk~D05j?TIzJv3+7zRaLGWCqO zM*^Tx5m;QI^WdUG?`mg6#jG%P`6*wJ^R%roaDJ<~KA) zv9Zj-K)%v~kWfC>y2ZUgaGJo`X$2mOqhGDq&ufQvbX&rEK4#haB1$bRyOa5TEe-rr z&bK!N@+!X7x2;@-Y#z6kZcqgx^q>U=>Yc6}Q5VpbmFb|?80t%Bju-vwG^SI;_ zfflX(pc<4I@iB+-lXdD1wRuVcEs#$5)OCyVFu?qCuIr%h(rx<9(Dj$D2q zdrJLky27+$YFFF|%~4H|*vY|BI}4q`(}4d4e(2nd@+2TL*6^q9f}DHiih`+(8okj1 ztvdVT`4Qk1hr6MbjVeQ%EZPK)MuhV7)9+t!_BmgsHQr5JdlcwO$^9Uo`%liQ>*}99 zDkJJ~M;zGK1D@dE)B@*$rF1XktWjwNSP!qR8M(d*x7&;Ljpd3#o$y?1( zo_`NddgXyY?Tbjddu)OraZwWY8K;?N42U@Db!a0OA`k@}!KvFYq&p7yjK}ITWbCy+HUJF+@P28IF$1_%T_rxp`R%$UCFE;TUg{DVirjezT7HAq?A38(%hLFM@ z)HqWa$y)Td3O|WA=a7QmN3a$WS655g77Vwn1lab@7wCP&?B%5r*35^|rK7Dbw7K@d z$qBKTf645f^u72({=ccu2TumgYPvpLKE;Xx|aY<_V^YC_#c@OA$SBOqq#f6jr$9mM}$&NM$sa2qKC=zRIj41$Q(EZKB5fQJoDgb>!672GjZS8@)pd;zTW?kXN59iQE^#SGN=HdQuO&R3Z^7y_ZOn4^ z`nd(y92~)>rX4j#6q17Ajk*I|vt69ca-?cgPuU4WF|>DCP-3ME zl@=<_IfDz_Ndt_iUK;PQT+u>?_N$GO5dfzXu?l3KMPXcyP-|@=$EcZ}B@x}S2Dn`p zRinMFS_kcT^F5t|hW&(f766&mR9U{LgXJgxiWA#-7VXYMK6eB7I%iioeKGHz1GHdS zK+rIRizHOMgR^O&>e=As`)R)c{+g_kPw3QF>mV9Gim)d`O{2#$Mo8zSzAm20M!z2? zo(q!ruHAUF3%!nDZF8KXY9<3@zeH)XH7dNjs0J|OM>qkg(?j3_w$AVCAn*qwagqZh z=a0~fMon>qlp|a^D8VN^P|xpRJcn)@mR#|SGXJlpsO&!_`IvILU9XofHQ-_J8$9k7 zIpPY4;1d>Tl7VFNOu6&Gfi_Ea5kS}C#P5?>)z|CRUnTZ{lPg41QaSKGvvDydhb<;+ zJSmb0bQ9k0KrVW0%REEBeOB=>)R#dpN6U60j%3gcRms}6oJ&TxD-;g!!s$ILb1?P? zr^JliKe`r4@&!^S%b})4zUl{T;EYh1MLoMs-pkH~!(k zX?S{%m7qHc7H8_4Tcp1}F)p?-9?7P#uDAK1&jq{J8c{A8%r^Qdq@TiE%=u+Vv*oMV zmLY_x548)#zRyfdH|q4(O`hTbg~PqQ(bQ0Wa!%p2{V3LhQV!qW+}*PElhi7(G`odA z++)`ku;jjnF-JqAnEL{t**R*hfjCy79DaxQ5MkEqV1yG!N`!Eaw`|xxXQxyP)F2}G zQfPFzJ(+N(;v7^@q<_UQRD56@m8rg5a??+~R7Z^{9N|SgkGkJ2?w_I8v5xFWrlD?X zIC5irZ4d2t(Wiv*G96k4DT;^<2Gse@cnM@7R@i4o)%XieghH~%-|bz`LwJw<^5*!p z=Ab>6rTu<=KQZ_u(3NhOIM~rOi#skMg$`SsPEr)OT{a79SJ{}h_JzCtLDAk`QW*lL zvo8XYJGfmMw{J#vViL2?b@_Oy3Sg^^b}O(3W|9{pG|A4`;8?};1^3o+;`i-bWq(B+Z&2WTT@d?LhOHK0sp z5ektsf^cKV8Ri9dN*FhLQD(h#jc(m#aGXCq7OQS~eT2U~Bu{eau6BQhJS=c98GhDh z_!xSzWy4t_e*)9F=F-?q-wv8jmrilVcCB+uCEoF`YP3Jv5_ym_ajYlhT!$gAJ$<%c zvVER*PrkE_M;v%J9<4hp#Q_T-#2%%3zngTlB2Y?W0h4#hry2SR2pXoblJTiiZ6nde zQSXNJ)fE$7VJk+0DTQxGK?ZT{N|`*1$dLid#Y!Sf%nVFvE@4%)GL@Stcg?yM!IQ1B zgD2R|or$<*hd>2As+zf8ATN37^C8pxWaKo_AAl=2(gM|;L-fyQs z)32CyXQpR#CQG=_g|68){B_JlFMX?z-dkxHm?fyOCAS zi{fUJPiO8i+%jW|r?YK{399vtU7QqWgb|@QkzO;$rq9Mq9^`2G57lRuVdBH_aqTdk z7z5@5fkRv{63u+98m~#O^OWFod9m6Z;hOO1WMe9$P+WMP!~wE2CI2qN1usj|z4XrP zpFiWd{hKM=Nh1V#1Ek3t(Q;gxqdQmHZU&v(bmE&oimhFMOME9U8$6eJvA1ir1q3MR zNo*Ob2tmKDZBh%Ho!1GK1M0}92o)49yB~z?cFoHC>y#4ZPMvv&g45T<*GX4nWG8$D zHf-)-f59*e#3siH=yJ`#=_E<8=0>%a6$NDM3)y?<(|f;M6;Yi%^)LLJgx+FnQa!F6aB($+~jss`NLtOz~I~c=)ZMCY>+ck;xQK*2C9u z*Yu#}KJk2%p3%5K&YR-CTEl2ArgpT58oHNTd$k6s`|^P9V|ud?!`aRL;!XZ^YV&FP zw?u!01)s4kU1=XBtD_3wcRT4!L{~-FVS{%xER-@_pDQ7w97%+N;uc5fd0*H9%ygQ27_37N+VUq#GaFg;6NNw>5y%i@e&4HO94 zSRl^w%h=mWsBog$3~n7(=f6Vlq!t%SFrFD+TFH+}U6KqFKQq{>wlvW`p5^XxV`ms; zHhzpWR!2b7;dr5G?;tGdh!Pb~7v2Do-il`3wxn3%?Lsj^W@B)~<_HXG_0`KtE;6cR zP6fQa?|O&4;)3`0aZGo`I39xq@37NP-B1CNH>;;(wC_kKOwHvdXAFDt9qwcC?A1#r zOL4$zIk+91uOFu*oGnq;D8AZG-LnvL=1}33=9aaAV@4ms(R4@K+t|qjJj+9hXh}BM zyWk0gkDju7vVqiG0MfzPwvz$LWdi7~hJuGtEw*s+IgP>b5zI%(s%BV$8cy&kB==(( zjgF+BYy%9Qkv-n=E(^d|cH0vd8Pna$1j>NcHV*_BKs}9Vk1G1uP0cO~7~iA65>aik64T{K7N}@;{CgD7aFI3tQXu6)>CAsJ`ze_z*LH87 zDR+vWF|Y1w-d%sxp6BZJUm1Spe`P>Q=by<0gFG1m4;t+q;|Gk|_e%$BV@M^i#WIzF zdSg5IP!*eD>RsehVY~Y-b+XlrgRDdcwrg!JvIK+=P(n+-Ydyrj29Gm0SNg`%Tq}X|nLJN+V@9 z8AVyfp#RTukCWl0@7Is@AR;8QTS%oncT0^r;NW=6I^RHQ;|LdBG5LQmbPFCIM$PDE zaVBl3K2G0?#_x diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case1_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case1_trace.json.gz deleted file mode 100644 index 4e5615f94ade0db5a719d5fa9605dc9a1b54eb63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39157 zcmV)pK%2iGiwFqSY~)P<17mM(aB^jHb7^mGUt?i&WielLa$#d-E^2dcZUF3ETW=%B znSIZ%5cIgv&~?A~&2gMXu(o5&*w}|fU{F$z#SA4XBxPq3?0?_ye8o#OyV%tvMUBQ- zk43WYRn^t!eE0tMA1*E~ALoN@KORDw?ab!;%hJH3UDqE&2H#U-aK)cEpb#A5#Oq`|5}F`tfqv z+&?Z`*QeFf+0A%4nLS|j!_#znwccvX}=bBv&+0$JWZE; zmUlmW{q;BR-fa(mKY5re?mEXuE&XPnRl8S%uv+RFho8mv{5RCQ5APnQlXbVXh~nxZ zxYeJn{l56y_FRuoKP|?;G^;a7PdiBOHy?u+vvdA>-`xM#^~dGk=-Xz@+h}$vdPKTA{5L(y%Z8`2 z$mZCzX&qkJlpW}VG1i35KJ?iB<>B#Z`L?;4&2M?Ij8M_%JN)%&NqhWpJ(x5U)@>f) ze3!i^xtZNxPac}xD~aqWx_!Dy+y8SudwN{#3{ti|JHE5SyL1yaP3`Q^X=i?q9w*aj zbK5r(+<@%tyy<_}vta-8u2yFuKyKbQb85@CD_rW})%asGU#+}cq0;45f-84<@warv zt6>NDLl01!12%mE-o9IomrsiV#$8TY1JatgX+dkO`5{v9578eA8p5_1D`p53?9yS52uRh|{A&b3iVzgp5 z!Mp;SNT--h1U+xy!Vqa$d(Z~h#5<+HCe8#8HnBtlU=yQ=kBLpR2nuXM8#~;Wjs-IDWC!rg_-1&2*^?j-eSb&B01Aq0Ci90FhXSuyQVlD-lAq+W<&~Y0IFeVad=_3gzoueO=atROE%3@_Gz+}4os}hCp(BU! ziaV57^vm%|tn-S~*@QiYSGG^~fxMzCyu$d)0)ECHdw=&SEfy+>+xM}5YcH?pWM0xz z3Gj*xtPB|HreR*uF7b+l#$^mC7f`RHb%F`NXy_WmD*|RI(s^hNctzM);}r`glF>p7 z(aL(}6~~HQaIl1V=|IZCFt!z)g9ciDTA&zD!)BXKmZtl{n?UOB;_HSmCVGOuiBZi!dcqgk?mZDwVWSF9Pv zD?V%XAYL&q$19=AD_(?b!XCpbTWRk=UNJ-Tm9WDhVc)tJ=M^G8=9T20@aQ3UMJcEX znluLRhz`OzHipFz&>s?4B3vvXXkoxB-X>$1^Kg;)Xrqxe*9xvk!^#)X7J3gc2wTR4 zLDRjCLc_H}DmlAWJo}1Bi2>&kni4gEP>Ax9YsD&iHew+HJsYu*R8t`q8lI{lOcZQo zdr$J&63fm=97`oBNks* zSVTTy4<{C*+_A)BYYGble6jkI+3(_VAF%*UiywC1hP1U`VPUm_@Z4BdScoE6VNrq= z7Ge(IzW2tlA9xAW)C8l z@N(p$29S%-ChQSfi#=Lv2{o++;42}D?|c{6^?6ws{g3$QB^S?uV1k~sq_so?UBZxD z2N%B75?T!*w*z?)qAMm#SiL|lG<+Z#=SZi36^te_Kt2eXc$I)KY1pAdDhRGj>I&4M z7&NpYNml{6ktX7p{DNX_NRfg9JDJiUCUWrtq^F|g&T6HJXU;_~L}cgFT)eTagP3iH zscfk>CCvruTR*wvC;4p2WoIOg)m+@OXf7vk#fzE5wllZn!k2C3B-dQFv$E*Imv#WT z1if})4<{G*a^zBtHm3HUb%rmglfoGIRp<>a&d!(gT?rbi7iAe6V@eH)b3eOb$ zD!WQd&GnL>EW4C0crTZmi` zxyU&=aC;DgcqkJ@F05n_xd_MPqP^j)7Gi@$E<{IcA@jcC(uai%r<4k6k_(RG!JITH z4w;5IS;(SD7BY+x?J8haQ(9XnO|X!8!xl1QQXF!W=kx1}%=P}<dVFu&m}t?~>+Xph#$VH$0OI z2mKPcSdb5q3o`Vexd_B^5xIDd99GguPI95qid74l6tIwSB!L$KzNi?4PZlzf+%HBl z>CybuhAm_Wae;-5En>>i-GJs2VQ7PeOeuXf_lrA|PhWrYX;hw=&GbWADGC)1_uH(8qL-Ccky0@JtUmm(Mc;C&?=X}~Q0zA! z!xoL~P3pIbBbkMDj@1k}W57_(!dIfDi*T*z;0@FfV|~DWmc}lEsUmHF+UBARoQ5A+ zZ3%RiTBZ!$K32RWQ;}Oa{yqEog-yJuJ=3B@)SDF%Aq2Dq);DM1cDwMBGk1KDreadt zAd@p$(#tMKZTIrBpz3t_rbJYV_?#$yKV6yVyv<_pOQdB<_LM<)khqNFUB)VHEFXIu zQPDs}SK1{zg(e-^?(DNmS0<8t8T8Ixo%Xg*)upZW_G4))3LV$t{yy3|h9p{@?2ts( z_Fa-_O{FeL@R7qbkl}8Wd0%e*x#0fXN=Q^uZt3DcxbIJ|_cF5kSk^vBsD>tjYANfF z9=OL5oe$MnCsPF1`mawNvC1&mTdy43j+ErwbwY1|s3G+va$2Wzn%y1JKn)vh@Ot;=JKJeq59k7WnMxD@7JWY7v$Q zJ>x*I_eSqmNVa=VxJi7z1;=!F4$|iO9)-C zcUCyHvsVG^^HY_;KHq*c*eet+ItSQioh*R;rtMv@&!$od?CHp1V1KY|Uru{J7ueS` z6oWdcmP!onXt1wjzK6(pcrcr=;5zh|(s4i7YfeY!l=1X2aIq!yc4d3XeraKiNbKVr zyEbgpj%E841WXb!P}x}LA@jr71c!u;o`Zg~6~jI9jOuV7cJ}GQy|qH`l0p&gv)fjL`)BZXkOY1nxX(ISg!?_- zh1OIm!~H<-g3g*f2=2?-=;wm_dZCjOWqYCg;oj@@Q1runM2KoC0d>fS)P2r|BTYG4 z_nUG!YmeYw1kS0j(y+6^D#5sG73?QESPd<}SPVSi-Xc=|0y24IxVIM4xkrp6qp^=PV`-NhjFgYNVtWVeLqx%YD%!VBRY3dJ z_7f~Q8+*&MqJ7@UF4}L~-bMRtDizQkM-D^#;pKPdeL3RiLi>7}cu=RrDgo`cQ~p4- zucV2yT|*&iR3#AG`L$<*)V>Gpj}`81zi`jxqa;eKaXl=UF&OP_N*T9~DT5?x*vU~U z1TJLa0IsuWW3uTuN5Ve~_s)U0f^a@mY&jY+*%vVi4(YY*FVM+tu&S%&xEDr6^n+Lh zOT;EvqN{+7Xr!^^Ej_2tEZd7h@!g?lZ(`7WXdh{uGc)rZ*8|c2Fm|X;nNTcxXKo6||3Rh~N*q`L(miQKg(e0C{%(@f>!0w!w2OC;ocv_DnSd z=^P?T5YClrHA(8QlNe83*07+HK#k`45V>4oNVRM^7DKMS)$VdX))VG(z>wuk5D`&t zO2NXxUpj<~K{6ZRE>z1xN8F4#v=6YWX0lzNEWK0j3n>|;R>I>K(RYOzJffPJfz1+b4| zuV|l5r4rcFk;A}#cv-=DU#{D^z`mYK9dte;k8#o-ZOG|QcO&o#!@%A^e&&jLjze3F z=mUGkaI^W?SzND^sqQQbl>e9E{U9NyV=VjwYs8oCkD6b>Ok!s8FK1h)U%158-Od$p~M2o6fQ5d)vqSTy> ztyCNuk>gEPR=dwhdqPA`3^vOZGx1B73z1dTnyfu}IU~dN0CJ)M+gClav31^=w025s}DYv;5 z_H`iG_vf5BBph78qd4fVC+JdhUDx7=-M1lat=Mj4vfZSdGs{($l(B|wHYDhC&RMV= z4QZ^6iVJ7BlyerHg71{Tm*0WmwKJdyR0q^Gh}WF5OhXD!u;da=S{Tlwj!conK9bEf zHkB0Q@KjHC3*@3KhvT5=A1px84UNNbEi1rY}%-B)p$YV$F0 z(f6C>6-WCB8&>buGi>HDUZB02R=`xFLr@I1HX!Vepgn5N{9-ZmieGq#ID2m-J8=n; zy{=SpH4arKP#Gx|pMa%`#C2Hxjbby7mF(F?@)uW4Vk^Cm&a)6N_%%quC~m*^v6AVv z70mNup!>yl=S~Tz2Uqop@78!(6W{5%)~{K7_i9(@E(Fx;x?w&9=XXu~rGR?fZpo?Zb=S&HGY%KUL5Tust{E9fR$M7gb#k zMGf0MV|dU1%CiS0%tvE4e3r?j5U^1-sO43{gie-U;gO>(*VM zOf#ooyR78KvfRFr(#t>kv0d`prq$+S;9@nLMy*UTA(>>jHYj1ch{+_A-oRjkNWqhl zUuw-2s*_0umVKCH0@pHi{E}*ZVMC=*HqU3|2Oun73A}bV&#Rmov8al^knFdm2Yi7#l?D-=*hg3h3Lt!KUO}QN~P$@FeFw!lX-_j`|HYs zMHfy;jWV|N>W%}Uz4DrA6Voe_w;y)sVh`N29i#YR_iad9d*NQQt8-ONO_BhsxaBwUCzIj3XeR;N>|M9q=YOVS|LaTeHAx7Uc!&4$`srS#Wc7 z6kKD@JB0CAw|e)2P#hQU5G79%4!pimq880Xj9v^6mX8B6VYjcKI!2P0c<*VSB(H+4 zO7cP~`I;kYTpS?Dhh0kOO7b@58Nd4_`Rr6hNj{wXiZ_75T0MDYNj~djNsf_pQ5fPeV-E0<4vyGA6ELU!Zw=gVgjA{Pt|_+ zG0au^GgkwC_m+FJ$-t6of=U{_WFS%^8Hl7x1|p%^K!nUe$n`W&*+4{OlL}RPcF&?r zG?Wb=X|7fbM9QPSTTnKciMZNaoL>x|HyyUga4y zx90BQcwDyZeEsb=UwwZLM6SsH)CVI^KxDj%K6}r{fr#91+EIqH{26mfzxHqF39yu_ z7GJk|lnjfWdeZTI3K-kN6Li;*_wmSZUztL7ivgIUYvIROeZE z)MNI6#FR?Rjl%1)FFf9&i%5FqSLs@uK?bKQ*Ot8Ew>ooNJ--IWD2t#TLhs}t=Hy!I zojOl-=l{p%&l8)u0_0jye%08#lGXn{yZ&K5du-;*Njh$Y*wp_tfFs&t^mI)-P-{oc z!}xldaPs|lx@gvoZSB6Ck8eIS^U?kIpR}Hy{Mr2D=>D3Iq9=Zn|2mnC__-X>?EHrRtvfW;$semZPLyj4-`N^M(L#3+k6!dPs+j{_)g2HKW_+{g{AxG`^X> z8QUQWKQ!}q%?O|g{&}(Ye$cc2IBjqXMvt@UwAJ0co!!nTnk4hBT6ZaHGb*j@ zom7kFAKW_tE*&)IsXv|2tXb{dDxbR0X)qU)f31ejaJ{sH%LeH#JhUw*-oh4?ZECHTI6@$2Ma{Bc=6#p1EKd79D`|Fy|~-;5vAR2<2C zT0D>x^Dw)`l%F=g@Po0M9rNa)`Rz^X?oc0FBSAf*Ytw|iZT`74ZB@vIE8X}vzY(uA zZys@HmT$JBM@p32GjzBs^t6+hM5k_O1Znwpxz^s>h|=oK-E#RzPwwsiwfCk?avVpt z=y&}J7)>AU8v_clFEYDkqDXPX8B*jWDBVR@Mk{m|fEIe2>TVF=nEw0oB`YhkGBP5w zs*Rr1FK-A6N{`3a zx8Kqz+&)yB4K&N(-G;~G_RZDXr#0V;53BV<3s%V`-32n8UWUu%*e+G_F|RA zB$V`KpSI>t7Oz%dTi}Y|-DfA`E80@|(D6NE*Uj=4>t0HPjd54-+vWZJ_DRcv zJiL7e1{(35P~-OL28_l1`tB_r(L+1M`E2VXG`oTE^8}#uX|a5IdA~#i#Z9 z?(O1w^;p;zs^_~GIDMYF)io9pa(Cy=%PmunaDHbWX6z!xwiUeq1H-3JMd z@p`qoMKYXmx59Ue!`VngEypSZi%e*>GfbKw2QxHsEK zp5gp;d3*13rlOPWC#|*k z_tmFAFR!0gKLRS!M0?13<_$x8hKrQc`|KsJ_p({+<>lRNI(7kdDi2|cOMj$4uXNwJ z+a4NPz3zBZ!VKIa^z&)_(Q-o$e>%(ntM1;Qr-$>&_2cW+^0D`nfydq)FJ9T@2XLs{ z`FY;r6(Q{%JeWJvuW$TIyqx|Fad+VNd=$Q~Z`W6sFU8Bt)rV%X^zsv& z-|hRK$mFknLVSJsZsSLmFDxL@3Xe1cEA9{+QEoF39~(|WHkWL7va|MUP87Q*-Cu>HjA~EC^GJ{D*g?x^7=RnfBSHQ zJi?Z1%(JHL7~ng$GZJ7B^hd$~JG^lStxJYX&oLPCm{ZT-Uw^r}Cv*IKya(}ogmteh zGisl|`#)Frs^crbuk=*xPO+s1i;|hs)6H2XL5>Yv=VTpbS{N-l70nVI;{_1gg zb^8WM?T;gzk1^id<5q9{#dkk^x!K73((^PXM)Yv8zPbl*dD%?5C&D;y>?hjVFsdv+ zb|!VL{d@fhC;N*JI344kUV~$Ifu6zL-TNzWsqSvzLZ&A>;vr6`f&%BUTo1D69WoEl zD80Cw=d^3FnlU%bGe79k!$>24JCEJVLEZtZ2RPl!r>e{L1%3;sieB5Rc9p_hf0zH< z@z4=~D7d{dNr=-pfF2<|=xN>WdIyCV*7e=bh_yS0ZP6#|Iv&T+iCP^zybaFMacPKPiyeA`#O4={(7b?BU^?eJ13%Uf&r)_qW-b*~akT z=Miyfj!5@#W6&e*j^hEtP19PY&pI%vvYV%q$VMd1Ktytwb=h1~JoDeYe3{N9KP=ZT z+XXWY8WN8P?1N7qomzu`w9o>#+qu7uHsazP+`R=3)9tgSm3JY<{V8mH>&y-jWSb}{ zjz2i}M~Y)yJzl}1_six{`yE@N&%p$IMT>mBT_QV5Ii|e$aCiL#?ms-^fTYXEW~SX4 z*iSbYi-UFeC+~}+o@Vc~q|e5M&=mzV;i<>g+sIM2o7poCIJkFjTlv%W_?R%M8(Cfi zZ*Y!>;9rybJrww&X*q_R*5oq1NW3MO|L^Dn*uA^H1M`?HXM*(|+y8)gRCtalBJu}Z zs!FjAIW9Gln9+Vanx(M`hmOZL=(LgfX@)LtAmh*Hr{=q{(+!m*1{jeJ!^1=jhW&Q1 zr+?!%GA0<@cU`meE{P*`hw?207?0T8%(!t!F5X>T!@PU>VY#^5T=XW|_w2?0y7}mg zxOw*COIqM|g(NTP+`j()gL(A`XY=28r@x&@U;|b*Pb4IAfsz?x7pD|+czV3LUi^=z ztBd!q(9)z+|N3LqIi%NcN>BNKxD~R??R1!#35Js0c-+Dc6_cLLJCruGGmx97HT*Z| z+<<+r@X&PapX|M3$AtN07WW12Sk7Qq8N_A7X9E+2|F*u06)|L-ks@EKi(=Y)UhSBk#U=~srnvgucjzVhi;fxe3TO?To4pz=e) zAm$Y@aLGtlxs_EQIk07>nn2nWc!%KB5?sS6y}HIX|{x2+&H z*$<-r4GdzOWZXSu1upNaVisKD-|rr7?jB0sUH9bEAr`|zYQF%#a-sHN(o%J!+l{~s z#0oohk^(X5)vpM6==U$tA-j701oMr`O(+E$dV!|?)3T92;MgTONjmx~^73JB)DCi^ ztv9}YkK)~FG3a3}+vTV!C64<^QG+2Smp^Q*^@h~@iND@#=5MRV$4{Gp-rbhCgQ>vd z>*c2f|9%U0`qk86`cjv zZ@{R#yt~;zE6x9>2b}qkU+~eq5DTRi;>D{!e*XQdKYaJ&OH|3f-0bOl6b&si_M)re z$s*|E;}Cvs3{HFKoE}mH%W@mx;@+8ipN#QR>iaVP+C%nG06Xpc@KSG=Zls z(Nw;}L=m=waA&TZ_?-YOkE|)71$Uxg-Q_#6vY#IBeq!+vuJ^;AzWM!c{-S>KYx&z> zi@*N2#lQUa%U6ppzWd?(1wJP5?%V(8;pJ}^|MK!>GuMLu@j7ykb=v*>yn2wxF&CT&)wpt&v~z3{{E}a|Mbm|=`%8Zvf8p! zd$Cf0usZ^wX54=DD$jfjAP6g4HlolbGjHQqBrw6x^XQYy$E$I%f5AgScR4w9&JjwO z#=MxQ^-w1Ho{1EFB&$9stHX#~Ax&$DH{H$rL1L?ug!T9Co*NH^(oK;gX{ZGB)1UwN z&F4EvgOmk}yauw`z_QESOdz%06DY%)Dq~BC{_dOazWDcqMuUq_fue2Zb)IJ2ECa4w4 z=+E${F3aG#$tICuqh-Qr8bA5bZ$2RX!jgzP#8D ziJnA&)4w}%zMNZsLwRh2baHP-$0++xK&IZ-yqRWJhwG=FV{w>l=;?u>*Dn0(-Rk<9 z*y%srUVY@k5Ia0|hrk)gQXGy zVs`_h(ai+#*Za!!DSX1n)RqVsq|x85ZUOHv?(PW{?w4ykJ~+rB_3~f< zHjTV?ef}-c|FC*|LceXbynVW-RJ(!wY)Q(eMUybU(Ezu~{I0(=HI;HhU34^M;zefZ zJUK+~$Hl%{u8r1t3D@}X#mx&s`^DQ|p6|P|JY;2c$jbVVmCYe5+e21%hpg-mSvefC za)gzOpwy3P*t{FD0T>dyP6{V!Tsp!gYM69yztS4Hm>-E!a z&a>@WuOdmxqF@}yBvTv`p7nLNH+Pp;Z$9;vw?o11_N#78ZI^TGIrg~0Il1{e{1wde`yPPZeN^LEP>0Yl-6De?SeJlTkLw+ECh3=W}z4Tr8eCr*2`Ngo3>Lfk=?C7 zw`oe<#&G|&`)147fvmqj?Ki!AcedYF$A!mXcTrq;#i6htcqQ8Ng8DWkyPvkUJZR_#^4jL0m5aMJs=W4LE0@-ex-wGSK`R$`Z7SEyAGC5| z*G9<7H46u=T;8=VuN@Csx!Ls~-bn(y#vpN)&wm-C|Jwa__dQ>Q{if{*!6o}g=)6^? ze@tGs{Z4B3a=Yk0_OiZq!CsD7xv*=DlLRKMEHWZ8O-gU3_ak6+QQF|Ph2iWq*pdxcoetmt2!$%WXp{;=d%>t(Bv z1E8hfHy3DAo1ecWwu|PyDa-I#!(YJGzWp7Yi%h@fi`4lAX3*`zo9Q-umo5ok|LX5_ zF+aOsU)^C`m3I8c?|%69^KaUTc+=-2mk-9oCsB#C46`}^v253E+m*Z`brM|S|9Q8* z{DNq=&4nD-7YqBz$c+W8^W?9;*O0z5{srh3t)Im~sYNM_N_Gf{ciwz*bN5gI~K866>j!I%v zb+knub|Iys-Y*i{d*NS$%fVT4khUW_{pS|qlv zQQhvmy#^@VjqKNU@gLr(rFSLvY1V>I{)Y4!Y}T?xuH~mj4fGe3fYbj!d(OaRKYRAq zp7}1Vpr@|j+ZFa|AJZARy&f{j)!c0((;1chUNW@iuWGHnuyJ*8$zhK&G5J#gO$>nO)HYw+>rig zhOTsGHJ6OUxiflIOPT()B73b;kh0i2* zA)CpXc#qAD%hn{0uqLLz$lyl)d96u2f;F*X)64HLYoewa2lo%KChf@0S(7+uO_EWW zwI*?-HSx(|kFqA_bk-!+tw{{YfSqnlq}V>$6RnAd8G##Ty`=Oo0`39JBO*0)SXe$;w_(mfP^|K5#O~TH?K2YypV`x4nBko%|r^9S> z6Yx=H>Ko~lvr)w!M0TECX)~sxV@)g=@QO7_H}X$wO?Ixtp4J3hl4DpCKh-!)Hb3!T zYqA}=8EevB&Av5BMrF>Lz?$Q%Nk|TRlr>SOvnGCoH94RKG4)}d+7y0!9V*rY(H$__ zC9gXl-O1-B+Osv0Dp2R)Kockfuuh$a!7L!*<-u4)>O35HZepDwqRZ$=@ULNtfYt=A zzCt@7z`&HP30MP3-QFekGC$lyl)c`ZsjxHU165Vh9Cb5A!$ zu3!(JpR^-4XHnV~&3(3OJ1VmlC3d9_gBB$whds)o*wa~*P_-yZq~XTN7R5xjcR4MZqZqMp1&Lsfxp> z3rtlU5mmvF5dup>QyQ46I3%fHs^WsE85bD3Xk09DU6JN0FeAdo_EI&+Wnn6V*9dF} z8Z#xlm3UGbJTN?A82>oMqDTrweS!>jw&{vdvxQQ;$9Y)MxM*d#<;XsGe>^4qcUe)V9im+rL|t8jf*~=aj_$e zOFCfpn6B(ke(9QVLGC6b|9t6l$+)1)u6+A4`eV_!7*7!ka8Z~C)6S7`(KyWl`uA$ozN9vByaT$HmWM&iMAMB@aDhv2Hl#j$aTWLz|w!srD@PK+n6%PKZ9 zK`4x*0C+}R35<)w{V4}C9GtmCNi!!fE?xfZxW*-_`DQLr8Qnw7E{|)>A zgB$s$H7+|>V&9od>y)3C3!7|>j$mBck(-OGY_4Wz=CU1?*~p4@GZ`0mI^&}1#zh`9 zb0JcHPvhb$#)Uu;|M})`@qNj-gy)-=_LT$z@Wg3j7vazN+avU zGZ&a!pm7O8lX3AFW^=F}USA}NFVGVSqjzy+uIQ1Eyz zL6WJA+AET(IYo9D)})CatcofD3F`_!n_bb;_ZK+Qqy=1?ivCNwDkBzbP5+f{|BX`V=QeH`?QSM_b)N7QZH5)7_4O)LWG5OKZ|B+pkO&U1XUB3A4Q?20sN0o7&N8PYh2=sEobWne)_ zJg8`#Cs9~bs2Bq)5->J{ks8O*n5gly^Cr$WVUf=C7dX;{1>>w0B1~o!U%L~QnkX#Y z$Um)N*|`#Xhw%R~6PC$_

j&cI4)Wu+7!XOjx#~GE0O>InJ=?mUueDGDZ}Z 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 diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case2_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case2_trace.json.gz deleted file mode 100644 index faba98bcdf1956c393cd68b49caa565ef45d7b62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39686 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 diff --git a/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case3_trace.json.gz b/hadoop-mapreduce-project/src/contrib/gridmix/src/test/system/resources/compression_case3_trace.json.gz deleted file mode 100644 index 5adbf43b0576f7da4277d3458430533c1999cb85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29064 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

l?(424KVfh>l-Bt=b!&@K#Q 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