Exemplo n.º 1
0
        private void Disconnect(RelationshipRecord rel, RelationshipConnection pointer, RecordAccess <RelationshipRecord, Void> relChanges, ResourceLocker locks)
        {
            long otherRelId = pointer.otherSide().get(rel);

            if (otherRelId == Record.NO_NEXT_RELATIONSHIP.intValue())
            {
                return;
            }

            locks.AcquireExclusive(LockTracer.NONE, ResourceTypes.RELATIONSHIP, otherRelId);
            RelationshipRecord otherRel = relChanges.GetOrLoad(otherRelId, null).forChangingLinkage();
            bool changed    = false;
            long newId      = pointer.get(rel);
            bool newIsFirst = pointer.isFirstInChain(rel);

            if (otherRel.FirstNode == pointer.compareNode(rel))
            {
                pointer.start().set(otherRel, newId, newIsFirst);
                changed = true;
            }
            if (otherRel.SecondNode == pointer.compareNode(rel))
            {
                pointer.end().set(otherRel, newId, newIsFirst);
                changed = true;
            }
            if (!changed)
            {
                throw new InvalidRecordException(otherRel + " don't match " + rel);
            }
        }
Exemplo n.º 2
0
        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));
        }
Exemplo n.º 3
0
        private void DecrementTotalRelationshipCount(long nodeId, RelationshipRecord rel, long firstRelId, RecordAccess <RelationshipRecord, Void> relRecords, ResourceLocker locks)
        {
            if (firstRelId == Record.NO_PREV_RELATIONSHIP.intValue())
            {
                return;
            }
            bool firstInChain = RelIsFirstInChain(nodeId, rel);

            if (!firstInChain)
            {
                locks.AcquireExclusive(LockTracer.NONE, ResourceTypes.RELATIONSHIP, firstRelId);
            }
            RelationshipRecord firstRel = relRecords.GetOrLoad(firstRelId, null).forChangingLinkage();

            if (nodeId == firstRel.FirstNode)
            {
                firstRel.FirstPrevRel      = firstInChain ? relCount(nodeId, rel) - 1 : relCount(nodeId, firstRel) - 1;
                firstRel.FirstInFirstChain = true;
            }
            if (nodeId == firstRel.SecondNode)
            {
                firstRel.SecondPrevRel      = firstInChain ? relCount(nodeId, rel) - 1 : relCount(nodeId, firstRel) - 1;
                firstRel.FirstInSecondChain = true;
            }
        }
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
0
 public virtual void GetPropertyChain(long nextProp, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, Listener <PropertyBlock> collector)
 {
     while (nextProp != Record.NO_NEXT_PROPERTY.intValue())
     {
         PropertyRecord propRecord = propertyRecords.GetOrLoad(nextProp, null).forReadingData();
         foreach (PropertyBlock propBlock in propRecord)
         {
             collector.Receive(propBlock);
         }
         nextProp = propRecord.NextProp;
     }
 }
Exemplo n.º 6
0
        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;
        }
Exemplo n.º 7
0
        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);
                }
            }
        }
Exemplo n.º 8
0
        private void ConvertNodeToDenseNode(NodeRecord node, RelationshipRecord firstRel, RecordAccess <RelationshipRecord, Void> relRecords, RecordAccess <RelationshipGroupRecord, int> relGroupRecords, ResourceLocker locks)
        {
            node.Dense   = true;
            node.NextRel = Record.NO_NEXT_RELATIONSHIP.intValue();
            long relId = firstRel.Id;
            RelationshipRecord relRecord = firstRel;

            while (relId != Record.NO_NEXT_RELATIONSHIP.intValue())
            {
                // Get the next relationship id before connecting it (where linkage is overwritten)
                relId = RelChain(relRecord, node.Id).get(relRecord);
                ConnectRelationshipToDenseNode(node, relRecord, relRecords, relGroupRecords, locks);
                if (relId != Record.NO_NEXT_RELATIONSHIP.intValue())
                {                         // Lock and load the next relationship in the chain
                    locks.AcquireExclusive(LockTracer.NONE, ResourceTypes.RELATIONSHIP, relId);
                    relRecord = relRecords.GetOrLoad(relId, null).forChangingLinkage();
                }
            }
        }
Exemplo n.º 9
0
        private void Connect(long nodeId, long firstRelId, RelationshipRecord rel, RecordAccess <RelationshipRecord, Void> relRecords, ResourceLocker locks)
        {
            long newCount = 1;

            if (firstRelId != Record.NO_NEXT_RELATIONSHIP.intValue())
            {
                locks.AcquireExclusive(LockTracer.NONE, ResourceTypes.RELATIONSHIP, firstRelId);
                RelationshipRecord firstRel = relRecords.GetOrLoad(firstRelId, null).forChangingLinkage();
                bool changed = false;
                if (firstRel.FirstNode == nodeId)
                {
                    newCount = firstRel.FirstPrevRel + 1;
                    firstRel.FirstPrevRel      = rel.Id;
                    firstRel.FirstInFirstChain = false;
                    changed = true;
                }
                if (firstRel.SecondNode == nodeId)
                {
                    newCount = firstRel.SecondPrevRel + 1;
                    firstRel.SecondPrevRel      = rel.Id;
                    firstRel.FirstInSecondChain = false;
                    changed = true;
                }
                if (!changed)
                {
                    throw new InvalidRecordException(nodeId + " doesn't match " + firstRel);
                }
            }

            // Set the relationship count
            if (rel.FirstNode == nodeId)
            {
                rel.FirstPrevRel      = newCount;
                rel.FirstInFirstChain = true;
            }
            if (rel.SecondNode == nodeId)
            {
                rel.SecondPrevRel      = newCount;
                rel.FirstInSecondChain = true;
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Traverses a property record chain and finds the record containing the property with key {@code propertyKey}.
        /// If none is found and {@code strict} is {@code true} then <seealso cref="System.InvalidOperationException"/> is thrown,
        /// otherwise id value of <seealso cref="Record.NO_NEXT_PROPERTY"/> is returned.
        /// </summary>
        /// <param name="primitive"> <seealso cref="PrimitiveRecord"/> which is the owner of the chain. </param>
        /// <param name="propertyKey"> property key token id to look for. </param>
        /// <param name="propertyRecords"> access to records. </param>
        /// <param name="strict"> dictates behavior on property key not found. If {@code true} then <seealso cref="System.InvalidOperationException"/>
        /// is thrown, otherwise value of <seealso cref="Record.NO_NEXT_PROPERTY"/> is returned. </param>
        /// <returns> property record id containing property with the given {@code propertyKey}, otherwise if
        /// {@code strict} is false value of <seealso cref="Record.NO_NEXT_PROPERTY"/>. </returns>
        public virtual long FindPropertyRecordContaining(PrimitiveRecord primitive, int propertyKey, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords, bool strict)
        {
            long propertyRecordId = primitive.NextProp;

            while (!Record.NO_NEXT_PROPERTY.@is(propertyRecordId))
            {
                PropertyRecord propertyRecord = propertyRecords.GetOrLoad(propertyRecordId, primitive).forReadingLinkage();
                if (propertyRecord.GetPropertyBlock(propertyKey) != null)
                {
                    return(propertyRecordId);
                }
                propertyRecordId = propertyRecord.NextProp;
            }

            if (strict)
            {
                throw new System.InvalidOperationException("No property record in property chain for " + primitive + " contained property with key " + propertyKey);
            }

            return(Record.NO_NEXT_PROPERTY.intValue());
        }
Exemplo n.º 11
0
        public virtual bool AssertPropertyChain(PrimitiveRecord primitive, RecordAccess <PropertyRecord, PrimitiveRecord> propertyRecords)
        {
            IList <PropertyRecord> toCheck = new LinkedList <PropertyRecord>();
            long nextIdToFetch             = primitive.NextProp;

            while (nextIdToFetch != Record.NO_NEXT_PROPERTY.intValue())
            {
                PropertyRecord propRecord = propertyRecords.GetOrLoad(nextIdToFetch, primitive).forReadingLinkage();
                toCheck.Add(propRecord);
                Debug.Assert(propRecord.InUse(), primitive + "->");
                +Arrays.ToString(toCheck.ToArray());
                Debug.Assert(propRecord.Size() <= PropertyType.PayloadSize, propRecord + " size " + propRecord.Size());
                nextIdToFetch = propRecord.NextProp;
            }
            if (toCheck.Count == 0)
            {
                Debug.Assert(primitive.NextProp == Record.NO_NEXT_PROPERTY.intValue(), primitive);
                return(true);
            }
            PropertyRecord first = toCheck[0];
            PropertyRecord last  = toCheck[toCheck.Count - 1];

            Debug.Assert(first.PrevProp == Record.NO_PREVIOUS_PROPERTY.intValue(), primitive + "->");
            +Arrays.ToString(toCheck.ToArray());
            Debug.Assert(last.NextProp == Record.NO_NEXT_PROPERTY.intValue(), primitive + "->");
            +Arrays.ToString(toCheck.ToArray());
            PropertyRecord current;
            PropertyRecord previous = first;

            for (int i = 1; i < toCheck.Count; i++)
            {
                current = toCheck[i];
                Debug.Assert(current.PrevProp == previous.Id, primitive + "->");
                +Arrays.ToString(toCheck.ToArray());
                Debug.Assert(previous.NextProp == current.Id, primitive + "->");
                +Arrays.ToString(toCheck.ToArray());
                previous = current;
            }
            return(true);
        }
Exemplo n.º 12
0
        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);
        }
Exemplo n.º 13
0
        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));
        }
Exemplo n.º 14
0
        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();
        }
Exemplo n.º 15
0
        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);
            }
        }