/* * Copyright (c) 2002-2009 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.kernel.impl.nioneo.xa; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import org.neo4j.graphdb.TransactionFailureException; import org.neo4j.kernel.impl.core.PropertyIndex; import org.neo4j.kernel.impl.nioneo.store.NeoStore; import org.neo4j.kernel.impl.nioneo.store.NodeStore; import org.neo4j.kernel.impl.nioneo.store.PropertyData; import org.neo4j.kernel.impl.nioneo.store.PropertyIndexData; import org.neo4j.kernel.impl.nioneo.store.PropertyStore; import org.neo4j.kernel.impl.nioneo.store.RelationshipChainPosition; import org.neo4j.kernel.impl.nioneo.store.RelationshipData; import org.neo4j.kernel.impl.nioneo.store.RelationshipStore; import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeData; import org.neo4j.kernel.impl.nioneo.store.RelationshipTypeStore; import org.neo4j.kernel.impl.transaction.xaframework.XaConnectionHelpImpl; import org.neo4j.kernel.impl.transaction.xaframework.XaResourceHelpImpl; import org.neo4j.kernel.impl.transaction.xaframework.XaResourceManager; import org.neo4j.kernel.impl.util.ArrayMap; import org.neo4j.kernel.impl.util.IntArray; /** * {@link XaConnection} implementation for the Neo4j kernel native store. Contains * getter methods for the different stores (node,relationship,property and * relationship type). * <p> * A <CODE>NeoStoreXaConnection</CODE> is obtained from * {@link NeoStoreXaDataSource} and then Neo4j persistence layer can perform the * operations requested via the store implementations. */ public class NeoStoreXaConnection extends XaConnectionHelpImpl { private final NeoStoreXaResource xaResource; private final NeoStore neoStore; private final NodeEventConsumer nodeConsumer; private final RelationshipEventConsumer relConsumer; private final RelationshipTypeEventConsumer relTypeConsumer; private final PropertyIndexEventConsumer propIndexConsumer; private WriteTransaction neoTransaction = null; NeoStoreXaConnection( NeoStore neoStore, XaResourceManager xaRm, byte branchId[] ) { super( xaRm ); this.neoStore = neoStore; this.nodeConsumer = new NodeEventConsumerImpl( this ); this.relConsumer = new RelationshipEventConsumerImpl( this ); this.relTypeConsumer = new RelationshipTypeEventConsumerImpl( this ); this.propIndexConsumer = new PropertyIndexEventConsumerImpl( this ); this.xaResource = new NeoStoreXaResource( neoStore.getStorageFileName(), xaRm, branchId ); } /** * Returns this the {@link NodeStore}. * * @return The node store */ public NodeEventConsumer getNodeConsumer() { return nodeConsumer; } /** * Returns this the {@link RelationshipStore}. * * @return The relationship store */ public RelationshipEventConsumer getRelationshipConsumer() { return relConsumer; } public PropertyIndexEventConsumer getPropertyIndexConsumer() { return propIndexConsumer; } /** * Returns this the {@link RelationshipTypeStore}. * * @return The relationship type store */ public RelationshipTypeEventConsumer getRelationshipTypeConsumer() { return relTypeConsumer; } /** * Made public for testing, dont use. */ public PropertyStore getPropertyStore() { return neoStore.getPropertyStore(); } NodeStore getNodeStore() { return neoStore.getNodeStore(); } RelationshipStore getRelationshipStore() { return neoStore.getRelationshipStore(); } RelationshipTypeStore getRelationshipTypeStore() { return neoStore.getRelationshipTypeStore(); } public XAResource getXaResource() { return this.xaResource; } WriteTransaction getWriteTransaction() { if ( neoTransaction != null ) { return neoTransaction; } try { neoTransaction = (WriteTransaction) getTransaction(); return neoTransaction; } catch ( XAException e ) { throw new TransactionFailureException( "Unable to get transaction.", e ); } } private static class NeoStoreXaResource extends XaResourceHelpImpl { private final Object identifier; NeoStoreXaResource( Object identifier, XaResourceManager xaRm, byte branchId[] ) { super( xaRm, branchId ); this.identifier = identifier; } public boolean isSameRM( XAResource xares ) { if ( xares instanceof NeoStoreXaResource ) { return identifier .equals( ((NeoStoreXaResource) xares).identifier ); } return false; } }; private static class NodeEventConsumerImpl implements NodeEventConsumer { private final NeoStoreXaConnection xaCon; public NodeEventConsumerImpl( NeoStoreXaConnection xaCon ) { this.xaCon = xaCon; } public void createNode( int nodeId ) { xaCon.getWriteTransaction().nodeCreate( nodeId ); } public ArrayMap<Integer,PropertyData> deleteNode( int nodeId ) { return xaCon.getWriteTransaction().nodeDelete( nodeId ); } // checks for created in tx else get from store public boolean loadLightNode( int nodeId ) { return xaCon.getWriteTransaction().nodeLoadLight( nodeId ); } public void addProperty( int nodeId, int propertyId, PropertyIndex index, Object value ) { xaCon.getWriteTransaction().nodeAddProperty( nodeId, propertyId, index, value ); } public void changeProperty( int nodeId, int propertyId, Object value ) { xaCon.getWriteTransaction().nodeChangeProperty( nodeId, propertyId, value ); } public void removeProperty( int nodeId, int propertyId ) { xaCon.getWriteTransaction().nodeRemoveProperty( nodeId, propertyId ); } public ArrayMap<Integer,PropertyData> getProperties( int nodeId, boolean light ) { return xaCon.getWriteTransaction().nodeGetProperties( nodeId, light ); } public IntArray getCreatedNodes() { return xaCon.getWriteTransaction().getCreatedNodes(); } public boolean isNodeCreated( int nodeId ) { return xaCon.getWriteTransaction().nodeCreated( nodeId ); } }; private static class RelationshipEventConsumerImpl implements RelationshipEventConsumer { private final NeoStoreXaConnection xaCon; public RelationshipEventConsumerImpl( NeoStoreXaConnection xaCon ) { this.xaCon = xaCon; } public void createRelationship( int id, int firstNode, int secondNode, int type ) { xaCon.getWriteTransaction().relationshipCreate( id, firstNode, secondNode, type ); } public ArrayMap<Integer,PropertyData> deleteRelationship( int id ) { return xaCon.getWriteTransaction().relDelete( id ); } public void addProperty( int relId, int propertyId, PropertyIndex index, Object value ) { xaCon.getWriteTransaction().relAddProperty( relId, propertyId, index, value ); } public void changeProperty( int relId, int propertyId, Object value ) { xaCon.getWriteTransaction().relChangeProperty( relId, propertyId, value ); } public void removeProperty( int relId, int propertyId ) { xaCon.getWriteTransaction().relRemoveProperty( relId, propertyId ); } public ArrayMap<Integer,PropertyData> getProperties( int relId, boolean light ) { return xaCon.getWriteTransaction().relGetProperties( relId, light ); } public RelationshipData getRelationship( int id ) { return xaCon.getWriteTransaction().relationshipLoad( id ); } public RelationshipChainPosition getRelationshipChainPosition( int nodeId ) { return xaCon.getWriteTransaction().getRelationshipChainPosition( nodeId ); } public Iterable<RelationshipData> getMoreRelationships( int nodeId, RelationshipChainPosition position ) { return xaCon.getWriteTransaction().getMoreRelationships( nodeId, position ); } public boolean isRelationshipCreated( int relId ) { // TODO Auto-generated method stub return xaCon.getWriteTransaction().relCreated( relId ); } }; private static class RelationshipTypeEventConsumerImpl implements RelationshipTypeEventConsumer { private final NeoStoreXaConnection xaCon; private final RelationshipTypeStore relTypeStore; RelationshipTypeEventConsumerImpl( NeoStoreXaConnection xaCon ) { this.xaCon = xaCon; this.relTypeStore = xaCon.getRelationshipTypeStore(); } public void addRelationshipType( int id, String name ) { xaCon.getWriteTransaction().relationshipTypeAdd( id, name ); } public RelationshipTypeData getRelationshipType( int id ) { return relTypeStore.getRelationshipType( id ); } public RelationshipTypeData[] getRelationshipTypes() { return relTypeStore.getRelationshipTypes(); } }; private static class PropertyIndexEventConsumerImpl implements PropertyIndexEventConsumer { private final NeoStoreXaConnection xaCon; PropertyIndexEventConsumerImpl( NeoStoreXaConnection xaCon ) { this.xaCon = xaCon; } public void createPropertyIndex( int id, String key ) { xaCon.getWriteTransaction().createPropertyIndex( id, key ); } public String getKeyFor( int id ) { return xaCon.getWriteTransaction().getPropertyIndex( id ); } public PropertyIndexData[] getPropertyIndexes( int count ) { return xaCon.getWriteTransaction().getPropertyIndexes( count ); } }; }