Exemple #1
0
        /// <summary>
        ///   Checks if something in the Arary has changed, if yes, stores the change
        /// </summary>
        /// <param name="nnoi1"> The first Object meta representation (nnoi = NonNativeObjectInfo) </param>
        /// <param name="nnoi2"> The second object meta representation </param>
        /// <param name="fieldId"> The field index that this collection represents </param>
        /// <param name="aoi1"> The Meta representation of the array 1 (aoi = ArraybjectInfo) </param>
        /// <param name="aoi2"> The Meta representation of the array 2 </param>
        /// <param name="objectRecursionLevel"> </param>
        /// <returns> true if the 2 array representations are different </returns>
        private bool ManageArrayChanges(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int fieldId,
                                        ArrayObjectInfo aoi1, ArrayObjectInfo aoi2, int objectRecursionLevel)
        {
            var array1 = aoi1.GetArray();
            var array2 = aoi2.GetArray();

            if (array1.Length != array2.Length)
            {
                var buffer = new StringBuilder();
                buffer.Append("Array size has changed oldsize=").Append(array1.Length).Append("/newsize=").Append(
                    array2.Length);
                StoreChangedObject(nnoi1, nnoi2, fieldId, aoi1, aoi2, buffer.ToString(), objectRecursionLevel);
                return(true);
            }

            for (var i = 0; i < array1.Length; i++)
            {
                var value1          = (AbstractObjectInfo)array1[i];
                var value2          = (AbstractObjectInfo)array2[i];
                var localHasChanged = HasChanged(value1, value2, objectRecursionLevel);
                if (!localHasChanged)
                {
                    continue;
                }

                _nbChanges++;
                return(true);
            }
            return(false);
        }
 /// <param name="oid"> The Oid of the object to be inserted </param>
 /// <param name="nnoi"> The object meta representation The object to be inserted in the database </param>
 /// <param name="isNewObject"> To indicate if object is new </param>
 /// <returns> The position of the inserted object </returns>
 public OID InsertNonNativeObject(OID oid, NonNativeObjectInfo nnoi, bool isNewObject)
 {
     var ci = nnoi.GetClassInfo();
     var @object = nnoi.GetObject();
     // First check if object is already being inserted
     // This method returns -1 if object is not being inserted
     var cachedOid = _session.GetCache().IdOfInsertingObject(@object);
     if (cachedOid != null)
         return cachedOid;
     // Then checks if the class of this object already exist in the
     // meta model
     ci = _objectWriter.AddClass(ci, true);
     // Resets the ClassInfo in the objectInfo to be sure it contains all
     // updated class info data
     nnoi.SetClassInfo(ci);
     // Mark this object as being inserted. To manage cyclic relations
     // The oid may be equal to -1
     // Later in the process the cache will be updated with the right oid
     _session.GetCache().StartInsertingObjectWithOid(@object, oid);
     // false : do not write data in transaction. Data are always written
     // directly to disk. Pointers are written in transaction
     var newOid = WriteNonNativeObjectInfo(oid, nnoi, -1, false, isNewObject);
     if (!Equals(newOid, StorageEngineConstant.NullObjectId))
         _session.GetCache().AddObject(newOid, @object, nnoi.GetHeader());
     
     return newOid;
 }
Exemple #3
0
        private void StoreChangedObject(NonNativeObjectInfo aoi1, NonNativeObjectInfo aoi2, int fieldId,
                                        AbstractObjectInfo oldValue, AbstractObjectInfo newValue, string message,
                                        int objectRecursionLevel)
        {
            if (aoi1 == null || aoi2 == null)
            {
                return;
            }

            if (aoi1.GetOid() != null && aoi1.GetOid().Equals(aoi2.GetOid()))
            {
                _changedObjectMetaRepresentations.Add(aoi2);
                _changes.Add(new ChangedObjectInfo(aoi1.GetClassInfo(), aoi2.GetClassInfo(), fieldId, oldValue,
                                                   newValue, message, objectRecursionLevel));
                // also the max recursion level
                if (objectRecursionLevel > _maxObjectRecursionLevel)
                {
                    _maxObjectRecursionLevel = objectRecursionLevel;
                }
                _nbChanges++;
            }
            else
            {
                _newObjects.Add(aoi2.GetObject());
                _nbChanges++;
            }
        }
        public void ManageUpdateTriggerAfter(Type type, NonNativeObjectInfo oldNnoi, object newObject, OID oid)
        {
            if (!HasUpdateTriggersFor(type))
            {
                return;
            }

            foreach (UpdateTrigger trigger in GetListOfUpdateTriggersFor(type))
            {
                if (trigger.Odb == null)
                {
                    trigger.Odb = DependencyContainer.Resolve <IOdbForTrigger>(_storageEngine);
                }

                try
                {
                    var classInfoProvider = ((IClassInfoProvider)trigger.Odb).GetClassInfoProvider();
                    trigger.AfterUpdate(new ObjectRepresentation(oldNnoi, classInfoProvider), newObject, oid);
                }
                catch (Exception e)
                {
                    var warning =
                        NDatabaseError.AfterUpdateTriggerHasThrownException.AddParameter(trigger.GetType().FullName).
                        AddParameter(e.ToString());

                    throw new OdbRuntimeException(warning, e);
                }
            }
        }
Exemple #5
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));
        }
        /// <param name="oid"> The Oid of the object to be inserted </param>
        /// <param name="nnoi"> The object meta representation The object to be inserted in the database </param>
        /// <param name="isNewObject"> To indicate if object is new </param>
        /// <returns> The position of the inserted object </returns>
        public OID InsertNonNativeObject(OID oid, NonNativeObjectInfo nnoi, bool isNewObject)
        {
            var ci      = nnoi.GetClassInfo();
            var @object = nnoi.GetObject();
            // First check if object is already being inserted
            // This method returns -1 if object is not being inserted
            var cachedOid = _session.GetCache().IdOfInsertingObject(@object);

            if (cachedOid != null)
            {
                return(cachedOid);
            }
            // Then checks if the class of this object already exist in the
            // meta model
            ci = _objectWriter.AddClass(ci, true);
            // Resets the ClassInfo in the objectInfo to be sure it contains all
            // updated class info data
            nnoi.SetClassInfo(ci);
            // Mark this object as being inserted. To manage cyclic relations
            // The oid may be equal to -1
            // Later in the process the cache will be updated with the right oid
            _session.GetCache().StartInsertingObjectWithOid(@object, oid);
            // false : do not write data in transaction. Data are always written
            // directly to disk. Pointers are written in transaction
            var newOid = WriteNonNativeObjectInfo(oid, nnoi, -1, false, isNewObject);

            if (!Equals(newOid, StorageEngineConstant.NullObjectId))
            {
                _session.GetCache().AddObject(newOid, @object, nnoi.GetHeader());
            }

            return(newOid);
        }
        private static void ManageIndexesForUpdate(OID oid, NonNativeObjectInfo nnoi, NonNativeObjectInfo oldMetaRepresentation)
        {
            // takes the indexes from the oldMetaRepresentation because noi comes
            // from the client and is not always
            // in sync with the server meta model (In Client Server mode)
            var indexes = oldMetaRepresentation.GetClassInfo().GetIndexes();

            foreach (var index in indexes)
            {
                var oldKey = IndexTool.BuildIndexKey(index.Name, oldMetaRepresentation, index.AttributeIds);
                var newKey = IndexTool.BuildIndexKey(index.Name, nnoi, index.AttributeIds);

                // Only update index if key has changed!
                if (oldKey.CompareTo(newKey) != 0)
                {
                    var btree = index.BTree;
                    // TODO manage collision!
                    // Unused old value - result from delete
                    btree.Delete(oldKey, oid);
                    // TODO check if old is equal to oldKey
                    btree.Insert(newKey, oid);
                    // Check consistency : index should have size equal to the class
                    // info element number
                    if (index.BTree.GetSize() != nnoi.GetClassInfo().NumberOfObjects)
                    {
                        throw new OdbRuntimeException(
                                  NDatabaseError.BtreeSizeDiffersFromClassElementNumber.AddParameter(index.BTree.GetSize())
                                  .AddParameter(nnoi.GetClassInfo().NumberOfObjects));
                    }
                }
            }
        }
        protected override void Establish_context()
        {
            _person = new Person("Julia", 3);

            _objectWriterMock = new Mock <IObjectWriter>();
            _objectWriterMock.Setup(x => x.AddClasses(It.IsAny <ClassInfoList>())).Verifiable();

            _metaModelMock = new Mock <IMetaModel>();
            _metaModelMock.Setup(x => x.ExistClass(typeof(Person))).Returns(false).Verifiable();

            var objectInfoHeader = new ObjectInfoHeader(1, null, null, null, null, null);

            _cacheMock = new Mock <IOdbCache>();
            _cacheMock.Setup(x => x.GetOid(_person)).Returns(_sampleOid).Verifiable();
            _cacheMock.Setup(x => x.GetObjectInfoHeaderByOid(_sampleOid, true)).Returns(objectInfoHeader).Verifiable();

            _session = new Mock <ISession>();
            _session.Setup(x => x.GetMetaModel()).Returns(_metaModelMock.Object).Verifiable();
            _session.Setup(x => x.GetObjectWriter()).Returns(_objectWriterMock.Object).Verifiable();
            _session.Setup(x => x.GetCache()).Returns(_cacheMock.Object).Verifiable();

            _classInfoProvider = new SessionDataProvider(_session.Object);

            var introspector = (IObjectIntrospector) new ObjectIntrospector(_classInfoProvider);

            _nnoi = introspector.GetMetaRepresentation(_person, true, null, new DefaultInstrumentationCallback()) as NonNativeObjectInfo;
        }
 public virtual void StartReadingObjectInfoWithOid(NeoDatis.Odb.OID oid, NonNativeObjectInfo
                                                   objectInfo)
 {
     if (oid == null)
     {
         throw new ODBRuntimeException(NeoDatisError.CacheNullOid);
     }
     object[] objects = (object[])readingObjectInfo[oid];
     if (objects == null)
     {
         // The key is the oid, the value is an array of 2 objects :
         // 1-the read count, 2-The object info
         // Here we are saying that the object with oid 'oid' is
         // being read for the first time
         object[] values = new object[] { (short)1, objectInfo };
         readingObjectInfo[oid] = values;
     }
     else
     {
         // Here the object is already being read. It is necessary to
         // increase the read count
         short currentReadCount = ((short)objects[0]);
         objects[0] = (short)(currentReadCount + 1);
     }
 }
        private IOdbComparable BuildOrderByKey(NonNativeObjectInfo nnoi)
        {
            // TODO cache the attributes ids to compute them only once
            var queryManager        = DependencyContainer.Resolve <IQueryManager>();
            var orderByAttributeIds = queryManager.GetOrderByAttributeIds(ClassInfo, Query);

            return(IndexTool.BuildIndexKey("OrderBy", nnoi, orderByAttributeIds));
        }
        /// <summary>Checks if something in the Map has changed, if yes, stores the change</summary>
        /// <param name="nnoi1">
        /// The first Object meta representation (nnoi =
        /// NonNativeObjectInfo)
        /// </param>
        /// <param name="nnoi2">The second object meta representation</param>
        /// <param name="fieldIndex">The field index that this map represents</param>
        /// <param name="moi1">The Meta representation of the map 1 (moi = MapObjectInfo)</param>
        /// <param name="moi2">The Meta representation of the map 2</param>
        /// <param name="objectRecursionLevel"></param>
        /// <returns>true if the 2 map representations are different</returns>
        private bool ManageMapChanges(NonNativeObjectInfo
                                      nnoi1, NonNativeObjectInfo nnoi2, int fieldId
                                      , MapObjectInfo moi1, MapObjectInfo
                                      moi2, int objectRecursionLevel)
        {
            if (true)
            {
                return(true);
            }
            IDictionary <AbstractObjectInfo
                         , AbstractObjectInfo> map1 = moi1.GetMap();
            IDictionary <AbstractObjectInfo
                         , AbstractObjectInfo> map2 = moi2.GetMap();

            if (map1.Count != map2.Count)
            {
                System.Text.StringBuilder buffer = new System.Text.StringBuilder();
                buffer.Append("Map size has changed oldsize=").Append(map1.Count).Append("/newsize="
                                                                                         ).Append(map2.Count);
                StoreChangedObject(nnoi1, nnoi2, fieldId, moi1, moi2, buffer.ToString(), objectRecursionLevel
                                   );
                return(true);
            }
            IEnumerator <AbstractObjectInfo
                         > keys1 = map1.Keys.GetEnumerator();
            IEnumerator <AbstractObjectInfo
                         >     keys2  = map2.Keys.GetEnumerator();
            AbstractObjectInfo key1   = null;
            AbstractObjectInfo key2   = null;
            AbstractObjectInfo value1 = null;
            AbstractObjectInfo value2 = null;
            int index = 0;

            while (keys1.MoveNext())
            {
                keys2.MoveNext();
                key1 = keys1.Current;
                key2 = keys2.Current;
                bool keysHaveChanged = this.HasChanged(key1, key2, objectRecursionLevel);
                if (keysHaveChanged)
                {
                    StoreChangedObject(nnoi1, nnoi2, fieldId, key1, key2, "Map key index " + index +
                                       " has changed", objectRecursionLevel);
                    return(true);
                }
                value1 = map1[key1];
                value2 = map2[key2];
                bool valuesHaveChanged = this.HasChanged(value1, value2, objectRecursionLevel);
                if (valuesHaveChanged)
                {
                    StoreChangedObject(nnoi1, nnoi2, fieldId, value1, value2, "Map value index " + index
                                       + " has changed", objectRecursionLevel);
                    return(true);
                }
                index++;
            }
            return(false);
        }
        private void StoreActionSetAttributetoNull(NonNativeObjectInfo
                                                   nnoi, int id, int objectRecursionLevel)
        {
            nbChanges++;
            SetAttributeToNullAction action = new
                                              SetAttributeToNullAction(nnoi, id);

            attributeToSetToNull.Add(action);
        }
        /// <summary>Checks if something in the Arary has changed, if yes, stores the change</summary>
        /// <param name="nnoi1">
        /// The first Object meta representation (nnoi =
        /// NonNativeObjectInfo)
        /// </param>
        /// <param name="nnoi2">The second object meta representation</param>
        /// <param name="fieldIndex">The field index that this collection represents</param>
        /// <param name="aoi1">The Meta representation of the array 1 (aoi = ArraybjectInfo)</param>
        /// <param name="aoi2">The Meta representation of the array 2</param>
        /// <param name="objectRecursionLevel"></param>
        /// <returns>true if the 2 array representations are different</returns>
        private bool ManageArrayChanges(NonNativeObjectInfo
                                        nnoi1, NonNativeObjectInfo nnoi2, int fieldId
                                        , ArrayObjectInfo aoi1, ArrayObjectInfo
                                        aoi2, int objectRecursionLevel)
        {
            object[] array1 = aoi1.GetArray();
            object[] array2 = aoi2.GetArray();
            if (array1.Length != array2.Length)
            {
                System.Text.StringBuilder buffer = new System.Text.StringBuilder();
                buffer.Append("Array size has changed oldsize=").Append(array1.Length).Append("/newsize="
                                                                                              ).Append(array2.Length);
                StoreChangedObject(nnoi1, nnoi2, fieldId, aoi1, aoi2, buffer.ToString(), objectRecursionLevel
                                   );
                supportInPlaceUpdate = false;
                return(true);
            }
            AbstractObjectInfo value1 = null;
            AbstractObjectInfo value2 = null;
            // check if this array supports in place update
            bool localSupportInPlaceUpdate = ODBType.HasFixSize
                                                 (aoi2.GetComponentTypeId());
            int  index      = 0;
            bool hasChanged = false;

            try
            {
                for (int i = 0; i < array1.Length; i++)
                {
                    value1 = (AbstractObjectInfo)array1[i];
                    value2 = (AbstractObjectInfo)array2[i];
                    bool localHasChanged = this.HasChanged(value1, value2, objectRecursionLevel);
                    if (localHasChanged)
                    {
                        StoreArrayChange(nnoi1, fieldId, i, value2, localSupportInPlaceUpdate);
                        if (localSupportInPlaceUpdate)
                        {
                            hasChanged = true;
                        }
                        else
                        {
                            hasChanged = true;
                            return(hasChanged);
                        }
                    }
                    index++;
                }
            }
            finally
            {
                if (hasChanged && !localSupportInPlaceUpdate)
                {
                    supportInPlaceUpdate = false;
                }
            }
            return(hasChanged);
        }
        private void StoreArrayChange(NonNativeObjectInfo
                                      nnoi, int arrayAttributeId, int arrayIndex, AbstractObjectInfo
                                      value, bool supportInPlaceUpdate)
        {
            nbChanges++;
            ArrayModifyElement ame = new ArrayModifyElement
                                         (nnoi, arrayAttributeId, arrayIndex, value, supportInPlaceUpdate);

            arrayChanges.Add(ame);
        }
        private void StoreNewObjectReference(long positionToUpdateReference, NonNativeObjectInfo
                                             oi2, int objectRecursionLevel, string attributeName)
        {
            NewNonNativeObjectAction nnnoa = new
                                             NewNonNativeObjectAction(positionToUpdateReference
                                                                      , oi2, objectRecursionLevel, attributeName);

            newObjectMetaRepresentations.Add(nnnoa);
            nbChanges++;
        }
Exemple #16
0
        public void StartReadingObjectInfoWithOid(OID oid, NonNativeObjectInfo objectInfo)
        {
            if (oid == null)
            {
                throw new OdbRuntimeException(NDatabaseError.CacheNullOid);
            }

            NonNativeObjectInfo nnoi;
            var success = _readingObjectInfo.TryGetValue(oid, out nnoi);

            if (!success)
            {
                _readingObjectInfo[oid] = objectInfo;
            }
        }
        protected override void Establish_context()
        {
            _object = new Employee {
                Name = "Object"
            };
            _oid = new ObjectOID(1234L);

            var classInfoList = ClassIntrospector.Introspect(typeof(Employee), true);

            var mainClassInfo = classInfoList.GetMainClassInfo();

            mainClassInfo.ClassInfoId = new ClassOID(12345L);
            _objectInfo = new NonNativeObjectInfo(_object, mainClassInfo);
            _objectInfo.SetOid(_oid);
        }
Exemple #18
0
        public virtual object NewFullInstanceOf(System.Type clazz, NonNativeObjectInfo
                                                nnoi)
        {
            string className = clazz.FullName;

            NeoDatis.Odb.Core.Layers.Layer2.Instance.FullInstantiationHelper helper = (NeoDatis.Odb.Core.Layers.Layer2.Instance.FullInstantiationHelper
                                                                                       )fullInstantiationHelpers[className];
            if (helper != null)
            {
                object o = helper.Instantiate(nnoi);
                if (o != null)
                {
                    return(o);
                }
            }
            return(null);
        }
Exemple #19
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;
            }
        }
Exemple #20
0
        public NonNativeObjectInfo EnrichWithOid(NonNativeObjectInfo nnoi, object o)
        {
            var cache = _session.GetCache();

            var oid = cache.GetOid(o);

            if (oid != null)
            {
                nnoi.SetOid(oid);
                // Sets some values to the new header to keep track of the infos when
                // executing NDatabase without closing it, just committing.
                var objectInfoHeader = cache.GetObjectInfoHeaderByOid(oid, true);
                nnoi.GetHeader().SetObjectVersion(objectInfoHeader.GetObjectVersion());
                nnoi.GetHeader().SetUpdateDate(objectInfoHeader.GetUpdateDate());
                nnoi.GetHeader().SetCreationDate(objectInfoHeader.GetCreationDate());
            }

            return(nnoi);
        }
Exemple #21
0
        public virtual void ObjectMatch(OID oid, object o, OdbComparable orderByKey)
        {
            NonNativeObjectInfo nnoi = (NonNativeObjectInfo)o;

            if (inMemory)
            {
                if (returnObjects)
                {
                    if (queryHasOrderBy)
                    {
                        result.AddWithKey(orderByKey, (T)GetCurrentInstance(nnoi));
                    }
                    else
                    {
                        result.Add((T)GetCurrentInstance(nnoi));
                    }
                }
                else
                {
                    if (queryHasOrderBy)
                    {
                        //result.AddWithKey(orderByKey, (T)nnoi);
                    }
                    else
                    {
                        //result.Add((T)nnoi);
                    }
                }
            }
            else
            {
                if (queryHasOrderBy)
                {
                    result.AddWithKey(orderByKey, (T)oid);
                }
                else
                {
                    result.AddOid(oid);
                }
            }
        }
 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");
     }
 }
Exemple #23
0
        //throw new ODBRuntimeException(Error.CACHE_IS_FULL.addParameter(objectInfoPointersCacheFromOid.size()).addParameter(OdbConfiguration.getMaxNumberOfObjectInCache()));
        public virtual void StartInsertingObjectWithOid(object o, NeoDatis.Odb.OID
                                                        oid, NonNativeObjectInfo nnoi)
        {
            // In this case oid can be -1,because object is beeing inserted and do
            // not have yet a defined oid.
            if (o == null)
            {
                return;
            }
            ObjectInsertingInfo oii = null;

            insertingObjects.TryGetValue(o, out oii);
            if (oii == null)
            {
                insertingObjects[o] = new ObjectInsertingInfo(oid, 1);
            }
            else
            {
                oii.level++;
            }
        }
 private void StoreChangedObject(NonNativeObjectInfo
                                 aoi1, NonNativeObjectInfo aoi2, int fieldId
                                 , AbstractObjectInfo oldValue, AbstractObjectInfo
                                 newValue, string message, int objectRecursionLevel)
 {
     if (aoi1 != null && aoi2 != null)
     {
         if (aoi1.GetOid() != null && aoi1.GetOid().Equals(aoi2.GetOid()))
         {
             changedObjectMetaRepresentations.Add(aoi2);
             changes.Add(new ChangedObjectInfo(aoi1
                                               .GetClassInfo(), aoi2.GetClassInfo(), fieldId, oldValue, newValue, message, objectRecursionLevel
                                               ));
             // also the max recursion level
             if (objectRecursionLevel > maxObjectRecursionLevel)
             {
                 maxObjectRecursionLevel = objectRecursionLevel;
             }
             nbChanges++;
         }
         else
         {
             newObjects.Add(aoi2.GetObject());
             string fieldName = aoi1.GetClassInfo().GetAttributeInfoFromId(fieldId).GetName();
             // keep track of the position where the reference must be
             // updated - use aoi1 to get position, because aoi2 do not have position defined yet
             long positionToUpdateReference = aoi1.GetAttributeDefinitionPosition(fieldId);
             StoreNewObjectReference(positionToUpdateReference, aoi2, objectRecursionLevel, fieldName
                                     );
         }
     }
     else
     {
         //newObjectMetaRepresentations.add(aoi2);
         NeoDatis.Tool.DLogger.Info("Non native object with null object");
     }
 }
 public ObjectReference(NonNativeObjectInfo nnoi) : base(OdbType.NonNativeId)
 {
     _id = null;
     _nnoi = nnoi;
 }
        /// <summary>
        ///   Updates an object.
        /// </summary>
        /// <remarks>
        ///   Updates an object. <pre>Try to update in place. Only change what has changed. This is restricted to particular types (fixed size types). If in place update is
        ///                        not possible, then deletes the current object and creates a new at the end of the database file and updates
        ///                        OID object position.
        ///                        &#064;param object The object to be updated
        ///                        &#064;param forceUpdate when true, no verification is done to check if update must be done.
        ///                        &#064;return The oid of the object, as a negative number
        ///                        &#064;</pre>
        /// </remarks>
        public OID UpdateNonNativeObjectInfo(NonNativeObjectInfo nnoi, bool forceUpdate)
        {
            var hasObject = true;
            var @object   = nnoi.GetObject();
            var oid       = nnoi.GetOid();

            if (@object == null)
            {
                hasObject = false;
            }
            // When there is index,we must *always* load the old meta representation
            // to compute index keys
            var withIndex = !nnoi.GetClassInfo().GetIndexes().IsEmpty();
            NonNativeObjectInfo oldMetaRepresentation = null;

            // Used to check consistency, at the end, the number of
            // nbConnectedObjects must and nbUnconnected must remain unchanged
            //TODO: why we are not using / checking that? (below is continuity)
            nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
            nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();

            var objectHasChanged = false;

            try
            {
                var lsession            = _session;
                var positionBeforeWrite = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                var tmpCache            = lsession.GetTmpCache();
                var cache = lsession.GetCache();
                // Get header of the object (position, previous object position,
                // next
                // object position and class info position)
                // The header must be in the cache.
                var lastHeader = cache.GetObjectInfoHeaderByOid(oid, true);
                if (lastHeader == null)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.UnexpectedSituation.AddParameter("Header is null in update"));
                }
                if (lastHeader.GetOid() == null)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.InternalError.AddParameter("Header oid is null for oid " + oid));
                }
                var objectIsInConnectedZone = cache.IsInCommitedZone(oid);
                var currentPosition         = lastHeader.GetPosition();

                if (currentPosition == -1)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.InstancePositionIsNegative.AddParameter(currentPosition).AddParameter(oid).
                              AddParameter("In Object Info Header"));
                }

                // triggers,FIXME passing null to old object representation
                _storageEngine.GetTriggerManager().ManageUpdateTriggerBefore(nnoi.GetClassInfo().UnderlyingType,
                                                                             null, hasObject ? @object : nnoi, oid);
                // Use to control if the in place update is ok. The
                // ObjectInstrospector stores the number of changes
                // that were detected and here we try to apply them using in place
                // update.If at the end
                // of the in place update the number of applied changes is smaller
                // then the number
                // of detected changes, then in place update was not successfully,
                // we
                // must do a real update,
                // creating an object elsewhere :-(
                if (!forceUpdate)
                {
                    var cachedOid = cache.IdOfInsertingObject(@object);
                    if (cachedOid != null)
                    {
                        // The object is being inserted (must be a cyclic
                        // reference), simply returns id id
                        return(cachedOid);
                    }
                    // the nnoi (NonNativeObjectInfo is the meta representation of
                    // the object to update
                    // To know what must be upated we must get the meta
                    // representation of this object before
                    // The modification. Taking this 'old' meta representation from
                    // the
                    // cache does not resolve
                    // : because cache is a reference to the real object and object
                    // has been changed,
                    // so the cache is pointing to the reference, that has changed!
                    // This old meta representation must be re-read from the last
                    // committed database
                    // false, = returnInstance (java object) = false
                    try
                    {
                        var useCache = !objectIsInConnectedZone;
                        oldMetaRepresentation = _objectReader.ReadNonNativeObjectInfoFromPosition(null, oid,
                                                                                                  currentPosition,
                                                                                                  useCache, false);
                        tmpCache.ClearObjectInfos();
                    }
                    catch (OdbRuntimeException e)
                    {
                        var position = currentPosition.ToString();

                        throw new OdbRuntimeException(
                                  NDatabaseError.InternalError.AddParameter("Error while reading old Object Info of oid " +
                                                                            oid + " at pos " + position), e);
                    }
                    // Make sure we work with the last version of the object
                    var onDiskVersion     = oldMetaRepresentation.GetHeader().GetObjectVersion();
                    var onDiskUpdateDate  = oldMetaRepresentation.GetHeader().GetUpdateDate();
                    var inCacheVersion    = lastHeader.GetObjectVersion();
                    var inCacheUpdateDate = lastHeader.GetUpdateDate();
                    if (onDiskUpdateDate > inCacheUpdateDate || onDiskVersion > inCacheVersion)
                    {
                        lastHeader = oldMetaRepresentation.GetHeader();
                    }
                    nnoi.SetHeader(lastHeader);
                    // increase the object version number from the old meta
                    // representation
                    nnoi.GetHeader().IncrementVersionAndUpdateDate();
                    // Keep the creation date
                    nnoi.GetHeader().SetCreationDate(oldMetaRepresentation.GetHeader().GetCreationDate());
                    // Set the object of the old meta to make the object comparator
                    // understand, they are 2
                    // meta representation of the same object
                    // TODO , check if if is the best way to do
                    oldMetaRepresentation.SetObject(nnoi.GetObject());
                    // Reset the comparator
                    _comparator.Clear();
                    objectHasChanged = _comparator.HasChanged(oldMetaRepresentation, nnoi);

                    if (!objectHasChanged)
                    {
                        _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionBeforeWrite, true);

                        return(oid);
                    }
                }
                // If we reach this update, In Place Update was not possible. Do a
                // normal update. Deletes the
                // current object and creates a new one
                if (oldMetaRepresentation == null && withIndex)
                {
                    // We must load old meta representation to be able to compute
                    // old index key to update index
                    oldMetaRepresentation = _objectReader.ReadNonNativeObjectInfoFromPosition(null, oid, currentPosition,
                                                                                              false, false);
                }

                var previousObjectOID = lastHeader.GetPreviousObjectOID();
                var nextObjectOid     = lastHeader.GetNextObjectOID();

                nnoi.SetPreviousInstanceOID(previousObjectOID);
                nnoi.SetNextObjectOID(nextObjectOid);

                // Mark the block of current object as deleted
                _objectWriter.MarkAsDeleted(currentPosition, objectIsInConnectedZone);

                // Creates the new object
                oid = InsertNonNativeObject(oid, nnoi, false);

                // This position after write must be call just after the insert!!
                var positionAfterWrite = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                if (hasObject)
                {
                    // update cache
                    cache.AddObject(oid, @object, nnoi.GetHeader());
                }

                _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionAfterWrite, true);
                //TODO: why we are not using / checking that? (below is continuity)
                nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
                nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();

                return(oid);
            }
            catch (Exception e)
            {
                var message = string.Format("Error updating object {0} : {1}", nnoi, e);
                throw new OdbRuntimeException(e, message);
            }
            finally
            {
                if (objectHasChanged)
                {
                    if (withIndex)
                    {
                        ManageIndexesForUpdate(oid, nnoi, oldMetaRepresentation);
                    }

                    // triggers,FIXME passing null to old object representation
                    // (oldMetaRepresentation may be null)
                    _storageEngine.GetTriggerManager().ManageUpdateTriggerAfter(
                        nnoi.GetClassInfo().UnderlyingType, oldMetaRepresentation, hasObject ? @object : nnoi, oid);
                }
            }
        }
        private void StoreChangedObject(NonNativeObjectInfo aoi1, NonNativeObjectInfo aoi2, int fieldId,
                                        AbstractObjectInfo oldValue, AbstractObjectInfo newValue, string message,
                                        int objectRecursionLevel)
        {
            if (aoi1 == null || aoi2 == null) 
                return;

            if (aoi1.GetOid() != null && aoi1.GetOid().Equals(aoi2.GetOid()))
            {
                _changedObjectMetaRepresentations.Add(aoi2);
                _changes.Add(new ChangedObjectInfo(aoi1.GetClassInfo(), aoi2.GetClassInfo(), fieldId, oldValue,
                                                   newValue, message, objectRecursionLevel));
                // also the max recursion level
                if (objectRecursionLevel > _maxObjectRecursionLevel)
                    _maxObjectRecursionLevel = objectRecursionLevel;
                _nbChanges++;
            }
            else
            {
                _newObjects.Add(aoi2.GetObject());
                _nbChanges++;
            }
        }
        /// <summary>
        ///   Create a copy oh this meta object
        /// </summary>
        /// <param name="cache"> </param>
        /// <param name="onlyData"> if true, only copy attributes values </param>
        /// <returns> </returns>
        public override AbstractObjectInfo CreateCopy(IDictionary<OID, AbstractObjectInfo> cache, bool onlyData)
        {
            NonNativeObjectInfo nnoi;

            if (_objectHeader.GetOid() != null && cache.ContainsKey(_objectHeader.GetOid()))
            {
                nnoi = (NonNativeObjectInfo) cache[_objectHeader.GetOid()];
                if (nnoi != null)
                    return nnoi;
            }

            if (_theObject == null)
                return new NonNativeNullObjectInfo(_classInfo);

            if (onlyData)
            {
                var oih = new ObjectInfoHeader();
                nnoi = new NonNativeObjectInfo(_theObject, _classInfo, null, oih.GetAttributesIdentification(),
                                               oih.GetAttributeIds());
            }
            else
            {
                nnoi = new NonNativeObjectInfo(_theObject, _classInfo, null, _objectHeader.GetAttributesIdentification(),
                                               _objectHeader.GetAttributeIds());

                nnoi.GetHeader().SetOid(GetHeader().GetOid());
            }

            var newAttributeValues = new AbstractObjectInfo[_attributeValues.Length];

            for (var i = 0; i < _attributeValues.Length; i++)
                newAttributeValues[i] = _attributeValues[i].CreateCopy(cache, onlyData);

            nnoi._attributeValues = newAttributeValues;

            if (_objectHeader.GetOid() != null)
                cache.Add(_objectHeader.GetOid(), nnoi);

            return nnoi;
        }
Exemple #29
0
        private NonNativeObjectInfo BuildNnoi(object o, ClassInfo classInfo)
        {
            var nnoi = new NonNativeObjectInfo(o, classInfo);

            return(_classInfoProvider.EnrichWithOid(nnoi, o));
        }
        private NonNativeObjectInfo BuildNnoi(object o, ClassInfo classInfo)
        {
            var nnoi = new NonNativeObjectInfo(o, classInfo);

            return _classInfoProvider.EnrichWithOid(nnoi, o);
        }
Exemple #31
0
 private object GetCurrentInstance(NonNativeObjectInfo nnoi)
 {
     return(nnoi.GetObject() ??
            _instanceBuilder.BuildOneInstance(nnoi, _storageEngine.GetSession().GetCache()));
 }
        /// <summary>
        /// Build a meta representation of an object
        /// <pre>
        /// warning: When an object has two fields with the same name (a private field with the same name in a parent class, the deeper field (of the parent) is ignored!)
        /// </pre>
        /// </summary>
        /// <param name="o"></param>
        /// <param name="ci"></param>
        /// <param name="recursive"></param>
        /// <returns>The ObjectInfo</returns>
        protected virtual NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo GetObjectInfoInternal
            (NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo nnoi, object o, NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo
            ci, bool recursive, System.Collections.Generic.IDictionary <object, NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
                                                                        > alreadyReadObjects, NeoDatis.Odb.Core.Layers.Layer1.Introspector.IIntrospectionCallback
            callback)
        {
            object value = null;

            if (o == null)
            {
                return(NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo.GetInstance());
            }
            System.Type clazz = o.GetType();
            NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType type = NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType
                                                                .GetFromClass(clazz);
            string className = OdbClassUtil.GetFullName(clazz);

            if (type.IsNative())
            {
                return(GetNativeObjectInfoInternal(type, o, recursive, alreadyReadObjects,
                                                   callback));
            }
            // sometimes the clazz.getName() may not match the ci.getClassName()
            // It happens when the attribute is an interface or superclass of the
            // real attribute class
            // In this case, ci must be updated to the real class info
            if (ci != null && !clazz.FullName.Equals(ci.GetFullClassName()))
            {
                ci   = GetClassInfo(className);
                nnoi = null;
            }
            NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo mainAoi = (NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
                                                                                )nnoi;
            bool isRootObject = false;

            if (alreadyReadObjects == null)
            {
                alreadyReadObjects = new NeoDatis.Tool.Wrappers.Map.OdbHashMap <object, NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
                                                                                >();
                isRootObject = true;
            }
            if (o != null)
            {
                NonNativeObjectInfo cachedNnoi = null;
                alreadyReadObjects.TryGetValue(o, out cachedNnoi);

                if (cachedNnoi != null)
                {
                    ObjectReference or = new ObjectReference(cachedNnoi);
                    return(or);
                }
                if (callback != null)
                {
                    callback.ObjectFound(o);
                }
            }
            if (mainAoi == null)
            {
                mainAoi = BuildNnoi(o, ci, null, null, null, alreadyReadObjects);
            }
            alreadyReadObjects[o] = mainAoi;
            NeoDatis.Tool.Wrappers.List.IOdbList <System.Reflection.FieldInfo> fields = classIntrospector.GetAllFields(className);
            NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo            aoi    = null;
            int attributeId = -1;

            // For all fields
            for (int i = 0; i < fields.Count; i++)
            {
                System.Reflection.FieldInfo field = fields[i];
                try
                {
                    value       = field.GetValue(o);
                    attributeId = ci.GetAttributeId(field.Name);
                    if (attributeId == -1)
                    {
                        throw new ODBRuntimeException(NeoDatisError.ObjectIntrospectorNoFieldWithName.AddParameter(ci.GetFullClassName()).AddParameter(field.Name));
                    }
                    ODBType valueType = null;
                    if (value == null)
                    {
                        // If value is null, take the type from the field type
                        // declared in the class
                        valueType = ODBType.GetFromClass(field.FieldType);
                    }
                    else
                    {
                        // Else take the real attribute type!
                        valueType = ODBType.GetFromClass(value.GetType());
                    }
                    // for native fields
                    if (valueType.IsNative())
                    {
                        aoi = GetNativeObjectInfoInternal(valueType, value, recursive, alreadyReadObjects, callback);
                        mainAoi.SetAttributeValue(attributeId, aoi);
                    }
                    else
                    {
                        //callback.objectFound(value);
                        // Non Native Objects
                        if (value == null)
                        {
                            ClassInfo clai = GetClassInfo(OdbClassUtil.GetFullName(field.GetType()));

                            aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeNullObjectInfo(clai);
                            mainAoi.SetAttributeValue(attributeId, aoi);
                        }
                        else
                        {
                            ClassInfo clai = GetClassInfo(OdbClassUtil.GetFullName(value.GetType()));
                            if (recursive)
                            {
                                aoi = GetObjectInfoInternal(null, value, clai, recursive, alreadyReadObjects, callback
                                                            );
                                mainAoi.SetAttributeValue(attributeId, aoi);
                            }
                            else
                            {
                                // When it is not recursive, simply add the object
                                // values.add(value);
                                throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.InternalError
                                                                           .AddParameter("Should not enter here - ObjectIntrospector - 'simply add the object'"
                                                                                         ));
                            }
                        }
                    }
                }
                catch (System.ArgumentException e)
                {
                    throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.InternalError
                                                               .AddParameter("in getObjectInfoInternal"), e);
                }
                catch (System.MemberAccessException e)
                {
                    throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.InternalError
                                                               .AddParameter("getObjectInfoInternal"), e);
                }
            }
            if (isRootObject)
            {
                alreadyReadObjects.Clear();
                alreadyReadObjects = null;
            }
            return(mainAoi);
        }
        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 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;
        }
        /// <summary>
        ///   Checks if something in the Arary has changed, if yes, stores the change
        /// </summary>
        /// <param name="nnoi1"> The first Object meta representation (nnoi = NonNativeObjectInfo) </param>
        /// <param name="nnoi2"> The second object meta representation </param>
        /// <param name="fieldId"> The field index that this collection represents </param>
        /// <param name="aoi1"> The Meta representation of the array 1 (aoi = ArraybjectInfo) </param>
        /// <param name="aoi2"> The Meta representation of the array 2 </param>
        /// <param name="objectRecursionLevel"> </param>
        /// <returns> true if the 2 array representations are different </returns>
        private bool ManageArrayChanges(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int fieldId,
                                        ArrayObjectInfo aoi1, ArrayObjectInfo aoi2, int objectRecursionLevel)
        {
            var array1 = aoi1.GetArray();
            var array2 = aoi2.GetArray();
            if (array1.Length != array2.Length)
            {
                var buffer = new StringBuilder();
                buffer.Append("Array size has changed oldsize=").Append(array1.Length).Append("/newsize=").Append(
                    array2.Length);
                StoreChangedObject(nnoi1, nnoi2, fieldId, aoi1, aoi2, buffer.ToString(), objectRecursionLevel);
                return true;
            }
            
            for (var i = 0; i < array1.Length; i++)
            {
                var value1 = (AbstractObjectInfo) array1[i];
                var value2 = (AbstractObjectInfo) array2[i];
                var localHasChanged = HasChanged(value1, value2, objectRecursionLevel);
                if (!localHasChanged) 
                    continue;

                _nbChanges++;
                return true;
            }
            return false;
        }
        private static void ManageIndexesForUpdate(OID oid, NonNativeObjectInfo nnoi, NonNativeObjectInfo oldMetaRepresentation)
        {
            // takes the indexes from the oldMetaRepresentation because noi comes
            // from the client and is not always
            // in sync with the server meta model (In Client Server mode)
            var indexes = oldMetaRepresentation.GetClassInfo().GetIndexes();

            foreach (var index in indexes)
            {
                var oldKey = IndexTool.BuildIndexKey(index.Name, oldMetaRepresentation, index.AttributeIds);
                var newKey = IndexTool.BuildIndexKey(index.Name, nnoi, index.AttributeIds);

                // Only update index if key has changed!
                if (oldKey.CompareTo(newKey) != 0)
                {
                    var btree = index.BTree;
                    // TODO manage collision!
                    // Unused old value - result from delete
                    btree.Delete(oldKey, oid);
                    // TODO check if old is equal to oldKey
                    btree.Insert(newKey, oid);
                    // Check consistency : index should have size equal to the class
                    // info element number
                    if (index.BTree.GetSize() != nnoi.GetClassInfo().NumberOfObjects)
                    {
                        throw new OdbRuntimeException(
                            NDatabaseError.BtreeSizeDiffersFromClassElementNumber.AddParameter(index.BTree.GetSize())
                                .AddParameter(nnoi.GetClassInfo().NumberOfObjects));
                    }
                }
            }
        }
        /// <summary>
        ///   Updates an object.
        /// </summary>
        /// <remarks>
        ///   Updates an object. <pre>Try to update in place. Only change what has changed. This is restricted to particular types (fixed size types). If in place update is
        ///                        not possible, then deletes the current object and creates a new at the end of the database file and updates
        ///                        OID object position.
        ///                        &#064;param object The object to be updated
        ///                        &#064;param forceUpdate when true, no verification is done to check if update must be done.
        ///                        &#064;return The oid of the object, as a negative number
        ///                        &#064;</pre>
        /// </remarks>
        public OID UpdateNonNativeObjectInfo(NonNativeObjectInfo nnoi, bool forceUpdate)
        {
            var hasObject = true;
            var @object = nnoi.GetObject();
            var oid = nnoi.GetOid();
            if (@object == null)
                hasObject = false;
            // When there is index,we must *always* load the old meta representation
            // to compute index keys
            var withIndex = !nnoi.GetClassInfo().GetIndexes().IsEmpty();
            NonNativeObjectInfo oldMetaRepresentation = null;
            // Used to check consistency, at the end, the number of
            // nbConnectedObjects must and nbUnconnected must remain unchanged
            //TODO: why we are not using / checking that? (below is continuity)
            nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
            nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();

            var objectHasChanged = false;
            try
            {
                var lsession = _session;
                var positionBeforeWrite = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                var tmpCache = lsession.GetTmpCache();
                var cache = lsession.GetCache();
                // Get header of the object (position, previous object position,
                // next
                // object position and class info position)
                // The header must be in the cache.
                var lastHeader = cache.GetObjectInfoHeaderByOid(oid, true);
                if (lastHeader == null)
                    throw new OdbRuntimeException(
                        NDatabaseError.UnexpectedSituation.AddParameter("Header is null in update"));
                if (lastHeader.GetOid() == null)
                    throw new OdbRuntimeException(
                        NDatabaseError.InternalError.AddParameter("Header oid is null for oid " + oid));
                var objectIsInConnectedZone = cache.IsInCommitedZone(oid);
                var currentPosition = lastHeader.GetPosition();

                if (currentPosition == -1)
                {
                    throw new OdbRuntimeException(
                        NDatabaseError.InstancePositionIsNegative.AddParameter(currentPosition).AddParameter(oid).
                            AddParameter("In Object Info Header"));
                }
                
                // triggers,FIXME passing null to old object representation
                _storageEngine.GetTriggerManager().ManageUpdateTriggerBefore(nnoi.GetClassInfo().UnderlyingType,
                                                                            null, hasObject ? @object : nnoi, oid);
                // Use to control if the in place update is ok. The
                // ObjectInstrospector stores the number of changes
                // that were detected and here we try to apply them using in place
                // update.If at the end
                // of the in place update the number of applied changes is smaller
                // then the number
                // of detected changes, then in place update was not successfully,
                // we
                // must do a real update,
                // creating an object elsewhere :-(
                if (!forceUpdate)
                {
                    var cachedOid = cache.IdOfInsertingObject(@object);
                    if (cachedOid != null)
                    {
                        // The object is being inserted (must be a cyclic
                        // reference), simply returns id id
                        return cachedOid;
                    }
                    // the nnoi (NonNativeObjectInfo is the meta representation of
                    // the object to update
                    // To know what must be upated we must get the meta
                    // representation of this object before
                    // The modification. Taking this 'old' meta representation from
                    // the
                    // cache does not resolve
                    // : because cache is a reference to the real object and object
                    // has been changed,
                    // so the cache is pointing to the reference, that has changed!
                    // This old meta representation must be re-read from the last
                    // committed database
                    // false, = returnInstance (java object) = false
                    try
                    {
                        var useCache = !objectIsInConnectedZone;
                        oldMetaRepresentation = _objectReader.ReadNonNativeObjectInfoFromPosition(null, oid,
                                                                                                  currentPosition,
                                                                                                  useCache, false);
                        tmpCache.ClearObjectInfos();
                    }
                    catch (OdbRuntimeException e)
                    {
                        var position = currentPosition.ToString();

                        throw new OdbRuntimeException(
                            NDatabaseError.InternalError.AddParameter("Error while reading old Object Info of oid " +
                                                                      oid + " at pos " + position), e);
                    }
                    // Make sure we work with the last version of the object
                    var onDiskVersion = oldMetaRepresentation.GetHeader().GetObjectVersion();
                    var onDiskUpdateDate = oldMetaRepresentation.GetHeader().GetUpdateDate();
                    var inCacheVersion = lastHeader.GetObjectVersion();
                    var inCacheUpdateDate = lastHeader.GetUpdateDate();
                    if (onDiskUpdateDate > inCacheUpdateDate || onDiskVersion > inCacheVersion)
                        lastHeader = oldMetaRepresentation.GetHeader();
                    nnoi.SetHeader(lastHeader);
                    // increase the object version number from the old meta
                    // representation
                    nnoi.GetHeader().IncrementVersionAndUpdateDate();
                    // Keep the creation date
                    nnoi.GetHeader().SetCreationDate(oldMetaRepresentation.GetHeader().GetCreationDate());
                    // Set the object of the old meta to make the object comparator
                    // understand, they are 2
                    // meta representation of the same object
                    // TODO , check if if is the best way to do
                    oldMetaRepresentation.SetObject(nnoi.GetObject());
                    // Reset the comparator
                    _comparator.Clear();
                    objectHasChanged = _comparator.HasChanged(oldMetaRepresentation, nnoi);
                    
                    if (!objectHasChanged)
                    {
                        _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionBeforeWrite, true);
                        
                        return oid;
                    }
                }
                // If we reach this update, In Place Update was not possible. Do a
                // normal update. Deletes the
                // current object and creates a new one
                if (oldMetaRepresentation == null && withIndex)
                {
                    // We must load old meta representation to be able to compute
                    // old index key to update index
                    oldMetaRepresentation = _objectReader.ReadNonNativeObjectInfoFromPosition(null, oid, currentPosition,
                                                                                              false, false);
                }
                
                var previousObjectOID = lastHeader.GetPreviousObjectOID();
                var nextObjectOid = lastHeader.GetNextObjectOID();
                
                nnoi.SetPreviousInstanceOID(previousObjectOID);
                nnoi.SetNextObjectOID(nextObjectOid);
                
                // Mark the block of current object as deleted
                _objectWriter.MarkAsDeleted(currentPosition, objectIsInConnectedZone);
                
                // Creates the new object
                oid = InsertNonNativeObject(oid, nnoi, false);
                
                // This position after write must be call just after the insert!!
                var positionAfterWrite = _objectWriter.FileSystemProcessor.FileSystemInterface.GetPosition();
                if (hasObject)
                {
                    // update cache
                    cache.AddObject(oid, @object, nnoi.GetHeader());
                }

                _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionAfterWrite, true);
                //TODO: why we are not using / checking that? (below is continuity)
                nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
                nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();
                
                return oid;
            }
            catch (Exception e)
            {
                var message = string.Format("Error updating object {0} : {1}", nnoi, e);
                throw new OdbRuntimeException(e, message);
            }
            finally
            {
                if (objectHasChanged)
                {
                    if (withIndex)
                        ManageIndexesForUpdate(oid, nnoi, oldMetaRepresentation);
                    
                    // triggers,FIXME passing null to old object representation
                    // (oldMetaRepresentation may be null)
                    _storageEngine.GetTriggerManager().ManageUpdateTriggerAfter(
                        nnoi.GetClassInfo().UnderlyingType, oldMetaRepresentation, hasObject ? @object : nnoi, oid);
                }
            }
        }
        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);
        }
Exemple #39
0
 public ObjectRepresentation(NonNativeObjectInfo nnoi, IObjectIntrospectionDataProvider classInfoProvider)
 {
     _nnoi = nnoi;
     _classInfoProvider = classInfoProvider;
 }
 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;
 }
Exemple #41
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);
        }