/* * Copyright 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file 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 com.amazonaws.services.simpleworkflow.flow.examples.fileprocessing; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.simpleworkflow.flow.ActivityExecutionContext; import com.amazonaws.services.simpleworkflow.flow.ActivityExecutionContextProvider; import com.amazonaws.services.simpleworkflow.flow.ActivityExecutionContextProviderImpl; /** * This is an S3 Store implementation which provides Activities to * download/upload files from S3 * */ public class SimpleStoreActivitiesS3Impl implements SimpleStoreActivities { private static final int HEARTBEAT_INTERVAL = 60000; private final ActivityExecutionContextProvider contextProvider = new ActivityExecutionContextProviderImpl(); private final AmazonS3 s3Client; private final String localDirectory; private final String hostSpecificTaskList; public SimpleStoreActivitiesS3Impl(AmazonS3 s3Client, String localDirectory, String taskList) { this.s3Client = s3Client; this.localDirectory = localDirectory; this.hostSpecificTaskList = taskList; } @Override public void upload(String bucketName, String localName, String targetName) { uploadFileToS3(bucketName, localDirectory + localName, targetName); } /** * * @param bucket * Name of S3 bucket * @param localName * Name of the file to upload * @param remoteName * Key for the S3 object * @param fromBox * The value for this parameter is used to control the scheduling * of this Activity at runtime. In this case it is putting * requirement to run this activity on the machine name passed * in. We want to run this activity on the same box that ran the * download. * @return A Value object */ private void uploadFileToS3(String bucket, String localName, String remoteName) { System.out.println("uploadToS3 begin remoteName=" + remoteName + ", localName=" + localName); File f = new File(localName); s3Client.putObject(bucket, remoteName, f); System.out.println("uploadToS3 done"); } @Override public String download(String bucketName, String remoteName, String localName) throws Exception { return downloadFileFromS3(bucketName, remoteName, localDirectory + localName); } /** * * @param bucketName * Name of S3 bucket * @param remoteName * Key to use for uploaded S3 object * @param localName * Name of the file locally * @param toBox * This is an output parameter here. Used to communicate the name * of the box that runs download activity * @return A Value object * @throws IOException */ private String downloadFileFromS3(String bucketName, String remoteName, String localName) throws IOException { System.out.println("downloadFileFromS3 begin remoteName=" + remoteName + ", localName=" + localName); FileOutputStream f = new FileOutputStream(localName); try { S3Object obj = s3Client.getObject(bucketName, remoteName); InputStream inputStream = obj.getObjectContent(); long totalSize = obj.getObjectMetadata().getContentLength(); try { long totalRead = 0; int read = 0; byte[] bytes = new byte[1024]; long lastHeartbeatTime = System.currentTimeMillis(); while ((read = inputStream.read(bytes)) != -1) { totalRead += read; f.write(bytes, 0, read); int progress = (int) (totalRead / totalSize * 100); lastHeartbeatTime = heartbeat(lastHeartbeatTime, progress); } } finally { inputStream.close(); } } finally { f.close(); } // Return hostname file was downloaded to System.out.println("downloadFileFromS3 done"); return hostSpecificTaskList; } @Override public void deleteLocalFile(String fileName) { deleteLocalFiles(localDirectory + fileName); } /** * * @param fileName * Filename to delete locally * @param machineName * The value for this parameter is used to control the scheduling * of this Activity at runtime. In this case it is putting * requirement to run this activity on the machine name passed * in. * @return */ private void deleteLocalFiles(String fileName) { System.out.println("deleteLocalActivity begin fileName=" + fileName); File f = new File(fileName); f.delete(); System.out.println("deleteLocalActivity done"); } /** * Heartbeat every 5 minutes. It is not a good idea to heartbeat too * frequently as each noteActivityProgress event ends up eating history * events count. * * @return time of the last heartbeat */ private long heartbeat(long lastHeartbeatTime, int progress) { if (System.currentTimeMillis() - lastHeartbeatTime > HEARTBEAT_INTERVAL) { ActivityExecutionContext context = contextProvider.getActivityExecutionContext(); context.recordActivityHeartbeat(Integer.toString((progress))); lastHeartbeatTime = System.currentTimeMillis(); } return lastHeartbeatTime; } }