| /** |
| * 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.tools; |
| |
| import java.io.IOException; |
| import java.util.EnumSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.apache.commons.lang.WordUtils; |
| import org.apache.hadoop.classification.InterfaceAudience; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.conf.Configured; |
| import org.apache.hadoop.fs.CacheFlag; |
| import org.apache.hadoop.fs.Path; |
| import org.apache.hadoop.fs.RemoteIterator; |
| import org.apache.hadoop.fs.permission.FsPermission; |
| import org.apache.hadoop.hdfs.DFSUtil; |
| import org.apache.hadoop.hdfs.DistributedFileSystem; |
| import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry; |
| import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo; |
| import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo.Expiration; |
| import org.apache.hadoop.hdfs.protocol.CacheDirectiveStats; |
| import org.apache.hadoop.hdfs.protocol.CachePoolEntry; |
| import org.apache.hadoop.hdfs.protocol.CachePoolInfo; |
| import org.apache.hadoop.hdfs.protocol.CachePoolStats; |
| import org.apache.hadoop.tools.TableListing; |
| import org.apache.hadoop.tools.TableListing.Justification; |
| import org.apache.hadoop.util.StringUtils; |
| import org.apache.hadoop.util.Tool; |
| |
| import com.google.common.base.Joiner; |
| import org.apache.hadoop.util.ToolRunner; |
| |
| /** |
| * This class implements command-line operations on the HDFS Cache. |
| */ |
| @InterfaceAudience.Private |
| public class CacheAdmin extends Configured implements Tool { |
| |
| public CacheAdmin() { |
| this(null); |
| } |
| |
| public CacheAdmin(Configuration conf) { |
| super(conf); |
| } |
| |
| @Override |
| public int run(String[] args) throws IOException { |
| if (args.length == 0) { |
| AdminHelper.printUsage(false, "cacheadmin", COMMANDS); |
| ToolRunner.printGenericCommandUsage(System.err); |
| return 1; |
| } |
| AdminHelper.Command command = AdminHelper.determineCommand(args[0], |
| COMMANDS); |
| if (command == null) { |
| System.err.println("Can't understand command '" + args[0] + "'"); |
| if (!args[0].startsWith("-")) { |
| System.err.println("Command names must start with dashes."); |
| } |
| AdminHelper.printUsage(false, "cacheadmin", COMMANDS); |
| ToolRunner.printGenericCommandUsage(System.err); |
| return 1; |
| } |
| List<String> argsList = new LinkedList<String>(); |
| for (int j = 1; j < args.length; j++) { |
| argsList.add(args[j]); |
| } |
| try { |
| return command.run(getConf(), argsList); |
| } catch (IllegalArgumentException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return -1; |
| } |
| } |
| |
| public static void main(String[] argsArray) throws Exception { |
| CacheAdmin cacheAdmin = new CacheAdmin(new Configuration()); |
| int res = ToolRunner.run(cacheAdmin, argsArray); |
| System.exit(res); |
| } |
| |
| private static CacheDirectiveInfo.Expiration parseExpirationString(String ttlString) |
| throws IOException { |
| CacheDirectiveInfo.Expiration ex = null; |
| if (ttlString != null) { |
| if (ttlString.equalsIgnoreCase("never")) { |
| ex = CacheDirectiveInfo.Expiration.NEVER; |
| } else { |
| long ttl = DFSUtil.parseRelativeTime(ttlString); |
| ex = CacheDirectiveInfo.Expiration.newRelative(ttl); |
| } |
| } |
| return ex; |
| } |
| |
| private static class AddCacheDirectiveInfoCommand |
| implements AdminHelper.Command { |
| @Override |
| public String getName() { |
| return "-addDirective"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + |
| " -path <path> -pool <pool-name> " + |
| "[-force] " + |
| "[-replication <replication>] [-ttl <time-to-live>]]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("<path>", "A path to cache. The path can be " + |
| "a directory or a file."); |
| listing.addRow("<pool-name>", "The pool to which the directive will be " + |
| "added. You must have write permission on the cache pool " |
| + "in order to add new directives."); |
| listing.addRow("-force", |
| "Skips checking of cache pool resource limits."); |
| listing.addRow("<replication>", "The cache replication factor to use. " + |
| "Defaults to 1."); |
| listing.addRow("<time-to-live>", "How long the directive is " + |
| "valid. Can be specified in minutes, hours, and days, e.g. " + |
| "30m, 4h, 2d. Valid units are [smhd]." + |
| " \"never\" indicates a directive that never expires." + |
| " If unspecified, the directive never expires."); |
| return getShortUsage() + "\n" + |
| "Add a new cache directive.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| CacheDirectiveInfo.Builder builder = new CacheDirectiveInfo.Builder(); |
| |
| String path = StringUtils.popOptionWithArgument("-path", args); |
| if (path == null) { |
| System.err.println("You must specify a path with -path."); |
| return 1; |
| } |
| builder.setPath(new Path(path)); |
| |
| String poolName = StringUtils.popOptionWithArgument("-pool", args); |
| if (poolName == null) { |
| System.err.println("You must specify a pool name with -pool."); |
| return 1; |
| } |
| builder.setPool(poolName); |
| boolean force = StringUtils.popOption("-force", args); |
| String replicationString = |
| StringUtils.popOptionWithArgument("-replication", args); |
| if (replicationString != null) { |
| Short replication = Short.parseShort(replicationString); |
| builder.setReplication(replication); |
| } |
| |
| String ttlString = StringUtils.popOptionWithArgument("-ttl", args); |
| try { |
| Expiration ex = parseExpirationString(ttlString); |
| if (ex != null) { |
| builder.setExpiration(ex); |
| } |
| } catch (IOException e) { |
| System.err.println( |
| "Error while parsing ttl value: " + e.getMessage()); |
| return 1; |
| } |
| |
| if (!args.isEmpty()) { |
| System.err.println("Can't understand argument: " + args.get(0)); |
| return 1; |
| } |
| |
| DistributedFileSystem dfs = |
| AdminHelper.getDFS(new Path(path).toUri(), conf); |
| CacheDirectiveInfo directive = builder.build(); |
| EnumSet<CacheFlag> flags = EnumSet.noneOf(CacheFlag.class); |
| if (force) { |
| flags.add(CacheFlag.FORCE); |
| } |
| try { |
| long id = dfs.addCacheDirective(directive, flags); |
| System.out.println("Added cache directive " + id); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| |
| return 0; |
| } |
| } |
| |
| private static class RemoveCacheDirectiveInfoCommand |
| implements AdminHelper.Command { |
| @Override |
| public String getName() { |
| return "-removeDirective"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + " <id>]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("<id>", "The id of the cache directive to remove. " + |
| "You must have write permission on the pool of the " + |
| "directive in order to remove it. To see a list " + |
| "of cache directive IDs, use the -listDirectives command."); |
| return getShortUsage() + "\n" + |
| "Remove a cache directive.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String idString= StringUtils.popFirstNonOption(args); |
| if (idString == null) { |
| System.err.println("You must specify a directive ID to remove."); |
| return 1; |
| } |
| long id; |
| try { |
| id = Long.parseLong(idString); |
| } catch (NumberFormatException e) { |
| System.err.println("Invalid directive ID " + idString + ": expected " + |
| "a numeric value."); |
| return 1; |
| } |
| if (id <= 0) { |
| System.err.println("Invalid directive ID " + id + ": ids must " + |
| "be greater than 0."); |
| return 1; |
| } |
| if (!args.isEmpty()) { |
| System.err.println("Can't understand argument: " + args.get(0)); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| try { |
| dfs.getClient().removeCacheDirective(id); |
| System.out.println("Removed cached directive " + id); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| return 0; |
| } |
| } |
| |
| private static class ModifyCacheDirectiveInfoCommand |
| implements AdminHelper.Command { |
| @Override |
| public String getName() { |
| return "-modifyDirective"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + |
| " -id <id> [-path <path>] [-force] [-replication <replication>] " + |
| "[-pool <pool-name>] [-ttl <time-to-live>]]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("<id>", "The ID of the directive to modify (required)"); |
| listing.addRow("<path>", "A path to cache. The path can be " + |
| "a directory or a file. (optional)"); |
| listing.addRow("-force", |
| "Skips checking of cache pool resource limits."); |
| listing.addRow("<replication>", "The cache replication factor to use. " + |
| "(optional)"); |
| listing.addRow("<pool-name>", "The pool to which the directive will be " + |
| "added. You must have write permission on the cache pool " |
| + "in order to move a directive into it. (optional)"); |
| listing.addRow("<time-to-live>", "How long the directive is " + |
| "valid. Can be specified in minutes, hours, and days, e.g. " + |
| "30m, 4h, 2d. Valid units are [smhd]." + |
| " \"never\" indicates a directive that never expires."); |
| return getShortUsage() + "\n" + |
| "Modify a cache directive.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| CacheDirectiveInfo.Builder builder = |
| new CacheDirectiveInfo.Builder(); |
| boolean modified = false; |
| String idString = StringUtils.popOptionWithArgument("-id", args); |
| if (idString == null) { |
| System.err.println("You must specify a directive ID with -id."); |
| return 1; |
| } |
| builder.setId(Long.parseLong(idString)); |
| String path = StringUtils.popOptionWithArgument("-path", args); |
| if (path != null) { |
| builder.setPath(new Path(path)); |
| modified = true; |
| } |
| boolean force = StringUtils.popOption("-force", args); |
| String replicationString = |
| StringUtils.popOptionWithArgument("-replication", args); |
| if (replicationString != null) { |
| builder.setReplication(Short.parseShort(replicationString)); |
| modified = true; |
| } |
| String poolName = |
| StringUtils.popOptionWithArgument("-pool", args); |
| if (poolName != null) { |
| builder.setPool(poolName); |
| modified = true; |
| } |
| String ttlString = StringUtils.popOptionWithArgument("-ttl", args); |
| try { |
| Expiration ex = parseExpirationString(ttlString); |
| if (ex != null) { |
| builder.setExpiration(ex); |
| modified = true; |
| } |
| } catch (IOException e) { |
| System.err.println( |
| "Error while parsing ttl value: " + e.getMessage()); |
| return 1; |
| } |
| if (!args.isEmpty()) { |
| System.err.println("Can't understand argument: " + args.get(0)); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| if (!modified) { |
| System.err.println("No modifications were specified."); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| EnumSet<CacheFlag> flags = EnumSet.noneOf(CacheFlag.class); |
| if (force) { |
| flags.add(CacheFlag.FORCE); |
| } |
| try { |
| dfs.modifyCacheDirective(builder.build(), flags); |
| System.out.println("Modified cache directive " + idString); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| return 0; |
| } |
| } |
| |
| private static class RemoveCacheDirectiveInfosCommand |
| implements AdminHelper.Command { |
| @Override |
| public String getName() { |
| return "-removeDirectives"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + " -path <path>]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("-path <path>", "The path of the cache directives to remove. " + |
| "You must have write permission on the pool of the directive in order " + |
| "to remove it. To see a list of cache directives, use the " + |
| "-listDirectives command."); |
| return getShortUsage() + "\n" + |
| "Remove every cache directive with the specified path.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String path = StringUtils.popOptionWithArgument("-path", args); |
| if (path == null) { |
| System.err.println("You must specify a path with -path."); |
| return 1; |
| } |
| if (!args.isEmpty()) { |
| System.err.println("Can't understand argument: " + args.get(0)); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| int exitCode = 0; |
| try { |
| DistributedFileSystem dfs = |
| AdminHelper.getDFS(new Path(path).toUri(), conf); |
| RemoteIterator<CacheDirectiveEntry> iter = |
| dfs.listCacheDirectives( |
| new CacheDirectiveInfo.Builder(). |
| setPath(new Path(path)).build()); |
| while (iter.hasNext()) { |
| CacheDirectiveEntry entry = iter.next(); |
| try { |
| dfs.removeCacheDirective(entry.getInfo().getId()); |
| System.out.println("Removed cache directive " + |
| entry.getInfo().getId()); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| exitCode = 2; |
| } |
| } |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| exitCode = 2; |
| } |
| if (exitCode == 0) { |
| System.out.println("Removed every cache directive with path " + |
| path); |
| } |
| return exitCode; |
| } |
| } |
| |
| private static class ListCacheDirectiveInfoCommand |
| implements AdminHelper.Command { |
| @Override |
| public String getName() { |
| return "-listDirectives"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() |
| + " [-stats] [-path <path>] [-pool <pool>] [-id <id>]" |
| + "]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("-stats", "List path-based cache directive statistics."); |
| listing.addRow("<path>", "List only " + |
| "cache directives with this path. " + |
| "Note that if there is a cache directive for <path> " + |
| "in a cache pool that we don't have read access for, it " + |
| "will not be listed."); |
| listing.addRow("<pool>", "List only path cache directives in that pool."); |
| listing.addRow("<id>", "List the cache directive with this id."); |
| return getShortUsage() + "\n" + |
| "List cache directives.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| CacheDirectiveInfo.Builder builder = |
| new CacheDirectiveInfo.Builder(); |
| String pathFilter = StringUtils.popOptionWithArgument("-path", args); |
| if (pathFilter != null) { |
| builder.setPath(new Path(pathFilter)); |
| } |
| String poolFilter = StringUtils.popOptionWithArgument("-pool", args); |
| if (poolFilter != null) { |
| builder.setPool(poolFilter); |
| } |
| boolean printStats = StringUtils.popOption("-stats", args); |
| String idFilter = StringUtils.popOptionWithArgument("-id", args); |
| if (idFilter != null) { |
| builder.setId(Long.parseLong(idFilter)); |
| } |
| if (!args.isEmpty()) { |
| System.err.println("Can't understand argument: " + args.get(0)); |
| return 1; |
| } |
| TableListing.Builder tableBuilder = new TableListing.Builder(). |
| addField("ID", Justification.RIGHT). |
| addField("POOL", Justification.LEFT). |
| addField("REPL", Justification.RIGHT). |
| addField("EXPIRY", Justification.LEFT). |
| addField("PATH", Justification.LEFT); |
| if (printStats) { |
| tableBuilder.addField("BYTES_NEEDED", Justification.RIGHT). |
| addField("BYTES_CACHED", Justification.RIGHT). |
| addField("FILES_NEEDED", Justification.RIGHT). |
| addField("FILES_CACHED", Justification.RIGHT); |
| } |
| TableListing tableListing = tableBuilder.build(); |
| try { |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| RemoteIterator<CacheDirectiveEntry> iter = |
| dfs.listCacheDirectives(builder.build()); |
| int numEntries = 0; |
| while (iter.hasNext()) { |
| CacheDirectiveEntry entry = iter.next(); |
| CacheDirectiveInfo directive = entry.getInfo(); |
| CacheDirectiveStats stats = entry.getStats(); |
| List<String> row = new LinkedList<String>(); |
| row.add("" + directive.getId()); |
| row.add(directive.getPool()); |
| row.add("" + directive.getReplication()); |
| String expiry; |
| // This is effectively never, round for nice printing |
| if (directive.getExpiration().getMillis() > |
| Expiration.MAX_RELATIVE_EXPIRY_MS / 2) { |
| expiry = "never"; |
| } else { |
| expiry = directive.getExpiration().toString(); |
| } |
| row.add(expiry); |
| row.add(directive.getPath().toUri().getPath()); |
| if (printStats) { |
| row.add("" + stats.getBytesNeeded()); |
| row.add("" + stats.getBytesCached()); |
| row.add("" + stats.getFilesNeeded()); |
| row.add("" + stats.getFilesCached()); |
| } |
| tableListing.addRow(row.toArray(new String[row.size()])); |
| numEntries++; |
| } |
| System.out.print(String.format("Found %d entr%s%n", |
| numEntries, numEntries == 1 ? "y" : "ies")); |
| if (numEntries > 0) { |
| System.out.print(tableListing); |
| } |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| return 0; |
| } |
| } |
| |
| private static class AddCachePoolCommand implements AdminHelper.Command { |
| |
| private static final String NAME = "-addPool"; |
| |
| @Override |
| public String getName() { |
| return NAME; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + NAME + " <name> [-owner <owner>] " + |
| "[-group <group>] [-mode <mode>] [-limit <limit>] " + |
| "[-defaultReplication <defaultReplication>] [-maxTtl <maxTtl>]" + |
| "]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| |
| listing.addRow("<name>", "Name of the new pool."); |
| listing.addRow("<owner>", "Username of the owner of the pool. " + |
| "Defaults to the current user."); |
| listing.addRow("<group>", "Group of the pool. " + |
| "Defaults to the primary group name of the current user."); |
| listing.addRow("<mode>", "UNIX-style permissions for the pool. " + |
| "Permissions are specified in octal, e.g. 0755. " + |
| "By default, this is set to " + String.format("0%03o", |
| FsPermission.getCachePoolDefault().toShort()) + "."); |
| listing.addRow("<limit>", "The maximum number of bytes that can be " + |
| "cached by directives in this pool, in aggregate. By default, " + |
| "no limit is set."); |
| listing.addRow("<defaultReplication>", "The default replication " + |
| "number for cache directive in the pool. " + |
| "If not set, the replication is set to 1"); |
| listing.addRow("<maxTtl>", "The maximum allowed time-to-live for " + |
| "directives being added to the pool. This can be specified in " + |
| "seconds, minutes, hours, and days, e.g. 120s, 30m, 4h, 2d. " + |
| "Valid units are [smhd]. By default, no maximum is set. " + |
| "A value of \"never\" specifies that there is no limit."); |
| return getShortUsage() + "\n" + |
| "Add a new cache pool.\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String name = StringUtils.popFirstNonOption(args); |
| if (name == null) { |
| System.err.println("You must specify a name when creating a " + |
| "cache pool."); |
| return 1; |
| } |
| CachePoolInfo info = new CachePoolInfo(name); |
| |
| String owner = StringUtils.popOptionWithArgument("-owner", args); |
| if (owner != null) { |
| info.setOwnerName(owner); |
| } |
| String group = StringUtils.popOptionWithArgument("-group", args); |
| if (group != null) { |
| info.setGroupName(group); |
| } |
| String modeString = StringUtils.popOptionWithArgument("-mode", args); |
| if (modeString != null) { |
| short mode = Short.parseShort(modeString, 8); |
| info.setMode(new FsPermission(mode)); |
| } |
| String limitString = StringUtils.popOptionWithArgument("-limit", args); |
| Long limit = AdminHelper.parseLimitString(limitString); |
| if (limit != null) { |
| info.setLimit(limit); |
| } |
| String replicationString = StringUtils. |
| popOptionWithArgument("-defaultReplication", args); |
| if (replicationString != null) { |
| short defaultReplication = Short.parseShort(replicationString); |
| info.setDefaultReplication(defaultReplication); |
| } |
| String maxTtlString = StringUtils.popOptionWithArgument("-maxTtl", args); |
| try { |
| Long maxTtl = AdminHelper.parseTtlString(maxTtlString); |
| if (maxTtl != null) { |
| info.setMaxRelativeExpiryMs(maxTtl); |
| } |
| } catch (IOException e) { |
| System.err.println( |
| "Error while parsing maxTtl value: " + e.getMessage()); |
| return 1; |
| } |
| |
| if (!args.isEmpty()) { |
| System.err.print("Can't understand arguments: " + |
| Joiner.on(" ").join(args) + "\n"); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| try { |
| dfs.addCachePool(info); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| System.out.println("Successfully added cache pool " + name + "."); |
| return 0; |
| } |
| } |
| |
| private static class ModifyCachePoolCommand implements AdminHelper.Command { |
| |
| @Override |
| public String getName() { |
| return "-modifyPool"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + " <name> [-owner <owner>] " + |
| "[-group <group>] [-mode <mode>] [-limit <limit>] " + |
| "[-defaultReplication <defaultReplication>] [-maxTtl <maxTtl>]]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| |
| listing.addRow("<name>", "Name of the pool to modify."); |
| listing.addRow("<owner>", "Username of the owner of the pool"); |
| listing.addRow("<group>", "Groupname of the group of the pool."); |
| listing.addRow("<mode>", "Unix-style permissions of the pool in octal."); |
| listing.addRow("<limit>", "Maximum number of bytes that can be cached " + |
| "by this pool."); |
| listing.addRow("<defaultReplication>", "Default replication num for " + |
| "directives in this pool"); |
| listing.addRow("<maxTtl>", "The maximum allowed time-to-live for " + |
| "directives being added to the pool."); |
| |
| return getShortUsage() + "\n" + |
| WordUtils.wrap("Modifies the metadata of an existing cache pool. " + |
| "See usage of " + AddCachePoolCommand.NAME + " for more details.", |
| AdminHelper.MAX_LINE_WIDTH) + "\n\n" + |
| listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String owner = StringUtils.popOptionWithArgument("-owner", args); |
| String group = StringUtils.popOptionWithArgument("-group", args); |
| String modeString = StringUtils.popOptionWithArgument("-mode", args); |
| Integer mode = (modeString == null) ? |
| null : Integer.parseInt(modeString, 8); |
| String limitString = StringUtils.popOptionWithArgument("-limit", args); |
| Long limit = AdminHelper.parseLimitString(limitString); |
| String replicationString = |
| StringUtils.popOptionWithArgument("-defaultReplication", args); |
| Short defaultReplication = null; |
| if (replicationString != null) { |
| defaultReplication = Short.parseShort(replicationString); |
| } |
| String maxTtlString = StringUtils.popOptionWithArgument("-maxTtl", args); |
| Long maxTtl; |
| try { |
| maxTtl = AdminHelper.parseTtlString(maxTtlString); |
| } catch (IOException e) { |
| System.err.println( |
| "Error while parsing maxTtl value: " + e.getMessage()); |
| return 1; |
| } |
| String name = StringUtils.popFirstNonOption(args); |
| if (name == null) { |
| System.err.println("You must specify a name when creating a " + |
| "cache pool."); |
| return 1; |
| } |
| if (!args.isEmpty()) { |
| System.err.print("Can't understand arguments: " + |
| Joiner.on(" ").join(args) + "\n"); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| boolean changed = false; |
| CachePoolInfo info = new CachePoolInfo(name); |
| if (owner != null) { |
| info.setOwnerName(owner); |
| changed = true; |
| } |
| if (group != null) { |
| info.setGroupName(group); |
| changed = true; |
| } |
| if (mode != null) { |
| info.setMode(new FsPermission(mode.shortValue())); |
| changed = true; |
| } |
| if (limit != null) { |
| info.setLimit(limit); |
| changed = true; |
| } |
| if (defaultReplication != null) { |
| info.setDefaultReplication(defaultReplication); |
| changed = true; |
| } |
| if (maxTtl != null) { |
| info.setMaxRelativeExpiryMs(maxTtl); |
| changed = true; |
| } |
| if (!changed) { |
| System.err.println("You must specify at least one attribute to " + |
| "change in the cache pool."); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| try { |
| dfs.modifyCachePool(info); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| System.out.print("Successfully modified cache pool " + name); |
| String prefix = " to have "; |
| if (owner != null) { |
| System.out.print(prefix + "owner name " + owner); |
| prefix = " and "; |
| } |
| if (group != null) { |
| System.out.print(prefix + "group name " + group); |
| prefix = " and "; |
| } |
| if (mode != null) { |
| System.out.print(prefix + "mode " + new FsPermission(mode.shortValue())); |
| prefix = " and "; |
| } |
| if (limit != null) { |
| System.out.print(prefix + "limit " + limit); |
| prefix = " and "; |
| } |
| if (defaultReplication != null) { |
| System.out.println(prefix + "replication " + defaultReplication); |
| prefix = " replication "; |
| } |
| if (maxTtl != null) { |
| System.out.print(prefix + "max time-to-live " + maxTtlString); |
| } |
| System.out.print("\n"); |
| return 0; |
| } |
| } |
| |
| private static class RemoveCachePoolCommand implements AdminHelper.Command { |
| |
| @Override |
| public String getName() { |
| return "-removePool"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + " <name>]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| return getShortUsage() + "\n" + |
| WordUtils.wrap("Remove a cache pool. This also uncaches paths " + |
| "associated with the pool.\n\n", AdminHelper.MAX_LINE_WIDTH) + |
| "<name> Name of the cache pool to remove.\n"; |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String name = StringUtils.popFirstNonOption(args); |
| if (name == null) { |
| System.err.println("You must specify a name when deleting a " + |
| "cache pool."); |
| return 1; |
| } |
| if (!args.isEmpty()) { |
| System.err.print("Can't understand arguments: " + |
| Joiner.on(" ").join(args) + "\n"); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| try { |
| dfs.removeCachePool(name); |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| System.out.println("Successfully removed cache pool " + name + "."); |
| return 0; |
| } |
| } |
| |
| private static class ListCachePoolsCommand implements AdminHelper.Command { |
| |
| @Override |
| public String getName() { |
| return "-listPools"; |
| } |
| |
| @Override |
| public String getShortUsage() { |
| return "[" + getName() + " [-stats] [<name>]]\n"; |
| } |
| |
| @Override |
| public String getLongUsage() { |
| TableListing listing = AdminHelper.getOptionDescriptionListing(); |
| listing.addRow("-stats", "Display additional cache pool statistics."); |
| listing.addRow("<name>", "If specified, list only the named cache pool."); |
| |
| return getShortUsage() + "\n" + |
| WordUtils.wrap("Display information about one or more cache pools, " + |
| "e.g. name, owner, group, permissions, etc.", |
| AdminHelper.MAX_LINE_WIDTH) + "\n\n" + listing.toString(); |
| } |
| |
| @Override |
| public int run(Configuration conf, List<String> args) throws IOException { |
| String name = StringUtils.popFirstNonOption(args); |
| final boolean printStats = StringUtils.popOption("-stats", args); |
| if (!args.isEmpty()) { |
| System.err.print("Can't understand arguments: " + |
| Joiner.on(" ").join(args) + "\n"); |
| System.err.println("Usage is " + getShortUsage()); |
| return 1; |
| } |
| DistributedFileSystem dfs = AdminHelper.getDFS(conf); |
| TableListing.Builder builder = new TableListing.Builder(). |
| addField("NAME", Justification.LEFT). |
| addField("OWNER", Justification.LEFT). |
| addField("GROUP", Justification.LEFT). |
| addField("MODE", Justification.LEFT). |
| addField("LIMIT", Justification.RIGHT). |
| addField("MAXTTL", Justification.RIGHT). |
| addField("DEFAULT_REPLICATION", Justification.RIGHT); |
| if (printStats) { |
| builder. |
| addField("BYTES_NEEDED", Justification.RIGHT). |
| addField("BYTES_CACHED", Justification.RIGHT). |
| addField("BYTES_OVERLIMIT", Justification.RIGHT). |
| addField("FILES_NEEDED", Justification.RIGHT). |
| addField("FILES_CACHED", Justification.RIGHT); |
| } |
| TableListing listing = builder.build(); |
| int numResults = 0; |
| try { |
| RemoteIterator<CachePoolEntry> iter = dfs.listCachePools(); |
| while (iter.hasNext()) { |
| CachePoolEntry entry = iter.next(); |
| CachePoolInfo info = entry.getInfo(); |
| LinkedList<String> row = new LinkedList<String>(); |
| if (name == null || info.getPoolName().equals(name)) { |
| row.add(info.getPoolName()); |
| row.add(info.getOwnerName()); |
| row.add(info.getGroupName()); |
| row.add(info.getMode() != null ? info.getMode().toString() : null); |
| Long limit = info.getLimit(); |
| String limitString; |
| if (limit != null && limit.equals(CachePoolInfo.LIMIT_UNLIMITED)) { |
| limitString = "unlimited"; |
| } else { |
| limitString = "" + limit; |
| } |
| row.add(limitString); |
| Long maxTtl = info.getMaxRelativeExpiryMs(); |
| String maxTtlString = null; |
| |
| if (maxTtl != null) { |
| if (maxTtl == CachePoolInfo.RELATIVE_EXPIRY_NEVER) { |
| maxTtlString = "never"; |
| } else { |
| maxTtlString = DFSUtil.durationToString(maxTtl); |
| } |
| } |
| row.add(maxTtlString); |
| row.add("" + info.getDefaultReplication()); |
| |
| if (printStats) { |
| CachePoolStats stats = entry.getStats(); |
| row.add(Long.toString(stats.getBytesNeeded())); |
| row.add(Long.toString(stats.getBytesCached())); |
| row.add(Long.toString(stats.getBytesOverlimit())); |
| row.add(Long.toString(stats.getFilesNeeded())); |
| row.add(Long.toString(stats.getFilesCached())); |
| } |
| listing.addRow(row.toArray(new String[row.size()])); |
| ++numResults; |
| if (name != null) { |
| break; |
| } |
| } |
| } |
| } catch (IOException e) { |
| System.err.println(AdminHelper.prettifyException(e)); |
| return 2; |
| } |
| System.out.print(String.format("Found %d result%s.%n", numResults, |
| (numResults == 1 ? "" : "s"))); |
| if (numResults > 0) { |
| System.out.print(listing); |
| } |
| // If list pools succeed, we return 0 (success exit code) |
| return 0; |
| } |
| } |
| |
| private static final AdminHelper.Command[] COMMANDS = { |
| new AddCacheDirectiveInfoCommand(), |
| new ModifyCacheDirectiveInfoCommand(), |
| new ListCacheDirectiveInfoCommand(), |
| new RemoveCacheDirectiveInfoCommand(), |
| new RemoveCacheDirectiveInfosCommand(), |
| new AddCachePoolCommand(), |
| new ModifyCachePoolCommand(), |
| new RemoveCachePoolCommand(), |
| new ListCachePoolsCommand() |
| }; |
| } |