|
17 | 17 | */ |
18 | 18 | package org.apache.hadoop.hdfs.server.namenode; |
19 | 19 |
|
| 20 | +import static org.apache.hadoop.fs.permission.AclEntryScope.*; |
| 21 | +import static org.apache.hadoop.fs.permission.AclEntryType.*; |
| 22 | +import static org.apache.hadoop.fs.permission.FsAction.*; |
| 23 | +import static org.apache.hadoop.hdfs.server.namenode.AclTestHelpers.*; |
20 | 24 | import static org.apache.hadoop.test.MetricsAsserts.assertCounter; |
21 | 25 | import static org.apache.hadoop.test.MetricsAsserts.getMetrics; |
22 | 26 | import static org.junit.Assert.assertEquals; |
| 27 | +import static org.junit.Assert.assertFalse; |
23 | 28 | import static org.junit.Assert.assertNotNull; |
24 | 29 | import static org.junit.Assert.assertTrue; |
25 | 30 | import static org.junit.Assert.fail; |
|
57 | 62 | import org.apache.hadoop.fs.FileSystem; |
58 | 63 | import org.apache.hadoop.fs.FileUtil; |
59 | 64 | import org.apache.hadoop.fs.Path; |
| 65 | +import org.apache.hadoop.fs.permission.AclEntry; |
60 | 66 | import org.apache.hadoop.fs.permission.FsPermission; |
61 | 67 | import org.apache.hadoop.fs.permission.PermissionStatus; |
62 | 68 | import org.apache.hadoop.hdfs.DFSConfigKeys; |
@@ -1499,4 +1505,65 @@ public void testManyEditLogSegments() throws IOException { |
1499 | 1505 | LOG.info(String.format("loaded %d edit log segments in %.2f seconds", |
1500 | 1506 | NUM_EDIT_LOG_ROLLS, delta)); |
1501 | 1507 | } |
| 1508 | + |
| 1509 | + /** |
| 1510 | + * Edit log op instances are cached internally using thread-local storage. |
| 1511 | + * This test checks that the cached instances are reset in between different |
| 1512 | + * transactions processed on the same thread, so that we don't accidentally |
| 1513 | + * apply incorrect attributes to an inode. |
| 1514 | + * |
| 1515 | + * @throws IOException if there is an I/O error |
| 1516 | + */ |
| 1517 | + @Test |
| 1518 | + public void testResetThreadLocalCachedOps() throws IOException { |
| 1519 | + Configuration conf = new HdfsConfiguration(); |
| 1520 | + conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_ACLS_ENABLED_KEY, true); |
| 1521 | + // Set single handler thread, so all transactions hit same thread-local ops. |
| 1522 | + conf.setInt(DFSConfigKeys.DFS_NAMENODE_HANDLER_COUNT_KEY, 1); |
| 1523 | + MiniDFSCluster cluster = null; |
| 1524 | + FileSystem fileSys = null; |
| 1525 | + try { |
| 1526 | + cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build(); |
| 1527 | + cluster.waitActive(); |
| 1528 | + fileSys = cluster.getFileSystem(); |
| 1529 | + |
| 1530 | + // Create /dir1 with a default ACL. |
| 1531 | + Path dir1 = new Path("/dir1"); |
| 1532 | + fileSys.mkdirs(dir1); |
| 1533 | + List<AclEntry> aclSpec = Lists.newArrayList( |
| 1534 | + aclEntry(DEFAULT, USER, "foo", READ_EXECUTE)); |
| 1535 | + fileSys.modifyAclEntries(dir1, aclSpec); |
| 1536 | + |
| 1537 | + // /dir1/dir2 is expected to clone the default ACL. |
| 1538 | + Path dir2 = new Path("/dir1/dir2"); |
| 1539 | + fileSys.mkdirs(dir2); |
| 1540 | + |
| 1541 | + // /dir1/file1 is expected to clone the default ACL. |
| 1542 | + Path file1 = new Path("/dir1/file1"); |
| 1543 | + fileSys.create(file1).close(); |
| 1544 | + |
| 1545 | + // /dir3 is not a child of /dir1, so must not clone the default ACL. |
| 1546 | + Path dir3 = new Path("/dir3"); |
| 1547 | + fileSys.mkdirs(dir3); |
| 1548 | + |
| 1549 | + // /file2 is not a child of /dir1, so must not clone the default ACL. |
| 1550 | + Path file2 = new Path("/file2"); |
| 1551 | + fileSys.create(file2).close(); |
| 1552 | + |
| 1553 | + // Restart and assert the above stated expectations. |
| 1554 | + IOUtils.cleanup(LOG, fileSys); |
| 1555 | + cluster.restartNameNode(); |
| 1556 | + fileSys = cluster.getFileSystem(); |
| 1557 | + assertFalse(fileSys.getAclStatus(dir1).getEntries().isEmpty()); |
| 1558 | + assertFalse(fileSys.getAclStatus(dir2).getEntries().isEmpty()); |
| 1559 | + assertFalse(fileSys.getAclStatus(file1).getEntries().isEmpty()); |
| 1560 | + assertTrue(fileSys.getAclStatus(dir3).getEntries().isEmpty()); |
| 1561 | + assertTrue(fileSys.getAclStatus(file2).getEntries().isEmpty()); |
| 1562 | + } finally { |
| 1563 | + IOUtils.cleanup(LOG, fileSys); |
| 1564 | + if (cluster != null) { |
| 1565 | + cluster.shutdown(); |
| 1566 | + } |
| 1567 | + } |
| 1568 | + } |
1502 | 1569 | } |
0 commit comments