Example #1
0
        public IBTree LoadBTree(object id)
        {
            var oid = (OID)id;

            try
            {
                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Format("LazyOdbBtreePersister: Loading btree with id {0}", oid));
                }

                if (oid == StorageEngineConstant.NullObjectId)
                {
                    throw new OdbRuntimeException(
                              BTreeError.InvalidIdForBtree.AddParameter(StorageEngineConstant.NullObjectId));
                }

                _tree = (IBTree)_engine.GetObjectFromOid(oid);
                _tree.SetId(oid);
                _tree.SetPersister(this);
                var root = _tree.GetRoot();

                root.SetBTree(_tree);

                return(_tree);
            }
            catch (Exception e)
            {
                throw new OdbRuntimeException(BTreeError.InternalError, e);
            }
        }
Example #2
0
        public long ReadOidPosition(OID oid)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug("ObjectReader: Start of readOidPosition for oid " + oid);
            }

            var blockNumber   = StorageEngineConstant.GetIdBlockNumberOfOid(oid);
            var blockPosition = GetIdBlockPositionFromNumber(blockNumber);

            if (OdbConfiguration.IsLoggingEnabled())
            {
                var blockNumberAsString   = blockNumber.ToString();
                var blockPositionAsString = blockPosition.ToString();
                DLogger.Debug(string.Format("ObjectReader: Block number of oid {0} is ", oid) + blockNumberAsString +
                              " / block position = " + blockPositionAsString);
            }

            var position = blockPosition + StorageEngineConstant.BlockIdOffsetForStartOfRepetition +
                           ((oid.ObjectId - 1) % StorageEngineConstant.NbIdsPerBlock) *
                           StorageEngineConstant.IdBlockRepetitionSize;

            if (OdbConfiguration.IsLoggingEnabled())
            {
                var positionAsString = position.ToString();
                DLogger.Debug(string.Format("ObjectReader: End of readOidPosition for oid {0} returning position ", oid) + positionAsString);
            }

            return(position);
        }
Example #3
0
        /// <summary>
        ///   Gets the real object position from its OID
        /// </summary>
        /// <param name="oid"> The oid of the object to get the position </param>
        /// <param name="useCache"> </param>
        /// <param name="throwException"> To indicate if an exception must be thrown if object is not found </param>
        /// <returns> The object position, if object has been marked as deleted then return StorageEngineConstant.DELETED_OBJECT_POSITION @ </returns>
        public long GetObjectPositionFromItsOid(OID oid, bool useCache, bool throwException)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug("ObjectReader: getObjectPositionFromItsId for oid " + oid);
            }
            // Check if oid is in cache
            var position = StorageEngineConstant.ObjectIsNotInCache;

            if (useCache)
            {
                // This return -1 if not in the cache
                position = _storageEngine.GetSession().GetCache().GetObjectPositionByOid(oid);
            }
            // FIXME Check if we need this. Removing it causes the TestDelete.test6 to fail
            if (position == StorageEngineConstant.DeletedObjectPosition)
            {
                if (throwException)
                {
                    throw new CorruptedDatabaseException(NDatabaseError.ObjectIsMarkedAsDeletedForOid.AddParameter(oid));
                }
                return(StorageEngineConstant.DeletedObjectPosition);
            }
            if (position != StorageEngineConstant.ObjectIsNotInCache &&
                position != StorageEngineConstant.DeletedObjectPosition)
            {
                return(position);
            }
            // The position was not found is the cache
            position  = ReadOidPosition(oid);
            position += StorageEngineConstant.BlockIdRepetitionIdStatus;
            _fsi.SetReadPosition(position);
            var idStatus       = _fsi.ReadByte();
            var objectPosition = _fsi.ReadLong();

            if (!IDStatus.IsActive(idStatus))
            {
                // if object position == 0, The object dos not exist
                if (throwException)
                {
                    if (objectPosition == 0)
                    {
                        throw new CorruptedDatabaseException(NDatabaseError.ObjectWithOidDoesNotExist.AddParameter(oid));
                    }
                    throw new CorruptedDatabaseException(NDatabaseError.ObjectIsMarkedAsDeletedForOid.AddParameter(oid));
                }

                return(objectPosition == 0
                           ? StorageEngineConstant.ObjectDoesNotExist
                           : StorageEngineConstant.DeletedObjectPosition);
            }
            if (OdbConfiguration.IsLoggingEnabled())
            {
                var positionAsString = objectPosition.ToString();
                DLogger.Debug("ObjectReader: object position of object with oid " + oid + " is " + positionAsString);
            }
            return(objectPosition);
        }
Example #4
0
        /// <summary>
        ///   Read the class info header with the specific oid
        /// </summary>
        /// <returns> The read class info object @ </returns>
        public ClassInfo ReadClassInfoHeader(OID classInfoOid)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug("FileSystemReader: Reading new Class info Header with oid " + classInfoOid);
            }
            var classInfoPosition = GetObjectPositionFromItsOid(classInfoOid, true, true);

            _fsi.SetReadPosition(classInfoPosition);
            var blockSize = _fsi.ReadInt();
            var blockType = _fsi.ReadByte();

            if (!BlockTypes.IsClassHeader(blockType))
            {
                throw new OdbRuntimeException(
                          NDatabaseError.WrongTypeForBlockType.AddParameter("Class Header").AddParameter(blockType).
                          AddParameter(classInfoPosition));
            }
            //class info category, to remove
            _fsi.ReadByte();

            var classInfoId                  = OIDFactory.BuildClassOID(_fsi.ReadLong());
            var previousClassOID             = ReadOid();
            var nextClassOID                 = ReadOid();
            var nbObjects                    = _fsi.ReadLong();
            var originalZoneInfoFirst        = ReadOid();
            var originalZoneInfoLast         = ReadOid();
            var fullClassName                = _fsi.ReadString();
            var maxAttributeId               = _fsi.ReadInt();
            var attributesDefinitionPosition = _fsi.ReadLong();

            var classInfo = new ClassInfo(fullClassName)
            {
                Position                     = classInfoPosition,
                ClassInfoId                  = classInfoId,
                PreviousClassOID             = previousClassOID,
                NextClassOID                 = nextClassOID,
                MaxAttributeId               = maxAttributeId,
                AttributesDefinitionPosition = attributesDefinitionPosition
            };

            classInfo.OriginalZoneInfo.SetNbObjects(nbObjects);
            classInfo.OriginalZoneInfo.First = originalZoneInfoFirst;
            classInfo.OriginalZoneInfo.Last  = originalZoneInfoLast;
            classInfo.CommitedZoneInfo.SetBasedOn(classInfo.OriginalZoneInfo);

            // FIXME Convert block size to long ??
            var realBlockSize = (int)(_fsi.GetPosition() - classInfoPosition);

            if (blockSize != realBlockSize)
            {
                throw new OdbRuntimeException(
                          NDatabaseError.WrongBlockSize.AddParameter(blockSize).AddParameter(realBlockSize).AddParameter(
                              classInfoPosition));
            }
            return(classInfo);
        }
Example #5
0
        private void Persist()
        {
            _nbPersist++;

            if (OdbConfiguration.IsLoggingEnabled())
            {
                var count = _modifiedObjectOids.Count.ToString();
                DLogger.Debug(string.Concat("LazyOdbBtreePersister: ", "persist ", _nbPersist.ToString(), "  : Saving " + count + " objects - ",
                                            GetHashCode().ToString()));
            }

            var         nbCommited = 0;
            var         i          = 0;
            var         size       = _modifiedObjectOids.Count;
            IEnumerator iterator   = _modifiedObjectOidList.GetEnumerator();

            while (iterator.MoveNext())
            {
                var oid = (OID)iterator.Current;

                if (oid == null)
                {
                    continue;
                }

                nbCommited++;
                long t0;
                long t1;

                try
                {
                    t0 = OdbTime.GetCurrentTimeInMs();
                    var @object = _oids[oid];
                    _engine.Store(@object);
                    t1 = OdbTime.GetCurrentTimeInMs();
                }
                catch (Exception e)
                {
                    throw new OdbRuntimeException(
                              BTreeError.InternalError.AddParameter("Error while storing object with oid " + oid), e);
                }

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Concat("LazyOdbBtreePersister: ", "Committing oid " + oid, " | ", i.ToString(), "/", size.ToString(),
                                                " | ", (t1 - t0).ToString(), " ms"));
                }

                i++;
            }

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Concat("LazyOdbBtreePersister: ", nbCommited.ToString(), " commits / ", size.ToString()));
            }
        }
Example #6
0
        /// <summary>
        ///   Adds a write action to the transaction
        /// </summary>
        /// <param name="writeAction"> The write action to be added </param>
        /// <param name="persistWriteAction"> To indicate if write action must be persisted </param>
        private void AddWriteAction(WriteAction writeAction, bool persistWriteAction)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Format("OdbTransaction: Adding WriteAction in Transaction of session {0}", _session.GetId()));
            }

            if (writeAction.IsEmpty())
            {
                return;
            }

            CheckRollback();
            if (!_hasBeenPersisted && persistWriteAction)
            {
                Persist();
            }

            if (persistWriteAction)
            {
                writeAction.PersistMeTo(_fsi);
            }

            // Only adds the write action to the list if the transaction keeps all in
            // memory
            if (_hasAllWriteActionsInMemory)
            {
                _writeActions.Add(writeAction);
            }

            _numberOfWriteActions++;

            if (_hasAllWriteActionsInMemory &&
                _numberOfWriteActions > StorageEngineConstant.MaxNumberOfWriteObjectPerTransaction)
            {
                _hasAllWriteActionsInMemory = false;

                foreach (var defaultWriteAction in _writeActions)
                {
                    defaultWriteAction.Clear();
                }

                _writeActions.Clear();

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    var numberOfWriteActions = _numberOfWriteActions.ToString();
                    var maxNumberOfWriteObjectPerTransactionAsString =
                        StorageEngineConstant.MaxNumberOfWriteObjectPerTransaction.ToString();

                    DLogger.Info("OdbTransaction: Number of objects has exceeded the max number " + numberOfWriteActions + "/" +
                                 maxNumberOfWriteObjectPerTransactionAsString +
                                 ": switching to persistent transaction managment");
                }
            }
        }
        public void Check_turning_on_the_logging()
        {
            Assert.That(OdbConfiguration.IsLoggingEnabled(), Is.False);

            OdbConfiguration.EnableLogging();

            Assert.That(OdbConfiguration.IsLoggingEnabled(), Is.True);

            OdbConfiguration.DisableLogging();

            Assert.That(OdbConfiguration.IsLoggingEnabled(), Is.False);
        }
        /// <summary>
        ///     Used to rebuild an index
        /// </summary>
        public void RebuildIndex(string className, string indexName)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Format("StorageEngine: Rebuilding index {0} on class {1}", indexName, className));
            }

            var classInfo      = GetMetaModel().GetClassInfo(className, true);
            var classInfoIndex = GetClassInfoIndex(className, indexName, classInfo);

            DeleteIndex(className, indexName);

            AddIndexOn(className, indexName, classInfo.GetAttributeNames(classInfoIndex.AttributeIds),
                       !classInfoIndex.IsUnique);
        }
Example #9
0
        private void UpdateMetaModel()
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info("StorageEngine: Automatic refactoring : updating meta model");
            }

            var metaModel = GetMetaModel();

            var storedClasses = metaModel.GetAllClasses().ToList();

            foreach (var userClass in storedClasses)
            {
                _objectWriter.UpdateClassInfo(userClass, true);
            }
        }
Example #10
0
        private void Persist()
        {
            CheckFileAccess(null);

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Format("OdbTransaction: # Persisting transaction {0}", GetName()));
            }

            _fsi.SetWritePosition(0, false);
            _fsi.WriteBoolean(_isCommited, false);
            _fsi.WriteLong(_creationDateTime, false);

            // Size
            _fsi.WriteLong(0, false);
            _hasBeenPersisted = true;
        }
        public void DeleteIndex(string className, string indexName)
        {
            var classInfo = GetMetaModel().GetClassInfo(className, true);

            var classInfoIndex = GetClassInfoIndex(className, indexName, classInfo);

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Format("StorageEngine: Deleting index {0} on class {1}", indexName, className));
            }

            Delete(classInfoIndex);
            classInfo.RemoveIndex(classInfoIndex);

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Format("StorageEngine: Index {0} deleted", indexName));
            }
        }
Example #12
0
        public override void DefragmentTo(string newFileName)
        {
            var start          = OdbTime.GetCurrentTimeInMs();
            var totalNbObjects = 0L;

            var newStorageEngine = new StorageEngine(new FileIdentification(newFileName));
            var j = 0;

            var criteriaQuery = new SodaQuery(typeof(object));
            var defragObjects = GetObjects <object>(criteriaQuery, true, -1, -1);

            foreach (var defragObject in defragObjects)
            {
                newStorageEngine.Store(defragObject);
                totalNbObjects++;

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    if (j % 10000 == 0)
                    {
                        DLogger.Info(string.Concat("\nStorageEngine: ", totalNbObjects.ToString(), " objects saved."));
                    }
                }

                j++;
            }

            newStorageEngine.Close();

            var time = OdbTime.GetCurrentTimeInMs() - start;

            if (!OdbConfiguration.IsLoggingEnabled())
            {
                return;
            }

            var nbObjectsAsString = totalNbObjects.ToString();
            var timeAsString      = time.ToString();

            DLogger.Info(string.Format("StorageEngine: New storage {0} created with {1} objects in {2} ms.", newFileName,
                                       nbObjectsAsString, timeAsString));
        }
Example #13
0
        /// <summary>
        ///   saves the bree node Only puts the current node in an 'modified Node' map to be saved on commit
        /// </summary>
        public void SaveNode(IBTreeNode node)
        {
            OID oid;

            // Here we only save the node if it does not have id,
            // else we just save into the hashmap
            if (node.GetId() == StorageEngineConstant.NullObjectId)
            {
                try
                {
                    // first get the oid. : -2:it could be any value
                    oid = _engine.GetObjectWriter().GetIdManager().GetNextObjectId(-2);
                    node.SetId(oid);

                    oid = _engine.Store(oid, node);

                    if (OdbConfiguration.IsLoggingEnabled())
                    {
                        DLogger.Debug(string.Format("LazyOdbBtreePersister: Saved node id {0}", oid));
                    }

                    // + " : " +
                    // node.toString());
                    if (_tree != null && node.GetBTree() == null)
                    {
                        node.SetBTree(_tree);
                    }

                    _oids.Add(oid, node);
                    return;
                }
                catch (Exception e)
                {
                    throw new OdbRuntimeException(BTreeError.InternalError.AddParameter("While saving node"), e);
                }
            }

            oid = (OID)node.GetId();

            _oids.Add(oid, node);
            AddModifiedOid(oid);
        }
Example #14
0
        /// <summary>
        ///   Loads a node from its id.
        /// </summary>
        /// <remarks>
        ///   Loads a node from its id. Tries to get if from memory, if not present then loads it from odb storage
        /// </remarks>
        /// <param name="id"> The id of the nod </param>
        /// <returns> The node with the specific id </returns>
        public IBTreeNode LoadNodeById(object id)
        {
            var oid = (OID)id;
            // Check if node is in memory
            var node = (IBTreeNode)_oids[oid];

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

            // else load from odb
            try
            {
                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Format("LazyOdbBtreePersister: Loading node with id {0}", oid));
                }

                if (oid == null)
                {
                    throw new OdbRuntimeException(BTreeError.InvalidIdForBtree.AddParameter("oid"));
                }

                var pn = (IBTreeNode)_engine.GetObjectFromOid(oid);
                pn.SetId(oid);

                if (_tree != null)
                {
                    pn.SetBTree(_tree);
                }

                // Keep the node in memory
                _oids.Add(oid, pn);
                return(pn);
            }
            catch (Exception e)
            {
                throw new OdbRuntimeException(BTreeError.InternalError, e);
            }
        }
Example #15
0
        internal static WriteAction Read(IFileSystemInterface fsi)
        {
            try
            {
                var position    = fsi.ReadLong();
                var size        = fsi.ReadInt();
                var bytes       = fsi.ReadBytes(size);
                var writeAction = new WriteAction(position, bytes);

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Format("Transaction WriteAction: Loading Write Action at {0} => {1}", fsi.GetPosition(), writeAction));
                }

                return(writeAction);
            }
            catch (OdbRuntimeException)
            {
                DLogger.Error(string.Format("Transaction WriteAction: error reading write action at position {0}", fsi.GetPosition()));
                throw;
            }
        }
Example #16
0
        private void LoadWriteActions(string filename, bool apply)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Format("OdbTransaction: Load write actions of {0}", filename));
            }

            CheckFileAccess(filename);
            _fsi.SetReadPosition(0);
            _isCommited       = _fsi.ReadByte() == 1;
            _creationDateTime = _fsi.ReadLong();
            var totalNumberOfWriteActions = _fsi.ReadLong();

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Concat("OdbTransaction: ", _writeActions.Count.ToString(), " write actions in file"));
            }

            for (var i = 0; i < totalNumberOfWriteActions; i++)
            {
                var defaultWriteAction = WriteAction.Read(_fsi);

                if (apply)
                {
                    defaultWriteAction.ApplyTo(_fsiToApplyWriteActions);
                    defaultWriteAction.Clear();
                }
                else
                {
                    AddWriteAction(defaultWriteAction, false);
                }
            }

            if (apply)
            {
                _fsiToApplyWriteActions.Flush();
            }
        }
Example #17
0
        public void SaveBTree(IBTree treeToSave)
        {
            try
            {
                var oid = (OID)treeToSave.GetId();

                if (oid == null)
                {
                    // first get the oid. -2 : it could be any value
                    oid = _engine.GetObjectWriter().GetIdManager().GetNextObjectId(-2);
                    treeToSave.SetId(oid);
                    oid = _engine.Store(oid, treeToSave);

                    if (OdbConfiguration.IsLoggingEnabled())
                    {
                        DLogger.Debug(string.Format("LazyOdbBtreePersister: Saved btree {0} with id {1} and  root {2}", treeToSave.GetId(), oid,
                                                    treeToSave.GetRoot()));
                    }

                    if (_tree == null)
                    {
                        _tree = treeToSave;
                    }

                    _oids.Add(oid, treeToSave);
                }
                else
                {
                    _oids.Add(oid, treeToSave);
                    AddModifiedOid(oid);
                }
            }
            catch (Exception e)
            {
                throw new OdbRuntimeException(BTreeError.InternalError, e);
            }
        }
        /// <summary>
        ///   Execute query using index
        /// </summary>
        /// <param name="inMemory"> </param>
        /// <param name="returnObjects"> </param>
        /// <param name="queryResultAction"> </param>
        private IInternalObjectSet <T> ExecuteForOneOid <T>(bool inMemory, bool returnObjects,
                                                            IMatchingObjectAction queryResultAction)
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Format("GenericQueryExecutor: loading Object with oid {0} - class {1}", Query.GetOidOfObjectToQuery(),
                                            ClassInfo.FullClassName));
            }

            if (ExecuteStartAndEndOfQueryAction())
            {
                queryResultAction.Start();
            }

            PrepareQuery();
            var oid = Query.GetOidOfObjectToQuery();

            MatchObjectWithOid(oid, returnObjects, inMemory);

            queryResultAction.ObjectMatch(oid, GetCurrentObjectMetaRepresentation(), _orderByKey);
            queryResultAction.End();

            return(queryResultAction.GetObjects <T>());
        }
        public void AddIndexOn(string className, string indexName, string[] indexFields,
                               bool acceptMultipleValuesForSameKey)
        {
            var classInfo = GetMetaModel().GetClassInfo(className, true);

            if (classInfo.HasIndex(indexName))
            {
                throw new OdbRuntimeException(
                          NDatabaseError.IndexAlreadyExist.AddParameter(indexName).AddParameter(className));
            }

            var    classInfoIndex = classInfo.AddIndexOn(indexName, indexFields, acceptMultipleValuesForSameKey);
            IBTree btree;

            var lazyOdbBtreePersister = new LazyOdbBtreePersister(this);

            if (acceptMultipleValuesForSameKey)
            {
                btree = new OdbBtreeMultiple(OdbConfiguration.GetIndexBTreeDegree(), lazyOdbBtreePersister);
            }
            else
            {
                btree = new OdbBtreeSingle(OdbConfiguration.GetIndexBTreeDegree(), lazyOdbBtreePersister);
            }

            classInfoIndex.BTree = btree;
            Store(classInfoIndex);

            // Now The index must be updated with all existing objects.
            if (classInfo.NumberOfObjects == 0)
            {
                // There are no objects. Nothing to do
                return;
            }

            if (OdbConfiguration.IsLoggingEnabled())
            {
                var numberOfObjectsAsString = classInfo.NumberOfObjects.ToString();
                DLogger.Info(
                    string.Format(
                        "StorageEngine: Creating index {0} on class {1} - Class has already {2} Objects. Updating index",
                        indexName, className, numberOfObjectsAsString));

                DLogger.Info(string.Format("StorageEngine: {0} : loading {1} objects from database", indexName,
                                           numberOfObjectsAsString));
            }

            // We must load all objects and insert them in the index!
            var criteriaQuery = new SodaQuery(classInfo.UnderlyingType);
            var objects       = GetObjectInfos(criteriaQuery);

            if (OdbConfiguration.IsLoggingEnabled())
            {
                var numberOfObjectsAsString = classInfo.NumberOfObjects.ToString();
                DLogger.Info(string.Format("StorageEngine: {0} : {1} objects loaded", indexName, numberOfObjectsAsString));
            }

            while (objects.HasNext())
            {
                var nnoi = (NonNativeObjectInfo)objects.Next();

                var odbComparable = IndexTool.BuildIndexKey(classInfoIndex.Name, nnoi, classInfoIndex.AttributeIds);
                btree.Insert(odbComparable, nnoi.GetOid());
            }

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Info(string.Format("StorageEngine: {0} created!", indexName));
            }
        }
        /// <summary>
        ///   Query execution full scan <pre>startIndex &amp; endIndex
        ///                               A B C D E F G H I J K L
        ///                               [1,3] : nb &gt;=1 &amp;&amp; nb&lt;3
        ///                               1)
        ///                               analyze A
        ///                               nb = 0
        ///                               nb E [1,3] ? no
        ///                               r=[]
        ///                               2)
        ///                               analyze B
        ///                               nb = 1
        ///                               nb E [1,3] ? yes
        ///                               r=[B]
        ///                               3) analyze C
        ///                               nb = 2
        ///                               nb E [1,3] ? yes
        ///                               r=[B,C]
        ///                               4) analyze C
        ///                               nb = 3
        ///                               nb E [1,3] ? no and 3&gt; upperBound([1,3]) =&gt; exit</pre>
        /// </summary>
        /// <param name="inMemory"> </param>
        /// <param name="startIndex"> </param>
        /// <param name="endIndex"> </param>
        /// <param name="returnObjects"> </param>
        /// <param name="queryResultAction"> </param>
        private IInternalObjectSet <T> ExecuteFullScan <T>(bool inMemory, int startIndex, int endIndex, bool returnObjects,
                                                           IMatchingObjectAction queryResultAction)
        {
            if (StorageEngine.IsClosed())
            {
                throw new OdbRuntimeException(
                          NDatabaseError.OdbIsClosed.AddParameter(StorageEngine.GetBaseIdentification().Id));
            }
            var nbObjects = ClassInfo.NumberOfObjects;

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Format("GenericQueryExecutor: loading {0} instance(s) of {1}", nbObjects, ClassInfo.FullClassName));
            }

            if (ExecuteStartAndEndOfQueryAction())
            {
                queryResultAction.Start();
            }

            OID currentOID = null;

            // TODO check if all instances are in the cache! and then load from the cache
            NextOID = ClassInfo.CommitedZoneInfo.First;

            if (nbObjects > 0 && NextOID == null)
            {
                // This means that some changes have not been commited!
                // Take next position from uncommited zone
                NextOID = ClassInfo.UncommittedZoneInfo.First;
            }

            PrepareQuery();
            if (Query != null)
            {
                _queryHasOrderBy = Query.HasOrderBy();
            }

            // used when startIndex and endIndex are not negative
            var nbObjectsInResult = 0;

            for (var i = 0; i < nbObjects; i++)
            {
                // Reset the order by key
                _orderByKey = null;
                var prevOID = currentOID;
                currentOID = NextOID;

                // This is an error
                if (currentOID == null)
                {
                    throw new OdbRuntimeException(
                              NDatabaseError.NullNextObjectOid.AddParameter(ClassInfo.FullClassName).AddParameter(i).
                              AddParameter(nbObjects).AddParameter(prevOID));
                }

                // If there is an endIndex condition
                if (endIndex != -1 && nbObjectsInResult >= endIndex)
                {
                    break;
                }

                // If there is a startIndex condition
                bool objectInRange;
                if (startIndex != -1 && nbObjectsInResult < startIndex)
                {
                    objectInRange = false;
                }
                else
                {
                    objectInRange = true;
                }

                // There is no query
                if (!inMemory && Query == null)
                {
                    nbObjectsInResult++;

                    // keep object position if we must
                    if (objectInRange)
                    {
                        _orderByKey = BuildOrderByKey(CurrentNnoi);
                        // TODO Where is the key for order by
                        queryResultAction.ObjectMatch(NextOID, _orderByKey);
                    }

                    NextOID = ObjectReader.GetNextObjectOID(currentOID);
                }
                else
                {
                    var objectMatches = MatchObjectWithOid(currentOID, returnObjects, inMemory);

                    if (objectMatches)
                    {
                        nbObjectsInResult++;

                        if (objectInRange)
                        {
                            if (_queryHasOrderBy)
                            {
                                _orderByKey = BuildOrderByKey(GetCurrentObjectMetaRepresentation());
                            }

                            queryResultAction.ObjectMatch(currentOID, GetCurrentObjectMetaRepresentation(), _orderByKey);
                        }
                    }
                }
            }

            if (ExecuteStartAndEndOfQueryAction())
            {
                queryResultAction.End();
            }

            return(queryResultAction.GetObjects <T>());
        }
        /// <summary>
        ///   Execute query using index
        /// </summary>
        /// <param name="index"> </param>
        /// <param name="inMemory"> </param>
        /// <param name="returnObjects"> </param>
        /// <param name="queryResultAction"> </param>
        private IInternalObjectSet <T> ExecuteUsingIndex <T>(ClassInfoIndex index, bool inMemory,
                                                             bool returnObjects, IMatchingObjectAction queryResultAction)
        {
            // Index that have not been used yet do not have persister!
            if (index.BTree.GetPersister() == null)
            {
                index.BTree.SetPersister(new LazyOdbBtreePersister(StorageEngine));
            }

            var nbObjects = ClassInfo.NumberOfObjects;
            var btreeSize = index.BTree.GetSize();

            // the two values should be equal
            if (nbObjects != btreeSize)
            {
                var classInfo = StorageEngine.GetSession().GetMetaModel().GetClassInfoFromId(index.ClassInfoId);

                throw new OdbRuntimeException(
                          NDatabaseError.IndexIsCorrupted.AddParameter(index.Name).AddParameter(classInfo.FullClassName).
                          AddParameter(nbObjects).AddParameter(btreeSize));
            }

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug(string.Format("GenericQueryExecutor: loading {0} instance(s) of {1}", nbObjects, ClassInfo.FullClassName));
            }

            if (ExecuteStartAndEndOfQueryAction())
            {
                queryResultAction.Start();
            }

            PrepareQuery();
            if (Query != null)
            {
                _queryHasOrderBy = Query.HasOrderBy();
            }

            var tree     = index.BTree;
            var isUnique = index.IsUnique;

            // Iterator iterator = new BTreeIterator(tree,
            // OrderByConstants.ORDER_BY_ASC);
            var   key  = ComputeIndexKey(index);
            IList list = null;

            // If index is unique, get the object
            if (isUnique)
            {
                var treeSingle = (IBTreeSingleValuePerKey)tree;
                var value      = treeSingle.Search(key);
                if (value != null)
                {
                    list = new List <object> {
                        value
                    }
                }
                ;
            }
            else
            {
                var treeMultiple = (IBTreeMultipleValuesPerKey)tree;
                list = treeMultiple.Search(key);
            }

            if (list != null)
            {
                foreach (OID oid in list)
                {
                    // FIXME Why calling this method
                    ObjectReader.GetObjectPositionFromItsOid(oid, true, true);
                    _orderByKey = null;

                    var objectMatches = MatchObjectWithOid(oid, returnObjects, inMemory);
                    if (objectMatches)
                    {
                        queryResultAction.ObjectMatch(oid, GetCurrentObjectMetaRepresentation(), _orderByKey);
                    }
                }

                queryResultAction.End();
                return(queryResultAction.GetObjects <T>());
            }

            if (ExecuteStartAndEndOfQueryAction())
            {
                queryResultAction.End();
            }

            return(queryResultAction.GetObjects <T>());
        }
Example #22
0
        public void Commit()
        {
            if (OdbConfiguration.IsLoggingEnabled())
            {
                var numberOfWriteActionsAsString       = _numberOfWriteActions.ToString();
                var hasAllWriteActionsInMemoryAsString = _hasAllWriteActionsInMemory.ToString();

                DLogger.Info("OdbTransaction: Commiting " + numberOfWriteActionsAsString + " write actions - In Memory : " +
                             hasAllWriteActionsInMemoryAsString + string.Format(" - sid={0}", _session.GetId()));
            }

            // Check if database has been rollbacked
            CheckRollback();

            // call the commit listeners
            ManageCommitListenersBefore();

            if (_currentWriteAction != null && !_currentWriteAction.IsEmpty())
            {
                AddWriteAction(_currentWriteAction, true);
                _currentWriteAction = null;
            }

            if (_fsi == null && _numberOfWriteActions != 0)
            {
                throw new OdbRuntimeException(NDatabaseError.TransactionAlreadyCommitedOrRollbacked);
            }

            if (_numberOfWriteActions == 0)
            {
                // FIXME call commitMetaModel in realOnlyMode?
                CommitMetaModel();
                // Nothing to do
                if (_fsi != null)
                {
                    _fsi.Close();
                    _fsi = null;
                }
                if (_session != null)
                {
                    _session.GetCache().ClearOnCommit();
                }
                return;
            }

            // Marks the transaction as committed
            SetCommited();

            // Apply the write actions the main database file
            ApplyTo();

            // Commit Meta Model changes
            CommitMetaModel();

            if (_fsi != null)
            {
                _fsi.Close();
                _fsi = null;
            }

            if (_session != null)
            {
                _session.GetCache().ClearOnCommit();
            }

            ManageCommitListenersAfter();
        }
Example #23
0
        /// <summary>
        ///   Used to commit meta model : classes This is useful when running in client server mode TODO Check this
        /// </summary>
        private void CommitMetaModel()
        {
            var sessionMetaModel = _session.GetMetaModel();

            // If meta model has not been modified, there is nothing to do
            if (!sessionMetaModel.HasChanged())
            {
                return;
            }

            if (OdbConfiguration.IsLoggingEnabled())
            {
                DLogger.Debug("OdbTransaction: Start commitMetaModel");
            }

            // In local mode, we must not reload the meta model as there is no
            // concurrent access
            var lastCommitedMetaModel = sessionMetaModel;

            var writer = _session.GetStorageEngine().GetObjectWriter();

            // Gets the classes that have changed (that have modified ,deleted or inserted objects)
            var enumerator = sessionMetaModel.GetChangedClassInfo().GetEnumerator();

            // for all changes between old and new meta model
            while (enumerator.MoveNext())
            {
                var newClassInfo = enumerator.Current;

                if (newClassInfo == null)
                {
                    continue;
                }

                ClassInfo lastCommittedClassInfo;

                if (lastCommitedMetaModel.ExistClass(newClassInfo.UnderlyingType))
                {
                    // The last CI represents the last committed meta model of the
                    // database
                    lastCommittedClassInfo = lastCommitedMetaModel.GetClassInfoFromId(newClassInfo.ClassInfoId);
                    // Just be careful to keep track of current CI committed zone
                    // deleted objects
                    lastCommittedClassInfo.CommitedZoneInfo.SetNbDeletedObjects(
                        newClassInfo.CommitedZoneInfo.GetNbDeletedObjects());
                }
                else
                {
                    lastCommittedClassInfo = newClassInfo;
                }

                var lastCommittedObjectOidOfThisTransaction = newClassInfo.CommitedZoneInfo.Last;
                var lastCommittedObjectOidOfPrevTransaction = lastCommittedClassInfo.CommitedZoneInfo.Last;
                var lastCommittedObjectOid = lastCommittedObjectOidOfPrevTransaction;

                // If some object have been created then
                if (lastCommittedObjectOidOfPrevTransaction != null)
                {
                    // Checks if last object of committed meta model has not been
                    // deleted
                    if (_session.GetCache().IsDeleted(lastCommittedObjectOidOfPrevTransaction))
                    {
                        // TODO This is wrong: if a committed transaction deleted a
                        // committed object and creates x new
                        // objects, then all these new objects will be lost:
                        // if it has been deleted then use the last object of the
                        // session class info
                        lastCommittedObjectOid             = lastCommittedObjectOidOfThisTransaction;
                        newClassInfo.CommitedZoneInfo.Last = lastCommittedObjectOid;
                    }
                }

                // Connect Unconnected zone to connected zone
                // make next oid of last committed object point to first
                // uncommitted object
                // make previous oid of first uncommitted object point to
                // last committed object
                if (lastCommittedObjectOid != null && newClassInfo.UncommittedZoneInfo.HasObjects())
                {
                    if (newClassInfo.CommitedZoneInfo.HasObjects())
                    {
                        // these 2 updates are executed directly without
                        // transaction, because
                        // We are in the commit process.
                        writer.UpdateNextObjectFieldOfObjectInfo(lastCommittedObjectOid,
                                                                 newClassInfo.UncommittedZoneInfo.First, false);
                        writer.UpdatePreviousObjectFieldOfObjectInfo(newClassInfo.UncommittedZoneInfo.First,
                                                                     lastCommittedObjectOid, false);
                    }
                    else
                    {
                        // Committed zone has 0 object
                        writer.UpdatePreviousObjectFieldOfObjectInfo(newClassInfo.UncommittedZoneInfo.First, null,
                                                                     false);
                    }
                }

                // The number of committed objects must be updated with the number
                // of the last committed CI because a transaction may have been
                // committed changing this number.
                // Notice that the setNbObjects receive the full CommittedCIZoneInfo
                // object
                // because it will set the number of objects and the number of
                // deleted objects
                newClassInfo.CommitedZoneInfo.SetNbObjects(lastCommittedClassInfo.CommitedZoneInfo);

                // and don't forget to set the deleted objects
                // This sets the number of objects, the first object OID and the
                // last object OID
                newClassInfo = BuildClassInfoForCommit(newClassInfo);

                writer.FileSystemProcessor.UpdateInstanceFieldsOfClassInfo(newClassInfo, false);

                if (OdbConfiguration.IsLoggingEnabled())
                {
                    DLogger.Debug(string.Format("OdbTransaction: Analysing class {0}", newClassInfo.FullClassName));
                    DLogger.Debug(string.Format("\t-Commited CI   = {0}", newClassInfo));
                    DLogger.Debug(
                        string.Format("\t-connect last commited object with oid {0} to first uncommited object {1}",
                                      lastCommittedObjectOid, newClassInfo.UncommittedZoneInfo.First));
                    DLogger.Debug(string.Concat("\t-Commiting new Number of objects = ",
                                                newClassInfo.NumberOfObjects.ToString()));
                }
            }

            sessionMetaModel.ResetChangedClasses();
        }
Example #24
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);
        }