/*
* This file is part of the Wayback archival access software
* (http://archive-access.sourceforge.net/projects/wayback/).
*
* Licensed to the Internet Archive (IA) by one or more individual
* contributors.
*
* The IA 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.archive.wayback.liveweb;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import org.archive.format.ArchiveFileConstants;
import org.archive.format.arc.ARCConstants;
import org.archive.io.WriterPoolSettings;
import org.archive.io.arc.ARCWriter;
import org.archive.io.arc.ARCWriterPool;
import org.archive.wayback.core.Resource;
import org.archive.wayback.exception.ResourceNotAvailableException;
import org.archive.wayback.resourcestore.resourcefile.ResourceFactory;
import org.archive.wayback.util.DirMaker;
/**
* Class uses an ARCWriterPool to provide access to a set of ARCWriters,
* exposing getting and setters which simplify Spring configuration.
*
* This class also provides one method, getResource() which transforms a String
* path and an long offset into a Resource.
*
* @author brad
* @version $Date$, $Revision$
*/
public class ARCCacheDirectory {
private static final Logger LOGGER = Logger.getLogger(
ARCCacheDirectory.class.getName());
private int poolWriters = 5;
private int maxPoolWait = 300;
private long maxARCSize = ARCConstants.DEFAULT_MAX_ARC_FILE_SIZE;
private String arcPrefix = "wayback-live";
/**
* template string used to configure the ARC writer pool
*/
public static String LIVE_WAYBACK_TEMPLATE =
"${prefix}-${timestamp17}-${serialno}";
private File arcDir = null;
private ARCWriterPool pool = null;
/**
* @throws IOException for usual reasons
*/
public void init() throws IOException {
// TODO: check that all props have been set
arcDir = DirMaker.ensureDir(arcDir.getAbsolutePath(),"arcPath");
File[] files = { arcDir };
WriterPoolSettings settings = getSettings(true, arcPrefix, files);
pool = new ARCWriterPool(settings, poolWriters, maxPoolWait);
}
/**
* shut down the ARC Writer pool.
*/
public void shutdown() {
pool.close();
}
/**
* get an ARCWriter. be sure to return it to the pool with returnWriter.
*
* @return an ARCWriter prepared to store an ARCRecord
* @throws IOException for usual reasons
*/
public ARCWriter getWriter() throws IOException {
return (ARCWriter) pool.borrowFile();
}
/**
* @param w previously borrowed ARCWriter
* @throws IOException for usual reasons
*/
public void returnWriter(ARCWriter w) throws IOException {
pool.returnFile(w);
}
/**
* transform an ARCLocation into a Resource. Be sure to call close() on it
* when processing is finished.
* @param path to ARC file
* @param offset within file where record begins
* @return the Resource for the location
* @throws IOException for usual reasons
*/
public Resource getResource(String path, long offset) throws IOException {
File arc = new File(path);
if(!arc.exists()) {
String base = arc.getName();
arc = new File(arcDir,base);
if(!arc.exists()) {
if(base.endsWith(ArchiveFileConstants.OCCUPIED_SUFFIX)) {
String newBase = base.substring(0,base.length() -
ArchiveFileConstants.OCCUPIED_SUFFIX.length());
arc = new File(arcDir,newBase);
}
}
}
LOGGER.info("Retrieving record at " + offset + " in " +
arc.getAbsolutePath());
try {
return ResourceFactory.getResource(arc, offset);
} catch (ResourceNotAvailableException e1) {
throw new IOException(e1.getMessage());
}
}
private WriterPoolSettings getSettings(final boolean isCompressed,
final String prefix, final File[] arcDirs) {
return new WriterPoolSettings() {
public List<File> calcOutputDirs() {
return Arrays.asList(arcDirs);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public List getMetadata() {
return null;
}
public String getPrefix() {
return prefix;
}
public boolean getCompress() {
// TODO Auto-generated method stub
return isCompressed;
}
public long getMaxFileSizeBytes() {
// TODO Auto-generated method stub
return maxARCSize;
}
public String getTemplate() {
return LIVE_WAYBACK_TEMPLATE;
}
public boolean getFrequentFlushes() {
return true;
}
public int getWriteBufferSize() {
return 4096;
}
// public List<File> calcOutputDirs() {
// // TODO Auto-generated method stub
// return null;
// }
};
}
/**
* @return the arcPrefix
*/
public String getArcPrefix() {
return arcPrefix;
}
/**
* @param arcPrefix the arcPrefix to set
*/
public void setArcPrefix(String arcPrefix) {
this.arcPrefix = arcPrefix;
}
/**
* @return the arcDir
*/
public String getArcDir() {
return arcDir.getAbsolutePath();
}
/**
* @param arcPath the arcPath to set
*/
public void setArcDir(String arcPath) {
this.arcDir = new File(arcPath);
}
/**
* @return the poolWriters
*/
public int getPoolWriters() {
return poolWriters;
}
/**
* @param poolWriters the poolWriters to set
*/
public void setPoolWriters(int poolWriters) {
this.poolWriters = poolWriters;
}
/**
* @return the maxPoolWait
*/
public int getMaxPoolWait() {
return maxPoolWait;
}
/**
* @param maxPoolWait the maxPoolWait to set
*/
public void setMaxPoolWait(int maxPoolWait) {
this.maxPoolWait = maxPoolWait;
}
/**
* @return the maxARCSize
*/
public long getMaxARCSize() {
return maxARCSize;
}
/**
* @param maxARCSize the maxARCSize to set
*/
public void setMaxARCSize(long maxARCSize) {
this.maxARCSize = maxARCSize;
}
}