package s3.services.transactions;

import ovm.core.OVMBase;
import ovm.core.domain.Domain;
import ovm.core.domain.LinkageException;
import ovm.core.domain.Method;
import ovm.core.domain.Oop;
import ovm.core.domain.ReflectiveConstructor;
import ovm.core.domain.Type.Class;
import ovm.core.repository.RepositoryMember;
import ovm.core.repository.RepositoryUtils;
import ovm.core.repository.Selector;
import ovm.core.repository.TypeName;
import ovm.core.repository.UnboundSelector;
import ovm.core.repository.TypeName.Scalar;
import ovm.core.services.memory.VM_Address;
import ovm.core.services.threads.OVMThread;
import ovm.core.stitcher.InvisibleStitcher;
import ovm.core.stitcher.InvisibleStitcher.PragmaStitchSingleton;
import ovm.services.bytecode.SpecificationIR.ValueSource;
import ovm.util.BitSet;
import ovm.util.OVMError;
import s3.core.domain.S3Type;

public abstract class Transaction extends OVMBase {

    static final String PACKAGE_NAME = "org/ovmj/transact";
    static final int PACKAGE = RepositoryUtils.asUTF(PACKAGE_NAME);       
    public static final Scalar transaction = Scalar.make(PACKAGE, RepositoryUtils.asUTF("Transaction"));
    public static final Selector.Method Transaction_start = RepositoryUtils.
    	selectorFor(transaction, TypeName.VOID, "start", new TypeName[] {});
    public static final Selector.Method Transaction_commit = RepositoryUtils.
    	selectorFor(transaction, TypeName.VOID, "commit", new TypeName[] {});
     public static final Scalar  ABORTED_EXCEPTION = (Scalar) RepositoryUtils.makeTypeName(PACKAGE_NAME, "AbortedException");     
     static final Scalar ATOMIC = (Scalar) RepositoryUtils.makeTypeName(PACKAGE_NAME, "Atomic");
   
     public static final Scalar s3transaction = Scalar.make(PACKAGE,RepositoryUtils.asUTF("S3Transaction"));
     public static final Selector.Method S3Transaction_doLog = RepositoryUtils.selectorFor(s3transaction, TypeName.VOID, "doLog", new TypeName[] {});

     /**
      * Method used to stich the singleton Transaction object. The config/s3common
      * file tells us which one of S3Transaction or EmptyTransaction it will be. 
      */
     static public Transaction the() throws PragmaStitchSingleton {
 	return (Transaction) InvisibleStitcher.singletonFor(Transaction.class.getName());
     }
    
    // RUNTIME METHODS
    public void  boot() {};
    public boolean inTransaction() { return false; }    
    public abstract void par_log(VM_Address object, int offset);   
    public abstract void par_logw(VM_Address object, int offset);    
    public abstract void par_log_arr(Oop arr, int idx);    
    public abstract void par_log_arrw(Oop arr, int idx);    
    public void par_read() {}
    public abstract void undo();    
    public abstract void retry();
    public abstract void openCommit(int id);    
    public abstract void start(int size, boolean commit);    
    public abstract void start();   
    public abstract int  openStart();    
    public abstract void commit();    
    public int logSize() { return -1; }
    public void abort() {}
    public void postRunThreadHook(boolean aborting) {};    
    public boolean preRunThreadHook(OVMThread currentThread, OVMThread nextThread) { return false;}
    public boolean PARenabled() { return false; }
    
    // BUILD TIME METHODS
    public void setAbortedExceptionConstructor(ReflectiveConstructor _) {}    
    public abstract Method selectReflectiveMethod(Method method);    
    public String getTRANS_SUFFIX() { return "";}
    public void setReflectiveCalls(BitSet[] reflectiveCalls, Domain d, Method[] meth, int i) {}    
    public UnboundSelector.Method translateTransactionalSelector(UnboundSelector.Method usel) { return usel;  }    
    public boolean isTransMethod(Method m) { return false; }    
    public boolean transactionalMode() { return false; }    
    public RepositoryMember.Method[] initMethods(S3Type t, RepositoryMember.Method[] r, RepositoryMember.Method[] c) {
	throw new OVMError.Configuration("Unimplemented");     
    }
    public boolean isAtomic(Method method) {
	int cnt = method.getThrownTypeCount();
	for (int i = 0; i < cnt; i++) 
	    try {
		Class exception = method.getThrownType(i);
		if (exception.getName().equals(ATOMIC)) return true;
	    } catch (LinkageException e) { throw new OVMError.Internal(e); }	
         return false;
    }
    
    public boolean ignoreLogCall(ValueSource _exp) { return false;  }

    public boolean gatherStatistics() {return false; }

}