Ejemplo n.º 1
0
        internal static IOdbComparable BuildIndexKey(string indexName, NonNativeObjectInfo oi, int[] fieldIds)
        {
            var keys = new IOdbComparable[fieldIds.Length];

            for (var i = 0; i < fieldIds.Length; i++)
            {
                try
                {
                    var aoi  = oi.GetAttributeValueFromId(fieldIds[i]);
                    var item = (IComparable)aoi.GetObject();

                    // If the index is on NonNativeObjectInfo, then the key is the oid of the object
                    if (aoi.IsNonNativeObject())
                    {
                        var nnoi = (NonNativeObjectInfo)aoi;
                        item = nnoi.GetOid();
                    }

                    keys[i] = new SimpleCompareKey(item);
                }
                catch (Exception)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.IndexKeysMustImplementComparable.AddParameter(indexName).AddParameter(fieldIds[i]).AddParameter(
                                  oi.GetAttributeValueFromId(fieldIds[i]).GetType().FullName));
                }
            }

            return(keys.Length == 1 ? keys[0] : new ComposedCompareKey(keys));
        }
Ejemplo n.º 2
0
        private void StoreChangedObject(NonNativeObjectInfo aoi1, NonNativeObjectInfo aoi2, int fieldId,
                                        int objectRecursionLevel)
        {
            _nbChanges++;
            if (aoi1 == null || aoi2 == null)
            {
                return;
            }

            _changes.Add(new ChangedObjectInfo(aoi1.GetClassInfo(), aoi2.GetClassInfo(), fieldId,
                                               aoi1.GetAttributeValueFromId(fieldId),
                                               aoi2.GetAttributeValueFromId(fieldId), objectRecursionLevel));
            // also the max recursion level
            if (objectRecursionLevel > _maxObjectRecursionLevel)
            {
                _maxObjectRecursionLevel = objectRecursionLevel;
            }
        }
Ejemplo n.º 3
0
        private OID WriteNonNativeObjectInfo(OID existingOid, NonNativeObjectInfo objectInfo, long position,
                                             bool writeDataInTransaction, bool isNewObject)
        {
            var lsession  = _session;
            var cache     = lsession.GetCache();
            var hasObject = objectInfo.GetObject() != null;

            // Checks if object is null,for null objects,there is nothing to do
            if (objectInfo.IsNull())
            {
                return(StorageEngineConstant.NullObjectId);
            }

            var metaModel = lsession.GetMetaModel();

            // first checks if the class of this object already exist in the
            // metamodel
            if (!metaModel.ExistClass(objectInfo.GetClassInfo().UnderlyingType))
            {
                _objectWriter.AddClass(objectInfo.GetClassInfo(), true);
            }

            // if position is -1, gets the position where to write the object
            if (position == -1)
            {
                // Write at the end of the file
                position = _objectWriter.FileSystemProcessor.FileSystemInterface.GetAvailablePosition();
                // Updates the meta object position
                objectInfo.SetPosition(position);
            }

            // Gets the object id
            var oid = existingOid;

            if (oid == null)
            {
                // If, to get the next id, a new id block must be created, then
                // there is an extra work
                // to update the current object position
                if (_objectWriter.GetIdManager().MustShift())
                {
                    oid = _objectWriter.GetIdManager().GetNextObjectId(position);
                    // The id manager wrote in the file so the position for the
                    // object must be re-computed
                    position = _objectWriter.FileSystemProcessor.FileSystemInterface.GetAvailablePosition();
                    // The oid must be associated to this new position - id
                    // operations are always out of transaction
                    // in this case, the update is done out of the transaction as a
                    // rollback won t need to
                    // undo this. We are just creating the id
                    // => third parameter(write in transaction) = false
                    _objectWriter.GetIdManager().UpdateObjectPositionForOid(oid, position, false);
                }
                else
                {
                    oid = _objectWriter.GetIdManager().GetNextObjectId(position);
                }
            }
            else
            {
                // If an oid was passed, it is because object already exist and
                // is being updated. So we
                // must update the object position
                // Here the update of the position of the id must be done in
                // transaction as the object
                // position of the id is being updated, and a rollback should undo
                // this
                // => third parameter(write in transaction) = true
                _objectWriter.GetIdManager().UpdateObjectPositionForOid(oid, position, true);
                // Keep the relation of id and position in the cache until the
                // commit
                cache.SavePositionOfObjectWithOid(oid, position);
            }

            // Sets the oid of the object in the inserting cache
            cache.UpdateIdOfInsertingObject(objectInfo.GetObject(), oid);

            // Only add the oid to unconnected zone if it is a new object
            if (isNewObject)
            {
                cache.AddOIDToUnconnectedZone(oid);
            }

            objectInfo.SetOid(oid);

            if (objectInfo.GetClassInfo() == null || objectInfo.GetClassInfo().ClassInfoId == null)
            {
                if (objectInfo.GetClassInfo() != null)
                {
                    var clinfo =
                        _storageEngine.GetSession().GetMetaModel().GetClassInfo(
                            objectInfo.GetClassInfo().FullClassName, true);
                    objectInfo.SetClassInfo(clinfo);
                }
                else
                {
                    throw new OdbRuntimeException(NDatabaseError.UndefinedClassInfo.AddParameter(objectInfo.ToString()));
                }
            }

            // updates the meta model - If class already exist, it returns the
            // metamodel class, which contains
            // a bit more informations
            var classInfo = _objectWriter.AddClass(objectInfo.GetClassInfo(), true);

            objectInfo.SetClassInfo(classInfo);
            //
            if (isNewObject)
            {
                _objectWriter.ManageNewObjectPointers(objectInfo, classInfo);
            }


            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(position, writeDataInTransaction);
            objectInfo.SetPosition(position);
            var nbAttributes = objectInfo.GetClassInfo().Attributes.Count;
            // compute the size of the array of byte needed till the attibute
            // positions
            // BlockSize + Block Type + OID  + ClassOid + PrevOid + NextOid + CreatDate + UpdateDate + objectVersion + NbAttributes + RefCoutner + IsRoot
            // Int       + Byte        + Long + Long     + Long    + Long    + Long      + Long       + int          + int          + long       + byte
            // 6 Longs + 3Ints + Byte
            var tsize = 7 * OdbType.SizeOfLong + 3 * OdbType.SizeOfInt + 2 * OdbType.SizeOfByte;
            var bytes = new byte[tsize];

            // Block size
            IntToByteArray(0, bytes, 0);
            // Block type
            bytes[4] = BlockTypes.BlockTypeNonNativeObject;

            // The object id
            EncodeOid(oid, bytes, 5);

            // Class info id
            LongToByteArray(classInfo.ClassInfoId.ObjectId, bytes, 13);

            // previous instance
            EncodeOid(objectInfo.GetPreviousObjectOID(), bytes, 21);

            // next instance
            EncodeOid(objectInfo.GetNextObjectOID(), bytes, 29);

            // creation date, for update operation must be the original one
            LongToByteArray(objectInfo.GetHeader().GetCreationDate(), bytes, 37);

            LongToByteArray(OdbTime.GetCurrentTimeInTicks(), bytes, 45);

            IntToByteArray(objectInfo.GetHeader().GetObjectVersion(), bytes, 53);

            LongToByteArray(objectInfo.GetHeader().RefCounter, bytes, 57);

            BooleanToByteArray(objectInfo.GetHeader().IsRoot, bytes, 65);

            // now write the number of attributes and the position of all
            // attributes, we do not know them yet, so write 00 but at the end of the write operation
            // These positions will be updated The positions that is going to be written are 'int' representing
            // the offset position of the attribute first write the number of attributes
            IntToByteArray(nbAttributes, bytes, 66);

            // Then write the array of bytes
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(bytes, writeDataInTransaction);
            // Store the position
            var attributePositionStart = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
            var attributeSize          = OdbType.SizeOfInt + OdbType.SizeOfLong;
            var abytes = new byte[nbAttributes * (attributeSize)];

            // here, just write an empty (0) array, as real values will be set at
            // the end
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(abytes, writeDataInTransaction);
            var attributesIdentification = new long[nbAttributes];
            var attributeIds             = new int[nbAttributes];
            // Puts the object info in the cache
            // storageEngine.getSession().getCache().addObject(position,
            // aoi.getObject(), objectInfo.getHeader());

            var maxWritePosition = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();

            // Loop on all attributes
            for (var i = 0; i < nbAttributes; i++)
            {
                // Gets the attribute meta description
                var classAttributeInfo = classInfo.GetAttributeInfo(i);
                // Gets the id of the attribute
                attributeIds[i] = classAttributeInfo.GetId();
                // Gets the attribute data
                var aoi2 = objectInfo.GetAttributeValueFromId(classAttributeInfo.GetId());
                if (aoi2 == null)
                {
                    // This only happens in 1 case : when a class has a field with
                    // the same name of one of is superclass. In this, the deeper
                    // attribute is null
                    if (classAttributeInfo.IsNative())
                    {
                        aoi2 = new NullNativeObjectInfo(classAttributeInfo.GetAttributeType().Id);
                    }
                    else
                    {
                        aoi2 = new NonNativeNullObjectInfo(classAttributeInfo.GetClassInfo());
                    }
                }
                if (aoi2.IsNative())
                {
                    var nativeAttributePosition = _objectWriter.InternalStoreObject((NativeObjectInfo)aoi2);
                    // For native objects , odb stores their position
                    attributesIdentification[i] = nativeAttributePosition;
                }
                else
                {
                    OID nonNativeAttributeOid;
                    if (aoi2.IsObjectReference())
                    {
                        var or = (ObjectReference)aoi2;
                        nonNativeAttributeOid = or.GetOid();
                    }
                    else
                    {
                        nonNativeAttributeOid = _objectWriter.StoreObject(null, (NonNativeObjectInfo)aoi2);
                    }
                    // For non native objects , odb stores its oid as a negative
                    // number!!u
                    if (nonNativeAttributeOid != null)
                    {
                        attributesIdentification[i] = -nonNativeAttributeOid.ObjectId;
                    }
                    else
                    {
                        attributesIdentification[i] = StorageEngineConstant.NullObjectIdId;
                    }
                }
                var p = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                if (p > maxWritePosition)
                {
                    maxWritePosition = p;
                }
            }
            // Updates attributes identification in the object info header
            objectInfo.GetHeader().SetAttributesIdentification(attributesIdentification);
            objectInfo.GetHeader().SetAttributesIds(attributeIds);
            var positionAfterWrite = maxWritePosition;

            // Now writes back the attribute positions
            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(attributePositionStart, writeDataInTransaction);
            abytes = new byte[attributesIdentification.Length * (attributeSize)];
            for (var i = 0; i < attributesIdentification.Length; i++)
            {
                IntToByteArray(attributeIds[i], abytes, i * attributeSize);
                LongToByteArray(attributesIdentification[i], abytes,
                                i * (attributeSize) + OdbType.SizeOfInt);
                // fsi.writeInt(attributeIds[i], writeDataInTransaction, "attr id");
                // fsi.writeLong(attributesIdentification[i],
                // writeDataInTransaction, "att real pos",
                // WriteAction.DATA_WRITE_ACTION);
                // if (classInfo.getAttributeInfo(i).isNonNative() &&
                // attributesIdentification[i] > 0) {
                if (objectInfo.GetAttributeValueFromId(attributeIds[i]).IsNonNativeObject() &&
                    attributesIdentification[i] > 0)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.NonNativeAttributeStoredByPositionInsteadOfOid.AddParameter(
                                  classInfo.GetAttributeInfo(i).GetName()).AddParameter(classInfo.FullClassName).
                              AddParameter(attributesIdentification[i]));
                }
            }
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(abytes, writeDataInTransaction);
            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionAfterWrite, writeDataInTransaction);
            var blockSize = (int)(positionAfterWrite - position);

            WriteBlockSizeAt(position, blockSize, writeDataInTransaction, objectInfo);

            // Only insert in index for new objects
            if (isNewObject)
            {
                // insert object id in indexes, if exist
                _objectWriter.ManageIndexesForInsert(oid, objectInfo);
                var value = hasObject
                                ? objectInfo.GetObject()
                                : objectInfo;

                _triggerManager.ManageInsertTriggerAfter(objectInfo.GetClassInfo().UnderlyingType, value, oid);
            }

            return(oid);
        }
Ejemplo n.º 4
0
        public virtual object BuildOneInstance(NonNativeObjectInfo objectInfo)
        {
            ICache cache = GetSession().GetCache();

            // verify if the object is check to delete
            if (objectInfo.IsDeletedObject())
            {
                throw new ODBRuntimeException(NeoDatisError.ObjectIsMarkedAsDeletedForOid.AddParameter(objectInfo.GetOid()));
            }
            // Then check if object is in cache
            object o = cache.GetObjectWithOid(objectInfo.GetOid());

            if (o != null)
            {
                return(o);
            }
            Type instanceClazz = null;

            instanceClazz = classPool.GetClass(objectInfo.GetClassInfo().GetFullClassName());
            try
            {
                o = classIntrospector.NewInstanceOf(instanceClazz);
            }
            catch (System.Exception e)
            {
                throw new ODBRuntimeException(NeoDatisError.InstanciationError.AddParameter(objectInfo.GetClassInfo().GetFullClassName()), e);
            }
            // This can happen if ODB can not create the instance
            // TODO Check if returning null is correct
            if (o == null)
            {
                return(null);
            }
            // Keep the initial hash code. In some cases, when the class redefines
            // the hash code method
            // Hash code can return wrong values when attributes are not set (when
            // hash code depends on attribute values)
            // Hash codes are used as the key of the map,
            // So at the end of this method, if hash codes are different, object
            // will be removed from the cache and inserted back
            bool hashCodeIsOk    = true;
            int  initialHashCode = 0;

            try
            {
                initialHashCode = o.GetHashCode();
            }
            catch (System.Exception)
            {
                hashCodeIsOk = false;
            }
            // Adds this incomplete instance in the cache to manage cyclic reference
            if (hashCodeIsOk)
            {
                cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
            }
            ClassInfo            ci     = objectInfo.GetClassInfo();
            IOdbList <FieldInfo> fields = classIntrospector.GetAllFields(ci.GetFullClassName());

            FieldInfo          field = null;
            AbstractObjectInfo aoi   = null;
            object             value = null;

            for (int i = 0; i < fields.Count; i++)
            {
                field = fields[i];
                // Gets the id of this field
                int attributeId = ci.GetAttributeId(field.Name);
                if (OdbConfiguration.IsDebugEnabled(LogIdDebug))
                {
                    DLogger.Debug("getting field with name " + field.Name + ", attribute id is " + attributeId);
                }
                aoi = objectInfo.GetAttributeValueFromId(attributeId);
                // Check consistency
                // ensureClassCompatibily(field,
                // instanceInfo.getClassInfo().getAttributeinfo(i).getFullClassname());
                if (aoi != null && (!aoi.IsNull()))
                {
                    if (aoi.IsNative())
                    {
                        if (aoi.IsAtomicNativeObject())
                        {
                            if (aoi.IsNull())
                            {
                                value = null;
                            }
                            else
                            {
                                value = aoi.GetObject();
                            }
                        }
                        if (aoi.IsCollectionObject())
                        {
                            value = BuildCollectionInstance((CollectionObjectInfo)aoi);
                            // Manage a specific case of Set

                            /*
                             * if (typeof(Java.Util.Set).IsAssignableFrom(field.GetType()) && typeof(ICollection).IsAssignableFrom(value.GetType()))
                             * {
                             *      Java.Util.Set s = new Java.Util.HashSet();
                             *      s.AddAll((System.Collections.ICollection)value);
                             *      value = s;
                             * }*/
                        }
                        if (aoi.IsArrayObject())
                        {
                            value = BuildArrayInstance((ArrayObjectInfo)aoi);
                        }
                        if (aoi.IsMapObject())
                        {
                            value = BuildMapInstance((MapObjectInfo)aoi);
                        }
                        if (aoi.IsEnumObject())
                        {
                            value = BuildEnumInstance((EnumNativeObjectInfo)aoi, field.FieldType);
                        }
                    }
                    else
                    {
                        if (aoi.IsNonNativeObject())
                        {
                            if (aoi.IsDeletedObject())
                            {
                                if (NeoDatis.Odb.OdbConfiguration.DisplayWarnings())
                                {
                                    IError warning = NeoDatisError.AttributeReferencesADeletedObject
                                                     .AddParameter(objectInfo.GetClassInfo().GetFullClassName())
                                                     .AddParameter(objectInfo.GetOid()).AddParameter(field.Name);
                                    DLogger.Info(warning.ToString());
                                }
                                value = null;
                            }
                            else
                            {
                                value = BuildOneInstance((NonNativeObjectInfo)aoi);
                            }
                        }
                    }
                    if (value != null)
                    {
                        if (OdbConfiguration.IsDebugEnabled(LogIdDebug))
                        {
                            DLogger.Debug("Setting field " + field.Name + "(" + field.GetType().FullName + ") to " + value + " / " + value.GetType().FullName);
                        }
                        try
                        {
                            field.SetValue(o, value);
                        }
                        catch (System.Exception e)
                        {
                            throw new ODBRuntimeException(NeoDatisError.InstanceBuilderWrongObjectContainerType
                                                          .AddParameter(objectInfo.GetClassInfo().GetFullClassName())
                                                          .AddParameter(value.GetType().FullName).AddParameter(field.GetType().FullName), e);
                        }
                    }
                }
            }
            if (o != null && !OdbClassUtil.GetFullName(o.GetType()).Equals(objectInfo.GetClassInfo().GetFullClassName()))
            {
                new ODBRuntimeException(NeoDatisError.InstanceBuilderWrongObjectType
                                        .AddParameter(objectInfo.GetClassInfo().GetFullClassName())
                                        .AddParameter(o.GetType().FullName));
            }
            if (hashCodeIsOk || initialHashCode != o.GetHashCode())
            {
                // Bug (sf bug id=1875544 )detected by glsender
                // This can happen when an object has redefined its own hashcode
                // method and depends on the field values
                // Then, we have to remove object from the cache and re-insert to
                // correct map hash code
                cache.RemoveObjectWithOid(objectInfo.GetOid());
                // re-Adds instance in the cache
                cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
            }
            if (triggerManager != null)
            {
                triggerManager.ManageSelectTriggerAfter(objectInfo.GetClassInfo().GetFullClassName
                                                            (), objectInfo, objectInfo.GetOid());
            }
            if (OdbConfiguration.ReconnectObjectsToSession())
            {
                ICrossSessionCache crossSessionCache = CacheFactory.GetCrossSessionCache(engine.GetBaseIdentification().GetIdentification());
                crossSessionCache.AddObject(o, objectInfo.GetOid());
            }

            return(o);
        }
Ejemplo n.º 5
0
        private bool HasChanged(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int objectRecursionLevel)
        {
            var hasChanged = false;
            // If the object is already being checked, return false, this second
            // check will not affect the check
            int n;

            _alreadyCheckingObjects.TryGetValue(nnoi2, out n);
            if (n != 0)
            {
                return(false);
            }
            // Put the object in the temporary cache
            _alreadyCheckingObjects[nnoi1] = 1;
            _alreadyCheckingObjects[nnoi2] = 1;
            // Warning ID Start with 1 and not 0
            for (var id = 1; id <= nnoi1.GetMaxNbattributes(); id++)
            {
                var value1 = nnoi1.GetAttributeValueFromId(id);
                // Gets the value by the attribute id to be sure
                // Problem because a new object info may not have the right ids ?
                // Check if
                // the new oiD is ok.
                var value2 = nnoi2.GetAttributeValueFromId(id);
                if (value2 == null)
                {
                    // this means the object to have attribute id
                    StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                    hasChanged = true;
                    continue;
                }
                if (value1 == null)
                {
                    //throw new ODBRuntimeException("ObjectInfoComparator.hasChanged:attribute with id "+id+" does not exist on "+nnoi2);
                    // This happens when this object was created with an version of ClassInfo (which has been refactored).
                    // In this case,we simply tell that in place update is not supported so that the object will be rewritten with
                    // new metamodel
                    continue;
                }
                // If both are null, no effect
                if (value1.IsNull() && value2.IsNull())
                {
                    continue;
                }
                if (value2.IsNull())
                {
                    hasChanged = true;
                    _nbChanges++;
                    continue;
                }
                if (value1.IsNull() && value2.IsNonNativeObject())
                {
                    hasChanged = true;
                    _nbChanges++;
                    continue;
                }
                if (!ClassAreCompatible(value1, value2))
                {
                    var nativeObjectInfo = value2 as NativeObjectInfo;
                    if (nativeObjectInfo != null)
                    {
                        StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                        _nbChanges++;
                    }
                    var objectReference = value2 as ObjectReference;
                    if (objectReference != null)
                    {
                        var nnoi = (NonNativeObjectInfo)value1;
                        var oref = objectReference;
                        if (!nnoi.GetOid().Equals(oref.GetOid()))
                        {
                            StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                            _nbChanges++;
                        }
                        else
                        {
                            continue;
                        }
                    }
                    hasChanged = true;
                    continue;
                }
                if (value1.IsAtomicNativeObject())
                {
                    if (!value1.Equals(value2))
                    {
                        _nbChanges++;
                        hasChanged = true;
                    }
                    continue;
                }
                if (value1.IsArrayObject())
                {
                    var aoi1            = (ArrayObjectInfo)value1;
                    var aoi2            = (ArrayObjectInfo)value2;
                    var arrayHasChanged = ManageArrayChanges(nnoi1, nnoi2, id, aoi1, aoi2, objectRecursionLevel);
                    hasChanged = hasChanged || arrayHasChanged;
                    continue;
                }
                if (value1.IsEnumObject())
                {
                    var enoi1          = (EnumNativeObjectInfo)value1;
                    var enoi2          = (EnumNativeObjectInfo)value2;
                    var enumHasChanged = !enoi1.GetEnumClassInfo().ClassInfoId.Equals(enoi2.GetEnumClassInfo().ClassInfoId) ||
                                         !enoi1.GetEnumValue().Equals(enoi2.GetEnumValue());
                    hasChanged = hasChanged || enumHasChanged;
                    continue;
                }
                if (value1.IsNonNativeObject())
                {
                    var oi1 = (NonNativeObjectInfo)value1;
                    var oi2 = (NonNativeObjectInfo)value2;
                    // If oids are equal, they are the same objects
                    if (oi1.GetOid() != null && oi1.GetOid().Equals(oi2.GetOid()))
                    {
                        hasChanged = HasChanged(value1, value2, objectRecursionLevel + 1) || hasChanged;
                    }
                    else
                    {
                        // This means that an object reference has changed.
                        hasChanged = true;
                        _nbChanges++;
                        objectRecursionLevel++;
                    }
                }
            }
            var i1 = _alreadyCheckingObjects[nnoi1];
            var i2 = _alreadyCheckingObjects[nnoi2];

            i1 = i1 - 1;
            i2 = i2 - 1;
            if (i1 == 0)
            {
                _alreadyCheckingObjects.Remove(nnoi1);
            }
            else
            {
                _alreadyCheckingObjects.Add(nnoi1, i1);
            }
            if (i2 == 0)
            {
                _alreadyCheckingObjects.Remove(nnoi2);
            }
            else
            {
                _alreadyCheckingObjects.Add(nnoi2, i2);
            }
            return(hasChanged);
        }
Ejemplo n.º 6
0
 private bool HasChanged(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int objectRecursionLevel)
 {
     var hasChanged = false;
     // If the object is already being checked, return false, this second
     // check will not affect the check
     int n;
     _alreadyCheckingObjects.TryGetValue(nnoi2, out n);
     if (n != 0)
         return false;
     // Put the object in the temporary cache
     _alreadyCheckingObjects[nnoi1] = 1;
     _alreadyCheckingObjects[nnoi2] = 1;
     // Warning ID Start with 1 and not 0
     for (var id = 1; id <= nnoi1.GetMaxNbattributes(); id++)
     {
         var value1 = nnoi1.GetAttributeValueFromId(id);
         // Gets the value by the attribute id to be sure
         // Problem because a new object info may not have the right ids ?
         // Check if
         // the new oiD is ok.
         var value2 = nnoi2.GetAttributeValueFromId(id);
         if (value2 == null)
         {
             // this means the object to have attribute id
             StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
             hasChanged = true;
             continue;
         }
         if (value1 == null)
         {
             //throw new ODBRuntimeException("ObjectInfoComparator.hasChanged:attribute with id "+id+" does not exist on "+nnoi2);
             // This happens when this object was created with an version of ClassInfo (which has been refactored).
             // In this case,we simply tell that in place update is not supported so that the object will be rewritten with 
             // new metamodel
             continue;
         }
         // If both are null, no effect
         if (value1.IsNull() && value2.IsNull())
             continue;
         if (value2.IsNull())
         {
             hasChanged = true;
             _nbChanges++;
             continue;
         }
         if (value1.IsNull() && value2.IsNonNativeObject())
         {
             hasChanged = true;
             _nbChanges++;
             continue;
         }
         if (!ClassAreCompatible(value1, value2))
         {
             var nativeObjectInfo = value2 as NativeObjectInfo;
             if (nativeObjectInfo != null)
             {
                 StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                 _nbChanges++;
             }
             var objectReference = value2 as ObjectReference;
             if (objectReference != null)
             {
                 var nnoi = (NonNativeObjectInfo) value1;
                 var oref = objectReference;
                 if (!nnoi.GetOid().Equals(oref.GetOid()))
                 {
                     StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                     _nbChanges++;
                 }
                 else
                     continue;
             }
             hasChanged = true;
             continue;
         }
         if (value1.IsAtomicNativeObject())
         {
             if (!value1.Equals(value2))
             {
                 _nbChanges++;
                 hasChanged = true;
             }
             continue;
         }
         if (value1.IsArrayObject())
         {
             var aoi1 = (ArrayObjectInfo) value1;
             var aoi2 = (ArrayObjectInfo) value2;
             var arrayHasChanged = ManageArrayChanges(nnoi1, nnoi2, id, aoi1, aoi2, objectRecursionLevel);
             hasChanged = hasChanged || arrayHasChanged;
             continue;
         }
         if (value1.IsEnumObject())
         {
             var enoi1 = (EnumNativeObjectInfo) value1;
             var enoi2 = (EnumNativeObjectInfo) value2;
             var enumHasChanged = !enoi1.GetEnumClassInfo().ClassInfoId.Equals(enoi2.GetEnumClassInfo().ClassInfoId) ||
                                   !enoi1.GetEnumValue().Equals(enoi2.GetEnumValue());
             hasChanged = hasChanged || enumHasChanged;
             continue;
         }
         if (value1.IsNonNativeObject())
         {
             var oi1 = (NonNativeObjectInfo) value1;
             var oi2 = (NonNativeObjectInfo) value2;
             // If oids are equal, they are the same objects
             if (oi1.GetOid() != null && oi1.GetOid().Equals(oi2.GetOid()))
                 hasChanged = HasChanged(value1, value2, objectRecursionLevel + 1) || hasChanged;
             else
             {
                 // This means that an object reference has changed.
                 hasChanged = true;
                 _nbChanges++;
                 objectRecursionLevel++;
             }
         }
     }
     var i1 = _alreadyCheckingObjects[nnoi1];
     var i2 = _alreadyCheckingObjects[nnoi2];
     i1 = i1 - 1;
     i2 = i2 - 1;
     if (i1 == 0)
         _alreadyCheckingObjects.Remove(nnoi1);
     else
         _alreadyCheckingObjects.Add(nnoi1, i1);
     if (i2 == 0)
         _alreadyCheckingObjects.Remove(nnoi2);
     else
         _alreadyCheckingObjects.Add(nnoi2, i2);
     return hasChanged;
 }
Ejemplo n.º 7
0
        private void StoreChangedObject(NonNativeObjectInfo aoi1, NonNativeObjectInfo aoi2, int fieldId,
                                        int objectRecursionLevel)
        {
            _nbChanges++;
            if (aoi1 == null || aoi2 == null) 
                return;

            _changes.Add(new ChangedObjectInfo(aoi1.GetClassInfo(), aoi2.GetClassInfo(), fieldId,
                                               aoi1.GetAttributeValueFromId(fieldId),
                                               aoi2.GetAttributeValueFromId(fieldId), objectRecursionLevel));
            // also the max recursion level
            if (objectRecursionLevel > _maxObjectRecursionLevel)
                _maxObjectRecursionLevel = objectRecursionLevel;
        }
Ejemplo n.º 8
0
        public object BuildOneInstance(NonNativeObjectInfo objectInfo, IOdbCache cache)
        {
            // verify if the object is check to delete
            if (objectInfo.IsDeletedObject())
            {
                throw new OdbRuntimeException(
                          NDatabaseError.ObjectIsMarkedAsDeletedForOid.AddParameter(objectInfo.GetOid()));
            }

            // Then check if object is in cache
            var o = cache.GetObject(objectInfo.GetOid());

            if (o != null)
            {
                return(o);
            }

            try
            {
                o = FormatterServices.GetUninitializedObject(objectInfo.GetClassInfo().UnderlyingType);
            }
            catch (Exception e)
            {
                throw new OdbRuntimeException(
                          NDatabaseError.InstanciationError.AddParameter(objectInfo.GetClassInfo().FullClassName), e);
            }

            // This can happen if ODB can not create the instance from security reasons
            if (o == null)
            {
                throw new OdbRuntimeException(
                          NDatabaseError.InstanciationError.AddParameter(objectInfo.GetClassInfo().FullClassName));
            }

            // Keep the initial hash code. In some cases, when the class redefines
            // the hash code method
            // Hash code can return wrong values when attributes are not set (when
            // hash code depends on attribute values)
            // Hash codes are used as the key of the map,
            // So at the end of this method, if hash codes are different, object
            // will be removed from the cache and inserted back
            var hashCodeIsOk    = true;
            var initialHashCode = 0;

            try
            {
                initialHashCode = o.GetHashCode();
            }
            catch
            {
                hashCodeIsOk = false;
            }

            // Adds this incomplete instance in the cache to manage cyclic reference
            if (hashCodeIsOk)
            {
                cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
            }

            var classInfo = objectInfo.GetClassInfo();
            var fields    = ClassIntrospector.GetAllFieldsFrom(classInfo.UnderlyingType);

            object value = null;

            foreach (var fieldInfo in fields)
            {
                // Gets the id of this field
                var attributeId = classInfo.GetAttributeId(fieldInfo.Name);
                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Concat("InstanceBuilder: ", "getting field with name ", fieldInfo.Name, ", attribute id is ",
                                                attributeId.ToString()));
                }

                var abstractObjectInfo = objectInfo.GetAttributeValueFromId(attributeId);

                // Check consistency
                // ensureClassCompatibily(field,
                // instanceInfo.getClassInfo().getAttributeinfo(i).getFullClassname());
                if (abstractObjectInfo == null || (abstractObjectInfo.IsNull()))
                {
                    continue;
                }

                if (abstractObjectInfo.IsNative())
                {
                    if (abstractObjectInfo.IsAtomicNativeObject())
                    {
                        value = abstractObjectInfo.IsNull()
                                    ? null
                                    : abstractObjectInfo.GetObject();
                    }

                    if (abstractObjectInfo.IsArrayObject())
                    {
                        value = BuildArrayInstance((ArrayObjectInfo)abstractObjectInfo);
                    }
                    if (abstractObjectInfo.IsEnumObject())
                    {
                        value = BuildEnumInstance((EnumNativeObjectInfo)abstractObjectInfo, fieldInfo.FieldType);
                    }
                }
                else
                {
                    if (abstractObjectInfo.IsNonNativeObject())
                    {
                        if (abstractObjectInfo.IsDeletedObject())
                        {
                            if (OdbConfiguration.IsLoggingEnabled())
                            {
                                var warning =
                                    NDatabaseError.AttributeReferencesADeletedObject.AddParameter(
                                        objectInfo.GetClassInfo().FullClassName).AddParameter(
                                        objectInfo.GetOid()).AddParameter(fieldInfo.Name);
                                DLogger.Warning("InstanceBuilder: " + warning);
                            }
                            value = null;
                        }
                        else
                        {
                            value = BuildOneInstance((NonNativeObjectInfo)abstractObjectInfo);
                        }
                    }
                }
                if (value == null)
                {
                    continue;
                }

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(String.Format("InstanceBuilder: Setting field {0}({1}) to {2} / {3}", fieldInfo.Name,
                                                fieldInfo.GetType().FullName, value, value.GetType().FullName));
                }
                try
                {
                    fieldInfo.SetValue(o, value);
                }
                catch (Exception e)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.InstanceBuilderWrongObjectContainerType.AddParameter(
                                  objectInfo.GetClassInfo().FullClassName).AddParameter(value.GetType().FullName)
                              .AddParameter(fieldInfo.GetType().FullName), e);
                }
            }
            if (o.GetType() != objectInfo.GetClassInfo().UnderlyingType)
            {
                throw new OdbRuntimeException(
                          NDatabaseError.InstanceBuilderWrongObjectType.AddParameter(
                              objectInfo.GetClassInfo().FullClassName).AddParameter(o.GetType().FullName));
            }
            if (hashCodeIsOk || initialHashCode != o.GetHashCode())
            {
                // Bug (sf bug id=1875544 )detected by glsender
                // This can happen when an object has redefined its own hashcode
                // method and depends on the field values
                // Then, we have to remove object from the cache and re-insert to
                // correct map hash code
                cache.RemoveObjectByOid(objectInfo.GetOid());
                // re-Adds instance in the cache
                cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
            }

            if (_triggerManager != null)
            {
                _triggerManager.ManageSelectTriggerAfter(objectInfo.GetClassInfo().UnderlyingType, o,
                                                         objectInfo.GetOid());
            }

            return(o);
        }
Ejemplo n.º 9
0
        private OID WriteNonNativeObjectInfo(OID existingOid, NonNativeObjectInfo objectInfo, long position,
                                                    bool writeDataInTransaction, bool isNewObject)
        {
            var lsession = _session;
            var cache = lsession.GetCache();
            var hasObject = objectInfo.GetObject() != null;

            // Checks if object is null,for null objects,there is nothing to do
            if (objectInfo.IsNull())
                return StorageEngineConstant.NullObjectId;

            var metaModel = lsession.GetMetaModel();
            
            // first checks if the class of this object already exist in the
            // metamodel
            if (!metaModel.ExistClass(objectInfo.GetClassInfo().UnderlyingType))
                _objectWriter.AddClass(objectInfo.GetClassInfo(), true);

            // if position is -1, gets the position where to write the object
            if (position == -1)
            {
                // Write at the end of the file
                position = _objectWriter.FileSystemProcessor.FileSystemInterface.GetAvailablePosition();
                // Updates the meta object position
                objectInfo.SetPosition(position);
            }

            // Gets the object id
            var oid = existingOid;
            if (oid == null)
            {
                // If, to get the next id, a new id block must be created, then
                // there is an extra work
                // to update the current object position
                if (_objectWriter.GetIdManager().MustShift())
                {
                    oid = _objectWriter.GetIdManager().GetNextObjectId(position);
                    // The id manager wrote in the file so the position for the
                    // object must be re-computed
                    position = _objectWriter.FileSystemProcessor.FileSystemInterface.GetAvailablePosition();
                    // The oid must be associated to this new position - id
                    // operations are always out of transaction
                    // in this case, the update is done out of the transaction as a
                    // rollback won t need to
                    // undo this. We are just creating the id
                    // => third parameter(write in transaction) = false
                    _objectWriter.GetIdManager().UpdateObjectPositionForOid(oid, position, false);
                }
                else
                    oid = _objectWriter.GetIdManager().GetNextObjectId(position);
            }
            else
            {
                // If an oid was passed, it is because object already exist and
                // is being updated. So we
                // must update the object position
                // Here the update of the position of the id must be done in
                // transaction as the object
                // position of the id is being updated, and a rollback should undo
                // this
                // => third parameter(write in transaction) = true
                _objectWriter.GetIdManager().UpdateObjectPositionForOid(oid, position, true);
                // Keep the relation of id and position in the cache until the
                // commit
                cache.SavePositionOfObjectWithOid(oid, position);
            }

            // Sets the oid of the object in the inserting cache
            cache.UpdateIdOfInsertingObject(objectInfo.GetObject(), oid);

            // Only add the oid to unconnected zone if it is a new object
            if (isNewObject)
                cache.AddOIDToUnconnectedZone(oid);

            objectInfo.SetOid(oid);

            if (objectInfo.GetClassInfo() == null || objectInfo.GetClassInfo().ClassInfoId == null)
            {
                if (objectInfo.GetClassInfo() != null)
                {
                    var clinfo =
                        _storageEngine.GetSession().GetMetaModel().GetClassInfo(
                            objectInfo.GetClassInfo().FullClassName, true);
                    objectInfo.SetClassInfo(clinfo);
                }
                else
                    throw new OdbRuntimeException(NDatabaseError.UndefinedClassInfo.AddParameter(objectInfo.ToString()));
            }

            // updates the meta model - If class already exist, it returns the
            // metamodel class, which contains
            // a bit more informations
            var classInfo = _objectWriter.AddClass(objectInfo.GetClassInfo(), true);
            objectInfo.SetClassInfo(classInfo);
            // 
            if (isNewObject)
                _objectWriter.ManageNewObjectPointers(objectInfo, classInfo);


            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(position, writeDataInTransaction);
            objectInfo.SetPosition(position);
            var nbAttributes = objectInfo.GetClassInfo().Attributes.Count;
            // compute the size of the array of byte needed till the attibute
            // positions
            // BlockSize + Block Type + OID  + ClassOid + PrevOid + NextOid + CreatDate + UpdateDate + objectVersion + NbAttributes + RefCoutner + IsRoot
            // Int       + Byte        + Long + Long     + Long    + Long    + Long      + Long       + int          + int          + long       + byte
            // 6 Longs + 3Ints + Byte
            var tsize = 7 * OdbType.SizeOfLong + 3 * OdbType.SizeOfInt + 2 * OdbType.SizeOfByte;
            var bytes = new byte[tsize];
            // Block size
            IntToByteArray(0, bytes, 0);
            // Block type
            bytes[4] = BlockTypes.BlockTypeNonNativeObject;

            // The object id
            EncodeOid(oid, bytes, 5);

            // Class info id
            LongToByteArray(classInfo.ClassInfoId.ObjectId, bytes, 13);

            // previous instance
            EncodeOid(objectInfo.GetPreviousObjectOID(), bytes, 21);

            // next instance
            EncodeOid(objectInfo.GetNextObjectOID(), bytes, 29);

            // creation date, for update operation must be the original one
            LongToByteArray(objectInfo.GetHeader().GetCreationDate(), bytes, 37);

            LongToByteArray(OdbTime.GetCurrentTimeInTicks(), bytes, 45);

            IntToByteArray(objectInfo.GetHeader().GetObjectVersion(), bytes, 53);

            LongToByteArray(objectInfo.GetHeader().RefCounter, bytes, 57);

            BooleanToByteArray(objectInfo.GetHeader().IsRoot, bytes, 65);

            // now write the number of attributes and the position of all
            // attributes, we do not know them yet, so write 00 but at the end of the write operation
            // These positions will be updated The positions that is going to be written are 'int' representing
            // the offset position of the attribute first write the number of attributes
            IntToByteArray(nbAttributes, bytes, 66);

            // Then write the array of bytes
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(bytes, writeDataInTransaction);
            // Store the position
            var attributePositionStart = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
            var attributeSize = OdbType.SizeOfInt + OdbType.SizeOfLong;
            var abytes = new byte[nbAttributes * (attributeSize)];
            // here, just write an empty (0) array, as real values will be set at
            // the end
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(abytes, writeDataInTransaction);
            var attributesIdentification = new long[nbAttributes];
            var attributeIds = new int[nbAttributes];
            // Puts the object info in the cache
            // storageEngine.getSession().getCache().addObject(position,
            // aoi.getObject(), objectInfo.getHeader());

            var maxWritePosition = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
            // Loop on all attributes
            for (var i = 0; i < nbAttributes; i++)
            {
                // Gets the attribute meta description
                var classAttributeInfo = classInfo.GetAttributeInfo(i);
                // Gets the id of the attribute
                attributeIds[i] = classAttributeInfo.GetId();
                // Gets the attribute data
                var aoi2 = objectInfo.GetAttributeValueFromId(classAttributeInfo.GetId());
                if (aoi2 == null)
                {
                    // This only happens in 1 case : when a class has a field with
                    // the same name of one of is superclass. In this, the deeper
                    // attribute is null
                    if (classAttributeInfo.IsNative())
                        aoi2 = new NullNativeObjectInfo(classAttributeInfo.GetAttributeType().Id);
                    else
                        aoi2 = new NonNativeNullObjectInfo(classAttributeInfo.GetClassInfo());
                }
                if (aoi2.IsNative())
                {
                    var nativeAttributePosition = _objectWriter.InternalStoreObject((NativeObjectInfo)aoi2);
                    // For native objects , odb stores their position
                    attributesIdentification[i] = nativeAttributePosition;
                }
                else
                {
                    OID nonNativeAttributeOid;
                    if (aoi2.IsObjectReference())
                    {
                        var or = (ObjectReference)aoi2;
                        nonNativeAttributeOid = or.GetOid();
                    }
                    else
                        nonNativeAttributeOid = _objectWriter.StoreObject(null, (NonNativeObjectInfo)aoi2);
                    // For non native objects , odb stores its oid as a negative
                    // number!!u
                    if (nonNativeAttributeOid != null)
                        attributesIdentification[i] = -nonNativeAttributeOid.ObjectId;
                    else
                        attributesIdentification[i] = StorageEngineConstant.NullObjectIdId;
                }
                var p = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                if (p > maxWritePosition)
                    maxWritePosition = p;
            }
            // Updates attributes identification in the object info header
            objectInfo.GetHeader().SetAttributesIdentification(attributesIdentification);
            objectInfo.GetHeader().SetAttributesIds(attributeIds);
            var positionAfterWrite = maxWritePosition;
            // Now writes back the attribute positions
            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(attributePositionStart, writeDataInTransaction);
            abytes = new byte[attributesIdentification.Length * (attributeSize)];
            for (var i = 0; i < attributesIdentification.Length; i++)
            {
                IntToByteArray(attributeIds[i], abytes, i * attributeSize);
                LongToByteArray(attributesIdentification[i], abytes,
                                i * (attributeSize) + OdbType.SizeOfInt);
                // fsi.writeInt(attributeIds[i], writeDataInTransaction, "attr id");
                // fsi.writeLong(attributesIdentification[i],
                // writeDataInTransaction, "att real pos",
                // WriteAction.DATA_WRITE_ACTION);
                // if (classInfo.getAttributeInfo(i).isNonNative() &&
                // attributesIdentification[i] > 0) {
                if (objectInfo.GetAttributeValueFromId(attributeIds[i]).IsNonNativeObject() &&
                    attributesIdentification[i] > 0)
                {
                    throw new OdbRuntimeException(
                        NDatabaseError.NonNativeAttributeStoredByPositionInsteadOfOid.AddParameter(
                            classInfo.GetAttributeInfo(i).GetName()).AddParameter(classInfo.FullClassName).
                            AddParameter(attributesIdentification[i]));
                }
            }
            _objectWriter.FileSystemProcessor.FileSystemInterface.WriteBytes(abytes, writeDataInTransaction);
            _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionAfterWrite, writeDataInTransaction);
            var blockSize = (int)(positionAfterWrite - position);
            
            WriteBlockSizeAt(position, blockSize, writeDataInTransaction, objectInfo);

            // Only insert in index for new objects
            if (isNewObject)
            {
                // insert object id in indexes, if exist
                _objectWriter.ManageIndexesForInsert(oid, objectInfo);
                var value = hasObject
                                ? objectInfo.GetObject()
                                : objectInfo;

                _triggerManager.ManageInsertTriggerAfter(objectInfo.GetClassInfo().UnderlyingType, value, oid);
            }

            return oid;
        }
        private bool HasChanged(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int objectRecursionLevel)
        {
            AbstractObjectInfo value1 = null;
            AbstractObjectInfo value2 = null;
            bool hasChanged           = false;
            // If the object is already being checked, return false, this second
            // check will not affect the check
            int n = 0;

            alreadyCheckingObjects.TryGetValue(nnoi2, out n);
            if (n != 0)
            {
                return(false);
            }
            // Put the object in the temporary cache
            alreadyCheckingObjects[nnoi1] = 1;
            alreadyCheckingObjects[nnoi2] = 1;
            // Warning ID Start with 1 and not 0
            for (int id = 1; id <= nnoi1.GetMaxNbattributes(); id++)
            {
                value1 = nnoi1.GetAttributeValueFromId(id);
                // Gets the value by the attribute id to be sure
                // Problem because a new object info may not have the right ids ?
                // Check if
                // the new oiD is ok.
                value2 = nnoi2.GetAttributeValueFromId(id);
                if (value2 == null)
                {
                    // this means the object to have attribute id
                    StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                    hasChanged = true;
                    continue;
                }
                if (value1 == null)
                {
                    //throw new ODBRuntimeException("ObjectInfoComparator.hasChanged:attribute with id "+id+" does not exist on "+nnoi2);
                    // This happens when this object was created with an version of ClassInfo (which has been refactored).
                    // In this case,we simply tell that in place update is not supported so that the object will be rewritten with
                    // new metamodel
                    supportInPlaceUpdate = false;
                    continue;
                }
                // If both are null, no effect
                if (value1.IsNull() && value2.IsNull())
                {
                    continue;
                }
                if (value1.IsNull() || value2.IsNull())
                {
                    supportInPlaceUpdate = false;
                    hasChanged           = true;
                    StoreActionSetAttributetoNull(nnoi1, id, objectRecursionLevel);
                    continue;
                }
                if (!ClassAreCompatible(value1, value2))
                {
                    if (value2 is NativeObjectInfo)
                    {
                        StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                        StoreChangedAttributeAction(new ChangedNativeAttributeAction
                                                        (nnoi1, nnoi2, nnoi1.GetHeader().GetAttributeIdentificationFromId(id), (NativeObjectInfo
                                                                                                                                )value2, objectRecursionLevel, false, nnoi1.GetClassInfo().GetAttributeInfoFromId
                                                            (id).GetName()));
                    }
                    if (value2 is ObjectReference)
                    {
                        NonNativeObjectInfo nnoi = (NonNativeObjectInfo
                                                    )value1;
                        ObjectReference oref = (ObjectReference
                                                )value2;
                        if (!nnoi.GetOid().Equals(oref.GetOid()))
                        {
                            StoreChangedObject(nnoi1, nnoi2, id, objectRecursionLevel);
                            int attributeIdThatHasChanged = id;
                            // this is the exact position where the object reference
                            // definition is stored
                            long attributeDefinitionPosition = nnoi2.GetAttributeDefinitionPosition(attributeIdThatHasChanged
                                                                                                    );
                            StoreChangedAttributeAction(new ChangedObjectReferenceAttributeAction
                                                            (attributeDefinitionPosition, (ObjectReference
                                                                                           )value2, objectRecursionLevel));
                        }
                        else
                        {
                            continue;
                        }
                    }
                    hasChanged = true;
                    continue;
                }
                if (value1.IsAtomicNativeObject())
                {
                    if (!value1.Equals(value2))
                    {
                        // storeChangedObject(nnoi1, nnoi2, id,
                        // objectRecursionLevel);
                        StoreChangedAttributeAction(new ChangedNativeAttributeAction
                                                        (nnoi1, nnoi2, nnoi1.GetHeader().GetAttributeIdentificationFromId(id), (NativeObjectInfo
                                                                                                                                )value2, objectRecursionLevel, false, nnoi1.GetClassInfo().GetAttributeInfoFromId
                                                            (id).GetName()));
                        hasChanged = true;
                        continue;
                    }
                    continue;
                }
                if (value1.IsCollectionObject())
                {
                    CollectionObjectInfo coi1 = (CollectionObjectInfo)value1;
                    CollectionObjectInfo coi2 = (CollectionObjectInfo)value2;
                    bool collectionHasChanged = ManageCollectionChanges(nnoi1, nnoi2, id, coi1, coi2, objectRecursionLevel);
                    hasChanged = hasChanged || collectionHasChanged;
                    continue;
                }
                if (value1.IsArrayObject())
                {
                    ArrayObjectInfo aoi1            = (ArrayObjectInfo)value1;
                    ArrayObjectInfo aoi2            = (ArrayObjectInfo)value2;
                    bool            arrayHasChanged = ManageArrayChanges(nnoi1, nnoi2, id, aoi1, aoi2, objectRecursionLevel
                                                                         );
                    hasChanged = hasChanged || arrayHasChanged;
                    continue;
                }
                if (value1.IsMapObject())
                {
                    MapObjectInfo moi1          = (MapObjectInfo)value1;
                    MapObjectInfo moi2          = (MapObjectInfo)value2;
                    bool          mapHasChanged = ManageMapChanges(nnoi1, nnoi2, id, moi1, moi2, objectRecursionLevel
                                                                   );
                    hasChanged = hasChanged || mapHasChanged;
                    continue;
                }
                if (value1.IsEnumObject())
                {
                    EnumNativeObjectInfo enoi1 = (EnumNativeObjectInfo)value1;
                    EnumNativeObjectInfo enoi2 = (EnumNativeObjectInfo)value2;
                    bool enumHasChanged        = !enoi1.GetEnumClassInfo().GetId().Equals(enoi2.GetEnumClassInfo
                                                                                              ().GetId()) || !enoi1.GetEnumName().Equals(enoi2.GetEnumName());
                    hasChanged = hasChanged || enumHasChanged;
                    continue;
                }
                if (value1.IsNonNativeObject())
                {
                    NonNativeObjectInfo oi1 = (NonNativeObjectInfo)value1;
                    NonNativeObjectInfo oi2 = (NonNativeObjectInfo)value2;
                    // If oids are equal, they are the same objects
                    if (oi1.GetOid() != null && oi1.GetOid().Equals(oi2.GetOid()))
                    {
                        hasChanged = HasChanged(value1, value2, objectRecursionLevel + 1) || hasChanged;
                    }
                    else
                    {
                        // This means that an object reference has changed.
                        hasChanged = true;
                        // keep track of the position where the reference must be
                        // updated
                        long positionToUpdateReference = nnoi1.GetAttributeDefinitionPosition(id);
                        StoreNewObjectReference(positionToUpdateReference, oi2, objectRecursionLevel, nnoi1
                                                .GetClassInfo().GetAttributeInfoFromId(id).GetName());
                        objectRecursionLevel++;
                        // Value2 may have change too
                        AddPendingVerification(value2);
                    }
                    continue;
                }
            }
            int i1 = (int)alreadyCheckingObjects[nnoi1];
            int i2 = (int)alreadyCheckingObjects[nnoi2];

            if (i1 != null)
            {
                i1 = i1 - 1;
            }
            if (i2 != null)
            {
                i2 = i2 - 1;
            }
            if (i1 == 0)
            {
                alreadyCheckingObjects.Remove(nnoi1);
            }
            else
            {
                alreadyCheckingObjects.Add(nnoi1, i1);
            }
            if (i2 == 0)
            {
                alreadyCheckingObjects.Remove(nnoi2);
            }
            else
            {
                alreadyCheckingObjects.Add(nnoi2, i2);
            }
            return(hasChanged);
        }
 private void StoreChangedObject(NonNativeObjectInfo
                                 aoi1, NonNativeObjectInfo aoi2, int fieldId
                                 , int objectRecursionLevel)
 {
     nbChanges++;
     if (aoi1 != null && aoi2 != null)
     {
         changes.Add(new ChangedObjectInfo(aoi1
                                           .GetClassInfo(), aoi2.GetClassInfo(), fieldId, aoi1.GetAttributeValueFromId(fieldId
                                                                                                                       ), aoi2.GetAttributeValueFromId(fieldId), objectRecursionLevel));
         // also the max recursion level
         if (objectRecursionLevel > maxObjectRecursionLevel)
         {
             maxObjectRecursionLevel = objectRecursionLevel;
         }
     }
     else
     {
         NeoDatis.Tool.DLogger.Info("Non native object with null object");
     }
 }