package com.neverwinterdp.scribengin.storage.s3.sink;
import java.util.LinkedHashMap;
import java.util.List;
import com.amazonaws.AmazonServiceException;
import com.neverwinterdp.scribengin.storage.StorageDescriptor;
import com.neverwinterdp.scribengin.storage.StreamDescriptor;
import com.neverwinterdp.scribengin.storage.s3.S3Client;
import com.neverwinterdp.scribengin.storage.s3.S3Folder;
import com.neverwinterdp.scribengin.storage.s3.S3Util;
import com.neverwinterdp.scribengin.storage.sink.Sink;
import com.neverwinterdp.scribengin.storage.sink.SinkStream;
public class S3Sink implements Sink {
private StorageDescriptor descriptor ;
private S3Folder sinkFolder ;
private int idTracker = 0;
private LinkedHashMap<Integer, S3SinkStream> streams = new LinkedHashMap<Integer, S3SinkStream>() ;
public S3Sink(StorageDescriptor descriptor) {
String regionName = descriptor.attribute("s3.region.name");
S3Client s3Client = new S3Client(regionName);
s3Client.onInit();
init(s3Client, descriptor);
}
private void init(S3Client s3Client, StorageDescriptor descriptor) {
this.descriptor = descriptor;
String bucketName = descriptor.attribute("s3.bucket.name");
if(!s3Client.hasBucket(bucketName)) {
throw new AmazonServiceException("Bucket " + bucketName + " does not exist");
}
String folderPath = descriptor.attribute("s3.storage.path");
if(!s3Client.hasKey(bucketName, folderPath)) {
s3Client.createS3Folder(bucketName, folderPath) ;
}
sinkFolder = s3Client.getS3Folder(bucketName, folderPath);
List<String> streamNames = sinkFolder.getChildrenNames();
for(String streamName : streamNames) {
StreamDescriptor streamDescriptor = new StreamDescriptor(descriptor);
streamDescriptor.attribute("s3.stream.name", streamName);
streamDescriptor.setId(S3Util.getStreamId(streamName));
S3SinkStream stream = new S3SinkStream(sinkFolder, streamDescriptor);
streams.put(stream.getDescriptor().getId(), stream);
if(idTracker < stream.getDescriptor().getId()) {
idTracker = stream.getDescriptor().getId();
}
}
}
public S3Sink(S3Client s3Client, StorageDescriptor descriptor) {
init(s3Client, descriptor);
}
public S3Folder getSinkFolder() { return this.sinkFolder ; }
@Override
public StorageDescriptor getDescriptor() { return descriptor; }
@Override
synchronized public SinkStream getStream(StreamDescriptor descriptor) throws Exception {
return streams.get(descriptor.getId());
}
@Override
synchronized public SinkStream[] getStreams() {
SinkStream[] array = new SinkStream[streams.size()];
return streams.values().toArray(array);
}
//TODO: Should consider a sort of transaction to make the operation reliable
@Override
synchronized public void delete(SinkStream stream) throws Exception {
SinkStream found = streams.remove(stream.getDescriptor().getId());
if(found != null) {
found.delete();
}
}
@Override
synchronized public SinkStream newStream() throws Exception {
int streamId = ++idTracker ;
StreamDescriptor streamDescriptor = new StreamDescriptor(descriptor);
streamDescriptor.setId(streamId);
streamDescriptor.attribute("s3.stream.name", "stream-" + streamId);
S3SinkStream stream = new S3SinkStream(sinkFolder, streamDescriptor);
streams.put(streamId, stream) ;
return stream;
}
@Override
public void close() throws Exception {
}
}