//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private org.neo4j.kernel.impl.store.record.RelationshipGroupRecord readRelationshipGroupRecord(long id, org.neo4j.storageengine.api.ReadableChannel channel) throws java.io.IOException
        private RelationshipGroupRecord ReadRelationshipGroupRecord(long id, ReadableChannel channel)
        {
            sbyte flags = channel.Get();
            bool  inUse = bitFlag(flags, Record.IN_USE.byteValue());
            bool  requireSecondaryUnit     = bitFlag(flags, Record.REQUIRE_SECONDARY_UNIT);
            bool  hasSecondaryUnit         = bitFlag(flags, Record.HAS_SECONDARY_UNIT);
            bool  usesFixedReferenceFormat = bitFlag(flags, Record.USES_FIXED_REFERENCE_FORMAT);

            int type = unsignedShortToInt(channel.Short);
            RelationshipGroupRecord record = new RelationshipGroupRecord(id, type);

            record.InUse                 = inUse;
            record.Next                  = channel.Long;
            record.FirstOut              = channel.Long;
            record.FirstIn               = channel.Long;
            record.FirstLoop             = channel.Long;
            record.OwningNode            = channel.Long;
            record.RequiresSecondaryUnit = requireSecondaryUnit;
            if (hasSecondaryUnit)
            {
                record.SecondaryUnitId = channel.Long;
            }
            record.UseFixedReferences = usesFixedReferenceFormat;
            return(record);
        }
예제 #2
0
        private void MarkRandomRelsInGroupNotInUse(long nodeId, TestRelType type)
        {
            NodeRecord node = GetNodeRecord(nodeId);

            assertTrue(node.Dense);

            long relGroupId = node.NextRel;

            while (relGroupId != NO_NEXT_RELATIONSHIP.intValue())
            {
                RelationshipGroupRecord relGroup = GetRelGroupRecord(relGroupId);

                if (type == RelTypeForId(relGroup.Type))
                {
                    MarkRandomRelsInChainNotInUse(relGroup.FirstOut);
                    MarkRandomRelsInChainNotInUse(relGroup.FirstIn);
                    MarkRandomRelsInChainNotInUse(relGroup.FirstLoop);
                    return;
                }

                relGroupId = relGroup.Next;
            }

            throw new System.InvalidOperationException("No relationship group with type: " + type + " found");
        }
예제 #3
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));
        }
예제 #4
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void useVariableLengthFormatWhenOneOfTheReferencesReferenceTooBig() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void UseVariableLengthFormatWhenOneOfTheReferencesReferenceTooBig()
        {
            RelationshipGroupRecord source = new RelationshipGroupRecord(1);
            RelationshipGroupRecord target = new RelationshipGroupRecord(1);

            VerifyRecordsWithPoisonedReference(source, target, 1L << ((sizeof(int) * 8) + 2));
        }
예제 #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void verifyRecordsWithPoisonedReference(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord source, org.neo4j.kernel.impl.store.record.RelationshipGroupRecord target, long poisonedReference) throws java.io.IOException
        private void VerifyRecordsWithPoisonedReference(RelationshipGroupRecord source, RelationshipGroupRecord target, long poisonedReference)
        {
            bool         nullPoisoned        = poisonedReference == BaseHighLimitRecordFormat.Null;
            int          differentReferences = 5;
            IList <long> references          = BuildReferenceList(differentReferences, poisonedReference);

            for (int i = 0; i < differentReferences; i++)
            {
                _pageCursor.Offset = 0;
                IEnumerator <long> iterator = references.GetEnumerator();

//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
                source.Initialize(true, 0, iterator.next(), iterator.next(), iterator.next(), iterator.next(), iterator.next());

                WriteReadRecord(source, target);

                if (nullPoisoned)
                {
                    assertTrue("Record should use fixed reference format.", target.UseFixedReferences);
                }
                else
                {
                    assertFalse("Record should use variable length reference format.", target.UseFixedReferences);
                }
                VerifySame(source, target);
                Collections.rotate(references, 1);
            }
        }
예제 #6
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void useFixedReferenceFormatWhenOneOfTheReferencesIsMissing() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void UseFixedReferenceFormatWhenOneOfTheReferencesIsMissing()
        {
            RelationshipGroupRecord source = new RelationshipGroupRecord(1);
            RelationshipGroupRecord target = new RelationshipGroupRecord(1);

            VerifyRecordsWithPoisonedReference(source, target, NULL);
        }
예제 #7
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void writeReadRecord(org.neo4j.kernel.impl.store.record.RelationshipGroupRecord source, org.neo4j.kernel.impl.store.record.RelationshipGroupRecord target, int recordSize) throws java.io.IOException
        private void WriteReadRecord(RelationshipGroupRecord source, RelationshipGroupRecord target, int recordSize)
        {
            _recordFormat.prepare(source, recordSize, _idSequence);
            _recordFormat.write(source, _pageCursor, recordSize);
            _pageCursor.Offset = 0;
            _recordFormat.read(target, _pageCursor, RecordLoad.NORMAL, recordSize);
        }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private Command visitRelationshipGroupCommand(org.neo4j.storageengine.api.ReadableChannel channel) throws java.io.IOException
        private Command VisitRelationshipGroupCommand(ReadableChannel channel)
        {
            long id = channel.Long;
            RelationshipGroupRecord before = ReadRelationshipGroupRecord(id, channel);
            RelationshipGroupRecord after  = ReadRelationshipGroupRecord(id, channel);

            return(new Command.RelationshipGroupCommand(before, after));
        }
예제 #9
0
파일: Commands.cs 프로젝트: Neo4Net/Neo4Net
        public static RelationshipGroupCommand CreateRelationshipGroup(long id, int type)
        {
            RelationshipGroupRecord before = new RelationshipGroupRecord(id);
            RelationshipGroupRecord after  = new RelationshipGroupRecord(id, type);

            after.InUse = true;
            after.SetCreated();
            return(new RelationshipGroupCommand(before, after));
        }
예제 #10
0
 public static RecordChangeSet NewChangeSet(params AbstractBaseRecord[] records)
 {
     return(new RecordChangeSet(new Loader(FilterType(records, typeof(NodeRecord)).collect(Collectors.toList()), (System.Func <long, object, NodeRecord>)(key, extra) => new NodeRecord(key)), null, new Loader(FilterType(records, typeof(RelationshipRecord)).collect(Collectors.toList()), (System.Func <long, object, RelationshipRecord>)(key, extra) => new RelationshipRecord(key)), new Loader(FilterType(records, typeof(RelationshipGroupRecord)).collect(Collectors.toList()), (System.Func <long, int, RelationshipGroupRecord>)(key, extra) =>
     {
         RelationshipGroupRecord group = new RelationshipGroupRecord(key);
         group.Type = extra;
         return group;
     }), null, null, null, null));
 }
예제 #11
0
        private void ConnectRelationshipToDenseNode(NodeRecord node, RelationshipRecord rel, RecordAccess <RelationshipRecord, Void> relRecords, RecordAccess <RelationshipGroupRecord, int> relGroupRecords, ResourceLocker locks)
        {
            RelationshipGroupRecord group = _relGroupGetter.getOrCreateRelationshipGroup(node, rel.Type, relGroupRecords).forChangingData();
            DirectionWrapper        dir   = DirectionIdentifier.wrapDirection(rel, node);
            long nextRel = dir.getNextRel(group);

            SetCorrectNextRel(node, rel, nextRel);
            Connect(node.Id, nextRel, rel, relRecords, locks);
            dir.setNextRel(group, rel.Id);
        }
예제 #12
0
 private void VerifySame(RelationshipGroupRecord recordA, RelationshipGroupRecord recordB)
 {
     assertEquals("Types should be equal.", recordA.Type, recordB.Type);
     assertEquals("First In references should be equal.", recordA.FirstIn, recordB.FirstIn);
     assertEquals("First Loop references should be equal.", recordA.FirstLoop, recordB.FirstLoop);
     assertEquals("First Out references should be equal.", recordA.FirstOut, recordB.FirstOut);
     assertEquals("Next references should be equal.", recordA.Next, recordB.Next);
     assertEquals("Prev references should be equal.", recordA.Prev, recordB.Prev);
     assertEquals("Owning node references should be equal.", recordA.OwningNode, recordB.OwningNode);
 }
예제 #13
0
        public static RelationshipGroupRecord RelGroup(long id, params System.Action <RelationshipGroupRecord>[] modifiers)
        {
            RelationshipGroupRecord record = new RelationshipGroupRecord(id);

            record.Initialize(true, 0, Record.NO_NEXT_RELATIONSHIP.longValue(), Record.NO_NEXT_RELATIONSHIP.longValue(), Record.NO_NEXT_RELATIONSHIP.longValue(), -1, Record.NO_NEXT_RELATIONSHIP.longValue());
            foreach (System.Action <RelationshipGroupRecord> modifier in modifiers)
            {
                modifier(record);
            }

            return(record);
        }
예제 #14
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void readWriteFixedReferencesRecord() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ReadWriteFixedReferencesRecord()
        {
            RelationshipGroupRecord source = new RelationshipGroupRecord(1);
            RelationshipGroupRecord target = new RelationshipGroupRecord(1);

            source.Initialize(true, RandomType(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference());

            WriteReadRecord(source, target);

            assertTrue("Record should use fixed reference format.", target.UseFixedReferences);
            VerifySame(source, target);
        }
예제 #15
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void useFixedReferenceFormatWhenRecordCanFitInRecordSizeRecord() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void UseFixedReferenceFormatWhenRecordCanFitInRecordSizeRecord()
        {
            RelationshipGroupRecord source = new RelationshipGroupRecord(1);
            RelationshipGroupRecord target = new RelationshipGroupRecord(1);

            source.Initialize(true, RandomType(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference());

            WriteReadRecord(source, target, RelationshipGroupRecordFormat.FixedFormatRecordSize);

            assertTrue("Record should use fixed reference if can fit in format record.", target.UseFixedReferences);
            VerifySame(source, target);
        }
예제 #16
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void useVariableLengthFormatWhenRecordSizeIsTooSmall() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void UseVariableLengthFormatWhenRecordSizeIsTooSmall()
        {
            RelationshipGroupRecord source = new RelationshipGroupRecord(1);
            RelationshipGroupRecord target = new RelationshipGroupRecord(1);

            source.Initialize(true, RandomType(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference(), RandomFixedReference());

            WriteReadRecord(source, target, RelationshipGroupRecordFormat.FixedFormatRecordSize - 1);

            assertFalse("Record should use variable length reference if format record is too small.", target.UseFixedReferences);
            VerifySame(source, target);
        }
예제 #17
0
 private void AssertBatch(RelationshipGroupRecord[] batch, long lastOwningNodeLastBatch)
 {
     for (int i = 0; i < batch.Length; i++)
     {
         RelationshipGroupRecord record = batch[i];
         assertTrue(record.Id > Record.NULL_REFERENCE.longValue());
         assertTrue(record.OwningNode > lastOwningNodeLastBatch);
         assertEquals(1, record.FirstOut);                           // the mark our store mock sets when preparing
         if (record.Next == Record.NULL_REFERENCE.longValue())
         {
             // This is the last in the chain, verify that this is either:
             assertTrue(i == batch.Length - 1 || batch[i + 1].OwningNode > record.OwningNode);
         }
     }
 }
예제 #18
0
        protected internal static IList <RelationshipGroupRecord> Groups(params Group[] groups)
        {
            IList <RelationshipGroupRecord> records = new List <RelationshipGroupRecord>();

            foreach (Group group in groups)
            {
                for (int i = 0; i < group.Count; i++)
                {
                    RelationshipGroupRecord record = new RelationshipGroupRecord(NULL_REFERENCE.longValue());
                    record.OwningNode = group.OwningNode;
                    record.Next       = group.Count - i - 1;                        // count: how many come after it (importer does this)
                    records.Add(record);
                }
            }
            return(records);
        }
예제 #19
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldDefragmentRelationshipGroupsWhenSomeDense()
        public virtual void ShouldDefragmentRelationshipGroupsWhenSomeDense()
        {
            // GIVEN some nodes which has their groups scattered
            int nodeCount             = 100;
            int relationshipTypeCount = 50;
            RecordStore <RelationshipGroupRecord> groupStore = _stores.TemporaryRelationshipGroupStore;
            RelationshipGroupRecord  groupRecord             = groupStore.NewRecord();
            RecordStore <NodeRecord> nodeStore = _stores.NodeStore;
            NodeRecord nodeRecord       = nodeStore.NewRecord();
            long       cursor           = 0;
            BitArray   initializedNodes = new BitArray();

            for (int typeId = relationshipTypeCount - 1; typeId >= 0; typeId--)
            {
                for (int nodeId = 0; nodeId < nodeCount; nodeId++, cursor++)
                {
                    // Reasoning behind this thing is that we want to have roughly 10% of the nodes dense
                    // right from the beginning and then some stray dense nodes coming into this in the
                    // middle of the type range somewhere
                    double comparison = typeId == 0 || initializedNodes.Get(nodeId) ? 0.1 : 0.001;

                    if (_random.NextDouble() < comparison)
                    {
                        // next doesn't matter at all, as we're rewriting it anyway
                        // firstOut/In/Loop we could use in verification phase later
                        groupRecord.Initialize(true, typeId, cursor, cursor + 1, cursor + 2, nodeId, 4);
                        groupRecord.Id = groupStore.nextId();
                        groupStore.UpdateRecord(groupRecord);

                        if (!initializedNodes.Get(nodeId))
                        {
                            nodeRecord.Initialize(true, -1, true, groupRecord.Id, 0);
                            nodeRecord.Id = nodeId;
                            nodeStore.UpdateRecord(nodeRecord);
                            nodeStore.HighestPossibleIdInUse = nodeId;
                            initializedNodes.Set(nodeId, true);
                        }
                    }
                }
            }

            // WHEN
            Defrag(nodeCount, groupStore);

            // THEN all groups should sit sequentially in the store
            VerifyGroupsAreSequentiallyOrderedByNode();
        }
예제 #20
0
        private void VerifyGroupsAreSequentiallyOrderedByNode()
        {
            RelationshipGroupStore store = _stores.RelationshipGroupStore;
            long firstId    = store.NumberOfReservedLowIds;
            long groupCount = store.HighId - firstId;
            RelationshipGroupRecord groupRecord = store.NewRecord();
            PageCursor groupCursor        = store.OpenPageCursorForReading(firstId);
            long       highGroupId        = store.HighId;
            long       currentNodeId      = -1;
            int        currentTypeId      = -1;
            int        newGroupCount      = 0;
            int        currentGroupLength = 0;

            for (long id = firstId; id < highGroupId; id++, newGroupCount++)
            {
                store.GetRecordByCursor(id, groupRecord, CHECK, groupCursor);
                if (!groupRecord.InUse())
                {
                    // This will be the case if we have double record units, just assert that fact
                    assertTrue(Units > 1);
                    assertTrue(currentGroupLength > 0);
                    currentGroupLength--;
                    continue;
                }

                long nodeId = groupRecord.OwningNode;
                assertTrue("Expected a group for node >= " + currentNodeId + ", but was " + nodeId + " in " + groupRecord, nodeId >= currentNodeId);
                if (nodeId != currentNodeId)
                {
                    currentNodeId = nodeId;
                    currentTypeId = -1;
                    if (Units > 1)
                    {
                        assertEquals(0, currentGroupLength);
                    }
                    currentGroupLength = 0;
                }
                currentGroupLength++;

                assertTrue("Expected this group to have a next of current + " + Units + " OR NULL, " + "but was " + groupRecord.ToString(), groupRecord.Next == groupRecord.Id + 1 || groupRecord.Next == Record.NO_NEXT_RELATIONSHIP.intValue());
                assertTrue("Expected " + groupRecord + " to have type > " + currentTypeId, groupRecord.Type > currentTypeId);
                currentTypeId = groupRecord.Type;
            }
            assertEquals(groupCount, newGroupCount);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldReadUnsignedRelationshipTypeId() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldReadUnsignedRelationshipTypeId()
        {
            // GIVEN
            using (PageCursor cursor = new StubPageCursor(1, _recordSize * 10))
            {
                int offset = 10;
                cursor.Next();
                RelationshipGroupRecord group = (new RelationshipGroupRecord(2)).initialize(true, short.MaxValue + offset, 1, 2, 3, 4, 5);
                cursor.Offset = offset;
                _format.write(group, cursor, _recordSize);

                // WHEN
                RelationshipGroupRecord read = new RelationshipGroupRecord(group.Id);
                cursor.Offset = offset;
                _format.read(read, cursor, NORMAL, _recordSize);

                // THEN
                assertEquals(group, read);
            }
        }
예제 #22
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;
        }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private Command visitRelationshipGroupCommand(org.neo4j.storageengine.api.ReadableChannel channel) throws java.io.IOException
        private Command VisitRelationshipGroupCommand(ReadableChannel channel)
        {
            long  id        = channel.Long;
            sbyte inUseByte = channel.Get();
            bool  inUse     = inUseByte == Record.IN_USE.byteValue();

            if (inUseByte != Record.IN_USE.byteValue() && inUseByte != Record.NOT_IN_USE.byteValue())
            {
                throw new IOException("Illegal in use flag: " + inUseByte);
            }
            int type = unsignedShortToInt(channel.Short);
            RelationshipGroupRecord record = new RelationshipGroupRecord(id, type);

            record.InUse      = inUse;
            record.Next       = channel.Long;
            record.FirstOut   = channel.Long;
            record.FirstIn    = channel.Long;
            record.FirstLoop  = channel.Long;
            record.OwningNode = channel.Long;

            return(new Command.RelationshipGroupCommand(null, record));
        }
예제 #24
0
        protected internal override object NextBatchOrNull(long ticket, int batchSize)
        {
//JAVA TO C# CONVERTER TODO TASK: Java iterators are only converted within the context of 'while' and 'for' loops:
            if (!_data.hasNext())
            {
                return(null);
            }

            int  i         = 0;
            long lastOwner = -1;

            for ( ; _data.MoveNext(); i++)
            {
                // Logic below makes it so that all groups for a specific node ends up in the same batch,
                // which means that batches are slightly bigger (varying) than the requested size.
                RelationshipGroupRecord item = _data.peek();
                if (i == batchSize - 1)
                {
                    // Remember which owner this "last" group has...
                    lastOwner = item.OwningNode;
                }
                else if (i >= batchSize)
                {
                    // ...and continue including groups in this batch until next owner comes
                    if (item.OwningNode != lastOwner)
                    {
                        break;
                    }
                }

                if (i >= _scratch.Length)
                {
                    _scratch = Arrays.copyOf(_scratch, _scratch.Length * 2);
                }
                _scratch[i] = _data.Current;                         // which is "item", but also advances the iterator
                _cursor++;
            }
            return(Arrays.copyOf(_scratch, i));
        }
예제 #25
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldDefragmentRelationshipGroupsWhenAllDense()
        public virtual void ShouldDefragmentRelationshipGroupsWhenAllDense()
        {
            // GIVEN some nodes which has their groups scattered
            int nodeCount             = 100;
            int relationshipTypeCount = 50;
            RecordStore <RelationshipGroupRecord> groupStore = _stores.TemporaryRelationshipGroupStore;
            RelationshipGroupRecord  groupRecord             = groupStore.NewRecord();
            RecordStore <NodeRecord> nodeStore = _stores.NodeStore;
            NodeRecord nodeRecord = nodeStore.NewRecord();
            long       cursor     = 0;

            for (int typeId = relationshipTypeCount - 1; typeId >= 0; typeId--)
            {
                for (long nodeId = 0; nodeId < nodeCount; nodeId++, cursor++)
                {
                    // next doesn't matter at all, as we're rewriting it anyway
                    // firstOut/In/Loop we could use in verification phase later
                    groupRecord.Initialize(true, typeId, cursor, cursor + 1, cursor + 2, nodeId, 4);
                    groupRecord.Id = groupStore.nextId();
                    groupStore.UpdateRecord(groupRecord);

                    if (typeId == 0)
                    {
                        // first round also create the nodes
                        nodeRecord.Initialize(true, -1, true, groupRecord.Id, 0);
                        nodeRecord.Id = nodeId;
                        nodeStore.UpdateRecord(nodeRecord);
                        nodeStore.HighestPossibleIdInUse = nodeId;
                    }
                }
            }

            // WHEN
            Defrag(nodeCount, groupStore);

            // THEN all groups should sit sequentially in the store
            VerifyGroupsAreSequentiallyOrderedByNode();
        }
예제 #26
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);
        }
예제 #27
0
        protected internal override void Process(RelationshipGroupRecord[] batch, BatchSender sender)
        {
            int groupStartIndex = 0;

            for (int i = 0; i < batch.Length; i++)
            {
                RelationshipGroupRecord group = batch[i];

                // The iterator over the groups will not produce real next pointers, they are instead
                // a count meaning how many groups come after it. This encoder will set the real group ids.
                long count       = group.Next;
                bool lastInChain = count == 0;

                group.Id = _nextId == -1 ? _nextId = _store.nextId() : _nextId;
                if (!lastInChain)
                {
                    group.Next = _nextId = _store.nextId();
                }
                else
                {
                    group.Next = _nextId = -1;

                    // OK so this group is the last in this chain, which means all the groups in this chain
                    // are now fully populated. We can now prepare these groups so that their potential
                    // secondary units ends up very close by.
                    for (int j = groupStartIndex; j <= i; j++)
                    {
                        _store.prepareForCommit(batch[j]);
                    }

                    groupStartIndex = i + 1;
                }
            }
            Debug.Assert(groupStartIndex == batch.Length);

            sender.Send(batch);
        }
예제 #28
0
        private void MarkRelGroupNotInUse(long nodeId, params TestRelType[] types)
        {
            NodeRecord node = GetNodeRecord(nodeId);

            assertTrue(node.Dense);

            ISet <TestRelType> typesToRemove = asSet(types);

            long relGroupId = node.NextRel;

            while (relGroupId != NO_NEXT_RELATIONSHIP.intValue())
            {
                RelationshipGroupRecord relGroup = GetRelGroupRecord(relGroupId);
                TestRelType             type     = RelTypeForId(relGroup.Type);

                if (typesToRemove.Contains(type))
                {
                    relGroup.InUse = false;
                    Update(relGroup);
                }

                relGroupId = relGroup.Next;
            }
        }
예제 #29
0
 private bool GroupIsEmpty(RelationshipGroupRecord group)
 {
     return(group.FirstOut == Record.NO_NEXT_RELATIONSHIP.intValue() && group.FirstIn == Record.NO_NEXT_RELATIONSHIP.intValue() && group.FirstLoop == Record.NO_NEXT_RELATIONSHIP.intValue());
 }
예제 #30
0
        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);
                }
            }
        }