/**
* Copyright (c) 2002-2010 "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 );
}
};
}