/// <summary> /// Insert the object in the index /// </summary> /// <param name="oid"> The object id </param> /// <param name="nnoi"> The object meta represenation </param> /// <returns> The number of indexes </returns> private static void ManageIndexesForDelete(OID oid, NonNativeObjectInfo nnoi) { var indexes = nnoi.GetClassInfo().GetIndexes(); foreach (var index in indexes) { // TODO manage collision! var odbComparable = IndexTool.BuildIndexKey(index.Name, nnoi, index.AttributeIds); index.BTree.Delete(odbComparable, 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)); } } }
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; }
/// <summary> /// Insert the object in the index /// </summary> /// <param name="oid"> The object id </param> /// <param name="nnoi"> The object meta represenation </param> /// <returns> The number of indexes </returns> public void ManageIndexesForInsert(OID oid, NonNativeObjectInfo nnoi) { var indexes = nnoi.GetClassInfo().GetIndexes(); foreach (var index in indexes) { try { var odbComparable = IndexTool.BuildIndexKey(index.Name, nnoi, index.AttributeIds); index.BTree.Insert(odbComparable, oid); } catch (DuplicatedKeyException) { // rollback what has been done // bug #2510966 _session.Rollback(); throw; } // 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)); } } }