Package com.mobixess.jodb.core.transaction

Source Code of com.mobixess.jodb.core.transaction.JODBSession$StaleReferencesCleanerThread

/**
* Copyright Mobixess Inc. 2007
*/
package com.mobixess.jodb.core.transaction;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.BitSet;
import java.util.ConcurrentModificationException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.mobixess.jodb.core.IPersistentObjectStatistics;
import com.mobixess.jodb.core.IllegalClassTypeException;
import com.mobixess.jodb.core.JODBConfig;
import com.mobixess.jodb.core.JODBTransient;
import com.mobixess.jodb.core.JodbIOException;
import com.mobixess.jodb.core.index.JODBIndexingRootAgent;
import com.mobixess.jodb.core.io.IOBase;
import com.mobixess.jodb.core.io.IOTicket;
import com.mobixess.jodb.core.io.ObjectDataContainer;
import com.mobixess.jodb.core.plugin.IObjectInstanceProvider;
import com.mobixess.jodb.core.plugin.JODBObjectInstanceFactory;
import com.mobixess.jodb.core.query.JODBQueryList;
import com.mobixess.jodb.core.query.SimpleArrayQueryList;
import com.mobixess.jodb.util.PrimitiveJavaTypesUtil;
import com.mobixess.jodb.util.Utils;

/**
* @author Mobixess
*
*/
public class JODBSession {
    private Hashtable<Object, PersistentObjectHandle> _activeObjects = new Hashtable<Object, PersistentObjectHandle>();
    private Object _activationSynchObject = new Object();
    private ClassLoader _classLoader;
   
    private IOBase _base;
    private WeakHashMap<Class, ClassDescriptor> _classDescriptors = new WeakHashMap<Class, ClassDescriptor>();//TODO add caching per class loader
//    private WeakHashMap<ClassDescriptor, int[]> _fieldSubstitutionsIDs = new WeakHashMap<ClassDescriptor, int[]>();
    private ActiveObjectReferenceCleaner _activeObjectReferenceCleaner = new ActiveObjectReferenceCleaner();
    private static WeakHashMap<ActiveObjectReferenceCleaner, Object> _cleanersCache = new WeakHashMap<ActiveObjectReferenceCleaner, Object>();
    private static StaleReferencesCleanerThread _staleReferencesCleanerThread;
    private Logger _logger = Utils.getLogger(getClass().getName());
    private static ThreadLocal<SearchKeysHolder> _persistentObjectHandleSearchCache = new ThreadLocal<SearchKeysHolder>(){
        @Override
        protected SearchKeysHolder initialValue()
        {
            return new SearchKeysHolder();
        }
    };
   
   
    /**
     * @param base
     */
    public JODBSession(IOBase base) {
        super();
        _base = base;
        _classLoader = JODBConfig.getCustomClassLoader();
        if (JODBConfig.isBackgroundReferenceCleanerEnabled()) {
            synchronized (_cleanersCache) {//synch with cleaner thread deactivation in StaleReferencesCleanerThread
                _cleanersCache.put(_activeObjectReferenceCleaner, null);
                if(_staleReferencesCleanerThread == null){
                    _staleReferencesCleanerThread = new StaleReferencesCleanerThread();
                    if(JODBConfig.DEBUG){
                        _logger.info("Background reference cleaner thread start");
                    }
                    _staleReferencesCleanerThread.start();
                }
            }
        }
    }
   
    public void close(){
        _activeObjects.clear();
        _cleanersCache.remove(_activeObjectReferenceCleaner);
    }

    public PersistentObjectHandle getHandleForActiveObject(Object obj){
        _activeObjectReferenceCleaner.removeStaleReferences();
        ActiveObjectWeakRefHolderSearchKey searchKey = _persistentObjectHandleSearchCache.get()._activeObjectWeakRefHolderSearchKey;
        searchKey.setSearchKey(obj);
        PersistentObjectHandle persistentObjectHandle = _activeObjects.get(searchKey);
        searchKey.setSearchKey(null);//reset hard reference
        if( persistentObjectHandle != null ){
            synchronized (persistentObjectHandle) {//just to make sure that object is actually initialized
                return persistentObjectHandle;
            }
        }
        return null;
    }
   
    public void putObject(Object obj, PersistentObjectHandle handle){
        _activeObjectReferenceCleaner.removeStaleReferences();
        _activeObjects.put(handle.getReference(), handle);
        _activeObjects.put(handle, handle);
    }
   
    private void removeObject(Object obj){
        _activeObjectReferenceCleaner.removeStaleReferences();
        ActiveObjectWeakRefHolderSearchKey searchKey = _persistentObjectHandleSearchCache.get()._activeObjectWeakRefHolderSearchKey;
        searchKey.setSearchKey(obj);
        PersistentObjectHandle persistentObjectHandle = _activeObjects.remove(searchKey);
        if(persistentObjectHandle != null){
            _activeObjects.remove(persistentObjectHandle);
        }
        searchKey.setSearchKey(null);//reset hard reference
    }
   
    public PersistentObjectHandle createHandleForObject(Object obj, long offset, ObjectDataContainer objectDataContainer) throws IOException{
        byte dataMask = objectDataContainer.getPrimaryDataMask();
        return createHandleForObject(obj, offset, dataMask, (byte) objectDataContainer.getCyclicVersionCounter(), objectDataContainer.getHashIdentity());
    }
   
    public PersistentObjectHandle createHandleForObject(Object obj, long offset, byte dataMask, byte version, int identityHash){
        ActiveObjectWeakRefHolder activeObjectWeakRefHolder = new ActiveObjectWeakRefHolder(obj,_activeObjectReferenceCleaner._referenceQueue);
        if(_base.isRemote()){
            ExtendedPersistentObjectHandle persistentObjectHandle = new ExtendedPersistentObjectHandle(activeObjectWeakRefHolder,dataMask,offset, version,identityHash);
            return persistentObjectHandle;
        }else {
            PersistentObjectHandle persistentObjectHandle = new PersistentObjectHandle(activeObjectWeakRefHolder,dataMask,offset, version);
            return persistentObjectHandle;
        }
    }
   
    public int getCachedObjectsCount(){
        _activeObjectReferenceCleaner.removeStaleReferences();
        return _activeObjects.size();
    }
   
    public JODBQueryList getAllObjects() throws IOException{
        IOTicket ioTicket = _base.getIOTicket(true, false);
        ioTicket.lock(false);
        long[] offsets;
        try {
            offsets = _base.getForAllObjects(ioTicket);
        } finally {
            ioTicket.unlock();
        }
        ioTicket.close();
        return new SimpleArrayQueryList(offsets,this);
    }
   
    public void setClassLoader(ClassLoader classLoader) {
        _classLoader = classLoader;
        _classDescriptors.clear();
    }
   
    public Class resolveClassForName(String className) throws ClassNotFoundException{
        try {
            ClassLoader classLoader = _classLoader;
            if (classLoader != null) {
                return classLoader.loadClass(className);
            }
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            Class clazz = PrimitiveJavaTypesUtil.primitiveClassForName(className);
            if(clazz == null){
                throw e;
            }
            return clazz;
        }       
    }
   
    public Class resolveClassForID(int classNameID) throws ClassNotFoundException, JodbIOException{
        String name = _base.getClassTypeForID(classNameID);
        if(name == null){
            throw new ClassNotFoundException("id="+classNameID);
        }
        return resolveClassForName(name);
    }
   
    public ClassDescriptor getDescriptorForClass(int classNameID) throws  ClassNotFoundException, JodbIOException{
        Class clazz = resolveClassForID(classNameID);
        return getDescriptorForClass(clazz);
    }
   
    public ClassDescriptor getDescriptorForClass(String name) throws ClassNotFoundException{
        return getDescriptorForClass(resolveClassForName(name));
    }
   
    public IPersistentObjectStatistics getPersistenceStatistics(Object object) throws IOException{
        PersistentObjectHandle objectHandle = getHandleForActiveObject(object);
        if(objectHandle == null){
            return null;
        }
        return _base.getPersistenceStatistics(objectHandle.getObjectEntryOffset(), this);
    }
   
    public void activate(Object obj, int depth) throws IOException {
        PersistentObjectHandle handle = getHandleForActiveObject(obj);
        if(handle == null){
            return;
        }
        IOTicket ioTicket = _base.getIOTicket(true, false);
        ioTicket.lock(false);
        try {
            TransactionUtils.launchObject(this, handle.getObjectEntryOffset(), obj, depth);
        }catch (Exception e) {
            ioTicket.unlock();
        }
    }
   
    public void deactivate(Object obj, int depth) {
        if(depth <=0 || obj == null){
            return;
        }
        PersistentObjectHandle handle = getHandleForActiveObject(obj);
        if(handle == null){
            return;
        }
        ClassDescriptor classDescriptor = getDescriptorForClass(obj.getClass());
        FieldAndIDRecord[] fields = classDescriptor.getAllFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i]._field;
            try {
                if (field.getType().isPrimitive()) {
                    Object defaultValue = PrimitiveJavaTypesUtil.getDefaultWrapperInstance(field.getType().getName());
                    field.set(obj, defaultValue);
                } else {
                    Object currentValue = field.get(obj);
                    if (currentValue != null) {
                        deactivate(currentValue, depth - 1);
                    }
                    if(JODBConfig.isAllowNullInReflectionSet()){
                        field.set(obj, null);
                    }
                }
            } catch (Exception e) {
                _logger.log(Level.SEVERE, "", e);
            }           
        }
        removeObject(obj);
    }
   
    public Object getObjectForOffset(long offset) throws IOException{
        return getObjectForOffset(offset, JODBConfig.getDefaultActivationDepth());
    }
   
    public Object getObjectForOffset(long offset, int activationDepth) throws IOException{
        Object result = getObjectFromCache(offset);
        if(result == null){
            result = TransactionUtils.launchObject(this, offset, null, activationDepth);
        }
        return result;
    }
   
    public long getIndexingRootAgentOffset() throws IOException{
        return _base.getFirstObjectOffset();
    }
   
    public JODBIndexingRootAgent getIndexingRootAgent() throws IOException{
        long offset = getIndexingRootAgentOffset();
        return (JODBIndexingRootAgent) getObjectForOffset(offset, Integer.MAX_VALUE);
    }
   
    public void ensureIndexVersion(long version) throws IOException{
        JODBIndexingRootAgent indexingRootAgent = getIndexingRootAgent();
        if(version!=indexingRootAgent.getVersion()){
            long offset = getIndexingRootAgentOffset();
            TransactionUtils.launchObject(this, offset, null, Integer.MAX_VALUE);
        }
    }
   
    public Object getObjectFromCache(long offset){
        PersistentObjectHandle searchHandle = _persistentObjectHandleSearchCache.get()._persistentObjectHandle;
        searchHandle.setObjectEntryOffset(offset);
        PersistentObjectHandle handle = _activeObjects.get(searchHandle);
        Object result = null;
        if(handle!=null){
            result = handle.getObject();
        }
        if(result!=null){
            synchronized (handle) {
                return result;
            }
        }
        return result;
    }

    public IOBase getBase() {
        return _base;
    }
   
    public Object getActivationSynchObject() {
        return _activationSynchObject;
    }
   
    public ClassDescriptor getDescriptorForClass(Class clazz){
        return getDescriptorForClass(clazz,true);
    }
   
    public ClassDescriptor getDescriptorForClass(Class clazz, boolean forPersistance, Field... fieldsToIgnore ) {
        synchronized (_classDescriptors) {
            ClassDescriptor result = _classDescriptors.get(clazz);
            if(result==null){
                result = new ClassDescriptor(clazz, this, forPersistance, fieldsToIgnore);
                _classDescriptors.put(clazz, result);
            }else if(forPersistance){
                result.setForPersistance(true);
            }
            return result;
        }
    }
   
   
   
    private static class SearchKeysHolder{
        ActiveObjectWeakRefHolderSearchKey _activeObjectWeakRefHolderSearchKey = new ActiveObjectWeakRefHolderSearchKey();
        PersistentObjectHandle _persistentObjectHandle = new PersistentObjectHandle();
    }
   
   
    private class ActiveObjectReferenceCleaner{

        private ReferenceQueue<Object> _referenceQueue = new ReferenceQueue<Object>();
       
        public void removeStaleReferences(){
            Object r;
            while ((r = _referenceQueue.poll()) != null) {
                clearReference(r);
            }
        }
       
//        public void removeStaleReferencesBlocking() throws InterruptedException{
//            Object r;
//            while ((r = _referenceQueue.remove()) != null) {
//                if(JODBConfig.DEBUG){
//                    _logger.info("clean reference "+r);
//                }
//                clearReference(r);
//            }
//        }
       
        private void clearReference(Object r){
            if(!(r instanceof ActiveObjectWeakRefHolder)){
                _logger.warning("unexpected reference in queue "+ r);
                return;
            }
            if(JODBConfig.DEBUG && false){
              _logger.info("clean reference "+r);
            }
            ActiveObjectWeakRefHolder activeObjectWeakRefHolder = (ActiveObjectWeakRefHolder) r;
            synchronized (_activeObjects) {
                PersistentObjectHandle handle = _activeObjects.remove(activeObjectWeakRefHolder);
                if(handle!=null){
                    _activeObjects.remove(handle);
                }
            }
        }
       
//        public void startCleanerThread(){
//            Thread thread = new Thread(this,"JODB Reference Cleaner");
//            thread.setDaemon(true);
//            thread.setPriority(Thread.MIN_PRIORITY);
//            thread.start();
//        }
       
    }
   
    private static class ActiveObjectWeakRefHolderSearchKey extends ActiveObjectWeakRefHolder{

        private Object _searchKey;
       
        public ActiveObjectWeakRefHolderSearchKey() {
            super(null);
        }

        @Override
        protected Object getReferencedObject()
        {
            return _searchKey;
        }
       
        public void setSearchKey(Object key){
            _identityHashCode = System.identityHashCode(key);
            _searchKey = key;
        }
    }
   
    public static class ClassDescriptor{
        private Class _class;
       
        private FieldAndIDRecord[] _cumulativeFields;
       
        private FieldAndIDRecord[] _declaredFields;
       
        private Method[] _cumulativeMethods;

        private String[] _types;
       
        private Constructor _instantiationConstructor;
       
        private Object[] _instantiationParams;
       
        private boolean _array;
       
        private boolean _isString;
       
        private boolean _primitiveArray;
       
        private Class _arrayType;
       
        private int _primitiveFieldSizeEstimationIncrement = -1;
       
        private int _primitiveFieldsStoreSize = -1;
       
        private IObjectInstanceProvider _instanceProvider;
       
        private FieldAndIDRecord[] _primitiveFields;
       
        private FieldAndIDRecord[] _objectFields;
       
        private boolean _needFieldsIdsSet = true;
       
        private boolean _initConstructors = true;
       
        private FieldAndIDRecord _searchKey = new FieldAndIDRecord(null);
       
        private JODBSession _session;
       
        private boolean _forPersistance;
       
        private boolean _innerClass;
       
        private Field _outerRefField;
       
        private Field[] _fieldsToIgnore;
       
        //private int[] _substitutionIDs = null;

        private ClassDescriptor(Class clazz, JODBSession session, boolean forPersistance, Field... fieldsToIgnore) {
            super();
            _session = session;
            _forPersistance = forPersistance;
            _fieldsToIgnore = fieldsToIgnore;
            if(clazz.isArray()){
                Class type = clazz.getComponentType();
                if(type == null && clazz == String.class){
                    type = clazz;
                }
                initForArray(type);
            }else{
                Vector<FieldAndIDRecord> fieldsResult = new Vector<FieldAndIDRecord>();
                Vector<String> typeResults = new Vector<String>();
                extractAllFieldsAndTypes(clazz, fieldsResult, typeResults);
                _instanceProvider = JODBObjectInstanceFactory.getProvider(clazz);
                _cumulativeFields = new FieldAndIDRecord[fieldsResult.size()];
                _types =  new String[typeResults.size()];
                fieldsResult.copyInto(_cumulativeFields);
                typeResults.copyInto(_types);
            }
            _class = clazz;
            _innerClass = false;
            try{
                _innerClass = _class.getEnclosingClass()!=null && (_class.getModifiers()&Modifier.STATIC) == 0;
            }catch (Exception e) {
                e.printStackTrace();
            }
            initDeclaredFields();
        }
       
        private final boolean isIgnoreField(Field field){
            if(_fieldsToIgnore==null){
                return false;
            }
            for (Field next : _fieldsToIgnore) {
                if(next.equals(field)){
                    return true;
                }
            }
            return false;
        }
       
        private void initForArray(Class arrayType){
            _isString = arrayType == String.class;
            _arrayType = _isString?char.class:arrayType;
            _array = true;
            _types = _isString? new String[]{String.class.getName(),arrayType.getName()}: new String[]{arrayType.getName()};
            _primitiveArray = arrayType.isPrimitive();
        }
       
        public boolean isInnerClass() {
            return _innerClass;
        }
       
        public Field getOuterRefField(){
            if(_innerClass && _outerRefField==null){
                Class outer = _class.getEnclosingClass();
                Class clazz = _class;
                while(clazz!=null){
                    Field[] fields = clazz.getDeclaredFields();
                    for (int i = 0; i < fields.length; i++) {
                        Field next = fields[i];
                        if((next.getModifiers()& Modifier.FINAL)!=0 && next.getName().startsWith("this$") && next.getType() == outer){
                            if(_outerRefField!=null){
                                throw new RuntimeException("Illegal inner type");
                            }
                            next.setAccessible(true);
                            _outerRefField = next;
                        }
                    }
                    clazz = clazz.getSuperclass();
                }
            }
            return _outerRefField;
        }

        public synchronized void testConstructor() throws IllegalClassTypeException{
            //Class clazz = _class;
            if(_class.isPrimitive()){
                return;
           
            if(!_initConstructors && _instantiationConstructor == null){
                throw new IllegalClassTypeException(_class);
            }
            _initConstructors = false;
            Constructor[] constructors = _class.getDeclaredConstructors();
            for (int i = 0; i < constructors.length; i++) {//find default constructor if exists, and move to first position
                Class[] params = constructors[i].getParameterTypes();
                if(params.length == 0){
                    if(i==0){
                        break;
                    }
                    Constructor temp = constructors[0];
                    constructors[0] = constructors[i];
                    constructors[i] = temp;
                }
            }
            for (int i = 0; i < constructors.length; i++) {
                Constructor constructor = constructors[i];
                constructor.setAccessible(true);
                Class[] params = constructor.getParameterTypes();
                Object[] paramValues = new Object[params.length];
                try {
                    for (int j = 0; j < params.length; j++) {
                        if(!params[j].isPrimitive()){
                            continue;
                        }
                        paramValues[j] = PrimitiveJavaTypesUtil.getDefaultWrapperInstance(params[j].getName());
                    }
                    constructor.newInstance(paramValues);
                    _instantiationConstructor = constructor;
                    _instantiationParams = paramValues;
                    return;
                } catch(Throwable e) {
                    //e.printStackTrace();
                }
            }
            throw new IllegalClassTypeException(_class);
        }
       
        private void initDeclaredFields(){
            Field[] fields = _class.getDeclaredFields();
            Vector<FieldAndIDRecord> declaredFields = new Vector<FieldAndIDRecord>();
            processFields(fields, declaredFields);
            _declaredFields = (FieldAndIDRecord[]) declaredFields.toArray(new FieldAndIDRecord[declaredFields.size()]);
            Arrays.sort(_declaredFields);
        }
       
        private void processFields(Field[] fields, Vector<FieldAndIDRecord> fieldsResult){
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                int modifiers = fields[i].getModifiers();
                if ( isIgnoreField(field) || (modifiers & (Modifier.FINAL | Modifier.STATIC)) != 0)
                {
                    continue;
                }
                if( (modifiers & Modifier.TRANSIENT)!= 0 && JODBConfig.isSkipNativeTransientFields()){
                    continue;
                }
                Annotation[] annotations = fields[i].getAnnotations();
                boolean transientField = false;
                for (int j = 0; j < annotations.length; j++) {
                    if(annotations[j] instanceof JODBTransient){
                        transientField = true;
                        break;
                    }
                }
                if(transientField){
                    continue;
                }
                fieldsResult.add(new FieldAndIDRecord(field));
                field.setAccessible(true);
            }
        }

        private void extractAllFieldsAndTypes(Class clazz, Vector<FieldAndIDRecord> fieldsResult, Vector<String> types){
            if(clazz.isArray()){
                return;
            }
            if(clazz.isPrimitive()){
                types.add(clazz.getName());
                return;
            }
            if (fieldsResult!=null) {
                Field[] fields = clazz.getDeclaredFields();
                processFields(fields, fieldsResult);
            }       
            if(types!=null){
                types.add(clazz.getName());
            }
            Class superClass = clazz.getSuperclass();
            if(superClass!=null && superClass != clazz && !superClass.equals(Object.class)){
                extractAllFieldsAndTypes(superClass, fieldsResult, types);
            }
        }
       
        private void extractAllMethods(Class clazz, Vector<Method> result){    
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (int i = 0; i < declaredMethods.length; i++) {
                result.add(declaredMethods[i]);
            }
            Class superClass = clazz.getSuperclass();
            if(superClass!=null && superClass != clazz && !superClass.equals(Object.class)){
                extractAllMethods(clazz, result);
            }
        }
       
        public Method getMethodForName(String name){
            if(_cumulativeMethods==null){
                Vector<Method> methods = new Vector<Method>();
                extractAllMethods(_class, methods);
                _cumulativeMethods = methods.toArray(new Method[methods.size()]);
            }
            for (int i = 0; i < _cumulativeMethods.length; i++) {
                if(_cumulativeMethods[i].getName().equals(name)){
                    return _cumulativeMethods[i];
                }
            }
            return null;
        }

        public Class getType() {
            return _class;
        }
       
        public boolean isHierarchyType(String type){
            for (int i = 0; i < _types.length; i++) {
                if(_types[i].equals(type)){
                    return true;
                }
            }
            return false;
        }
       
        public int getHierarchyTypeIndex(String type){
            for (int i = 0; i < _types.length; i++) {
                if(_types[i].equals(type)){
                    return i;
                }
            }
            return -1;
        }
       
        public void setForPersistance(boolean forPersistance) {
            _forPersistance = forPersistance;
        }

        private synchronized void checkSubstIdsSet(){
            if( _needFieldsIdsSet && _forPersistance){
                if(!_array){
                    for (int i = 0; i < _cumulativeFields.length; i++) {
                        _cumulativeFields[i]._id = _session._base.getOrSetFieldSubstitutionID(_cumulativeFields[i]._field);
                    }
                    Arrays.sort(_cumulativeFields);
                }
                _needFieldsIdsSet = false;
            }
        }
       
       
//        public synchronized int[] getFieldsSubstitutionIDs(){
//            if(_substitutionIDs!=null){
//                return _substitutionIDs;
//            }
//            _substitutionIDs = new int[_fields.length];
//            for (int i = 0; i < _substitutionIDs.length; i++) {
//                _substitutionIDs[i] = _base.getOrSetFieldSubstitutionID(_fields[i]);
//            }
//            return _substitutionIDs;
//        }
       
        public int getPrimitiveFieldsTotal() {
            if(_primitiveFields == null){
                calcFieldsCount();
            }
            return _primitiveFields.length;
        }
       
        public int getObjectFieldsTotal() {
            if(_objectFields == null){
                calcFieldsCount();
            }
            return _objectFields.length;
        }
       
        private void calcFieldsCount(){
            checkSubstIdsSet();
            Vector<FieldAndIDRecord> primitiveFields = new Vector<FieldAndIDRecord>();
            Vector<FieldAndIDRecord> objectFields = new Vector<FieldAndIDRecord>();
            for (int i = 0; i < _cumulativeFields.length; i++) {
                if(_cumulativeFields[i]._field.getType().isPrimitive()){
                    primitiveFields.add(_cumulativeFields[i]);
                }else{
                    objectFields.add(_cumulativeFields[i]);
                }
            }
            _primitiveFields = primitiveFields.toArray(new FieldAndIDRecord[primitiveFields.size()]);
            _objectFields = objectFields.toArray(new FieldAndIDRecord[objectFields.size()]);
        }
       
        public boolean isPrimitive(){
            return _class.isPrimitive();
        }
       
        public boolean isArray() {
            return _array;
        }
       
        public Class getArrayType() {
            return _arrayType;
        }
       
        public FieldAndIDRecord[] getAllFields() {
            checkSubstIdsSet();
            return _cumulativeFields;
        }
       
        public Class getTopmostFieldOwner(String name){
            for (int i = 0; i < _declaredFields.length; i++) {
                if(_declaredFields[i]._field.getName().equals(name)){
                    return _class;
                }
            }
            Class superClass = _class.getClass();
            if(superClass == null || superClass instanceof Object){
                return null;
            }
            ClassDescriptor superClassDescriptor = _session.getDescriptorForClass(superClass);
            return superClassDescriptor.getTopmostFieldOwner(name);
        }

        public String[] getTypes() {
            return _types;
        }
       
        public boolean isPrimitiveArray() {
            return _primitiveArray;
        }
       
        public Object newInstance() throws IllegalClassTypeException{
            return newInstance(null);
        }
       
        public Object newInstance(Object enclosingInstance) throws IllegalClassTypeException{
            if(_instanceProvider!=null){
                return _instanceProvider.newInstance();
            }
            if(!isArray()){
                testConstructor();
            }
            try {
                Object[] instantiationParams = _instantiationParams;
                if(isInnerClass() && enclosingInstance != null){
//                    if(enclosingInstance == null){
//                        throw new IllegalClassTypeException(_class);
//                    }
                    instantiationParams = _instantiationParams.clone();
                    Class[] constructParamTypes = _instantiationConstructor.getParameterTypes();
                    for (int i = 0; i < constructParamTypes.length; i++) {
                        if(constructParamTypes[i] == enclosingInstance.getClass()){
                            instantiationParams[i] = enclosingInstance;
                        }
                    }
                }
                return _instantiationConstructor.newInstance(instantiationParams);
            } catch (Exception e) {
                e.printStackTrace();
                throw new IllegalClassTypeException(_class);
            }
        }
       
        public synchronized int getPrimitiveFieldsStorageEstimate(int auxiliaryDataPerFieldSize) throws JodbIOException{
            if(auxiliaryDataPerFieldSize != _primitiveFieldSizeEstimationIncrement || _primitiveFieldsStoreSize == -1){
                _primitiveFieldsStoreSize = 0;
                for (int i = 0; i < _cumulativeFields.length; i++) {
                    Field field = _cumulativeFields[i]._field;
                    if(field.getType().isPrimitive()){
                        _primitiveFieldsStoreSize+= auxiliaryDataPerFieldSize+PrimitiveJavaTypesUtil.getDataOutputWriteLen(field.getType());
                    }
                }
                _primitiveFieldSizeEstimationIncrement = auxiliaryDataPerFieldSize;
            }
            return _primitiveFieldsStoreSize;
        }
       
        public Field getFieldForName(String name){
            for (int i = 0; i < _cumulativeFields.length; i++) {
                if(_cumulativeFields[i]._field.getName().equals(name)){
                    return _cumulativeFields[i]._field;
                }
            }
            return null;
        }
       
        public int getFieldIDForName(String name){
            checkSubstIdsSet();
            for (int i = 0; i < _cumulativeFields.length; i++) {
                if(_cumulativeFields[i]._field.getName().equals(name)){
                    return _cumulativeFields[i]._id;
                }
            }
            return -1;
        }
       
        public int getFieldIndexForID(int id){
            checkSubstIdsSet();
            if(_cumulativeFields.length <= 5){
                for (int i = 0; i < _cumulativeFields.length; i++) {
                    if(_cumulativeFields[i]._id == id){
                        return i;
                    }
                }
            }else{
                synchronized (_searchKey) {
                    _searchKey._id = id;
                    return Arrays.binarySearch(_cumulativeFields, _searchKey);
                }
            }
            return -1;
       

        public Field getFieldForID(int id, BitSet indexes){
            checkSubstIdsSet();
            int index = getFieldIndexForID(id);
            if(index!=-1){
                if(indexes!=null){
                    indexes.set(index);
                }
                return _cumulativeFields[index]._field;
            }
            return null;
        }       
    }
   
   
    public static class FieldAndIDRecord implements Comparable<FieldAndIDRecord>{

        public Field _field;
        public int _id = -1;
       
        public int compareTo(FieldAndIDRecord o) {
            return _id < o._id ? -1 : (_id == o._id ? 0 : 1);
        }

        /**
         * @param field
         */
        public FieldAndIDRecord(Field field) {
            super();
            _field = field;
        }
    }
   
   
    private static class StaleReferencesCleanerThread extends Thread{
        public StaleReferencesCleanerThread() {
            setDaemon(true);
            setPriority(MIN_PRIORITY);
            setName("JODB Reference Cleaner");
        }
        @Override
        public void run()
        {
            while (true) {
                synchronized (_cleanersCache) {
                    if(_cleanersCache.size() == 0){
                        _staleReferencesCleanerThread = null;
                        break;
                    }
                }
                try {
                    Iterator<ActiveObjectReferenceCleaner> iterator = _cleanersCache.keySet().iterator();
                    while (iterator.hasNext()) {
                        ActiveObjectReferenceCleaner activeObjectReferenceCleaner;
                        try {
                            activeObjectReferenceCleaner = iterator.next();
                        } catch (ConcurrentModificationException e) {
                            //just ignore this exception, will clean on next iteration
                            break;
                        }
                        activeObjectReferenceCleaner.removeStaleReferences();
                    }
                    sleep(JODBConfig.getReferenceCleanerInterval());
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
TOP

Related Classes of com.mobixess.jodb.core.transaction.JODBSession$StaleReferencesCleanerThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.