boolean getMoreRelationships(NodeManager nodeManager) { // ArrayMap<String, IntArray> tmpRelMap = relationshipMap; Pair<ArrayMap<String, RelIdArray>, Map<Long, RelationshipImpl>> pair; synchronized (this) { if (!relChainPosition.hasMore()) { return false; } pair = nodeManager.getMoreRelationships(this); ArrayMap<String, RelIdArray> addMap = pair.first(); if (addMap.size() == 0) { return false; } for (String type : addMap.keySet()) { RelIdArray addRels = addMap.get(type); // IntArray srcRels = tmpRelMap.get( type ); RelIdArray srcRels = relationshipMap.get(type); if (srcRels == null) { relationshipMap.put(type, addRels); } else { srcRels.addAll(addRels); } } } nodeManager.putAllInRelCache(pair.other()); return true; }
List<RelTypeElementIterator> getAllRelationships(NodeManager nodeManager) { ensureRelationshipMapNotNull(nodeManager); List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>(); ArrayMap<String, IntArray> addMap = nodeManager.getCowRelationshipAddMap(this); for (String type : relationshipMap.keySet()) { IntArray src = relationshipMap.get(type); IntArray remove = nodeManager.getCowRelationshipRemoveMap(this, type); IntArray add = null; if (addMap != null) { add = addMap.get(type); } if (src != null || add != null) { relTypeList.add(RelTypeElement.create(type, this, src, add, remove)); } } if (addMap != null) { for (String type : addMap.keySet()) { if (relationshipMap.get(type) == null) { IntArray remove = nodeManager.getCowRelationshipRemoveMap(this, type); IntArray add = addMap.get(type); relTypeList.add(RelTypeElement.create(type, this, null, add, remove)); } } } return relTypeList; }
List<RelTypeElementIterator> getAllRelationships(NodeManager nodeManager) { ensureRelationshipMapNotNull(nodeManager); List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>(); boolean hasModifications = nodeManager.getLockReleaser().hasRelationshipModifications(this); ArrayMap<String, RelIdArray> addMap = null; if (hasModifications) { addMap = nodeManager.getCowRelationshipAddMap(this); } for (String type : relationshipMap.keySet()) { RelIdArray src = relationshipMap.get(type); RelIdArray remove = null; RelIdArray add = null; if (hasModifications) { remove = nodeManager.getCowRelationshipRemoveMap(this, type); if (addMap != null) { add = addMap.get(type); } } // if ( src != null || add != null ) // { relTypeList.add(RelTypeElement.create(type, this, src, add, remove)); // } } if (addMap != null) { for (String type : addMap.keySet()) { if (relationshipMap.get(type) == null) { RelIdArray remove = nodeManager.getCowRelationshipRemoveMap(this, type); RelIdArray add = addMap.get(type); relTypeList.add(RelTypeElement.create(type, this, null, add, remove)); } } } return relTypeList; }
@Before public void createTestingGraph() { Node node1 = getGraphDb().createNode(); Node node2 = getGraphDb().createNode(); Relationship rel = node1.createRelationshipTo(node2, MyRelTypes.TEST); node1Id = (int) node1.getId(); node2Id = (int) node2.getId(); node1.setProperty(key1, int1); node1.setProperty(key2, string1); node2.setProperty(key1, int2); node2.setProperty(key2, string2); rel.setProperty(key1, int1); rel.setProperty(key2, string1); node1.setProperty(arrayKey, array); node2.setProperty(arrayKey, array); rel.setProperty(arrayKey, array); Transaction tx = getTransaction(); tx.success(); tx.finish(); NodeManager nodeManager = ((EmbeddedGraphDatabase) getGraphDb()).getConfig().getGraphDbModule().getNodeManager(); nodeManager.clearCache(); tx = getGraphDb().beginTx(); setTransaction(tx); }
private void populateRelationshipPropertyEvents( PrimitiveElement element, TransactionDataImpl result) { for (long relId : element.relationships.keySet()) { CowRelElement relElement = element.relationships.get(relId); RelationshipProxy rel = nodeManager.newRelationshipProxyById(relId); RelationshipImpl relImpl = nodeManager.getRelationshipForProxy(relId); if (relElement.isDeleted()) { if (primitiveElement.createdRelationships.contains(relId)) { continue; } // note: this is done in node populate data // result.deleted( rel ); } if (relElement.propertyAddMap != null && !relElement.isDeleted()) { for (DefinedProperty data : relElement.propertyAddMap.values()) { String key = nodeManager.getKeyForProperty(data); Object oldValue = relImpl.getCommittedPropertyValue(nodeManager, key); Object newValue = data.value(); result.assignedProperty(rel, key, newValue, oldValue); } } if (relElement.propertyRemoveMap != null) { for (DefinedProperty data : relElement.propertyRemoveMap.values()) { String key = nodeManager.getKeyForProperty(data); Object oldValue = data.value(); if (oldValue != null && !relElement.isDeleted()) { relImpl.getCommittedPropertyValue(nodeManager, key); } result.removedProperty(rel, key, oldValue); } } } }
public void setReferenceNodeId(Long nodeId) { nodeManager.setReferenceNodeId(nodeId.longValue()); try { nodeManager.getReferenceNode(); } catch (NotFoundException e) { log.warning("Reference node[" + nodeId + "] not valid."); } }
private void loadInitialRelationships(NodeManager nodeManager) { Map<Long, RelationshipImpl> map = null; synchronized (this) { if (relationshipMap == null) { this.relChainPosition = nodeManager.getRelationshipChainPosition(this); ArrayMap<String, RelIdArray> tmpRelMap = new ArrayMap<String, RelIdArray>(); map = getMoreRelationships(nodeManager, tmpRelMap); this.relationshipMap = tmpRelMap; } } if (map != null) { nodeManager.putAllInRelCache(map); } }
List<RelTypeElementIterator> getAllRelationshipsOfType( NodeManager nodeManager, RelationshipType... types) { ensureRelationshipMapNotNull(nodeManager); List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>(); for (RelationshipType type : types) { IntArray src = relationshipMap.get(type.name()); IntArray remove = nodeManager.getCowRelationshipRemoveMap(this, type.name()); IntArray add = nodeManager.getCowRelationshipAddMap(this, type.name()); if (src != null || add != null) { relTypeList.add(RelTypeElement.create(type.name(), this, src, add, remove)); } } return relTypeList; }
private void releaseCows(int param) { if (primitiveElement == null) { return; } ArrayMap<Long, CowNodeElement> cowNodeElements = primitiveElement.nodes; Set<Entry<Long, CowNodeElement>> nodeEntrySet = cowNodeElements.entrySet(); for (Entry<Long, CowNodeElement> entry : nodeEntrySet) { NodeImpl node = nodeManager.getNodeIfCached(entry.getKey()); if (node != null) { CowNodeElement nodeElement = entry.getValue(); if (param == Status.STATUS_COMMITTED) { node.commitRelationshipMaps( nodeElement.relationshipAddMap, nodeElement.relationshipRemoveMap); node.commitPropertyMaps( nodeElement.propertyAddMap, nodeElement.propertyRemoveMap, nodeElement.firstProp); } else if (param != Status.STATUS_ROLLEDBACK) { throw new TransactionFailureException("Unknown transaction status: " + param); } int sizeAfter = node.sizeOfObjectInBytesIncludingOverhead(); nodeManager.updateCacheSize(node, sizeAfter); } } ArrayMap<Long, CowRelElement> cowRelElements = primitiveElement.relationships; Set<Entry<Long, CowRelElement>> relEntrySet = cowRelElements.entrySet(); for (Entry<Long, CowRelElement> entry : relEntrySet) { RelationshipImpl rel = nodeManager.getRelIfCached(entry.getKey()); if (rel != null) { CowRelElement relElement = entry.getValue(); if (param == Status.STATUS_COMMITTED) { rel.commitPropertyMaps( relElement.propertyAddMap, relElement.propertyRemoveMap, Record.NO_NEXT_PROPERTY.intValue()); } else if (param != Status.STATUS_ROLLEDBACK) { throw new TransactionFailureException("Unknown transaction status: " + param); } int sizeAfter = rel.sizeOfObjectInBytesIncludingOverhead(); nodeManager.updateCacheSize(rel, sizeAfter); } } if (primitiveElement.graph != null && param == Status.STATUS_COMMITTED) { nodeManager .getGraphProperties() .commitPropertyMaps( primitiveElement.graph.getPropertyAddMap(false), primitiveElement.graph.getPropertyRemoveMap(false), Record.NO_NEXT_PROPERTY.intValue()); } }
private void populateNodeRelEvent( PrimitiveElement element, TransactionDataImpl result, long nodeId, RelIdArray createdRels) { for (RelIdIterator iterator = createdRels.iterator(DirectionWrapper.BOTH); iterator.hasNext(); ) { long relId = iterator.next(); CowRelElement relElement = element.relationships.get(relId); if (relElement != null && relElement.isDeleted()) { continue; } RelationshipProxy rel = nodeManager.newRelationshipProxyById(relId); if (rel.getStartNode().getId() == nodeId) { result.created(nodeManager.newRelationshipProxyById(relId)); } } }
public Long getCurrentReferenceNodeId() { try { return nodeManager.getReferenceNode().getId(); } catch (NotFoundException e) { return -1L; } }
@Test public void testTxCacheLoadIsolation() throws Exception { Node node = getGraphDb().createNode(); node.setProperty("someproptest", "testing"); Node node1 = getGraphDb().createNode(); node1.setProperty("someotherproptest", 2); commit(); EmbeddedGraphDatabase graphDb = (EmbeddedGraphDatabase) getGraphDb(); TransactionManager txManager = graphDb.getConfig().getTxModule().getTxManager(); NodeManager nodeManager = graphDb.getConfig().getGraphDbModule().getNodeManager(); txManager.begin(); node.setProperty("someotherproptest", "testing2"); Relationship rel = node.createRelationshipTo(node1, MyRelTypes.TEST); javax.transaction.Transaction txA = txManager.suspend(); txManager.begin(); assertEquals("testing", node.getProperty("someproptest")); assertTrue(!node.hasProperty("someotherproptest")); assertTrue(!node.hasRelationship()); nodeManager.clearCache(); assertEquals("testing", node.getProperty("someproptest")); assertTrue(!node.hasProperty("someotherproptest")); javax.transaction.Transaction txB = txManager.suspend(); txManager.resume(txA); assertEquals("testing", node.getProperty("someproptest")); assertTrue(node.hasProperty("someotherproptest")); assertTrue(node.hasRelationship()); nodeManager.clearCache(); assertEquals("testing", node.getProperty("someproptest")); assertTrue(node.hasProperty("someotherproptest")); assertTrue(node.hasRelationship()); txManager.suspend(); txManager.resume(txB); assertEquals("testing", node.getProperty("someproptest")); assertTrue(!node.hasProperty("someotherproptest")); assertTrue(!node.hasRelationship()); txManager.rollback(); txManager.resume(txA); node.delete(); node1.delete(); rel.delete(); txManager.commit(); newTransaction(); }
@Override public StatementOperationParts newStatementOperations() { // Store stuff StatementOperationParts parts = delegate.newStatementOperations(); // + Caching CachingStatementOperations cachingContext = new CachingStatementOperations( parts.entityReadOperations(), parts.schemaReadOperations(), persistenceCache, schemaCache); parts = parts.override(null, null, cachingContext, null, cachingContext, null, null); // + Transaction-local state awareness AuxiliaryStoreOperations auxStoreOperations = parts.resolve(AuxiliaryStoreOperations.class); auxStoreOperations = new LegacyAutoIndexAuxStoreOps( auxStoreOperations, propertyKeyTokenHolder, nodeManager.getNodePropertyTrackers(), nodeManager.getRelationshipPropertyTrackers(), nodeManager); StateHandlingStatementOperations stateHandlingContext = new StateHandlingStatementOperations( parts.entityReadOperations(), parts.schemaReadOperations(), auxStoreOperations, constraintIndexCreator); parts = parts.override( null, null, stateHandlingContext, stateHandlingContext, stateHandlingContext, stateHandlingContext, new SchemaStateConcern(schemaState)); // done return parts; }
public void delete(NodeManager nodeManager) { nodeManager.acquireLock(this, LockType.WRITE); boolean success = false; try { ArrayMap<Integer, PropertyData> skipMap = nodeManager.getCowPropertyRemoveMap(this, true); ArrayMap<Integer, PropertyData> removedProps = nodeManager.deleteNode(this); if (removedProps.size() > 0) { for (int index : removedProps.keySet()) { skipMap.put(index, removedProps.get(index)); } } success = true; } finally { nodeManager.releaseLock(this, LockType.WRITE); if (!success) { nodeManager.setRollbackOnly(); } } }
@Override public void patchDeletedRelationshipNodes( long relId, long firstNodeId, long firstNodeNextRelId, long secondNodeId, long secondNodeNextRelId) { nodeManager.patchDeletedRelationshipNodes( relId, firstNodeId, firstNodeNextRelId, secondNodeId, secondNodeNextRelId); }
List<RelTypeElementIterator> getAllRelationshipsOfType( NodeManager nodeManager, RelationshipType... types) { ensureRelationshipMapNotNull(nodeManager); List<RelTypeElementIterator> relTypeList = new LinkedList<RelTypeElementIterator>(); boolean hasModifications = nodeManager.getLockReleaser().hasRelationshipModifications(this); for (RelationshipType type : types) { RelIdArray src = relationshipMap.get(type.name()); RelIdArray remove = null; RelIdArray add = null; if (hasModifications) { remove = nodeManager.getCowRelationshipRemoveMap(this, type.name()); add = nodeManager.getCowRelationshipAddMap(this, type.name()); } // if ( src != null || add != null ) // { relTypeList.add(RelTypeElement.create(type.name(), this, src, add, remove)); // } } return relTypeList; }
private void populateCreatedNodes(PrimitiveElement element, TransactionDataImpl result) { for (Long nodeId : getCreatedNodes()) { if (element != null) { CowNodeElement nodeElement = element.nodes.get(nodeId); if (nodeElement != null && nodeElement.isDeleted()) { continue; } } result.created(nodeManager.newNodeProxyById(nodeId)); } }
@Test public void testSameTxWithArray() { getTransaction().success(); getTransaction().finish(); newTransaction(); Node nodeA = getGraphDb().createNode(); Node nodeB = getGraphDb().createNode(); Relationship relA = nodeA.createRelationshipTo(nodeB, MyRelTypes.TEST); nodeA.setProperty(arrayKey, array); relA.setProperty(arrayKey, array); NodeManager nodeManager = ((EmbeddedGraphDatabase) getGraphDb()).getConfig().getGraphDbModule().getNodeManager(); nodeManager.clearCache(); assertTrue(nodeA.getProperty(arrayKey) != null); assertTrue(relA.getProperty(arrayKey) != null); relA.delete(); nodeA.delete(); nodeB.delete(); }
@Test public void testAddCacheCleared() { Node nodeA = getGraphDb().createNode(); nodeA.setProperty("1", 1); Node nodeB = getGraphDb().createNode(); Relationship rel = nodeA.createRelationshipTo(nodeB, MyRelTypes.TEST); rel.setProperty("1", 1); getTransaction().success(); getTransaction().finish(); newTransaction(); NodeManager nodeManager = ((EmbeddedGraphDatabase) getGraphDb()).getConfig().getGraphDbModule().getNodeManager(); nodeManager.clearCache(); nodeA.createRelationshipTo(nodeB, MyRelTypes.TEST); int count = 0; for (Relationship relToB : nodeA.getRelationships(MyRelTypes.TEST)) { count++; } assertEquals(2, count); nodeA.setProperty("2", 2); assertEquals(1, nodeA.getProperty("1")); rel.setProperty("2", 2); assertEquals(1, rel.getProperty("1")); nodeManager.clearCache(); // trigger empty load getGraphDb().getNodeById(nodeA.getId()); getGraphDb().getRelationshipById(rel.getId()); // apply COW maps getTransaction().success(); getTransaction().finish(); newTransaction(); count = 0; for (Relationship relToB : nodeA.getRelationships(MyRelTypes.TEST)) { count++; } assertEquals(2, count); assertEquals(1, nodeA.getProperty("1")); assertEquals(1, rel.getProperty("1")); assertEquals(2, nodeA.getProperty("2")); assertEquals(2, rel.getProperty("2")); }
@Test public void arrayIndexOutOfBoundsInRelTypeArrayWhenCreatingRelationshipsConcurrently() throws Exception { // GIVEN // -- a node manager capable of serving light-weight RelationshipProxy capable of answering // getId() NodeManager nodeManager = mock(NodeManager.class); when(nodeManager.newRelationshipProxyById(anyLong())).thenAnswer(relationshipProxyWithId()); // -- a node that says it cannot load any more relationships NodeImpl node = mock(NodeImpl.class); when(node.getMoreRelationships(nodeManager)).thenReturn(LoadStatus.NOTHING); // -- a type iterator that at this point contains one relationship (0) ControlledRelIdIterator typeIterator = new ControlledRelIdIterator(0L); RelationshipIterator iterator = new RelationshipIterator( new RelIdIterator[] {typeIterator}, node, OUTGOING, nodeManager, false, false); // -- go forth one step in the iterator iterator.next(); // WHEN // -- one relationship has been returned, and we're in the middle of the next call to next() // typeIterator will get one more relationship in it. To mimic this we control the outcome of // RelIdIterator#hasNext() so that we get to the correct branch in the RelationshipIterator // code typeIterator.queueHasNextAnswers(false, false, true); long otherRelationship = 1, thirdRelationship = 2; typeIterator.add(otherRelationship, thirdRelationship); // -- go one more step, getting us into the state where the type index in RelationshipIterator // was incremented by mistake. Although this particular call to next() succeeds iterator.next(); // -- call next() again, where the first thing happening is to get the RelIdIterator with the // now invalid type index, causing ArrayIndexOutOfBoundsException Relationship returnedThirdRelationship = iterator.next(); // THEN assertEquals(thirdRelationship, returnedThirdRelationship.getId()); }
private void populateNodeRelEvent(PrimitiveElement element, TransactionDataImpl result) { for (long nodeId : element.nodes.keySet()) { CowNodeElement nodeElement = element.nodes.get(nodeId); NodeProxy node = nodeManager.newNodeProxyById(nodeId); NodeImpl nodeImpl = nodeManager.getNodeForProxy(nodeId, null); if (nodeElement.isDeleted()) { if (primitiveElement.createdNodes.contains(nodeId)) { continue; } result.deleted(node); } if (nodeElement.relationshipAddMap != null && !nodeElement.isDeleted()) { for (Integer type : nodeElement.relationshipAddMap.keySet()) { RelIdArray createdRels = nodeElement.relationshipAddMap.get(type); populateNodeRelEvent(element, result, nodeId, createdRels); } } if (nodeElement.relationshipRemoveMap != null) { for (Integer type : nodeElement.relationshipRemoveMap.keySet()) { Collection<Long> deletedRels = nodeElement.relationshipRemoveMap.get(type); for (long relId : deletedRels) { if (primitiveElement.createdRelationships.contains(relId)) { continue; } RelationshipProxy rel = nodeManager.newRelationshipProxyById(relId); if (rel.getStartNode().getId() == nodeId) { result.deleted(nodeManager.newRelationshipProxyById(relId)); } } } } if (nodeElement.propertyAddMap != null && !nodeElement.isDeleted()) { for (DefinedProperty data : nodeElement.propertyAddMap.values()) { String key = nodeManager.getKeyForProperty(data); Object oldValue = nodeImpl.getCommittedPropertyValue(nodeManager, key); Object newValue = data.value(); result.assignedProperty(node, key, newValue, oldValue); } } if (nodeElement.propertyRemoveMap != null) { for (DefinedProperty data : nodeElement.propertyRemoveMap.values()) { String key = nodeManager.getKeyForProperty(data); Object oldValue = data.value(); if (oldValue == null && !nodeElement.isDeleted()) { nodeImpl.getCommittedPropertyValue(nodeManager, key); } result.removedProperty(node, key, oldValue); } } } }
private Map<Long, RelationshipImpl> getMoreRelationships( NodeManager nodeManager, ArrayMap<String, RelIdArray> tmpRelMap) { if (!relChainPosition.hasMore()) { return null; } Pair<ArrayMap<String, RelIdArray>, Map<Long, RelationshipImpl>> pair = nodeManager.getMoreRelationships(this); ArrayMap<String, RelIdArray> addMap = pair.first(); if (addMap.size() == 0) { return null; } for (String type : addMap.keySet()) { RelIdArray addRels = addMap.get(type); RelIdArray srcRels = tmpRelMap.get(type); if (srcRels == null) { tmpRelMap.put(type, addRels); } else { srcRels.addAll(addRels); } } return pair.other(); // nodeManager.putAllInRelCache( pair.other() ); }
public Iterable<RelationshipType> getRelationshipTypes() { return nodeManager.getRelationshipTypes(); }
@Override protected ArrayMap<Integer, PropertyData> loadProperties(NodeManager nodeManager, boolean light) { return nodeManager.loadProperties(this, light); }
@Override protected void removeProperty(NodeManager nodeManager, long propertyId) { nodeManager.nodeRemoveProperty(this, propertyId); }
@Override protected long addProperty(NodeManager nodeManager, PropertyIndex index, Object value) { return nodeManager.nodeAddProperty(this, index, value); }
@Override protected void changeProperty(NodeManager nodeManager, long propertyId, Object value) { nodeManager.nodeChangeProperty(this, propertyId, value); }
public Relationship createRelationshipTo( NodeManager nodeManager, Node otherNode, RelationshipType type) { return nodeManager.createRelationship(this, otherNode, type); }
// caller is responsible for acquiring lock // this method is only called when a undo create relationship or // a relationship delete is invoked. void removeRelationship(NodeManager nodeManager, RelationshipType type, long relId) { RelIdArray relationshipSet = nodeManager.getCowRelationshipRemoveMap(this, type.name(), true); relationshipSet.add(relId); }
public void start( LockReleaser lockReleaser, PersistenceManager persistenceManager, RelationshipTypeCreator relTypeCreator, Map<Object, Object> params) { if (!startIsOk) { return; } String cacheTypeName = (String) params.get(Config.CACHE_TYPE); CacheType cacheType = null; try { cacheType = cacheTypeName != null ? CacheType.valueOf(cacheTypeName) : DEFAULT_CACHE_TYPE; } catch (IllegalArgumentException e) { throw new IllegalArgumentException( "Invalid cache type, please use one of: " + Arrays.asList(CacheType.values()) + " or keep empty for default (" + DEFAULT_CACHE_TYPE + ")", e.getCause()); } if (!readOnly) { nodeManager = new NodeManager( graphDbService, cacheManager, lockManager, lockReleaser, transactionManager, persistenceManager, idGenerator, relTypeCreator, cacheType); } else { nodeManager = new ReadOnlyNodeManager( graphDbService, cacheManager, lockManager, lockReleaser, transactionManager, persistenceManager, idGenerator, cacheType); } // load and verify from PS RelationshipTypeData relTypes[] = null; PropertyIndexData propertyIndexes[] = null; // beginTx(); relTypes = persistenceManager.loadAllRelationshipTypes(); propertyIndexes = persistenceManager.loadPropertyIndexes(INDEX_COUNT); // commitTx(); nodeManager.addRawRelationshipTypes(relTypes); nodeManager.addPropertyIndexes(propertyIndexes); if (propertyIndexes.length < INDEX_COUNT) { nodeManager.setHasAllpropertyIndexes(true); } nodeManager.start(params); startIsOk = false; }