public virtual RelationshipGroupPosition GetRelationshipGroup(NodeRecord node, int type, RecordAccess <RelationshipGroupRecord, int> relGroupRecords) { long groupId = node.NextRel; long previousGroupId = Record.NO_NEXT_RELATIONSHIP.intValue(); RecordAccess_RecordProxy <RelationshipGroupRecord, int> previous = null; RecordAccess_RecordProxy <RelationshipGroupRecord, int> current; while (groupId != Record.NO_NEXT_RELATIONSHIP.intValue()) { current = relGroupRecords.GetOrLoad(groupId, null); RelationshipGroupRecord record = current.ForReadingData(); record.Prev = previousGroupId; // not persistent so not a "change" if (record.Type == type) { return(new RelationshipGroupPosition(previous, current)); } else if (record.Type > type) { // The groups are sorted in the chain, so if we come too far we can return // empty handed right away return(new RelationshipGroupPosition(previous, null)); } previousGroupId = groupId; groupId = record.Next; previous = current; } return(new RelationshipGroupPosition(previous, null)); }
/// <summary> /// Removes property with given {@code propertyKey} from property chain owner by the primitive found in /// {@code primitiveProxy}. /// </summary> /// <param name="primitiveProxy"> access to the primitive record pointing to the start of the property chain. </param> /// <param name="propertyKey"> the property key token id to look for and remove. </param> /// <param name="propertyRecords"> access to records. </param> /// <exception cref="IllegalStateException"> if property key was not found in the property chain. </exception> public virtual void RemoveProperty <P>(RecordAccess_RecordProxy <P, Void> primitiveProxy, int propertyKey, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { PrimitiveRecord primitive = primitiveProxy.ForReadingData(); long propertyId = _traverser.findPropertyRecordContaining(primitive, propertyKey, propertyRecords, true); RemoveProperty(primitiveProxy, propertyKey, propertyRecords, primitive, propertyId); }
private RECORD Prepared <RECORD, T1>(RecordAccess_RecordProxy <T1> proxy, RecordStore <RECORD> store) where RECORD : Org.Neo4j.Kernel.impl.store.record.AbstractBaseRecord { RECORD after = proxy.ForReadingLinkage(); store.PrepareForCommit(after); return(after); }
public TrackingRecordProxy(RecordAccess_RecordProxy <RECORD, ADDITIONAL> @delegate, bool created, Tracker tracker) { this.@delegate = @delegate; this._created = created; this._tracker = tracker; this._changed = created; }
internal virtual void DropSchemaRule(SchemaRule rule) { RecordAccess_RecordProxy <SchemaRecord, SchemaRule> change = _recordChangeSet.SchemaRuleChanges.getOrLoad(rule.Id, rule); SchemaRecord records = change.ForChangingData(); foreach (DynamicRecord record in records) { record.InUse = false; } records.InUse = false; }
public override RecordAccess_RecordProxy <RECORD, ADDITIONAL> GetOrLoad(long key, ADDITIONAL additionalData) { RecordAccess_RecordProxy <RECORD, ADDITIONAL> result = _recordChanges.get(key); if (result == null) { RECORD record = _loader.load(key, additionalData); result = new RecordChange <RECORD, ADDITIONAL>(_recordChanges, _changeCounter, key, record, _loader, false, additionalData); } return(result); }
/// <summary> /// Removes property with given {@code propertyKey} from property chain owner by the primitive found in /// {@code primitiveProxy} if it exists. /// </summary> /// <param name="primitiveProxy"> access to the primitive record pointing to the start of the property chain. </param> /// <param name="propertyKey"> the property key token id to look for and remove. </param> /// <param name="propertyRecords"> access to records. </param> /// <returns> {@code true} if the property was found and removed, otherwise {@code false}. </returns> public virtual bool RemovePropertyIfExists <P>(RecordAccess_RecordProxy <P, Void> primitiveProxy, int propertyKey, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { PrimitiveRecord primitive = primitiveProxy.ForReadingData(); long propertyId = _traverser.findPropertyRecordContaining(primitive, propertyKey, propertyRecords, false); if (!Record.NO_NEXT_PROPERTY.@is(propertyId)) { RemoveProperty(primitiveProxy, propertyKey, propertyRecords, primitive, propertyId); return(true); } return(false); }
private void ChangeSchemaRule(SchemaRule rule, SchemaRule updatedRule) { //Read the current record RecordAccess_RecordProxy <SchemaRecord, SchemaRule> change = _recordChangeSet.SchemaRuleChanges.getOrLoad(rule.Id, rule); SchemaRecord records = change.ForReadingData(); //Register the change of the record RecordAccess_RecordProxy <SchemaRecord, SchemaRule> recordChange = _recordChangeSet.SchemaRuleChanges.setRecord(rule.Id, records, updatedRule); SchemaRecord dynamicRecords = recordChange.ForChangingData(); //Update the record dynamicRecords.DynamicRecords = _schemaStore.allocateFrom(updatedRule); }
internal virtual RECORD PrepareForChange() { EnsureHasBeforeRecordImage(); if (!this.ChangedConflict) { RecordAccess_RecordProxy <RECORD, ADDITIONAL> previous = this.AllChanges.put(KeyConflict, this); if (previous == null || !previous.Changed) { ChangeCounter.increment(); } this.ChangedConflict = true; } return(this.Record); }
public virtual void DeletePropertyChain(PrimitiveRecord primitive, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) { long nextProp = primitive.NextProp; while (nextProp != Record.NO_NEXT_PROPERTY.intValue()) { RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> propertyChange = propertyRecords.GetOrLoad(nextProp, primitive); // TODO forChanging/forReading piggy-backing PropertyRecord propRecord = propertyChange.ForChangingData(); DeletePropertyRecordIncludingValueRecords(propRecord); nextProp = propRecord.NextProp; propRecord.Changed = primitive; } primitive.NextProp = Record.NO_NEXT_PROPERTY.intValue(); }
private void DeleteGroup(RecordAccess_RecordProxy <NodeRecord, Void> nodeChange, RelationshipGroupRecord group, RecordAccess <RelationshipGroupRecord, int> relGroupRecords) { long previous = group.Prev; long next = group.Next; if (previous == Record.NO_NEXT_RELATIONSHIP.intValue()) { // This is the first one, just point the node to the next group nodeChange.ForChangingLinkage().NextRel = next; } else { // There are others before it, point the previous to the next group RelationshipGroupRecord previousRecord = relGroupRecords.GetOrLoad(previous, null).forChangingLinkage(); previousRecord.Next = next; } if (next != Record.NO_NEXT_RELATIONSHIP.intValue()) { // There are groups after this one, point that next group to the previous of the group to be deleted RelationshipGroupRecord nextRecord = relGroupRecords.GetOrLoad(next, null).forChangingLinkage(); nextRecord.Prev = previous; } group.InUse = false; }
public virtual RecordAccess_RecordProxy <RelationshipGroupRecord, int> GetOrCreateRelationshipGroup(NodeRecord node, int type, RecordAccess <RelationshipGroupRecord, int> relGroupRecords) { RelationshipGroupPosition existingGroup = GetRelationshipGroup(node, type, relGroupRecords); RecordAccess_RecordProxy <RelationshipGroupRecord, int> change = existingGroup.Group(); if (change == null) { Debug.Assert(node.Dense, "Node " + node + " should have been dense at this point"); long id = _idGenerator.nextId(); change = relGroupRecords.Create(id, type); RelationshipGroupRecord record = change.ForChangingData(); record.InUse = true; record.SetCreated(); record.OwningNode = node.Id; // Attach it... RecordAccess_RecordProxy <RelationshipGroupRecord, int> closestPreviousChange = existingGroup.ClosestPrevious(); if (closestPreviousChange != null) { // ...after the closest previous one RelationshipGroupRecord closestPrevious = closestPreviousChange.ForChangingLinkage(); record.Next = closestPrevious.Next; record.Prev = closestPrevious.Id; closestPrevious.Next = id; } else { // ...first in the chain long firstGroupId = node.NextRel; if (firstGroupId != Record.NO_NEXT_RELATIONSHIP.intValue()) { // There are others, make way for this new group RelationshipGroupRecord previousFirstRecord = relGroupRecords.GetOrLoad(firstGroupId, type).forReadingData(); record.Next = previousFirstRecord.Id; previousFirstRecord.Prev = id; } node.NextRel = id; } } return(change); }
private void ConvertNodeToDenseIfNecessary(NodeRecord node, RecordAccess <RelationshipRecord, Void> relRecords, RecordAccess <RelationshipGroupRecord, int> relGroupRecords, ResourceLocker locks) { if (node.Dense) { return; } long relId = node.NextRel; if (relId != Record.NO_NEXT_RELATIONSHIP.intValue()) { RecordAccess_RecordProxy <RelationshipRecord, Void> relChange = relRecords.GetOrLoad(relId, null); RelationshipRecord rel = relChange.ForReadingLinkage(); if (RelCount(node.Id, rel) >= _denseNodeThreshold) { locks.AcquireExclusive(LockTracer.NONE, ResourceTypes.RELATIONSHIP, relId); // Re-read the record after we've locked it since another transaction might have // changed in the meantime. relChange = relRecords.GetOrLoad(relId, null); ConvertNodeToDenseNode(node, relChange.ForChangingLinkage(), relRecords, relGroupRecords, locks); } } }
private void RemoveProperty <P>(RecordAccess_RecordProxy <P, Void> primitiveProxy, int propertyKey, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, PrimitiveRecord primitive, long propertyId) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> recordChange = propertyRecords.GetOrLoad(propertyId, primitive); PropertyRecord propRecord = recordChange.ForChangingData(); if (!propRecord.InUse()) { throw new System.InvalidOperationException("Unable to delete property[" + propertyId + "] since it is already deleted."); } PropertyBlock block = propRecord.RemovePropertyBlock(propertyKey); if (block == null) { throw new System.InvalidOperationException("Property with index[" + propertyKey + "] is not present in property[" + propertyId + "]"); } foreach (DynamicRecord valueRecord in block.ValueRecords) { Debug.Assert(valueRecord.InUse()); valueRecord.SetInUse(false, block.Type.intValue()); propRecord.AddDeletedRecord(valueRecord); } if (propRecord.Size() > 0) { /* * There are remaining blocks in the record. We do not unlink yet. */ propRecord.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); } else { UnlinkPropertyRecord(propRecord, propertyRecords, primitiveProxy); } }
private void UpdateNodesForDeletedRelationship(RelationshipRecord rel, RecordAccessSet recordChanges, ResourceLocker locks) { RecordAccess_RecordProxy <NodeRecord, Void> startNodeChange = recordChanges.NodeRecords.getOrLoad(rel.FirstNode, null); RecordAccess_RecordProxy <NodeRecord, Void> endNodeChange = recordChanges.NodeRecords.getOrLoad(rel.SecondNode, null); NodeRecord startNode = recordChanges.NodeRecords.getOrLoad(rel.FirstNode, null).forReadingLinkage(); NodeRecord endNode = recordChanges.NodeRecords.getOrLoad(rel.SecondNode, null).forReadingLinkage(); bool loop = startNode.Id == endNode.Id; if (!startNode.Dense) { if (rel.FirstInFirstChain) { startNode = startNodeChange.ForChangingLinkage(); startNode.NextRel = rel.FirstNextRel; } DecrementTotalRelationshipCount(startNode.Id, rel, startNode.NextRel, recordChanges.RelRecords, locks); } else { RecordAccess_RecordProxy <RelationshipGroupRecord, int> groupChange = _relGroupGetter.getRelationshipGroup(startNode, rel.Type, recordChanges.RelGroupRecords).group(); Debug.Assert(groupChange != null, "Relationship group " + rel.Type + " should have existed here"); RelationshipGroupRecord group = groupChange.ForReadingData(); DirectionWrapper dir = DirectionIdentifier.wrapDirection(rel, startNode); if (rel.FirstInFirstChain) { group = groupChange.ForChangingData(); dir.setNextRel(group, rel.FirstNextRel); if (GroupIsEmpty(group)) { DeleteGroup(startNodeChange, group, recordChanges.RelGroupRecords); } } DecrementTotalRelationshipCount(startNode.Id, rel, dir.getNextRel(group), recordChanges.RelRecords, locks); } if (!endNode.Dense) { if (rel.FirstInSecondChain) { endNode = endNodeChange.ForChangingLinkage(); endNode.NextRel = rel.SecondNextRel; } if (!loop) { DecrementTotalRelationshipCount(endNode.Id, rel, endNode.NextRel, recordChanges.RelRecords, locks); } } else { RecordAccess_RecordProxy <RelationshipGroupRecord, int> groupChange = _relGroupGetter.getRelationshipGroup(endNode, rel.Type, recordChanges.RelGroupRecords).group(); DirectionWrapper dir = DirectionIdentifier.wrapDirection(rel, endNode); Debug.Assert(groupChange != null || loop, "Group has been deleted"); if (groupChange != null) { RelationshipGroupRecord group; if (rel.FirstInSecondChain) { group = groupChange.ForChangingData(); dir.setNextRel(group, rel.SecondNextRel); if (GroupIsEmpty(group)) { DeleteGroup(endNodeChange, group, recordChanges.RelGroupRecords); } } } // Else this is a loop-rel and the group was deleted when dealing with the start node if (!loop) { DecrementTotalRelationshipCount(endNode.Id, rel, dir.getNextRel(groupChange.ForChangingData()), recordChanges.RelRecords, locks); } } }
public override RecordAccess_RecordProxy <RECORD, ADDITIONAL> GetIfLoaded(long key) { RecordAccess_RecordProxy <RECORD, ADDITIONAL> actual = @delegate.GetIfLoaded(key); return(actual == null ? null : new TrackingRecordProxy <RECORD, ADDITIONAL>(actual, false, _tracker)); }
protected internal override RecordAccess_RecordProxy <RECORD, ADDITIONAL> underlyingObjectToObject(RecordAccess_RecordProxy <RECORD, ADDITIONAL> actual) { return(new TrackingRecordProxy <RECORD, ADDITIONAL>(actual, false, _outerInstance.tracker)); }
/// <summary> /// Removes the given property identified by its index from the relationship /// with the given id. /// </summary> /// <param name="relId"> The id of the relationship that is to have the property /// removed. </param> /// <param name="propertyKey"> The index key of the property. </param> internal virtual void RelRemoveProperty(long relId, int propertyKey) { RecordAccess_RecordProxy <RelationshipRecord, Void> rel = _recordChangeSet.RelRecords.getOrLoad(relId, null); _propertyDeleter.removeProperty(rel, propertyKey, _recordChangeSet.PropertyRecords); }
/// <summary> /// Removes the given property identified by indexKeyId of the node with the /// given id. /// </summary> /// <param name="nodeId"> The id of the node that is to have the property removed. </param> /// <param name="propertyKey"> The index key of the property. </param> public virtual void NodeRemoveProperty(long nodeId, int propertyKey) { RecordAccess_RecordProxy <NodeRecord, Void> node = _recordChangeSet.NodeRecords.getOrLoad(nodeId, null); _propertyDeleter.removeProperty(node, propertyKey, _recordChangeSet.PropertyRecords); }
/// <summary> /// Adds a property to the given relationship, with the given index and /// value. </summary> /// <param name="relId"> The id of the relationship to which to add the property. </param> /// <param name="propertyKey"> The index of the key of the property to add. </param> /// <param name="value"> The value of the property. </param> internal virtual void RelAddProperty(long relId, int propertyKey, Value value) { RecordAccess_RecordProxy <RelationshipRecord, Void> rel = _recordChangeSet.RelRecords.getOrLoad(relId, null); _propertyCreator.primitiveSetProperty(rel, propertyKey, value, _recordChangeSet.PropertyRecords); }
public RelationshipGroupPosition(RecordAccess_RecordProxy <RelationshipGroupRecord, int> closestPrevious, RecordAccess_RecordProxy <RelationshipGroupRecord, int> group) { this.ClosestPreviousConflict = closestPrevious; this.GroupConflict = group; }
/// <summary> /// Adds a property to the given node, with the given index and value. </summary> /// <param name="nodeId"> The id of the node to which to add the property. </param> /// <param name="propertyKey"> The index of the key of the property to add. </param> /// <param name="value"> The value of the property. </param> internal virtual void NodeAddProperty(long nodeId, int propertyKey, Value value) { RecordAccess_RecordProxy <NodeRecord, Void> node = _recordChangeSet.NodeRecords.getOrLoad(nodeId, null); _propertyCreator.primitiveSetProperty(node, propertyKey, value, _recordChangeSet.PropertyRecords); }
private void UnlinkPropertyRecord <P>(PropertyRecord propRecord, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, RecordAccess_RecordProxy <P, Void> primitiveRecordChange) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { P primitive = primitiveRecordChange.ForReadingLinkage(); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); Debug.Assert(propRecord.Size() == 0); long prevProp = propRecord.PrevProp; long nextProp = propRecord.NextProp; if (primitive.NextProp == propRecord.Id) { Debug.Assert(propRecord.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue(), propRecord + " for "); +primitive; primitiveRecordChange.ForChangingLinkage().NextProp = nextProp; } if (prevProp != Record.NO_PREVIOUS_PROPERTY.intValue()) { PropertyRecord prevPropRecord = propertyRecords.GetOrLoad(prevProp, primitive).forChangingLinkage(); Debug.Assert(prevPropRecord.InUse(), prevPropRecord + "->" + propRecord + " for " + primitive); prevPropRecord.NextProp = nextProp; prevPropRecord.Changed = primitive; } if (nextProp != Record.NO_NEXT_PROPERTY.intValue()) { PropertyRecord nextPropRecord = propertyRecords.GetOrLoad(nextProp, primitive).forChangingLinkage(); Debug.Assert(nextPropRecord.InUse(), propRecord + "->" + nextPropRecord + " for " + primitive); nextPropRecord.PrevProp = prevProp; nextPropRecord.Changed = primitive; } propRecord.InUse = false; /* * The following two are not needed - the above line does all the work (PropertyStore * does not write out the prev/next for !inUse records). It is nice to set this * however to check for consistency when assertPropertyChain(). */ propRecord.PrevProp = Record.NO_PREVIOUS_PROPERTY.intValue(); propRecord.NextProp = Record.NO_NEXT_PROPERTY.intValue(); propRecord.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); }
public virtual void PrimitiveSetProperty <P>(RecordAccess_RecordProxy <P, Void> primitiveRecordChange, int propertyKey, Value value, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords) where P : Org.Neo4j.Kernel.impl.store.record.PrimitiveRecord { PropertyBlock block = EncodePropertyValue(propertyKey, value); P primitive = primitiveRecordChange.ForReadingLinkage(); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); int newBlockSizeInBytes = block.Size; // Traverse the existing property chain. Tracking two things along the way: // - (a) Free space for this block (candidateHost) // - (b) Existence of a block with the property key // Chain traversal can be aborted only if: // - (1) (b) occurs and new property block fits where the current is // - (2) (a) occurs and (b) has occurred, but new property block didn't fit // - (3) (b) occurs and (a) has occurred // - (4) Chain ends RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> freeHostProxy = null; RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> existingHostProxy = null; long prop = primitive.NextProp; while (prop != Record.NO_NEXT_PROPERTY.intValue()) // <-- (4) { RecordAccess_RecordProxy <PropertyRecord, PrimitiveRecord> proxy = propertyRecords.GetOrLoad(prop, primitive); PropertyRecord propRecord = proxy.ForReadingLinkage(); Debug.Assert(propRecord.InUse(), propRecord); // (a) search for free space if (PropertyFitsInside(newBlockSizeInBytes, propRecord)) { freeHostProxy = proxy; if (existingHostProxy != null) { // (2) PropertyRecord freeHost = proxy.ForChangingData(); freeHost.AddPropertyBlock(block); freeHost.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } } // (b) search for existence of property key PropertyBlock existingBlock = propRecord.GetPropertyBlock(propertyKey); if (existingBlock != null) { // We found an existing property and whatever happens we have to remove the existing // block so that we can add the new one, where ever we decide to place it existingHostProxy = proxy; PropertyRecord existingHost = existingHostProxy.ForChangingData(); RemoveProperty(primitive, existingHost, existingBlock); // Now see if we at this point can add the new block if (newBlockSizeInBytes <= existingBlock.Size || PropertyFitsInside(newBlockSizeInBytes, existingHost)) // fallback check { // (1) yes we could add it right into the host of the existing block existingHost.AddPropertyBlock(block); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } else if (freeHostProxy != null) { // (3) yes we could add it to a previously found host with sufficiently free space in it PropertyRecord freeHost = freeHostProxy.ForChangingData(); freeHost.AddPropertyBlock(block); freeHost.Changed = primitive; Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); return; } // else we can't add it at this point } // Continue down the chain prop = propRecord.NextProp; } // At this point we haven't added the property block, although we may have found room for it // along the way. If we didn't then just create a new record, it's fine PropertyRecord freeHost; if (freeHostProxy == null) { // We couldn't find free space along the way, so create a new host record freeHost = propertyRecords.Create(_propertyRecordIdGenerator.nextId(), primitive).forChangingData(); freeHost.InUse = true; if (primitive.NextProp != Record.NO_NEXT_PROPERTY.intValue()) { // This isn't the first property record for the entity, re-shuffle the first one so that // the new one becomes the first PropertyRecord prevProp = propertyRecords.GetOrLoad(primitive.NextProp, primitive).forChangingLinkage(); Debug.Assert(prevProp.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue()); prevProp.PrevProp = freeHost.Id; freeHost.NextProp = prevProp.Id; prevProp.Changed = primitive; } // By the way, this is the only condition where the primitive record also needs to change primitiveRecordChange.ForChangingLinkage().NextProp = freeHost.Id; } else { freeHost = freeHostProxy.ForChangingData(); } // At this point we know that we have a host record with sufficient space in it for the block // to add, so simply add it freeHost.AddPropertyBlock(block); Debug.Assert(_traverser.assertPropertyChain(primitive, propertyRecords)); }
/// <summary> /// Removes the given property identified by indexKeyId of the graph with the /// given id. /// </summary> /// <param name="propertyKey"> The index key of the property. </param> internal virtual void GraphRemoveProperty(int propertyKey) { RecordAccess_RecordProxy <NeoStoreRecord, Void> recordChange = OrLoadNeoStoreRecord; _propertyDeleter.removeProperty(recordChange, propertyKey, _recordChangeSet.PropertyRecords); }