///------------------------------------------------------------------------------------------------- /// <summary> /// Ajout d'une valeur. /// </summary> /// <exception cref="DuplicateElementException"> /// Thrown when a Duplicate Element error condition occurs. /// </exception> /// <param name="node"> /// . /// </param> /// <param name="ownerKey"> /// (Optional) /// </param> ///------------------------------------------------------------------------------------------------- public void AddNode(GraphNode node, Identity ownerKey = null) { DebugContract.Requires(node, "node"); using (var ctx = CreateCommandContext()) { var currentSlot = new Slot <GraphNode>(node); _valuesLock.EnterUpgradeableReadLock(); try { SlotList slots = null; if (!_values.TryGetValue(node.Id, out slots)) { // N'existe pas encore. On rajoute slots = new SlotList(node.Id, node.NodeType, ownerKey); _valuesLock.EnterWriteLock(); try { _values.Add(node.Id, slots); } finally { _valuesLock.ExitWriteLock(); } AddSlot(ctx, slots, currentSlot); // No vaccum notification here since the element is new } else { if (SelectSlot(node.Id, ctx) != null) { throw new DuplicateElementException(node.Id.ToString()); } if (_values.TryGetValue(node.Id, out slots)) { var initialSlot = slots.GetActiveSlot(); AddSlot(ctx, slots, currentSlot); if (initialSlot != null) { initialSlot.CMin = ctx.CommandId; initialSlot.XMax = ctx.Transaction.Id; } NotifyVacuum(slots); } } _trace.WriteTrace(TraceCategory.MemoryStore, "Add {0} - {1}", node.Id, node); ctx.Complete(); } finally { _statAddValue.Incr(); _valuesLock.ExitUpgradeableReadLock(); } } }
private void NotifyVacuum(SlotList slots) { #if !DEBUG if (_jobScheduler != null) { _involvedSlots.Enqueue(slots); _jobScheduler.RequestJob(); } #endif }
private void AddSlot(CommandContext ctx, SlotList slots, Slot <GraphNode> v) { DebugContract.Requires(ctx, "ctx"); DebugContract.Requires(slots, "slots"); DebugContract.Requires(v, "v"); v.XMin = ctx.Transaction.Id; v.XMax = null; v.CMin = ctx.CommandId; slots.Add(v); }
internal SlotList(SlotList clone) { DebugContract.Requires(clone, "clone"); _ownerKey = clone._ownerKey; _elementType = clone._elementType; Id = clone.Id; _ownerKey = clone._ownerKey; _slots = new List <ISlot>(Length + 2); _slots.AddRange(clone._slots.Where(s => s.Id > 0)); Length = _slots.Count; }
///------------------------------------------------------------------------------------------------- /// <summary> /// Mise à jour d'une valeur. /// </summary> /// <exception cref="Exception"> /// Thrown when an exception error condition occurs. /// </exception> /// <param name="node"> /// . /// </param> ///------------------------------------------------------------------------------------------------- public void UpdateNode(GraphNode node) { DebugContract.Requires(node); using (var ctx = CreateCommandContext()) { try { // Test existence tuple ? SlotList slots = null; _valuesLock.EnterReadLock(); try { _values.TryGetValue(node.Id, out slots); } finally { _valuesLock.ExitReadLock(); } if (slots != null) { var currentSlot = slots.GetActiveSlot(); var newSlot = new Slot <GraphNode>(node); AddSlot(ctx, slots, newSlot); if (currentSlot != null) { currentSlot.CMin = ctx.CommandId; currentSlot.XMax = ctx.Transaction.Id; } NotifyVacuum(slots); Debug.Assert(slots.Count(e => e.XMax == null) == 1); _trace.WriteTrace(TraceCategory.MemoryStore, "Update {0} - {1}", node.Id, node); } else { throw new HypergraphException(ExceptionMessages.NotFound + node.Id); } } finally { // On valide la transaction dans tous les cas pour qu'elle soit purgée par le vacuum ctx.Complete(); _statUpdateValue.Incr(); } } }