/// <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;
 }
Example #2
0
        internal static IOdbComparable BuildIndexKey(string indexName, NonNativeObjectInfo oi, int[] fieldIds)
        {
            var keys = new IOdbComparable[fieldIds.Length];

            for (var i = 0; i < fieldIds.Length; i++)
            {
                try
                {
                    var aoi = oi.GetAttributeValueFromId(fieldIds[i]);
                    var item = (IComparable) aoi.GetObject();
                    
                    // If the index is on NonNativeObjectInfo, then the key is the oid of the object
                    if (aoi.IsNonNativeObject())
                    {
                        var nnoi = (NonNativeObjectInfo) aoi;
                        item = nnoi.GetOid();
                    }

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

            return keys.Length == 1 ? keys[0] : new ComposedCompareKey(keys);
        }
Example #3
0
        public void StartReadingObjectInfoWithOid(OID oid, NonNativeObjectInfo objectInfo)
        {
            if (oid == null)
                throw new OdbRuntimeException(NDatabaseError.CacheNullOid);

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

            if (!success)
                _readingObjectInfo[oid] = objectInfo;
        }
Example #4
0
        /// <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);
        }
Example #5
0
        public NonNativeObjectInfo EnrichWithOid(NonNativeObjectInfo nnoi, object o)
        {
            var cache = _session.GetCache();

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

            return nnoi;
        }
Example #6
0
 /// <summary>
 ///   Updates pointers of objects, Only changes uncommitted info pointers
 /// </summary>
 /// <param name="objectInfo"> The meta representation of the object being inserted </param>
 /// <param name="classInfo"> The class of the object being inserted </param>
 public void ManageNewObjectPointers(NonNativeObjectInfo objectInfo, ClassInfo classInfo)
 {
     var cache = _storageEngine.GetSession().GetCache();
     var isFirstUncommitedObject = !classInfo.UncommittedZoneInfo.HasObjects();
     // if it is the first uncommitted object
     if (isFirstUncommitedObject)
     {
         classInfo.UncommittedZoneInfo.First = objectInfo.GetOid();
         var lastCommittedObjectOid = classInfo.CommitedZoneInfo.Last;
         if (lastCommittedObjectOid != null)
         {
             // Also updates the last committed object next object oid in
             // memory to connect the committed
             // zone with unconnected for THIS transaction (only in memory)
             var oih = cache.GetObjectInfoHeaderByOid(lastCommittedObjectOid, true);
             oih.SetNextObjectOID(objectInfo.GetOid());
             // And sets the previous oid of the current object with the last
             // committed oid
             objectInfo.SetPreviousInstanceOID(lastCommittedObjectOid);
         }
     }
     else
     {
         // Gets the last object, updates its (next object)
         // pointer to the new object and updates the class info 'last
         // uncommitted object
         // oid' field
         var oip = classInfo.LastObjectInfoHeader;
         if (oip == null)
         {
             throw new OdbRuntimeException(
                 NDatabaseError.InternalError.AddParameter("last OIP is null in manageNewObjectPointers oid=" +
                                                          objectInfo.GetOid()));
         }
         if (oip.GetNextObjectOID() != objectInfo.GetOid())
         {
             oip.SetNextObjectOID(objectInfo.GetOid());
             // Here we are working in unconnected zone, so this
             // can be done without transaction: actually
             // write in database file
             UpdateNextObjectFieldOfObjectInfo(oip.GetOid(), oip.GetNextObjectOID(), false);
             objectInfo.SetPreviousInstanceOID(oip.GetOid());
             // Resets the class info oid: In some case,
             // (client // server) it may be -1.
             oip.SetClassInfoId(classInfo.ClassInfoId);
             // object info oip has been changed, we must put it
             // in the cache to turn this change available for current
             // transaction until the commit
             _storageEngine.GetSession().GetCache().AddObjectInfoOfNonCommitedObject(oip);
         }
     }
     // always set the new last object oid and the number of objects
     classInfo.UncommittedZoneInfo.Last = objectInfo.GetOid();
     classInfo.UncommittedZoneInfo.IncreaseNbObjects();
     // Then updates the last info pointers of the class info
     // with this new created object
     // At this moment, the objectInfo.getHeader() do not have the
     // attribute ids.
     // but later in this code, the attributes will be set, so the class
     // info also will have them
     classInfo.LastObjectInfoHeader = objectInfo.GetHeader();
     // // Saves the fact that something has changed in the class (number of
     // objects and/or last object oid)
     _storageEngine.GetSession().GetMetaModel().AddChangedClass(classInfo);
 }
Example #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;
        }
Example #8
0
 public object BuildOneInstance(NonNativeObjectInfo objectInfo)
 {
     return BuildOneInstance(objectInfo, _engine.GetSession().GetCache());
 }
        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 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));
                    }
                }
            }
        }
Example #11
0
 public ObjectReference(NonNativeObjectInfo nnoi) : base(OdbType.NonNativeId)
 {
     _id = null;
     _nnoi = nnoi;
 }
        /// <summary>
        ///   Updates an object.
        /// </summary>
        /// <remarks>
        ///   Updates an object. <pre>Try to update in place. Only change what has changed. This is restricted to particular types (fixed size types). If in place update is
        ///                        not possible, then deletes the current object and creates a new at the end of the database file and updates
        ///                        OID object position.
        ///                        &#064;param object The object to be updated
        ///                        &#064;param forceUpdate when true, no verification is done to check if update must be done.
        ///                        &#064;return The oid of the object, as a negative number
        ///                        &#064;</pre>
        /// </remarks>
        public OID UpdateNonNativeObjectInfo(NonNativeObjectInfo nnoi, bool forceUpdate)
        {
            var hasObject = true;
            var @object = nnoi.GetObject();
            var oid = nnoi.GetOid();
            if (@object == null)
                hasObject = false;
            // When there is index,we must *always* load the old meta representation
            // to compute index keys
            var withIndex = !nnoi.GetClassInfo().GetIndexes().IsEmpty();
            NonNativeObjectInfo oldMetaRepresentation = null;
            // Used to check consistency, at the end, the number of
            // nbConnectedObjects must and nbUnconnected must remain unchanged
            //TODO: why we are not using / checking that? (below is continuity)
            nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
            nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();

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

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

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

                _objectWriter.FileSystemProcessor.FileSystemInterface.SetWritePosition(positionAfterWrite, true);
                //TODO: why we are not using / checking that? (below is continuity)
                nnoi.GetClassInfo().CommitedZoneInfo.GetNumberbOfObjects();
                nnoi.GetClassInfo().UncommittedZoneInfo.GetNumberbOfObjects();
                
                return oid;
            }
            catch (Exception e)
            {
                var message = string.Format("Error updating object {0} : {1}", nnoi, e);
                throw new OdbRuntimeException(e, message);
            }
            finally
            {
                if (objectHasChanged)
                {
                    if (withIndex)
                        ManageIndexesForUpdate(oid, nnoi, oldMetaRepresentation);
                    
                    // triggers,FIXME passing null to old object representation
                    // (oldMetaRepresentation may be null)
                    _storageEngine.GetTriggerManager().ManageUpdateTriggerAfter(
                        nnoi.GetClassInfo().UnderlyingType, oldMetaRepresentation, hasObject ? @object : nnoi, oid);
                }
            }
        }
Example #13
0
 public ObjectReference(NonNativeObjectInfo nnoi) : base(OdbType.NonNativeId)
 {
     _id   = null;
     _nnoi = nnoi;
 }
        private NonNativeObjectInfo BuildNnoi(object o, ClassInfo classInfo)
        {
            var nnoi = new NonNativeObjectInfo(o, classInfo);

            return _classInfoProvider.EnrichWithOid(nnoi, o);
        }
Example #15
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)
 {
     return _nonNativeObjectWriter.UpdateNonNativeObjectInfo(nnoi, forceUpdate);
 }
Example #16
0
 /// <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)
 {
     return _nonNativeObjectWriter.InsertNonNativeObject(oid, nnoi, isNewObject);
 }
Example #17
0
        /// <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));
                }
            }
        }
Example #18
0
        /// <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));
                }
            }
        }
Example #19
0
 public ObjectRepresentation(NonNativeObjectInfo nnoi, IObjectIntrospectionDataProvider classInfoProvider)
 {
     _nnoi = nnoi;
     _classInfoProvider = classInfoProvider;
 }
Example #20
0
 /// <summary>
 ///   Store a meta representation of an object(already as meta representation)in ODBFactory database.
 /// </summary>
 /// <remarks>
 ///   Store a meta representation of an object(already as meta representation)in ODBFactory database. To detect if object must be updated or insert, we use the cache. To update an object, it must be first selected from the database. When an object is to be stored, if it exist in the cache, then it will be updated, else it will be inserted as a new object. If the object is null, the cache will be used to check if the meta representation is in the cache
 /// </remarks>
 /// <param name="oid"> The oid of the object to be inserted/updates </param>
 /// <param name="nnoi"> The meta representation of an object </param>
 /// <returns> The object position </returns>
 public OID StoreObject(OID oid, NonNativeObjectInfo nnoi)
 {
     // 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
     var @object = nnoi.GetObject();
     var mustUpdate = false;
     var cache = _session.GetCache();
     if (@object != null)
     {
         var cacheOid = cache.IdOfInsertingObject(@object);
         if (cacheOid != null)
             return cacheOid;
         // throw new ODBRuntimeException("Inserting meta representation of
         // an object without the object itself is not yet supported");
         mustUpdate = cache.Contains(@object);
     }
     if (!mustUpdate)
         mustUpdate = !Equals(nnoi.GetOid(), StorageEngineConstant.NullObjectId);
     
     return mustUpdate
                ? UpdateNonNativeObjectInfo(nnoi, false)
                : InsertNonNativeObject(oid, nnoi, true);
 }
Example #21
0
        /// <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;
        }