@Override public Iterable<Long> getRelationshipIds(long nodeId) { NodeRecord nodeRecord = getNodeRecord(nodeId); long nextRel = nodeRecord.getNextRel(); List<Long> ids = new ArrayList<Long>(); while (nextRel != Record.NO_NEXT_RELATIONSHIP.intValue()) { RelationshipRecord relRecord = getRelationshipRecord(nextRel); ids.add(relRecord.getId()); long firstNode = relRecord.getFirstNode(); long secondNode = relRecord.getSecondNode(); if (firstNode == nodeId) { nextRel = relRecord.getFirstNextRel(); } else if (secondNode == nodeId) { nextRel = relRecord.getSecondNextRel(); } else { throw new InvalidRecordException( "Node[" + nodeId + "] not part of firstNode[" + firstNode + "] or secondNode[" + secondNode + "]"); } } return ids; }
public Iterable<SimpleRelationship> getSimpleRelationships(long nodeId) { NodeRecord nodeRecord = getNodeRecord(nodeId); long nextRel = nodeRecord.getNextRel(); List<SimpleRelationship> rels = new ArrayList<SimpleRelationship>(); while (nextRel != Record.NO_NEXT_RELATIONSHIP.intValue()) { RelationshipRecord relRecord = getRelationshipRecord(nextRel); RelationshipType type = new RelationshipTypeImpl(typeHolder.getName(relRecord.getType())); rels.add( new SimpleRelationship( relRecord.getId(), relRecord.getFirstNode(), relRecord.getSecondNode(), type)); long firstNode = relRecord.getFirstNode(); long secondNode = relRecord.getSecondNode(); if (firstNode == nodeId) { nextRel = relRecord.getFirstNextRel(); } else if (secondNode == nodeId) { nextRel = relRecord.getSecondNextRel(); } else { throw new InvalidRecordException( "Node[" + nodeId + "] not part of firstNode[" + firstNode + "] or secondNode[" + secondNode + "]"); } } return rels; }
// newNode will only be true for NodeManager.createNode NodeImpl(long id, boolean newNode) { super(id, newNode); if (newNode) { relationshipMap = new ArrayMap<String, RelIdArray>(); relChainPosition = new RelationshipChainPosition(Record.NO_NEXT_RELATIONSHIP.intValue()); } }
public static class CowNodeElement extends CowEntityElement { CowNodeElement(long id) { super(id); } private long firstRel = Record.NO_NEXT_RELATIONSHIP.intValue(); private long firstProp = Record.NO_NEXT_PROPERTY.intValue(); private ArrayMap<Integer, RelIdArray> relationshipAddMap; private ArrayMap<Integer, Collection<Long>> relationshipRemoveMap; public ArrayMap<Integer, RelIdArray> getRelationshipAddMap(boolean create) { if (relationshipAddMap == null && create) { relationshipAddMap = new ArrayMap<>(); } return relationshipAddMap; } public RelIdArray getRelationshipAddMap(int type, boolean create) { ArrayMap<Integer, RelIdArray> map = getRelationshipAddMap(create); if (map == null) { return null; } RelIdArray result = map.get(type); if (result == null && create) { result = new RelIdArrayWithLoops(type); map.put(type, result); } return result; } public ArrayMap<Integer, Collection<Long>> getRelationshipRemoveMap(boolean create) { if (relationshipRemoveMap == null && create) { relationshipRemoveMap = new ArrayMap<>(); } return relationshipRemoveMap; } public Collection<Long> getRelationshipRemoveMap(int type, boolean create) { ArrayMap<Integer, Collection<Long>> map = getRelationshipRemoveMap(create); if (map == null) { return null; } Collection<Long> result = map.get(type); if (result == null && create) { result = new HashSet<>(); map.put(type, result); } return result; } @Override public String toString() { return "Node[" + id + "]"; } }
private long internalCreateNode(long nodeId, Map<String, Object> properties) { NodeRecord nodeRecord = new NodeRecord( nodeId, Record.NO_NEXT_RELATIONSHIP.intValue(), Record.NO_NEXT_PROPERTY.intValue()); nodeRecord.setInUse(true); nodeRecord.setCreated(); nodeRecord.setNextProp(createPropertyChain(properties)); getNodeStore().updateRecord(nodeRecord); return nodeId; }
public RecordProxy<Long, RelationshipGroupRecord, Integer> getRelationshipGroup( NodeRecord node, int type) { long groupId = node.getNextRel(); long previousGroupId = Record.NO_NEXT_RELATIONSHIP.intValue(); Set<Integer> allTypes = new HashSet<>(); while (groupId != Record.NO_NEXT_RELATIONSHIP.intValue()) { RecordProxy<Long, RelationshipGroupRecord, Integer> change = recordChangeSet.getRelGroupRecords().getOrLoad(groupId, type); RelationshipGroupRecord record = change.forReadingData(); record.setPrev(previousGroupId); // not persistent so not a "change" allTypes.add(record.getType()); if (record.getType() == type) { return change; } previousGroupId = groupId; groupId = record.getNext(); } return null; }
private void convertNodeToDenseNode( NodeRecord node, RelationshipRecord firstRel, RecordAccess<Long, RelationshipRecord, Void> relRecords, RecordAccess<Long, RelationshipGroupRecord, Integer> relGroupRecords) { firstRel = relRecords.getOrLoad(firstRel.getId(), null).forChangingLinkage(); node.setDense(true); node.setNextRel(Record.NO_NEXT_RELATIONSHIP.intValue()); long relId = firstRel.getId(); RelationshipRecord relRecord = firstRel; while (relId != Record.NO_NEXT_RELATIONSHIP.intValue()) { locker.getWriteLock(relId); relId = relChain(relRecord, node.getId()).get(relRecord); connectRelationshipToDenseNode(node, relRecord, relRecords, relGroupRecords); if (relId == Record.NO_NEXT_RELATIONSHIP.intValue()) { break; } relRecord = relRecords.getOrLoad(relId, null).forChangingLinkage(); } if (upgradedDenseNodes == null) { upgradedDenseNodes = new ArrayList<>(); } upgradedDenseNodes.add(node); }
private void convertNodeToDenseIfNecessary( NodeRecord node, RecordAccess<Long, RelationshipRecord, Void> relRecords, RecordAccess<Long, RelationshipGroupRecord, Integer> relGroupRecords) { if (node.isDense()) { return; } long relId = node.getNextRel(); if (relId != Record.NO_NEXT_RELATIONSHIP.intValue()) { RecordProxy<Long, RelationshipRecord, Void> relChange = relRecords.getOrLoad(relId, null); RelationshipRecord rel = relChange.forReadingLinkage(); if (RelationshipCounter.relCount(node.getId(), rel) >= neoStore.getDenseNodeThreshold()) { convertNodeToDenseNode(node, relChange.forChangingLinkage(), relRecords, relGroupRecords); } } }
private void connect(NodeRecord node, RelationshipRecord rel) { if (node.getNextRel() != Record.NO_NEXT_RELATIONSHIP.intValue()) { RelationshipRecord nextRel = getRelationshipStore().getRecord(node.getNextRel()); boolean changed = false; if (nextRel.getFirstNode() == node.getId()) { nextRel.setFirstPrevRel(rel.getId()); changed = true; } if (nextRel.getSecondNode() == node.getId()) { nextRel.setSecondPrevRel(rel.getId()); changed = true; } if (!changed) { throw new InvalidRecordException(node + " dont match " + nextRel); } getRelationshipStore().updateRecord(nextRel); } }
private void migrateNodes(NodeStore nodeStore, PropertyWriter propertyWriter) throws IOException { Iterable<NodeRecord> records = legacyStore.getNodeStoreReader().readNodeStore(); // estimate total number of nodes using file size then calc number of dots or percentage // complete for (NodeRecord nodeRecord : records) { reportProgress(nodeRecord.getId()); nodeStore.setHighId(nodeRecord.getId() + 1); if (nodeRecord.inUse()) { long startOfPropertyChain = nodeRecord.getNextProp(); if (startOfPropertyChain != Record.NO_NEXT_RELATIONSHIP.intValue()) { long propertyRecordId = migrateProperties(startOfPropertyChain, propertyWriter); nodeRecord.setNextProp(propertyRecordId); } nodeStore.updateRecord(nodeRecord); } else { nodeStore.freeId(nodeRecord.getId()); } } legacyStore.getNodeStoreReader().close(); }
private void migrateRelationships( RelationshipStore relationshipStore, PropertyWriter propertyWriter) throws IOException { long nodeMaxId = legacyStore.getNodeStoreReader().getMaxId(); Iterable<RelationshipRecord> records = legacyStore.getRelationshipStoreReader().readRelationshipStore(); for (RelationshipRecord relationshipRecord : records) { reportProgress(nodeMaxId + relationshipRecord.getId()); relationshipStore.setHighId(relationshipRecord.getId() + 1); if (relationshipRecord.inUse()) { long startOfPropertyChain = relationshipRecord.getNextProp(); if (startOfPropertyChain != Record.NO_NEXT_RELATIONSHIP.intValue()) { long propertyRecordId = migrateProperties(startOfPropertyChain, propertyWriter); relationshipRecord.setNextProp(propertyRecordId); } relationshipStore.updateRecord(relationshipRecord); } else { relationshipStore.freeId(relationshipRecord.getId()); } } legacyStore.getRelationshipStoreReader().close(); }
private void connect( long nodeId, long firstRelId, RelationshipRecord rel, RecordAccess<Long, RelationshipRecord, Void> relRecords) { long newCount = 1; if (firstRelId != Record.NO_NEXT_RELATIONSHIP.intValue()) { locker.getWriteLock(firstRelId); RelationshipRecord firstRel = relRecords.getOrLoad(firstRelId, null).forChangingLinkage(); boolean changed = false; if (firstRel.getFirstNode() == nodeId) { newCount = firstRel.getFirstPrevRel() + 1; firstRel.setFirstPrevRel(rel.getId()); firstRel.setFirstInFirstChain(false); changed = true; } if (firstRel.getSecondNode() == nodeId) { newCount = firstRel.getSecondPrevRel() + 1; firstRel.setSecondPrevRel(rel.getId()); firstRel.setFirstInSecondChain(false); changed = true; } if (!changed) { throw new InvalidRecordException(nodeId + " doesn't match " + firstRel); } } // Set the relationship count if (rel.getFirstNode() == nodeId) { rel.setFirstPrevRel(newCount); rel.setFirstInFirstChain(true); } if (rel.getSecondNode() == nodeId) { rel.setSecondPrevRel(newCount); rel.setFirstInSecondChain(true); } }
@Override public boolean hasMore(DirectionWrapper direction, int[] types) { return position != Record.NO_NEXT_RELATIONSHIP.intValue(); }
@Override long get(RelationshipRecord rel) { return rel.isFirstInSecondChain() ? Record.NO_NEXT_RELATIONSHIP.intValue() : rel.getSecondPrevRel(); }
@Override public void create( long nodeId, NodeStruct event, Relationship relationship, long prevId, long nextId) throws IOException { long from = nodeId; long id = relationship.id; long firstNode, secondNode, firstNextRel, firstPrevRel, secondNextRel, secondPrevRel; if (relationship.outgoing()) { firstNode = from; secondNode = relationship.other(); firstPrevRel = prevId; firstNextRel = nextId; secondPrevRel = Record.NO_PREV_RELATIONSHIP.intValue(); secondNextRel = Record.NO_NEXT_RELATIONSHIP.intValue(); } else { firstNode = relationship.other(); secondNode = from; firstPrevRel = Record.NO_PREV_RELATIONSHIP.intValue(); firstNextRel = Record.NO_NEXT_RELATIONSHIP.intValue(); secondPrevRel = prevId; secondNextRel = nextId; } short firstNodeMod = (short) ((firstNode & 0x700000000L) >> 31); long secondNodeMod = (secondNode & 0x700000000L) >> 4; long firstPrevRelMod = firstPrevRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (firstPrevRel & 0x700000000L) >> 7; long firstNextRelMod = firstNextRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (firstNextRel & 0x700000000L) >> 10; long secondPrevRelMod = secondPrevRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (secondPrevRel & 0x700000000L) >> 13; long secondNextRelMod = secondNextRel == Record.NO_NEXT_RELATIONSHIP.intValue() ? 0 : (secondNextRel & 0x700000000L) >> 16; long nextProp = relationship.firstPropertyId; long nextPropMod = nextProp == Record.NO_NEXT_PROPERTY.intValue() ? 0 : (nextProp & 0xF00000000L) >> 28; // [ , x] in use flag // [ ,xxx ] first node high order bits // [xxxx, ] next prop high order bits short inUseUnsignedByte = (short) (Record.IN_USE.byteValue() | firstNodeMod | nextPropMod); // [ xxx, ][ , ][ , ][ , ] second node high order bits, 0x70000000 // [ ,xxx ][ , ][ , ][ , ] first prev rel high order bits, 0xE000000 // [ , x][xx , ][ , ][ , ] first next rel high order bits, 0x1C00000 // [ , ][ xx,x ][ , ][ , ] second prev rel high order bits, 0x380000 // [ , ][ , xxx][ , ][ , ] second next rel high order bits, 0x70000 // [ , ][ , ][xxxx,xxxx][xxxx,xxxx] type int typeInt = (int) (relationship.type | secondNodeMod | firstPrevRelMod | firstNextRelMod | secondPrevRelMod | secondNextRelMod); buffer .put((byte) inUseUnsignedByte) .putInt((int) firstNode) .putInt((int) secondNode) .putInt(typeInt) .putInt((int) firstPrevRel) .putInt((int) firstNextRel) .putInt((int) secondPrevRel) .putInt((int) secondNextRel) .putInt((int) nextProp); flushBuffer(false); }