001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.action.hadoop; 020 021import java.io.IOException; 022import java.net.URI; 023import java.net.URISyntaxException; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.fs.FileStatus; 027import org.apache.hadoop.fs.FileSystem; 028import org.apache.hadoop.fs.Path; 029import org.apache.hadoop.fs.PathFilter; 030import org.apache.oozie.DagELFunctions; 031import org.apache.oozie.action.ActionExecutorException; 032import org.apache.oozie.client.WorkflowJob; 033import org.apache.oozie.service.ConfigurationService; 034import org.apache.oozie.service.HadoopAccessorException; 035import org.apache.oozie.service.Services; 036import org.apache.oozie.service.HadoopAccessorService; 037 038/** 039 * EL function for fs action executor. 040 */ 041public class FsELFunctions { 042 043 private static FileSystem getFileSystem(URI uri) throws HadoopAccessorException { 044 WorkflowJob workflow = DagELFunctions.getWorkflow(); 045 String user = workflow.getUser(); 046 HadoopAccessorService has = Services.get().get(HadoopAccessorService.class); 047 Configuration conf = has.createConfiguration(uri.getAuthority()); 048 return has.createFileSystem(user, uri, conf); 049 } 050 051 /** 052 * Get file status. 053 * 054 * @param pathUri fs path uri 055 * @return file status 056 * @throws URISyntaxException 057 * @throws IOException 058 * @throws Exception 059 */ 060 private static FileStatus getFileStatus(String pathUri) throws Exception { 061 URI uri = new URI(pathUri); 062 String path = uri.getPath(); 063 FileSystem fs = getFileSystem(uri); 064 Path p = new Path(path); 065 return fs.exists(p) ? fs.getFileStatus(p) : null; 066 } 067 068 /** 069 * Return if a path exists. 070 * 071 * @param pathUri file system path uri. 072 * @return <code>true</code> if the path exists, <code>false</code> if it does not. 073 * @throws Exception 074 */ 075 public static boolean fs_exists(String pathUri) throws Exception { 076 Path path = new Path(pathUri); 077 FileSystem fs = getFileSystem(path.toUri()); 078 FileStatus[] pathArr; 079 try { 080 pathArr = fs.globStatus(path, new FSPathFilter()); 081 } 082 catch (ReachingGlobMaxException e) { 083 throw new ActionExecutorException(ActionExecutorException.ErrorType.ERROR, "FS013", 084 "too many globbed files/dirs to do FS operation"); 085 } 086 return (pathArr != null && pathArr.length > 0); 087 } 088 089 /** 090 * Return if a path is a directory. 091 * 092 * @param pathUri fs path uri. 093 * @return <code>true</code> if the path exists and it is a directory, <code>false</code> otherwise. 094 * @throws Exception 095 */ 096 public static boolean fs_isDir(String pathUri) throws Exception { 097 boolean isDir = false; 098 FileStatus fileStatus = getFileStatus(pathUri); 099 if (fileStatus != null) { 100 isDir = fileStatus.isDirectory(); 101 } 102 return isDir; 103 } 104 105 /** 106 * Return the len of a file. 107 * 108 * @param pathUri file system path uri. 109 * @return the file len in bytes, -1 if the file does not exist or if it is a directory. 110 * @throws Exception 111 */ 112 public static long fs_fileSize(String pathUri) throws Exception { 113 long len = -1; 114 FileStatus fileStatus = getFileStatus(pathUri); 115 if (fileStatus != null) { 116 len = fileStatus.getLen(); 117 } 118 return len; 119 } 120 121 /** 122 * Return the size of all files in the directory, it is not recursive. 123 * 124 * @param pathUri file system path uri. 125 * @return the size of all files in the directory, -1 if the directory does not exist or if it is a file. 126 * @throws Exception 127 */ 128 public static long fs_dirSize(String pathUri) throws Exception { 129 URI uri = new URI(pathUri); 130 String path = uri.getPath(); 131 long size = -1; 132 try { 133 FileSystem fs = getFileSystem(uri); 134 Path p = new Path(path); 135 if (fs.exists(p) && !fs.isFile(p)) { 136 FileStatus[] stati = fs.listStatus(p); 137 size = 0; 138 if (stati != null) { 139 for (FileStatus status : stati) { 140 if (!status.isDirectory()) { 141 size += status.getLen(); 142 } 143 } 144 } 145 } 146 } 147 catch (Exception ex) { 148 throw new RuntimeException(ex); 149 } 150 return size; 151 } 152 153 /** 154 * Return the file block size in bytes. 155 * 156 * @param pathUri file system path uri. 157 * @return the block size of the file in bytes, -1 if the file does not exist or if it is a directory. 158 * @throws Exception 159 */ 160 public static long fs_blockSize(String pathUri) throws Exception { 161 long blockSize = -1; 162 FileStatus fileStatus = getFileStatus(pathUri); 163 if (fileStatus != null) { 164 blockSize = fileStatus.getBlockSize(); 165 } 166 return blockSize; 167 } 168 169 static class FSPathFilter implements PathFilter { 170 int count = 0; 171 int globMax = Integer.MAX_VALUE; 172 public FSPathFilter() { 173 globMax = ConfigurationService.getInt(LauncherAMUtils.CONF_OOZIE_ACTION_FS_GLOB_MAX); 174 } 175 @Override 176 public boolean accept(Path p) { 177 count++; 178 if(count > globMax) { 179 throw new ReachingGlobMaxException(); 180 } 181 return true; 182 } 183 } 184 185 /** 186 * ReachingGlobMaxException thrown when globbed file count exceeds the limit 187 */ 188 static class ReachingGlobMaxException extends RuntimeException { 189 } 190 191}