use of org.neo4j.kernel.impl.store.record.RelationshipGroupRecord in project neo4j by neo4j.
the class ReadGroupsFromCacheStep method nextBatchOrNull.
@Override
protected Object nextBatchOrNull(long ticket, int batchSize) {
if (!data.hasNext()) {
return null;
}
int i = 0;
long lastOwner = -1;
for (; data.hasNext(); 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.getOwningNode();
} else if (i >= batchSize) {
// ...and continue including groups in this batch until next owner comes
if (item.getOwningNode() != lastOwner) {
break;
}
}
if (i >= scratch.length) {
scratch = Arrays.copyOf(scratch, scratch.length * 2);
}
// which is "item", but also advances the iterator
scratch[i] = data.next();
cursor++;
}
return Arrays.copyOf(scratch, i);
}
use of org.neo4j.kernel.impl.store.record.RelationshipGroupRecord in project neo4j by neo4j.
the class RelationshipGroupCache method iterator.
/**
* @return cached {@link RelationshipGroupRecord} sorted by node id and then type id.
*/
@Override
public Iterator<RelationshipGroupRecord> iterator() {
return new PrefetchingIterator<RelationshipGroupRecord>() {
private long cursor;
private long nodeId = fromNodeId;
private int countLeftForThisNode = groupCount(nodeId);
{
findNextNodeWithGroupsIfNeeded();
}
@Override
protected RelationshipGroupRecord fetchNextOrNull() {
while (cursor < highCacheId) {
RelationshipGroupRecord group = null;
if (cache.getByte(cursor, 0) == 1) {
// Here we have an alive group
group = new RelationshipGroupRecord(-1).initialize(true, cache.get3ByteInt(cursor, 1), cache.get6ByteLong(cursor, 1 + 3), cache.get6ByteLong(cursor, 1 + 3 + 6), cache.get6ByteLong(cursor, 1 + 3 + 6 + 6), nodeId, // so this isn't at all "next" in the true sense of chain next.
countLeftForThisNode - 1);
}
cursor++;
countLeftForThisNode--;
findNextNodeWithGroupsIfNeeded();
if (group != null) {
return group;
}
}
return null;
}
private void findNextNodeWithGroupsIfNeeded() {
if (countLeftForThisNode == 0) {
do {
nodeId++;
countLeftForThisNode = nodeId >= groupCountCache.length() ? 0 : groupCount(nodeId);
} while (countLeftForThisNode == 0 && nodeId < groupCountCache.length());
}
}
};
}
use of org.neo4j.kernel.impl.store.record.RelationshipGroupRecord in project neo4j by neo4j.
the class RelationshipDeleter method updateNodesForDeletedRelationship.
private void updateNodesForDeletedRelationship(RelationshipRecord rel, RecordAccessSet recordChanges, ResourceLocker locks) {
RecordProxy<Long, NodeRecord, Void> startNodeChange = recordChanges.getNodeRecords().getOrLoad(rel.getFirstNode(), null);
RecordProxy<Long, NodeRecord, Void> endNodeChange = recordChanges.getNodeRecords().getOrLoad(rel.getSecondNode(), null);
NodeRecord startNode = recordChanges.getNodeRecords().getOrLoad(rel.getFirstNode(), null).forReadingLinkage();
NodeRecord endNode = recordChanges.getNodeRecords().getOrLoad(rel.getSecondNode(), null).forReadingLinkage();
boolean loop = startNode.getId() == endNode.getId();
if (!startNode.isDense()) {
if (rel.isFirstInFirstChain()) {
startNode = startNodeChange.forChangingLinkage();
startNode.setNextRel(rel.getFirstNextRel());
}
decrementTotalRelationshipCount(startNode.getId(), rel, startNode.getNextRel(), recordChanges.getRelRecords(), locks);
} else {
RecordProxy<Long, RelationshipGroupRecord, Integer> groupChange = relGroupGetter.getRelationshipGroup(startNode, rel.getType(), recordChanges.getRelGroupRecords()).group();
assert groupChange != null : "Relationship group " + rel.getType() + " should have existed here";
RelationshipGroupRecord group = groupChange.forReadingData();
DirectionWrapper dir = DirectionIdentifier.wrapDirection(rel, startNode);
if (rel.isFirstInFirstChain()) {
group = groupChange.forChangingData();
dir.setNextRel(group, rel.getFirstNextRel());
if (groupIsEmpty(group)) {
deleteGroup(startNodeChange, group, recordChanges.getRelGroupRecords());
}
}
decrementTotalRelationshipCount(startNode.getId(), rel, dir.getNextRel(group), recordChanges.getRelRecords(), locks);
}
if (!endNode.isDense()) {
if (rel.isFirstInSecondChain()) {
endNode = endNodeChange.forChangingLinkage();
endNode.setNextRel(rel.getSecondNextRel());
}
if (!loop) {
decrementTotalRelationshipCount(endNode.getId(), rel, endNode.getNextRel(), recordChanges.getRelRecords(), locks);
}
} else {
RecordProxy<Long, RelationshipGroupRecord, Integer> groupChange = relGroupGetter.getRelationshipGroup(endNode, rel.getType(), recordChanges.getRelGroupRecords()).group();
DirectionWrapper dir = DirectionIdentifier.wrapDirection(rel, endNode);
assert groupChange != null || loop : "Group has been deleted";
if (groupChange != null) {
RelationshipGroupRecord group = groupChange.forReadingData();
if (rel.isFirstInSecondChain()) {
group = groupChange.forChangingData();
dir.setNextRel(group, rel.getSecondNextRel());
if (groupIsEmpty(group)) {
deleteGroup(endNodeChange, group, recordChanges.getRelGroupRecords());
}
}
}
// Else this is a loop-rel and the group was deleted when dealing with the start node
if (!loop) {
decrementTotalRelationshipCount(endNode.getId(), rel, dir.getNextRel(groupChange.forChangingData()), recordChanges.getRelRecords(), locks);
}
}
}
use of org.neo4j.kernel.impl.store.record.RelationshipGroupRecord in project neo4j by neo4j.
the class RelationshipDeleter method deleteGroup.
private void deleteGroup(RecordProxy<Long, NodeRecord, Void> nodeChange, RelationshipGroupRecord group, RecordAccess<Long, RelationshipGroupRecord, Integer> relGroupRecords) {
long previous = group.getPrev();
long next = group.getNext();
if (previous == Record.NO_NEXT_RELATIONSHIP.intValue()) {
// This is the first one, just point the node to the next group
nodeChange.forChangingLinkage().setNextRel(next);
} else {
// There are others before it, point the previous to the next group
RelationshipGroupRecord previousRecord = relGroupRecords.getOrLoad(previous, null).forChangingLinkage();
previousRecord.setNext(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.setPrev(previous);
}
group.setInUse(false);
}
use of org.neo4j.kernel.impl.store.record.RelationshipGroupRecord in project neo4j by neo4j.
the class RelationshipGroupGetter method getRelationshipGroup.
public RelationshipGroupPosition getRelationshipGroup(NodeRecord node, int type, RecordAccess<Long, RelationshipGroupRecord, Integer> relGroupRecords) {
long groupId = node.getNextRel();
long previousGroupId = Record.NO_NEXT_RELATIONSHIP.intValue();
RecordProxy<Long, RelationshipGroupRecord, Integer> previous = null, current = null;
while (groupId != Record.NO_NEXT_RELATIONSHIP.intValue()) {
current = relGroupRecords.getOrLoad(groupId, null);
RelationshipGroupRecord record = current.forReadingData();
// not persistent so not a "change"
record.setPrev(previousGroupId);
if (record.getType() == type) {
return new RelationshipGroupPosition(previous, current);
} else if (record.getType() > type) {
// empty handed right away
return new RelationshipGroupPosition(previous, null);
}
previousGroupId = groupId;
groupId = record.getNext();
previous = current;
}
return new RelationshipGroupPosition(previous, null);
}
Aggregations