/**
* Copyright 2007-2008 University Of Southern California
*
* 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 edu.isi.pegasus.planner.classes;
import java.util.BitSet;
import edu.isi.pegasus.planner.dax.File;
import edu.isi.pegasus.planner.namespace.Metadata;
import java.util.Iterator;
/**
* The logical file object that contains the logical filename which is got from
* the DAX, and the associated set of flags specifying the transient
* characteristics.
* It ends up associating the following information with a lfn
* -type of the file (data or executable)
* -optionality of a file
* -transient attributes of a file (dontTransfer and dontRegister)
*
* @author Gaurang Mehta
* @author Karan Vahi
* @version $Revision$
*/
public class PegasusFile extends Data {
/**
* Enumeration for denoting type of linkage
*/
public static enum LINKAGE {
INPUT, OUTPUT, INOUT, NONE
};
/**
* The index of the flags field which when set indicates that the file
* is to be considered optional.
*/
public static final int OPTIONAL_BIT_FLAG = 0;
/**
* The index of the flags field which when set indicates that the file is
* not to be registered in the RLS/ RC.
*/
public static final int DO_NOT_REGISTER_BIT_FLAG = 1;
/**
* If set, means can be considered for cleanup
*/
public static final int CLEANUP_BIT_FLAG = 2;
/**
* The number of transient flags. This is the length of the BitSet in the
* flags fields.
*/
public static final int NO_OF_TRANSIENT_FLAGS = 3;
/**
* The mode where the transfer for this file to the pool
* is constructed and the transfer job fails if the transfer fails.
* The corresponding dT (dontTransfer) value is false.
*/
public static final int TRANSFER_MANDATORY = 0;
/**
* The mode where the transfer for this file to the pool is constructed,
* but the transfer job should not fail if the transfer fails.
* The corresponding dT (dontTransfer) value is optional.
*/
public static final int TRANSFER_OPTIONAL = 1;
/**
* The mode where the transfer for this file is not constructed.
* The corresponding dT (dontTransfer) value is true.
*/
public static final int TRANSFER_NOT = 2;
/**
* The string value of a file that is of type data.
* @see #DATA_FILE
*/
public static final String DATA_TYPE = "data";
/**
* The string value of a file that is of type executable.
* @see #DATA_FILE
*/
public static final String EXECUTABLE_TYPE = "executable";
/**
* The string value of a file that is of type checkpoint file.
* @see #DATA_FILE
*/
public static final String CHECKPOINT_TYPE = "checkpoint";
/**
* The string value of a file that is of type other.
* @see #OTHER_FILE
*/
public static final String OTHER_TYPE = "other";
/**
* The type denoting that a logical file is a data file.
*/
public static final int DATA_FILE = 0;
/**
* The type denoting that a logical file is a executable file.
*/
public static final int EXECUTABLE_FILE = 1;
/**
* The type denoting that a logical file is a checkpoint file.
*/
public static final int CHECKPOINT_FILE = 2;
/**
* The type denoting that a logical file is an other file.
*/
public static final int OTHER_FILE = 3;
/**
* The logical name of the file.
*/
protected String mLogicalFile;
/**
* The type associated with the file. It can either be a data file or an
* executable file.
*
* @see #DATA_FILE
* @see #EXECUTABLE_FILE
* @see #OTHER_FILE
* @see #CHECKPOINT_FILE
*/
protected int mType;
/**
* Linkage of the file. Only used for parsers
*/
protected LINKAGE mLink;
/**
* The transfer flag associated with the file containing tristate of
* transfer,dontTransfer and optional.
*
* @see #TRANSFER_MANDATORY
* @see #TRANSFER_OPTIONAL
* @see #TRANSFER_NOT
*/
protected int mTransferFlag;
/**
* The transient flags field which is kept as a bit field. It keeps track
* of the dontRegister and optional attributes associated with the filename
* in the dax.
*/
protected BitSet mFlags;
/**
* The size of the file.
*/
protected double mSize;
/**
* Metadata attributes associated with the file.
*/
protected Metadata mMetadata;
/**
* The default constructor.
*/
public PegasusFile() {
super();
mFlags = new BitSet(NO_OF_TRANSIENT_FLAGS);
//by default files are eligible for cleanup
mFlags.set( PegasusFile.CLEANUP_BIT_FLAG );
mLogicalFile = "";
//by default the type is DATA
//and transfers are mandatory
mType = DATA_FILE;
mTransferFlag= this.TRANSFER_MANDATORY;
mSize = -1;
mLink = LINKAGE.NONE;
mMetadata = new Metadata();
}
/**
* The overloaded constructor.
*
* @param lfn the logical name of the file.
*/
public PegasusFile(String lfn) {
this();
mLogicalFile = lfn;
}
/**
* Sets the linkage for the file during parsing.
*
* @param link linkage type
*/
public void setLinkage( LINKAGE link ){
mLink = link;
}
/**
* Returns the linkage for the file during parsing.
*
* @return the linkage
*/
public LINKAGE getLinkage(){
return mLink;
}
/**
* It returns the lfn of the file that is associated with this transfer.
*
* @return the lfn associated with the transfer
*/
public String getLFN(){
return this.mLogicalFile;
}
/**
* It sets the logical filename of the file that is being transferred.
*
* @param lfn the logical name of the file that this transfer is associated
* with.
*/
public void setLFN(String lfn){
mLogicalFile = lfn;
}
/**
* Sets the size for the file.
*
* @param size the size of the file.
*/
public void setSize( double size ) {
mSize = size;
}
/**
* Sets the size for the file.
*
* @param size the size of the file.
*/
public void setSize( String size ) {
if( size == null ){
mSize = -1;
}
else{
mSize = Double.parseDouble( size );
}
}
/**
* Returns the size for the file. Can be -1 if not set.
*
* @return size if set else -1.
*/
public double getSize(){
return mSize;
}
/**
* Returns whether the type of file value is valid or not.
*
* @param type the value for the type of file.
*
* @return true if the value is in range.
* false if the value is not in range.
*/
public boolean typeValid(int type){
return (type >= PegasusFile.DATA_FILE &&
type <= PegasusFile.OTHER_FILE );
}
/**
* Returns whether the transfer value for the mode is in range or not.
*
* @param transfer the value for the transfer.
*
* @return true if the value is in range.
* false if the value is not in range.
*/
public boolean transferInRange(int transfer){
return (transfer >= PegasusFile.TRANSFER_MANDATORY &&
transfer <= PegasusFile.TRANSFER_NOT);
}
/**
* Sets the type flag to value passed.
*
* @param type valid transfer value.
* @exception IllegalArgumentException if the transfer mode is outside
* its legal range.
*
* @see #DATA_FILE
* @see #EXECUTABLE_FILE
* @see #CHECKPOINT_FILE
*/
public void setType(int type) throws IllegalArgumentException{
if(typeValid(type)){
mType = type;
if( mType == PegasusFile.CHECKPOINT_FILE ){
//a checkpoint file is also an optional file
this.setFileOptional();
}
}
else{
throw new IllegalArgumentException();
}
}
/**
* Sets the transient transfer flag to value passed.
*
* @param type valid transfer value.
* @exception IllegalArgumentException if the transfer mode is outside
* its legal range.
*
* @see #DATA_FILE
* @see #EXECUTABLE_FILE
*/
public void setType( String type) throws IllegalArgumentException{
if( type == null || type.length() == 0)
throw new IllegalArgumentException( "Invalid Type passed " + type );
if( type.equals( PegasusFile.DATA_TYPE )){
setType( PegasusFile.DATA_FILE );
}
else if( type.equals( PegasusFile.EXECUTABLE_TYPE )){
setType( PegasusFile.EXECUTABLE_FILE );
}
else if( type.equals( PegasusFile.CHECKPOINT_TYPE )){
setType( PegasusFile.CHECKPOINT_FILE );
}
else if( type.equals( PegasusFile.OTHER_TYPE )){
setType( PegasusFile.OTHER_FILE );
}
else{
throw new IllegalArgumentException( "Invalid Type passed " + type );
}
}
/**
* Sets the transient transfer flag to value passed.
*
* @param transfer valid transfer value.
* @exception IllegalArgumentException if the transfer mode is outside
* its legal range.
*
* @see #TRANSFER_MANDATORY
* @see #TRANSFER_NOT
* @see #TRANSFER_OPTIONAL
*/
public void setTransferFlag(int transfer) throws IllegalArgumentException{
if(this.transferInRange(transfer)){
mTransferFlag = transfer;
}
else{
throw new IllegalArgumentException();
}
}
/**
* Sets the transient transfer flag corresponding to the string
* value of transfer mode passed. The legal range of transfer values is
* true|false|optional.
*
* @param flag tri-state transfer value as got from dontTransfer flag.
*
* @exception IllegalArgumentException if the transfer mode is outside
* its legal range.
*
* @see #TRANSFER_MANDATORY
* @see #TRANSFER_NOT
* @see #TRANSFER_OPTIONAL
*/
public void setTransferFlag( String flag ) throws IllegalArgumentException{
this.setTransferFlag( flag, false );
}
/**
* Sets the transient transfer flag corresponding to the string
* value of transfer mode passed. The legal range of transfer values is
* true|false|optional.
*
* @param flag tri-state transfer value as got from dontTransfer flag.
* @param doubleNegative indicates whether a double negative or not.
*
* @exception IllegalArgumentException if the transfer mode is outside
* its legal range.
*
* @see #TRANSFER_MANDATORY
* @see #TRANSFER_NOT
* @see #TRANSFER_OPTIONAL
*/
public void setTransferFlag( String flag, boolean doubleNegative ) throws IllegalArgumentException{
if( flag == null || flag.length() == 0){
//set to default value.
//throw new IllegalArgumentException();
mTransferFlag = this.TRANSFER_MANDATORY;
return;
}
if( flag.equals("true") ){
mTransferFlag = (doubleNegative) ?
this.TRANSFER_NOT :
this.TRANSFER_MANDATORY;
}
else if( flag.equals("false")){
mTransferFlag = ( doubleNegative ) ?
this.TRANSFER_MANDATORY:
this.TRANSFER_NOT;
}
else if( flag.equals("optional"))
mTransferFlag = this.TRANSFER_OPTIONAL;
else{
throw new IllegalArgumentException( "Invalid transfer value passed " +
flag );
}
}
/**
* Returns whether the transfer is transient or not. By transient we mean
* no transfer.
*
* @return true if transfer mode is TRANSFER_NOT
* false if transfer mandatory or optional.
*/
public boolean getTransientTransferFlag(){
return (mTransferFlag == this.TRANSFER_NOT);
}
/**
* Sets the transient registration flag to true.
*
* @deprecated
* @see #setRegisterFlag( boolean )
*/
public void setTransientRegFlag(){
mFlags.set(DO_NOT_REGISTER_BIT_FLAG);
}
/**
* Sets the transient registration flag to value specified.
*
* @param value the value to set to
*/
public void setRegisterFlag( boolean value ){
mFlags.set( DO_NOT_REGISTER_BIT_FLAG, !value );
}
/**
* Sets the optional flag denoting the file to be optional to true.
*/
public void setFileOptional(){
mFlags.set(OPTIONAL_BIT_FLAG);
}
/**
* Returns optional flag denoting the file to be optional or not.
*
* @return true denoting the file is optional.
* false denoting that file is not optional.
*/
public boolean fileOptional(){
return mFlags.get(OPTIONAL_BIT_FLAG);
}
/**
* Sets the cleanup flag denoting the file can be cleaned up to true.
*/
public void setForCleanup(){
mFlags.set(CLEANUP_BIT_FLAG);
}
/**
* Sets the cleanup flag to the value passed
*
* @param value the boolean value to which the flag should be set to.
*/
public void setForCleanup( boolean value ){
mFlags.set(CLEANUP_BIT_FLAG, value );
}
/**
* Returns cleanup denoting whether the file can be cleaned up or not
*
* @return true denoting the file can be cleaned up.
*/
public boolean canBeCleanedup(){
return mFlags.get(CLEANUP_BIT_FLAG);
}
/**
* Returns the tristate transfer mode that is associated with the file.
*
* @return the int value denoting the type.
*
* @see #DATA_FILE
* @see #EXECUTABLE_FILE
* @see #OTHER_FILE
*/
public int getType(){
return mType;
}
/**
* Returns the tristate transfer mode that is associated with the file.
*
* @return the int value denoting the tristate.
*
* @see #TRANSFER_MANDATORY
* @see #TRANSFER_NOT
* @see #TRANSFER_OPTIONAL
*/
public int getTransferFlag(){
return mTransferFlag;
}
/**
* Returns the value of the register flag
*
* @return true denoting the file needs be registered into the replica
* catalog.
* false denoting that file does not need to be registered.
*/
public boolean getRegisterFlag(){
return !mFlags.get(DO_NOT_REGISTER_BIT_FLAG);
}
/**
* Returns the transient registration flag (the value of dontRegister).
*
* @return true denoting the file need not be registered into the replica
* catalog.
* false denoting that file needs to be registered.
*/
public boolean getTransientRegFlag(){
return mFlags.get(DO_NOT_REGISTER_BIT_FLAG);
}
/**
* Returns the bit fields that contain the transient flags (dR and optional).
*
*
* @see #NO_OF_TRANSIENT_FLAGS
* @see #OPTIONAL_BIT_FLAG
* @see #DO_NOT_REGISTER_BIT_FLAG
*/
public BitSet getFlags(){
return mFlags;
}
/**
* Add all the metadata to the file
*
* @param m
*/
public void addMetadata(Metadata m) {
if( !m.isEmpty() ){
for( Iterator<String> mit = m.getProfileKeyIterator(); mit.hasNext(); ){
String key = mit.next();
this.addMetadata( key, (String)m.get(key));
}
}
}
/**
* Add metadata to the object.
*
* @param key
* @param value
*/
public void addMetadata( String key, String value ){
this.mMetadata.checkKeyInNS( key, value );
}
/**
* Returns metadata attribute for a particular key
*
* @param key
*
* @return value returned else null if not found
*/
public String getMetadata( String key ){
return (String)mMetadata.get( key );
}
/**
* Returns all metadata attributes for the file
*
* @return Metadata
*/
public Metadata getAllMetadata( ){
return this.mMetadata;
}
/**
* Sets metadata attributes for the file
*
* @param m Metadata
*/
public void setMetadata( Metadata m ){
this.mMetadata = m;
}
/**
* Checks if an object is similar to the one referred to by this class.
* We compare the primary key to determine if it is the same or not.
*
* @return true if the primary key (lfn) matches.
* else false.
*/
public boolean equals( Object o ){
if(o instanceof PegasusFile){
PegasusFile file = (PegasusFile) o;
return (file.mLogicalFile.equals(this.mLogicalFile));
}
return false;
}
/**
* Calculate a hash code value for the object to support hash tables.
*
* @return a hash code value for the object.
*/
public int hashCode() {
return this.mLogicalFile.hashCode();
}
/**
* Returns a boolean indicating if a file that is being staged is an
* executable or not (i.e is a data file).
*
* @return boolean indicating whether a file is executable or not.
*/
public boolean isExecutable(){
return (this.mType == PegasusFile.EXECUTABLE_FILE);
}
/**
* Returns a boolean indicating if a file that is being staged is a
* checkpoint file or not.
*
* @return boolean indicating whether a file is a checkpoint file or not.
*/
public boolean isCheckpointFile(){
return (this.mType == PegasusFile.CHECKPOINT_FILE);
}
/**
* Returns a boolean indicating if a file that is being staged is an
* is a data file
*
* @return boolean indicating whether a file is a data file or not.
*/
public boolean isDataFile(){
return (this.mType == PegasusFile.DATA_FILE);
}
/**
* Returns a copy of the existing data object.
*
* @return clone of the object.
*/
public Object clone(){
PegasusFile pf = new PegasusFile();
pf.mLogicalFile = mLogicalFile;
pf.mFlags = (BitSet)this.mFlags.clone();
pf.mType = mType;
pf.mTransferFlag = mTransferFlag;
pf.mSize = mSize;
pf.mMetadata = (Metadata) this.mMetadata.clone();
return pf;
}
/**
* Returns the type associated with the logical file.
*
* @return type of the file.
*/
public String typeToString(){
String result = null;
switch( mType ){
case DATA_FILE:
result = DATA_TYPE;
break;
case EXECUTABLE_FILE:
result = EXECUTABLE_TYPE;
break;
case OTHER_FILE:
result = OTHER_TYPE;
break;
}
return result;
}
/**
* Returns the String version of the data object, which is in human readable
* form.
*
* @return the dump of the data object into a string.
*/
public String toString(){
StringBuffer sb = new StringBuffer();
sb.append( "\n Logical Name :" ).append( this.mLogicalFile ).
append( "\n Type :" ).append( typeToString() ).
append( "\n Size :" ).append( mSize ).
append( "\n Transient Flags (transfer,optional,dontRegister,cleanup):").
append( " ( " ).append( getTransferFlag() ).append( "," );
for(int i = 0; i < NO_OF_TRANSIENT_FLAGS; i ++) {
sb.append( mFlags.get(i) );
if( i < NO_OF_TRANSIENT_FLAGS - 1 ){
sb.append( "," );
}
}
sb.append( ")");
sb.append( "metadata").append( this.getAllMetadata() );
return sb.toString();
}
}