|
@@ -24,10 +24,12 @@ import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.nio.channels.ClosedChannelException;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
|
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
import org.apache.hadoop.classification.InterfaceStability;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
+import org.apache.hadoop.fs.permission.AclEntry;
|
|
|
import org.apache.hadoop.fs.permission.FsPermission;
|
|
|
import org.apache.hadoop.util.DataChecksum;
|
|
|
import org.apache.hadoop.util.Progressable;
|
|
@@ -151,11 +153,14 @@ public abstract class ChecksumFileSystem extends FilterFileSystem {
|
|
|
throw new IOException("Not a checksum file: "+sumFile);
|
|
|
this.bytesPerSum = sums.readInt();
|
|
|
set(fs.verifyChecksum, DataChecksum.newCrc32(), bytesPerSum, 4);
|
|
|
- } catch (FileNotFoundException e) { // quietly ignore
|
|
|
- set(fs.verifyChecksum, null, 1, 0);
|
|
|
- } catch (IOException e) { // loudly ignore
|
|
|
- LOG.warn("Problem opening checksum file: "+ file +
|
|
|
- ". Ignoring exception: " , e);
|
|
|
+ } catch (IOException e) {
|
|
|
+ // mincing the message is terrible, but java throws permission
|
|
|
+ // exceptions as FNF because that's all the method signatures allow!
|
|
|
+ if (!(e instanceof FileNotFoundException) ||
|
|
|
+ e.getMessage().endsWith(" (Permission denied)")) {
|
|
|
+ LOG.warn("Problem opening checksum file: "+ file +
|
|
|
+ ". Ignoring exception: " , e);
|
|
|
+ }
|
|
|
set(fs.verifyChecksum, null, 1, 0);
|
|
|
}
|
|
|
}
|
|
@@ -472,6 +477,103 @@ public abstract class ChecksumFileSystem extends FilterFileSystem {
|
|
|
blockSize, progress);
|
|
|
}
|
|
|
|
|
|
+ abstract class FsOperation {
|
|
|
+ boolean run(Path p) throws IOException {
|
|
|
+ boolean status = apply(p);
|
|
|
+ if (status) {
|
|
|
+ Path checkFile = getChecksumFile(p);
|
|
|
+ if (fs.exists(checkFile)) {
|
|
|
+ apply(checkFile);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+ abstract boolean apply(Path p) throws IOException;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setPermission(Path src, final FsPermission permission)
|
|
|
+ throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.setPermission(p, permission);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setOwner(Path src, final String username, final String groupname)
|
|
|
+ throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.setOwner(p, username, groupname);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setAcl(Path src, final List<AclEntry> aclSpec)
|
|
|
+ throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.setAcl(p, aclSpec);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void modifyAclEntries(Path src, final List<AclEntry> aclSpec)
|
|
|
+ throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.modifyAclEntries(p, aclSpec);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void removeAcl(Path src) throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.removeAcl(p);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void removeAclEntries(Path src, final List<AclEntry> aclSpec)
|
|
|
+ throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.removeAclEntries(p, aclSpec);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void removeDefaultAcl(Path src) throws IOException {
|
|
|
+ new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ fs.removeDefaultAcl(p);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Set replication for an existing file.
|
|
|
* Implement the abstract <tt>setReplication</tt> of <tt>FileSystem</tt>
|
|
@@ -482,16 +584,14 @@ public abstract class ChecksumFileSystem extends FilterFileSystem {
|
|
|
* false if file does not exist or is a directory
|
|
|
*/
|
|
|
@Override
|
|
|
- public boolean setReplication(Path src, short replication) throws IOException {
|
|
|
- boolean value = fs.setReplication(src, replication);
|
|
|
- if (!value)
|
|
|
- return false;
|
|
|
-
|
|
|
- Path checkFile = getChecksumFile(src);
|
|
|
- if (exists(checkFile))
|
|
|
- fs.setReplication(checkFile, replication);
|
|
|
-
|
|
|
- return true;
|
|
|
+ public boolean setReplication(Path src, final short replication)
|
|
|
+ throws IOException {
|
|
|
+ return new FsOperation(){
|
|
|
+ @Override
|
|
|
+ boolean apply(Path p) throws IOException {
|
|
|
+ return fs.setReplication(p, replication);
|
|
|
+ }
|
|
|
+ }.run(src);
|
|
|
}
|
|
|
|
|
|
/**
|