/// <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; }
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); } } }
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++; }
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); }
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); }
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; } }
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); }
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"); } }
//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. /// @param object The object to be updated /// @param forceUpdate when true, no verification is done to check if update must be done. /// @return The oid of the object, as a negative number /// @</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; }
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); }
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; }
/// <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. /// @param object The object to be updated /// @param forceUpdate when true, no verification is done to check if update must be done. /// @return The oid of the object, as a negative number /// @</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); }
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; }
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); }