/**
* 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;
import junit.framework.TestCase;
import java.io.*;
import java.util.Random;
import java.net.*;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.FSConstants.DatanodeReportType;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FileStatus;
import org.mortbay.log.Log;
/**
* This class tests the access time of files.
*
*/
public class TestAccessTime extends TestCase {
static final long seed = 0xDEADBEEFL;
static final int blockSize = 8192;
static final int fileSize = 16384;
static final int numDatanodes = 6;
Random myrand = new Random();
Path hostsFile;
Path excludeFile;
Configuration conf;
boolean touchable;
boolean changable;
static void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
System.out.println("ms=" + ms + e.getMessage());
}
}
private void createFile(FileSystem fileSys, Path name, int repl,
boolean overwrite) throws IOException {
// create and write a file that contains three blocks of data
FSDataOutputStream stm = fileSys.create(name, overwrite,
fileSys.getConf().getInt("io.file.buffer.size", 4096), (short) repl, (long) blockSize);
byte[] buffer = new byte[fileSize];
Random rand = new Random(seed);
rand.nextBytes(buffer);
sleep(1);
stm.write(buffer);
FileStatus stat = fileSys.getFileStatus(name);
long atime1 = stat.getAccessTime();
long mtime1 = stat.getModificationTime();
System.out.println("Creating after write: accessTime = " + atime1
+ " modTime = " + mtime1);
sleep(1);
stm.close();
stat = fileSys.getFileStatus(name);
atime1 = stat.getAccessTime();
mtime1 = stat.getModificationTime();
System.out.println("Creating after close: accessTime = " + atime1
+ " modTime = " + mtime1);
}
private void appendFile(FileSystem fileSys, Path name, int repl)
throws IOException {
// create and write a file that contains three blocks of data
FSDataOutputStream stm = fileSys.append(name,
fileSys.getConf().getInt("io.file.buffer.size", 4096));
byte[] buffer = new byte[fileSize];
Random rand = new Random(seed);
rand.nextBytes(buffer);
sleep(1);
stm.write(buffer);
FileStatus stat = fileSys.getFileStatus(name);
long atime1 = stat.getAccessTime();
long mtime1 = stat.getModificationTime();
System.out.println("Appending after write: accessTime = " + atime1
+ " modTime = " + mtime1);
sleep(1);
stm.close();
stat = fileSys.getFileStatus(name);
atime1 = stat.getAccessTime();
mtime1 = stat.getModificationTime();
System.out.println("Appending after close: accessTime = " + atime1
+ " modTime = " + mtime1);
}
private void cleanupFile(FileSystem fileSys, Path name) throws IOException {
assertTrue(fileSys.exists(name));
fileSys.delete(name, true);
assertTrue(!fileSys.exists(name));
}
private void printDatanodeReport(DatanodeInfo[] info) {
System.out.println("-------------------------------------------------");
for (int i = 0; i < info.length; i++) {
System.out.println(info[i].getDatanodeReport());
System.out.println();
}
}
public void dounit() throws IOException {
Configuration conf = new Configuration();
System.out.println("Testing accessTime with touchable = " + touchable
+ " changable = " + changable);
if (touchable) {
conf.set("dfs.access.time.touchable", "true");
} else {
conf.set("dfs.access.time.touchable", "false");
}
if (changable) {
conf.set("dfs.access.time.precision", "3600000");
} else {
conf.set("dfs.access.time.precision", "0");
}
MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, true, null);
cluster.waitActive();
InetSocketAddress addr = new InetSocketAddress("localhost",
cluster.getNameNodePort());
DFSClient client = new DFSClient(addr, conf);
DatanodeInfo[] info = client.datanodeReport(DatanodeReportType.LIVE);
assertEquals("Number of Datanodes ", numDatanodes, info.length);
FileSystem fileSys = cluster.getFileSystem();
int replicas = numDatanodes - 1;
assertTrue(fileSys instanceof DistributedFileSystem);
try {
//
// create file and record access time of test file
//
String testfilename = "test.dat1";
System.out.println("Creating testdir1 and " + testfilename);
Path dir1 = new Path("testdir1");
Path file1 = new Path(dir1, testfilename);
createFile(fileSys, file1, replicas, false);
FileStatus stat = fileSys.getFileStatus(file1);
long atime1 = stat.getAccessTime();
long mtime1 = stat.getModificationTime();
System.out.println("The access time after creating the file is " + atime1);
System.out.println("The mod time after creating the file is " + mtime1);
stat = fileSys.getFileStatus(dir1);
long adir1 = stat.getAccessTime();
System.out.println("The access time for the dir is " + adir1);
assertTrue(atime1 != 0);
//
// append file
//
System.out.println("Appending testdir1/" + testfilename);
appendFile(fileSys, file1, replicas);
stat = fileSys.getFileStatus(file1);
long atime2 = stat.getAccessTime();
long mtime2 = stat.getModificationTime();
System.out.println("The access time after appending the file is "
+ atime2);
System.out.println("The mod time after appending the file is " + mtime2);
stat = fileSys.getFileStatus(dir1);
long adir2 = stat.getAccessTime();
System.out.println("The access time for the dir is " + adir2);
if (!changable) {
assertTrue(atime1 == atime2);
} else {
assertTrue(atime1 != atime2);
}
assertTrue(mtime1 != mtime2);
//
// overwrite file
//
System.out.println("Overwriting testdir1/" + testfilename);
createFile(fileSys, file1, replicas, true);
stat = fileSys.getFileStatus(file1);
long atime3 = stat.getAccessTime();
long mtime3 = stat.getModificationTime();
System.out.println("The access time after overwriting the file is "
+ atime3);
System.out.println("The modification time after overwriting the file is "
+ mtime3);
stat = fileSys.getFileStatus(dir1);
long adir3 = stat.getAccessTime();
System.out.println("The access time for the dir is " + adir3);
if (!changable) {
assertTrue(atime1 == atime3);
} else {
assertTrue(atime2 != atime3);
}
assertTrue(mtime2 != mtime3);
// setTimes
System.out.println("setTime for testdir1/" + testfilename);
long atime4 = atime3 - (24L * 3600L * 1000L);
long mtime4 = mtime3 - (3600L * 1000L);
try {
fileSys.setTimes(file1, mtime4, atime4);
} catch (org.apache.hadoop.ipc.RemoteException e) {
assertTrue(touchable == false);
Log.info("Expected exception from the server for failed touch");
}
System.out.println("set modifictaion=" + mtime4 + " accessTime=" + atime4);
stat = fileSys.getFileStatus(file1);
long atime5 = stat.getAccessTime();
long mtime5 = stat.getModificationTime();
System.out.println("The access time after setting the file is " + atime5);
System.out.println("The modification time after setting the file is "
+ mtime5);
stat = fileSys.getFileStatus(dir1);
long adir4 = stat.getAccessTime();
System.out.println("The access time for the dir is " + adir4);
if (!touchable) {
assertTrue(atime4 != atime5);
assertTrue(mtime4 != mtime5);
assertTrue(atime3 == atime5);
assertTrue(mtime3 == mtime5);
} else {
assertTrue(atime4 == atime5);
assertTrue(mtime4 == mtime5);
}
cleanupFile(fileSys, file1);
cleanupFile(fileSys, dir1);
} catch (IOException e) {
info = client.datanodeReport(DatanodeReportType.ALL);
printDatanodeReport(info);
throw e;
} finally {
fileSys.close();
cluster.shutdown();
}
}
/**
* Tests access time in DFS.
*/
public void testNoTouchDoChange() throws IOException {
touchable = false;
changable = true;
dounit();
}
public void testNoTouchNoChange() throws IOException {
touchable = false;
changable = false;
dounit();
}
public void testTouchNoChange() throws IOException {
touchable = true;
changable = false;
dounit();
}
public void testTouchChange() throws IOException {
touchable = true;
changable = true;
dounit();
}
}