/*
* Copyright 2014 Rackspace
*
* Licensed 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 com.rackspacecloud.blueflood.outputs.cloudfiles;
import com.rackspacecloud.blueflood.eventemitter.RollupEvent;
import com.rackspacecloud.blueflood.outputs.serializers.RollupEventSerializer;
import com.rackspacecloud.blueflood.service.CloudfilesConfig;
import com.rackspacecloud.blueflood.service.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
// Not thread-safe
public class RollupFile implements Comparable {
private static final Logger log = LoggerFactory.getLogger(RollupFile.class);
private final File file;
private FileOutputStream outputStream;
private long timestamp;
private RollupEventSerializer serializer = new RollupEventSerializer();
public static final FileFilter fileFilter = new RollupFileFilter();
public RollupFile(File file) {
this.file = file;
this.timestamp = parseTimestamp(file.getName());
}
/**
* Retrieve the timestamp associated with this file.
*
* @return The timestamp associated with the file.
*/
public long getTimestamp() {
return timestamp;
}
/**
* Get the name of the buffer file.
*
* @return The name of the buffer file.
*/
public String getName() {
return file.getName();
}
/**
* Get the remote file name.
*
* @return The path to the remote file.
*/
public String getRemoteName() {
Date time = new Date(timestamp);
String formattedTime = new SimpleDateFormat("yyyyMMdd_").format(time);
return formattedTime + System.currentTimeMillis() + "_" + Configuration.getInstance().getStringProperty(CloudfilesConfig.CLOUDFILES_HOST_UNIQUE_IDENTIFIER);
}
/**
* Get the age of the rollup file in milliseconds.
*
* @return The age of the rollup file in milliseconds.
*/
public long getAge() {
return System.currentTimeMillis() - timestamp;
}
/**
* Get the size of the rollup file in bytes.
*
* @return The size of the rollup file in bytes.
* @throws IOException
*/
public long getSize() throws IOException {
ensureOpen();
return outputStream.getChannel().size();
}
/**
* Retrieve an InputStream which reads from this rollup file.
*
* @return An InputStream of data from the file.
* @throws FileNotFoundException
*/
public InputStream asReadStream() throws FileNotFoundException {
return new FileInputStream(file);
}
/**
* Serialize a Rollup Event and append it to the file.
*
* @param rollup The rollup to append.
* @throws IOException
*/
public void append(RollupEvent rollup) throws IOException {
ensureOpen();
outputStream.write(serializer.toBytes(rollup));
outputStream.write('\n');
outputStream.flush();
}
public void close() throws IOException {
if (outputStream != null) {
outputStream.close();
outputStream = null;
}
}
public void delete() throws FileNotFoundException, IllegalAccessException {
if (!file.delete()) {
if (!file.exists()) {
throw new FileNotFoundException("File does not exist");
}
throw new IllegalAccessException("File exists but could not be deleted. File is probably locked.");
}
}
public int compareTo(Object other) {
return new Long(getTimestamp()).compareTo(((RollupFile) other).getTimestamp());
}
private void ensureOpen() throws FileNotFoundException {
if (outputStream == null) {
log.info("opening buffer file for writing: {}", file.getName());
outputStream = new FileOutputStream(file, true);
}
}
/**
* Parse the timestamp from a filename.
*
* @param fileName The file name to parse.
* @return The timestamp contained in the file name.
* @throws NumberFormatException
*/
private static long parseTimestamp(String fileName) throws NumberFormatException {
String numberPart = fileName.substring(0, fileName.length() - 5);
return Long.parseLong(numberPart);
}
/**
* Build a new RollupFile using the current time as the timestamp. The file won't be created until it is actually
* written to for the first time.
*
* @param bufferDir The directory in which to create the file.
* @return The new RollupFile.
*/
public static RollupFile buildRollupFile(File bufferDir) {
return new RollupFile(new File(bufferDir, System.currentTimeMillis() + ".json"));
}
private static class RollupFileFilter implements FileFilter {
public boolean accept(File f) {
String fileName = f.getName();
if (!f.isFile()) {
return false;
}
if (!fileName.endsWith(".json")) {
log.info("skipping non-JSON file: {}", fileName);
return false;
}
try {
parseTimestamp(fileName);
} catch (NumberFormatException e) {
log.info("skipping malformatted filename: {}", fileName);
return false;
}
return true;
}
}
}