コード例 #1
0
ファイル: ObjectInfoComparator.cs プロジェクト: Myvar/Eclang
        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++;
            }
        }
コード例 #2
0
 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");
     }
 }
コード例 #3
0
        /// <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);
                }
            }
        }
コード例 #4
0
        public virtual object BuildOneInstance(NonNativeObjectInfo objectInfo)
        {
            ICache cache = GetSession().GetCache();

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

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

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

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

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

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

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

            return(o);
        }
コード例 #5
0
 public OID GetOid()
 {
     return(_nnoi.GetOid());
 }
コード例 #6
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++;
            }
        }
コード例 #7
0
        public object BuildOneInstance(NonNativeObjectInfo objectInfo, IOdbCache cache)
        {
            // verify if the object is check to delete
            if (objectInfo.IsDeletedObject())
            {
                throw new OdbRuntimeException(
                          NDatabaseError.ObjectIsMarkedAsDeletedForOid.AddParameter(objectInfo.GetOid()));
            }

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

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

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

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

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

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

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

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

            object value = null;

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

                var abstractObjectInfo = objectInfo.GetAttributeValueFromId(attributeId);

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

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

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

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

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

            return(o);
        }
コード例 #8
0
        /// <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);
                }
            }
        }
コード例 #9
0
        /// <summary>Store an object with the specific id</summary>
        /// <param name="oid"></param>
        /// <param name="@object"></param>
        /// <returns></returns>
        /// <></>
        protected virtual NeoDatis.Odb.OID InternalStore(OID oid, object o)
        {
            if (GetSession(true).IsRollbacked())
            {
                throw new ODBRuntimeException(NeoDatisError.OdbHasBeenRollbacked.AddParameter(GetBaseIdentification().ToString()));
            }
            if (o == null)
            {
                throw new ODBRuntimeException(NeoDatisError.OdbCanNotStoreNullObject);
            }
            Type clazz = o.GetType();

            if (ODBType.IsNative(clazz))
            {
                throw new ODBRuntimeException(NeoDatisError.OdbCanNotStoreNativeObjectDirectly
                                              .AddParameter(clazz.FullName).AddParameter(ODBType.GetFromClass(clazz).GetName()).AddParameter(clazz.FullName));
            }
            // The object must be transformed into meta representation
            ClassInfo ci        = null;
            string    className = OdbClassUtil.GetFullName(clazz);

            // first checks if the class of this object already exist in the
            // metamodel
            if (GetMetaModel().ExistClass(className))
            {
                ci = GetMetaModel().GetClassInfo(className, true);
            }
            else
            {
                ClassInfoList ciList = classIntrospector.Introspect(o.GetType(), true);
                // All new classes found
                objectWriter.AddClasses(ciList);
                ci = ciList.GetMainClassInfo();
            }
            // first detects if we must perform an insert or an update
            // If object is in the cache, we must perform an update, else an insert
            bool   mustUpdate = false;
            ICache cache      = GetSession(true).GetCache();

            if (o != null)
            {
                OID cacheOid = cache.IdOfInsertingObject(o);
                if (cacheOid != null)
                {
                    return(cacheOid);
                }
                // throw new ODBRuntimeException("Inserting meta representation of
                // an object without the object itself is not yet supported");
                mustUpdate = cache.ExistObject(o);
            }
            // The introspection callback is used to execute some specific task (like calling trigger, for example) while introspecting the object
            IIntrospectionCallback callback = introspectionCallbackForInsert;

            if (mustUpdate)
            {
                callback = introspectionCallbackForUpdate;
            }
            // Transform the object into an ObjectInfo
            NonNativeObjectInfo nnoi = (NonNativeObjectInfo)objectIntrospector.GetMetaRepresentation(o, ci, true, null, callback);

            // During the introspection process, if object is to be updated, then the oid has been set
            mustUpdate = nnoi.GetOid() != null;
            if (mustUpdate)
            {
                return(objectWriter.UpdateNonNativeObjectInfo(nnoi, false));
            }
            return(objectWriter.InsertNonNativeObject(oid, nnoi, true));
        }
コード例 #10
0
        private bool HasChanged(NonNativeObjectInfo nnoi1, NonNativeObjectInfo nnoi2, int objectRecursionLevel)
        {
            AbstractObjectInfo value1 = null;
            AbstractObjectInfo value2 = null;
            bool hasChanged           = false;
            // If the object is already being checked, return false, this second
            // check will not affect the check
            int n = 0;

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

            if (i1 != null)
            {
                i1 = i1 - 1;
            }
            if (i2 != null)
            {
                i2 = i2 - 1;
            }
            if (i1 == 0)
            {
                alreadyCheckingObjects.Remove(nnoi1);
            }
            else
            {
                alreadyCheckingObjects.Add(nnoi1, i1);
            }
            if (i2 == 0)
            {
                alreadyCheckingObjects.Remove(nnoi2);
            }
            else
            {
                alreadyCheckingObjects.Add(nnoi2, i2);
            }
            return(hasChanged);
        }
コード例 #11
0
        /// <summary>
        /// Checks if something in the Collection 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="coi1">
        /// The Meta representation of the collection 1 (coi =
        /// CollectionObjectInfo)
        /// </param>
        /// <param name="coi2">The Meta representation of the collection 2</param>
        /// <param name="objectRecursionLevel"></param>
        /// <returns>true if 2 collection representation are different</returns>
        private bool ManageCollectionChanges(NonNativeObjectInfo
                                             nnoi1, NonNativeObjectInfo nnoi2, int fieldId
                                             , CollectionObjectInfo coi1, CollectionObjectInfo
                                             coi2, int objectRecursionLevel)
        {
            ICollection <AbstractObjectInfo
                         > collection1 = coi1.GetCollection();
            ICollection <AbstractObjectInfo
                         > collection2 = coi2.GetCollection();

            if (collection1.Count != collection2.Count)
            {
                System.Text.StringBuilder buffer = new System.Text.StringBuilder();
                buffer.Append("Collection size has changed oldsize=").Append(collection1.Count).Append
                    ("/newsize=").Append(collection2.Count);
                StoreChangedObject(nnoi1, nnoi2, fieldId, coi1, coi2, buffer.ToString(), objectRecursionLevel
                                   );
                return(true);
            }
            System.Collections.IEnumerator iterator1 = collection1.GetEnumerator();
            System.Collections.IEnumerator iterator2 = collection2.GetEnumerator();
            AbstractObjectInfo             value1    = null;
            AbstractObjectInfo             value2    = null;
            int index = 0;

            while (iterator1.MoveNext())
            {
                iterator2.MoveNext();
                value1 = (AbstractObjectInfo)iterator1.Current;
                value2 = (AbstractObjectInfo)iterator2.Current;
                bool hasChanged = this.HasChanged(value1, value2, objectRecursionLevel);
                if (hasChanged)
                {
                    // We consider collection has changed only if object are
                    // different, If objects are the same instance, but something in
                    // the object has changed, then the collection has not
                    // changed,only the object
                    if (value1.IsNonNativeObject() && value2.IsNonNativeObject())
                    {
                        NonNativeObjectInfo nnoia = (NonNativeObjectInfo
                                                     )value1;
                        NonNativeObjectInfo nnoib = (NonNativeObjectInfo
                                                     )value2;
                        if (nnoia.GetOid() != null && !nnoia.GetOid().Equals(nnoi2.GetOid()))
                        {
                            // Objects are not the same instance -> the collection
                            // has changed
                            StoreChangedObject(nnoi1, nnoi2, fieldId, value1, value2, "List element index " +
                                               index + " has changed", objectRecursionLevel);
                        }
                    }
                    else
                    {
                        supportInPlaceUpdate = false;
                        nbChanges++;
                    }
                    //storeChangedObject(nnoi1, nnoi2, fieldId, value1, value2, "List element index " + index + " has changed", objectRecursionLevel);
                    return(true);
                }
                index++;
            }
            return(false);
        }