/**
* Copyright (c) 2002-2012 "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.ha;
import java.util.List;
import javax.transaction.Transaction;
import org.neo4j.com.Response;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.DeadlockDetectedException;
import org.neo4j.kernel.impl.core.GraphProperties;
import org.neo4j.kernel.impl.transaction.IllegalResourceException;
import org.neo4j.kernel.impl.transaction.LockManager;
import org.neo4j.kernel.impl.transaction.LockManagerImpl;
import org.neo4j.kernel.impl.transaction.LockNotFoundException;
import org.neo4j.kernel.impl.transaction.RagManager;
import org.neo4j.kernel.info.LockInfo;
public class SlaveLockManager implements LockManager
{
private final RequestContextFactory requestContextFactory;
private final LockManagerImpl local;
private final Master master;
private final TransactionSupport transactionSupport;
private final HaXaDataSourceManager xaDsm;
public SlaveLockManager( TransactionSupport transactionSupport,
RagManager ragManager, RequestContextFactory requestContextFactory, Master master,
HaXaDataSourceManager xaDsm )
{
this.requestContextFactory = requestContextFactory;
this.transactionSupport = transactionSupport;
this.xaDsm = xaDsm;
this.local = new LockManagerImpl( ragManager );
this.master = master;
}
@Override
public long getDetectedDeadlockCount()
{
return local.getDetectedDeadlockCount();
}
@Override
public void getReadLock( Object resource ) throws DeadlockDetectedException, IllegalResourceException
{
if ( getReadLockOnMaster( resource ) )
{
local.getReadLock( resource );
}
}
@Override
public void getReadLock( Object resource, Transaction tx ) throws DeadlockDetectedException, IllegalResourceException
{
if ( getReadLockOnMaster( resource ) )
{
local.getReadLock( resource, tx );
}
}
private boolean getReadLockOnMaster( Object resource )
{
Response<LockResult> response = null;
if ( resource instanceof Node )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireNodeReadLock( requestContextFactory.newRequestContext(), ((Node)resource).getId() );
}
else if ( resource instanceof Relationship )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireRelationshipReadLock( requestContextFactory.newRequestContext(), ((Relationship)resource).getId() );
}
else if ( resource instanceof GraphProperties )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireGraphReadLock( requestContextFactory.newRequestContext() );
}
else
{
return true;
}
return receiveLockResponse( response );
}
private boolean receiveLockResponse( Response<LockResult> response )
{
LockResult result = xaDsm.applyTransactions( response );
switch ( result.getStatus() )
{
case DEAD_LOCKED:
throw new DeadlockDetectedException( result.getDeadlockMessage() );
case NOT_LOCKED:
throw new UnsupportedOperationException();
case OK_LOCKED:
break;
default:
throw new UnsupportedOperationException( result.toString() );
}
return true;
}
@Override
public void getWriteLock( Object resource ) throws DeadlockDetectedException, IllegalResourceException
{
if ( getWriteLockOnMaster( resource ) )
{
local.getWriteLock( resource );
}
}
@Override
public void getWriteLock( Object resource, Transaction tx ) throws DeadlockDetectedException, IllegalResourceException
{
if ( getWriteLockOnMaster( resource ) )
{
local.getWriteLock( resource, tx );
}
}
private boolean getWriteLockOnMaster( Object resource )
{
Response<LockResult> response = null;
if ( resource instanceof Node )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireNodeWriteLock( requestContextFactory.newRequestContext(), ((Node)resource).getId() );
}
else if ( resource instanceof Relationship )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireRelationshipWriteLock( requestContextFactory.newRequestContext(), ((Relationship)resource).getId() );
}
else if ( resource instanceof GraphProperties )
{
transactionSupport.makeSureTxHasBeenInitialized();
response = master.acquireGraphWriteLock( requestContextFactory.newRequestContext() );
}
else
{
return true;
}
return receiveLockResponse( response );
}
@Override
public void releaseReadLock( Object resource, Transaction tx ) throws LockNotFoundException,
IllegalResourceException
{
local.releaseReadLock( resource, tx );
}
@Override
public void releaseWriteLock( Object resource, Transaction tx ) throws LockNotFoundException,
IllegalResourceException
{
local.releaseWriteLock( resource, tx );
}
@Override
public void dumpLocksOnResource( Object resource )
{
local.dumpLocksOnResource( resource );
}
@Override
public List<LockInfo> getAllLocks()
{
return local.getAllLocks();
}
@Override
public List<LockInfo> getAwaitedLocks( long minWaitTime )
{
return local.getAwaitedLocks( minWaitTime );
}
@Override
public void dumpRagStack()
{
local.dumpRagStack();
}
@Override
public void dumpAllLocks()
{
local.dumpAllLocks();
}
}