/// <summary>Shift all unconnected infos to connected (committed) infos</summary> /// <param name="classInfo"></param> /// <returns>The updated class info</returns> public virtual NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo BuildClassInfoForCommit (NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo classInfo) { long nbObjects = classInfo.GetNumberOfObjects(); classInfo.GetCommitedZoneInfo().SetNbObjects(nbObjects); if (classInfo.GetCommitedZoneInfo().first != null) { } else { // nothing to change classInfo.GetCommitedZoneInfo().first = classInfo.GetUncommittedZoneInfo().first; } if (classInfo.GetUncommittedZoneInfo().last != null) { classInfo.GetCommitedZoneInfo().last = classInfo.GetUncommittedZoneInfo().last; } // Resets the unconnected zone info classInfo.GetUncommittedZoneInfo().Set(new NeoDatis.Odb.Core.Layers.Layer2.Meta.CIZoneInfo (classInfo, null, null, 0)); return(classInfo); }
/// <summary> /// Query execution full scan /// <pre> /// startIndex & endIndex /// A B C D E F G H I J K L /// [1,3] : nb >=1 && nb<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> upperBound([1,3]) => exit /// </pre> /// </summary> /// <param name="inMemory"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="returnObjects"></param> /// <returns></returns> /// <exception cref="System.Exception">System.Exception</exception> private NeoDatis.Odb.Objects <T> ExecuteFullScan <T>(bool inMemory, int startIndex, int endIndex, bool returnObjects, NeoDatis.Odb.Core.Query.Execution.IMatchingObjectAction queryResultAction) { bool objectInRange = false; bool objectMatches = false; if (storageEngine.IsClosed()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.OdbIsClosed .AddParameter(storageEngine.GetBaseIdentification().GetIdentification())); } long nbObjects = classInfo.GetNumberOfObjects(); if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("loading " + nbObjects + " instance(s) of " + classInfo .GetFullClassName()); } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.Start(); } NeoDatis.Odb.OID currentOID = null; NeoDatis.Odb.OID prevOID = null; // TODO check if all instances are in the cache! and then load from the // cache nextOID = classInfo.GetCommitedZoneInfo().first; if (nbObjects > 0 && nextOID == null) { // This means that some changes have not been commited! // Take next position from uncommited zone nextOID = classInfo.GetUncommittedZoneInfo().first; } PrepareQuery(); if (query != null) { queryHasOrderBy = query.HasOrderBy(); } bool monitorMemory = NeoDatis.Odb.OdbConfiguration.IsMonitoringMemory(); // used when startIndex and endIndex are not negative int nbObjectsInResult = 0; for (int i = 0; i < nbObjects; i++) { //Console.WriteLine(i); if (monitorMemory && i % 10000 == 0) { NeoDatis.Odb.Impl.Tool.MemoryMonitor.DisplayCurrentMemory(string.Empty + (i + 1), true); } // Reset the order by key orderByKey = null; objectMatches = false; prevOID = currentOID; currentOID = nextOID; // This is an error if (currentOID == null) { if (NeoDatis.Odb.OdbConfiguration.ThrowExceptionWhenInconsistencyFound()) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.NullNextObjectOid .AddParameter(classInfo.GetFullClassName()).AddParameter(i).AddParameter(nbObjects ).AddParameter(prevOID)); } break; } // If there is an endIndex condition if (endIndex != -1 && nbObjectsInResult >= endIndex) { break; } // If there is a startIndex condition 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 { objectMatches = MatchObjectWithOid(currentOID, returnObjects, inMemory); if (objectMatches) { nbObjectsInResult++; if (objectInRange) { if (queryHasOrderBy) { orderByKey = BuildOrderByKey(GetCurrentObjectMetaRepresentation()); } queryResultAction.ObjectMatch(currentOID, GetCurrentObjectMetaRepresentation(), orderByKey ); if (callback != null) { callback.ReadingObject(i, -1); } } } } } if (ExecuteStartAndEndOfQueryAction()) { queryResultAction.End(); } return(queryResultAction.GetObjects <T>()); }
/// <summary> /// Used to commit meta model : classes This is useful when running in client /// server mode TODO Check this /// </summary> protected virtual void CommitMetaModel() { NeoDatis.Odb.Core.Layers.Layer2.Meta.MetaModel sessionMetaModel = session.GetMetaModel (); // If meta model has not been modified, there is nothing to do if (!sessionMetaModel.HasChanged()) { return; } if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("Start commitMetaModel"); } NeoDatis.Odb.Core.Layers.Layer2.Meta.MetaModel lastCommitedMetaModel = new NeoDatis.Odb.Core.Layers.Layer2.Meta.SessionMetaModel (); if (isLocal) { // In local mode, we must not reload the meta model as there is no // concurrent access lastCommitedMetaModel = sessionMetaModel; } else { // In ClientServer mode, re-read the meta-model from the database // base to get last update. lastCommitedMetaModel = session.GetStorageEngine().GetObjectReader().ReadMetaModel (lastCommitedMetaModel, false); } // Gets the classes that have changed (that have modified ,deleted or // inserted objects) System.Collections.Generic.IEnumerator <NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo > cis = sessionMetaModel.GetChangedClassInfo().GetEnumerator(); NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo newCi = null; NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo lastCommittedCI = null; NeoDatis.Odb.Core.Layers.Layer3.IObjectWriter writer = session.GetStorageEngine() .GetObjectWriter(); NeoDatis.Odb.OID lastCommittedObjectOIDOfThisTransaction = null; NeoDatis.Odb.OID lastCommittedObjectOIDOfPrevTransaction = null; // for all changes between old and new meta model while (cis.MoveNext()) { newCi = cis.Current; if (lastCommitedMetaModel.ExistClass(newCi.GetFullClassName())) { // The last CI represents the last committed meta model of the // database lastCommittedCI = lastCommitedMetaModel.GetClassInfoFromId(newCi.GetId()); // Just be careful to keep track of current CI committed zone // deleted objects lastCommittedCI.GetCommitedZoneInfo().SetNbDeletedObjects(newCi.GetCommitedZoneInfo ().GetNbDeletedObjects()); } else { lastCommittedCI = newCi; } lastCommittedObjectOIDOfThisTransaction = newCi.GetCommitedZoneInfo().last; lastCommittedObjectOIDOfPrevTransaction = lastCommittedCI.GetCommitedZoneInfo().last; NeoDatis.Odb.OID 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; newCi.GetCommitedZoneInfo().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 && newCi.GetUncommittedZoneInfo().HasObjects()) { if (newCi.GetCommitedZoneInfo().HasObjects()) { // these 2 updates are executed directly without // transaction, because // We are in the commit process. writer.UpdateNextObjectFieldOfObjectInfo(lastCommittedObjectOID, newCi.GetUncommittedZoneInfo ().first, false); writer.UpdatePreviousObjectFieldOfObjectInfo(newCi.GetUncommittedZoneInfo().first , lastCommittedObjectOID, false); } else { // Committed zone has 0 object writer.UpdatePreviousObjectFieldOfObjectInfo(newCi.GetUncommittedZoneInfo().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 newCi.GetCommitedZoneInfo().SetNbObjects(lastCommittedCI.GetCommitedZoneInfo()); // and don't forget to set the deleted objects // This sets the number of objects, the first object OID and the // last object OID newCi = BuildClassInfoForCommit(newCi); writer.UpdateInstanceFieldsOfClassInfo(newCi, false); if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId)) { NeoDatis.Tool.DLogger.Debug("Analysing class " + newCi.GetFullClassName()); NeoDatis.Tool.DLogger.Debug("\t-Commited CI = " + newCi); NeoDatis.Tool.DLogger.Debug("\t-connect last commited object with oid " + lastCommittedObjectOID + " to first uncommited object " + newCi.GetUncommittedZoneInfo().first); NeoDatis.Tool.DLogger.Debug("\t-Commiting new Number of objects = " + newCi.GetNumberOfObjects ()); } } sessionMetaModel.ResetChangedClasses(); // To guarantee integrity after commit, the meta model is set to null // If the user continues using odb instance after commit the meta model // will be lazy-reloaded. Only for Client Server mode if (!isLocal) { session.SetMetaModel(null); } }
public virtual void AddIndexOn(string className, string indexName, string[] indexFields , bool verbose, bool acceptMultipleValuesForSameKey) { NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo classInfo = GetMetaModel().GetClassInfo (className, true); if (classInfo.HasIndex(indexName)) { throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.IndexAlreadyExist .AddParameter(indexName).AddParameter(className)); } NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfoIndex cii = classInfo.AddIndexOn(indexName , indexFields, acceptMultipleValuesForSameKey); NeoDatis.Btree.IBTree btree = null; if (acceptMultipleValuesForSameKey) { btree = new NeoDatis.Odb.Impl.Core.Btree.ODBBTreeMultiple(className, NeoDatis.Odb.OdbConfiguration .GetDefaultIndexBTreeDegree(), new NeoDatis.Odb.Impl.Core.Btree.LazyODBBTreePersister (this)); } else { btree = new NeoDatis.Odb.Impl.Core.Btree.ODBBTreeSingle(className, NeoDatis.Odb.OdbConfiguration .GetDefaultIndexBTreeDegree(), new NeoDatis.Odb.Impl.Core.Btree.LazyODBBTreePersister (this)); } cii.SetBTree(btree); Store(cii); // Now The index must be updated with all existing objects. if (classInfo.GetNumberOfObjects() == 0) { // There are no objects. Nothing to do return; } if (verbose) { NeoDatis.Tool.DLogger.Info("Creating index " + indexName + " on class " + className + " - Class has already " + classInfo.GetNumberOfObjects() + " Objects. Updating index" ); } if (verbose) { NeoDatis.Tool.DLogger.Info(indexName + " : loading " + classInfo.GetNumberOfObjects () + " objects from database"); } // We must load all objects and insert them in the index! NeoDatis.Odb.Objects <object> objects = GetObjectInfos <object>(new NeoDatis.Odb.Impl.Core.Query.Criteria.CriteriaQuery (className), false, -1, -1, false); if (verbose) { NeoDatis.Tool.DLogger.Info(indexName + " : " + classInfo.GetNumberOfObjects() + " objects loaded" ); } NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo nnoi = null; int i = 0; bool monitorMemory = NeoDatis.Odb.OdbConfiguration.IsMonitoringMemory(); while (objects.HasNext()) { nnoi = (NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo)objects.Next(); btree.Insert(cii.ComputeKey(nnoi), nnoi.GetOid()); if (verbose && i % 1000 == 0) { if (monitorMemory) { NeoDatis.Odb.Impl.Tool.MemoryMonitor.DisplayCurrentMemory("Index " + indexName + " " + i + " objects inserted", true); } } i++; } if (verbose) { NeoDatis.Tool.DLogger.Info(indexName + " created!"); } }