/**
* 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.cassandra.hadoop.fs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.*;
import java.net.URI;
import java.security.MessageDigest;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.CleanupHelper;
import org.apache.cassandra.EmbeddedServer;
import org.apache.cassandra.Util;
import org.apache.cassandra.config.ConfigurationException;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.Table;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.thrift.transport.TTransportException;
public class CassandraFileSystemTest extends CleanupHelper
{
/**
* Set embedded cassandra up and spawn it in a new thread.
*
* @throws TTransportException
* @throws IOException
* @throws InterruptedException
*/
@BeforeClass
public static void setup() throws TTransportException, IOException, InterruptedException, ConfigurationException
{
EmbeddedServer.startBrisk();
}
@Test
public void testFileSystemWithoutFlush() throws Exception
{
testFileSystem(false);
}
@Test
public void testFileSystemWithFlush() throws Exception
{
testFileSystem(true);
}
private void testFileSystem(boolean flush) throws Exception
{
CassandraFileSystem fs = new CassandraFileSystem();
fs.initialize(URI.create("cfs://localhost:"+DatabaseDescriptor.getRpcPort()+"/"), new Configuration());
fs.mkdirs(new Path("/mytestdir"));
fs.mkdirs(new Path("/mytestdir/sub1"));
fs.mkdirs(new Path("/mytestdir/sub2"));
fs.mkdirs(new Path("/mytestdir/sub3"));
fs.mkdirs(new Path("/mytestdir/sub3/sub4"));
//Create a 1MB file to sent to fs
File tmp = File.createTempFile("testcfs", "input");
Writer writer = new FileWriter(tmp);
char buf[] = new char[1024];
fillArray(buf);
for(int i=0; i<1024; i++)
writer.write(buf);
writer.close();
tmp.deleteOnExit();
//Write file
fs.copyFromLocalFile(new Path("file://"+tmp.getAbsolutePath()), new Path("/mytestdir/testfile"));
if(flush)
{
List<Future<?>> cb = Table.open("cfs").flush();
for(Future c : cb)
c.get();
}
Set<Path> allPaths = fs.store.listDeepSubPaths(new Path("/mytestdir"));
//Verify deep paths
assertEquals(5, allPaths.size());
//verify shallow path
Set<Path> thisPath = fs.store.listSubPaths(new Path("/mytestdir"));
assertEquals(4, thisPath.size());
//Check file status
FileStatus stat = fs.getFileStatus(new Path("/mytestdir/testfile"));
assertEquals(tmp.getAbsoluteFile().length(), stat.getLen());
assertEquals(false, stat.isDir());
//Check block info
BlockLocation[] info = fs.getFileBlockLocations(stat, 0, stat.getLen());
assertEquals(1, info.length);
assertEquals(FBUtilities.getLocalAddress().getHostName(), info[0].getHosts()[0]);
info = fs.getFileBlockLocations(stat, 1, 10);
assertTrue(info.length == 1);
info = fs.getFileBlockLocations(stat, 0, 200);
assertTrue(info.length == 1);
//Check dir status
stat = fs.getFileStatus(new Path("/mytestdir"));
assertEquals(true, stat.isDir());
//Read back the file
File out = File.createTempFile("testcfs", "output");
fs.copyToLocalFile(new Path("/mytestdir/testfile"), new Path("file://"+ out.getAbsolutePath()));
Reader reader = new FileReader(out);
for(int i=0; i<1024; i++)
{
assertEquals(1024, reader.read(buf));
}
assertEquals(-1,reader.read());
reader.close();
out.deleteOnExit();
// Verify the digests
assertDigest(tmp, out);
}
private void fillArray(char[] buf) {
for (int j = 0; j < buf.length; j++) {
buf[j] = (char) j;
}
}
private void assertDigest(File srcFile, File outFile) throws Exception {
MessageDigest md5 = MessageDigest.getInstance("MD5");
InputStream srcFileIn = null;
InputStream outFileIn = null;
try {
srcFileIn = new BufferedInputStream(new FileInputStream(srcFile));
byte[] expected = Util.digestInputStream(md5, srcFileIn);
outFileIn = new BufferedInputStream(new FileInputStream(outFile));
byte[] actual = Util.digestInputStream(md5, outFileIn);
Assert.assertArrayEquals(expected, actual);
} finally {
srcFileIn.close();
outFileIn.close();
}
}
}