为什么hsync()没有刷新我的hdfs文件?

时间:2015-08-26 15:45:43

标签: hadoop hdfs

尽管有关于这个主题的所有资源,但我在磁盘上刷新我的hdfs文件时遇到了问题(hadoop 2.6) 调用FSDataOutputStream.hsync()应该可以解决这个问题,但它实际上只能用于未知原因...

这是一个简单的单元测试失败:

@Test
public void test() throws InterruptedException, IOException {
    final FileSystem filesys = HdfsTools.getFileSystem();
    final Path file = new Path("myHdfsFile"); 
    try (final FSDataOutputStream stream = filesys.create(file)) {
        Assert.assertEquals(0, getSize(filesys, file));  
        stream.writeBytes("0123456789");
        stream.hsync();
        stream.hflush();
        stream.flush();
        Thread.sleep(100);
        Assert.assertEquals(10, getSize(filesys, file)); // Works
        stream.writeBytes("0123456789");
        stream.hsync();
        stream.hflush();
        stream.flush();
        Thread.sleep(100);
        Assert.assertEquals(20, getSize(filesys, file)); // Fails, still 10           
    }
    Assert.assertEquals(20, getSize(filesys, file)); // works
}


private long getSize(FileSystem filesys, Path file) throws IOException {
    return filesys.getFileStatus(file).getLen();
}

知道为什么吗?

1 个答案:

答案 0 :(得分:3)

实际上,hsync()内部调用私有flushOrSync(boolean isSync, EnumSet<SyncFlag> syncFlags)没有标记,只有在提供SyncFlag.UPDATE_LENGTH时才会在namenode上更新长度。

在上面的测试中,用实际读取文件的代码替换getSize()

private long getSize(FileSystem filesys, Path file) throws IOException {        
    long length = 0;
    try (final  FSDataInputStream input = filesys.open(file)) {
        while (input.read() >= 0) {
            length++;
        }
    }
    return length;
}

要更新大小,您也可以调用(没有正确的类类型检查):

((DFSOutputStream) stream.getWrappedStream())).hsync(EnumSet.of(SyncFlag.UPDATE_LENGTH));