package org.dcache.chimera.namespace;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.util.List;
import diskCacheV111.util.AccessLatency;
import diskCacheV111.util.CacheException;
import diskCacheV111.util.FileNotFoundCacheException;
import diskCacheV111.util.HsmLocationExtractorFactory;
import diskCacheV111.util.RetentionPolicy;
import diskCacheV111.vehicles.StorageInfo;
import org.dcache.chimera.ChimeraFsException;
import org.dcache.chimera.FileNotFoundHimeraFsException;
import org.dcache.chimera.FsInode;
import org.dcache.chimera.StorageGenericLocation;
import org.dcache.chimera.posix.Stat;
import org.dcache.chimera.store.InodeStorageInformation;
public abstract class ChimeraHsmStorageInfoExtractor implements
ChimeraStorageInfoExtractable {
private static final Logger LOGGER =
LoggerFactory.getLogger(ChimeraHsmStorageInfoExtractor.class);
/**
* default access latency for newly created files
*/
private final AccessLatency _defaultAccessLatency;
/**
* default retention policy for newly created files
*/
private final RetentionPolicy _defaultRetentionPolicy;
public ChimeraHsmStorageInfoExtractor(AccessLatency defaultAL,
RetentionPolicy defaultRP) {
_defaultAccessLatency = defaultAL;
_defaultRetentionPolicy = defaultRP;
}
public final AccessLatency getDefaultAccessLatency() {
return _defaultAccessLatency;
}
public final RetentionPolicy getDefaultRetentionPolicy() {
return _defaultRetentionPolicy;
}
@Override
public AccessLatency getAccessLatency(ExtendedInode inode) throws CacheException
{
try {
if (!inode.exists()) {
throw new FileNotFoundCacheException(inode.toString() + " does not exist");
}
ExtendedInode dirInode;
if (inode.isDirectory()) {
dirInode = inode;
} else {
if (inode.statCache().isDefined(Stat.StatAttributes.ACCESS_LATENCY)) {
return inode.statCache().getAccessLatency();
}
dirInode = inode.getParent();
}
Optional<String> accessLatency = getFirstLine(dirInode.getTag("AccessLatency"));
if (accessLatency.isPresent()) {
try {
return AccessLatency.getAccessLatency(accessLatency.get());
} catch (IllegalArgumentException e) {
LOGGER.error("Badly formatted AccessLatency tag in {}: {}", dirInode, e.getMessage());
}
}
Optional<String> spaceToken = getFirstLine(dirInode.getTag("WriteToken"));
if (spaceToken.isPresent() ) {
return null;
}
return getDefaultAccessLatency();
} catch (FileNotFoundHimeraFsException e) {
throw new FileNotFoundCacheException(e.getMessage(), e);
} catch (ChimeraFsException e) {
throw new CacheException("Failed to obtain AccessLatency: " + e.getMessage(), e);
}
}
@Override
public RetentionPolicy getRetentionPolicy(ExtendedInode inode) throws CacheException
{
try {
if (!inode.exists()) {
throw new FileNotFoundCacheException(inode.toString() + " does not exists");
}
ExtendedInode dirInode;
if (inode.isDirectory()) {
dirInode = inode;
} else {
if (inode.statCache().isDefined(Stat.StatAttributes.RETENTION_POLICY)) {
return inode.statCache().getRetentionPolicy();
}
dirInode = inode.getParent();
}
Optional<String> retentionPolicy = getFirstLine(dirInode.getTag("RetentionPolicy"));
if (retentionPolicy.isPresent()) {
try {
return RetentionPolicy.getRetentionPolicy(retentionPolicy.get());
} catch (IllegalArgumentException e) {
LOGGER.error("Badly formatted RetentionPolicy tag in {}: {}", dirInode, e.getMessage());
}
}
Optional<String> spaceToken = getFirstLine(dirInode.getTag("WriteToken"));
if (spaceToken.isPresent() ) {
return null;
}
return getDefaultRetentionPolicy();
} catch (FileNotFoundHimeraFsException e) {
throw new FileNotFoundCacheException(e.getMessage(), e);
} catch (ChimeraFsException e) {
throw new CacheException("Failed to obtain RetentionPolicy: " + e.getMessage(), e);
}
}
/*
* (non-Javadoc)
*
* @see diskCacheV111.util.StorageInfoExtractable#getFileAttributes(java.lang.String,
* diskCacheV111.util.PnfsId)
*/
@Override
public StorageInfo getStorageInfo(ExtendedInode inode)
throws CacheException {
try {
if( !inode.exists() ) {
throw new FileNotFoundCacheException(inode.toString() + " does not exist");
}
} catch (ChimeraFsException e) {
throw new CacheException(e.getMessage());
}
StorageInfo info;
ExtendedInode dirInode;
if (inode.isDirectory()) {
info = getDirStorageInfo(inode);
dirInode = inode;
} else {
info = getFileStorageInfo(inode);
dirInode = inode.getParent();
}
// overwrite hsm type with hsmInstance tag
Optional<String> hsmInstance = getFirstLine(dirInode.getTag("hsmInstance"));
if (hsmInstance.isPresent()) {
info.setHsm(hsmInstance.get().intern());
}
Optional<String> cacheClass = getFirstLine(dirInode.getTag("cacheClass"));
if (cacheClass.isPresent()) {
info.setCacheClass(cacheClass.get().intern());
}
Optional<String> spaceToken = getFirstLine(dirInode.getTag("WriteToken"));
if (spaceToken.isPresent() ) {
info.setKey("writeToken", spaceToken.get());
}
Optional<String> path = getFirstLine(dirInode.getTag("Path"));
if (path.isPresent() ) {
info.setKey("path", path.get());
}
return info;
}
public abstract StorageInfo getFileStorageInfo(ExtendedInode inode) throws CacheException;
public abstract StorageInfo getDirStorageInfo(ExtendedInode inode) throws CacheException;
/*
* (non-Javadoc)
*
* @see diskCacheV111.util.StorageInfoExtractable#setStorageInfo(java.lang.String,
* diskCacheV111.util.PnfsId, diskCacheV111.vehicles.StorageInfo, int)
*/
@Override
public void setStorageInfo(FsInode inode, StorageInfo dCacheStorageInfo) throws CacheException {
try {
if(dCacheStorageInfo.isSetAddLocation() ) {
List<URI> locationURIs = dCacheStorageInfo.locations();
if( !locationURIs.isEmpty() ) {
InodeStorageInformation storageInfo = new InodeStorageInformation(inode,
dCacheStorageInfo.getHsm(),
dCacheStorageInfo.getKey("store"),
dCacheStorageInfo.getKey("group"));
inode.getFs().setStorageInfo(inode, storageInfo);
}
for(URI location : locationURIs) {
// skip bad URI's if the get here
if(location.toString().isEmpty()) {
continue;
}
HsmLocationExtractorFactory.validate(location);
inode.getFs().addInodeLocation(inode, StorageGenericLocation.TAPE, location.toString());
}
}
}catch(FileNotFoundHimeraFsException e) {
throw new FileNotFoundCacheException(e.getMessage());
}catch(ChimeraFsException he ) {
throw new CacheException(he.getMessage() );
}
}
protected static Optional<String> getFirstLine(ImmutableList<String> lines)
{
if (!lines.isEmpty()) {
String line = lines.get(0).trim();
if (!line.isEmpty()) {
return Optional.of(line);
}
}
return Optional.absent();
}
}