/**
* 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();
}
}
}
}
}