package org.opendedup.sdfs.filestore;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import org.opendedup.util.HashFunctions;
import org.opendedup.util.StringUtils;
/**
*
* @author Sam Silverberg The S3 chunk store implements the AbstractChunkStore
* and is used to store deduped chunks to AWS S3 data storage. It is
* used if the aws tag is used within the chunk store config file. It is
* important to make the chunk size very large on the client when using
* this chunk store since S3 charges per http request.
*
*/
public class S3ChunkStore implements AbstractChunkStore {
private static String awsAccessKey = null;
private static String awsSecretKey = null;
private static AWSCredentials awsCredentials = new AWSCredentials(
awsAccessKey, awsSecretKey);
private String name;
private S3Bucket s3Bucket = null;
S3Service s3Service;
private transient static Logger log = Logger.getLogger("sdfs");
// private static ReentrantLock lock = new ReentrantLock();
public S3ChunkStore(String name) throws IOException {
this.name = name;
try {
s3Service = new RestS3Service(awsCredentials);
this.s3Bucket = s3Service.getBucket(awsAccessKey);
if (this.s3Bucket == null) {
this.s3Bucket = s3Service.createBucket(awsAccessKey);
log.info("created new store " + awsAccessKey);
}
} catch (S3ServiceException e) {
e.printStackTrace();
throw new IOException(e.toString());
}
}
public long bytesRead() {
// TODO Auto-generated method stub
return 0;
}
public long bytesWritten() {
// TODO Auto-generated method stub
return 0;
}
public void closeStore() {
}
public void expandFile(long length) throws IOException {
// TODO Auto-generated method stub
}
public byte[] getChunk(byte[] hash, long start, int len) throws IOException {
String hashString = StringUtils.getHexString(hash);
try {
S3Object obj = s3Service.getObject(s3Bucket, hashString);
byte[] data = new byte[(int) obj.getContentLength()];
DataInputStream in = new DataInputStream(obj.getDataInputStream());
in.readFully(data);
obj.closeDataInputStream();
return data;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new IOException("unable to read " + hashString);
}
}
public String getName() {
return this.name;
}
public long reserveWritePosition(int len) throws IOException {
// TODO Auto-generated method stub
return 0;
}
public void setName(String name) {
}
public long size() {
// TODO Auto-generated method stub
return 0;
}
public void writeChunk(byte[] hash, byte[] chunk, int len, long start)
throws IOException {
String hashString = StringUtils.getHexString(hash);
S3Object s3Object = new S3Object(hashString);
ByteArrayInputStream s3IS = new ByteArrayInputStream(chunk);
s3Object.setDataInputStream(s3IS);
s3Object.setContentType("binary/octet-stream");
s3Object.setContentLength(s3IS.available());
try {
s3Service.putObject(s3Bucket, s3Object);
} catch (Exception e) {
// TODO Auto-generated catch block
log.log(Level.SEVERE, "unable to upload " + hashString, e);
throw new IOException(e.toString());
} finally {
s3IS.close();
}
}
public static void main(String[] args) throws IOException {
S3ChunkStore store = new S3ChunkStore("test");
String test = "This is a test";
byte[] md5 = HashFunctions.getMD5ByteHash(test.getBytes());
store.writeChunk(md5, test.getBytes(), 0, 0);
String outStr = new String(store.getChunk(md5, 0, 0));
System.out.println(outStr);
}
@Override
public void deleteChunk(byte[] hash, long start, int len)
throws IOException {
String hashString = StringUtils.getHexString(hash);
try {
s3Service.deleteObject(s3Bucket, hashString);
} catch (S3ServiceException e) {
log.log(Level.WARNING, "Unable to delete object " + hashString, e);
}
}
@Override
public void addChunkStoreListener(AbstractChunkStoreListener listener) {
// TODO Auto-generated method stub
}
@Override
public void claimChunk(byte[] hash, long start) throws IOException {
// TODO Auto-generated method stub
}
@Override
public boolean moveChunk(byte[] hash, long origLoc, long newLoc)
throws IOException {
// TODO Auto-generated method stub
return false;
}
}