Skip to content

Commit

Permalink
prototype write only mode
Browse files Browse the repository at this point in the history
  • Loading branch information
pgpv authored and henriknyman committed Feb 26, 2016
1 parent dcf58f0 commit 61d4f07
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 21 deletions.
Expand Up @@ -66,7 +66,29 @@ public boolean allowsSchemaWrites()
}
},

/** Allows reading data and schema, but not writing. */
/** Allows writing data */
WRITE_ONLY
{
@Override
public boolean allowsReads()
{
return false;
}

@Override
public boolean allowsWrites()
{
return true;
}

@Override
public boolean allowsSchemaWrites()
{
return false;
}
},

/** Allows reading and writing data, but not schema. */
WRITE
{
@Override
Expand Down
Expand Up @@ -58,6 +58,7 @@ public KernelStatement( KernelTransactionImplementation transaction,
@Override
public ReadOperations readOperations()
{
transaction.verifyReadTransaction();
return facade;
}

Expand All @@ -71,15 +72,15 @@ public TokenWriteOperations tokenWriteOperations()
public DataWriteOperations dataWriteOperations()
throws InvalidTransactionTypeKernelException
{
transaction.upgradeToDataTransaction();
transaction.verifyDataWriteTransaction();
return facade;
}

@Override
public SchemaWriteOperations schemaWriteOperations()
throws InvalidTransactionTypeKernelException
{
transaction.upgradeToSchemaTransaction();
transaction.verifySchemaWriteTransaction();
return facade;
}

Expand Down
Expand Up @@ -74,34 +74,52 @@ public class KernelTransactionImplementation implements KernelTransaction, TxSta

private enum TransactionType
{
READ,
DATA
NONE,
READ_ONLY,
READ_AND_DATA_WRITE
{
@Override
TransactionType upgradeToSchemaTransaction() throws InvalidTransactionTypeKernelException
TransactionType enableSchemaWriteTransaction() throws InvalidTransactionTypeKernelException
{
throw new InvalidTransactionTypeKernelException(
"Cannot perform schema updates in a transaction that has performed data updates." );
}

@Override
TransactionType enableReadTransaction()
{
return READ_AND_DATA_WRITE;
}
},
SCHEMA
READ_AND_SCHEMA_WRITE
{
@Override
TransactionType upgradeToDataTransaction() throws InvalidTransactionTypeKernelException
TransactionType enableDataWriteTransaction() throws InvalidTransactionTypeKernelException
{
throw new InvalidTransactionTypeKernelException(
"Cannot perform data updates in a transaction that has performed schema updates." );
}

@Override
TransactionType enableReadTransaction()
{
return READ_AND_SCHEMA_WRITE;
}
};

TransactionType upgradeToDataTransaction() throws InvalidTransactionTypeKernelException
TransactionType enableReadTransaction() throws IllegalStateException
{
return DATA;
return READ_ONLY;
}

TransactionType upgradeToSchemaTransaction() throws InvalidTransactionTypeKernelException
TransactionType enableDataWriteTransaction() throws InvalidTransactionTypeKernelException
{
return SCHEMA;
return READ_AND_DATA_WRITE;
}

TransactionType enableSchemaWriteTransaction() throws InvalidTransactionTypeKernelException
{
return READ_AND_SCHEMA_WRITE;
}
}

Expand All @@ -127,11 +145,11 @@ TransactionType upgradeToSchemaTransaction() throws InvalidTransactionTypeKernel
// whereas others, such as timestamp or txId when transaction starts, even locks, needs to be set in #initialize().
private TransactionState txState;
private LegacyIndexTransactionState legacyIndexTransactionState;
private TransactionType transactionType; // Tracks current state of transaction, which will upgrade to WRITE or SCHEMA mode when necessary
private TransactionType transactionType; // Tracks current state of transaction, which will upgrade to WRITE or READ_AND_SCHEMA_WRITE mode when necessary
private TransactionHooks.TransactionHooksState hooksState;
private KernelStatement currentStatement;
private CloseListener closeListener;
private AccessMode accessMode; // Defines whether a transaction is allowed to upgrade to WRITE or SCHEMA mode
private AccessMode accessMode; // Defines whether a transaction is allowed to upgrade to WRITE or READ_AND_SCHEMA_WRITE mode
private Locks.Client locks;
private boolean beforeHookInvoked;
private boolean closing, closed;
Expand Down Expand Up @@ -180,7 +198,7 @@ public KernelTransactionImplementation initialize(
this.type = type;
this.locks = locks;
this.closing = closed = failure = success = terminated = beforeHookInvoked = false;
this.transactionType = TransactionType.READ;
this.transactionType = TransactionType.NONE;
this.startTimeMillis = clock.currentTimeMillis();
this.lastTransactionIdWhenStarted = lastCommittedTx;
this.transactionEvent = tracer.beginTransaction();
Expand Down Expand Up @@ -252,25 +270,36 @@ public void releaseStatement( Statement statement )
currentStatement = null;
}

public void upgradeToDataTransaction() throws InvalidTransactionTypeKernelException
public void verifyReadTransaction()
{
if( !accessMode.allowsReads() )
{
throw new IllegalStateException(
String.format( "Read operations are not allowed for `%s` transactions.", accessMode.name() ) );
}

transactionType.enableReadTransaction();
}

public void verifyDataWriteTransaction() throws InvalidTransactionTypeKernelException
{
if( !accessMode.allowsWrites() )
{
throw new InvalidTransactionTypeKernelException(
String.format( "Write operations are not allowed for `%s` transactions.", accessMode.name() ) );
}
transactionType = transactionType.upgradeToDataTransaction();
transactionType = transactionType.enableDataWriteTransaction();
}

public void upgradeToSchemaTransaction() throws InvalidTransactionTypeKernelException
public void verifySchemaWriteTransaction() throws InvalidTransactionTypeKernelException
{
if( !accessMode.allowsSchemaWrites() )
{
throw new InvalidTransactionTypeKernelException(
String.format( "Schema write operations are not allowed for `%s` transactions.", accessMode.name() ) );
}
doUpgradeToSchemaTransaction();
transactionType = transactionType.upgradeToSchemaTransaction();
transactionType = transactionType.enableSchemaWriteTransaction();
}

public void doUpgradeToSchemaTransaction() throws InvalidTransactionTypeKernelException
Expand Down
Expand Up @@ -26,6 +26,7 @@
import org.neo4j.kernel.api.AccessMode;
import org.neo4j.kernel.api.DataWriteOperations;
import org.neo4j.kernel.api.KernelTransactionTestBase;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.SchemaWriteOperations;
import org.neo4j.kernel.api.exceptions.KernelException;

Expand All @@ -35,6 +36,19 @@ public class KernelTransactionAccessModeTest extends KernelTransactionTestBase
{
@Rule public ExpectedException exception = ExpectedException.none();

@Test
public void shouldAllowReadsInReadMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.READ );

// When
ReadOperations reads = tx.acquireStatement().readOperations();

// Then
assertNotNull( reads );
}

@Test
public void shouldNotAllowWriteAccessInReadMode() throws Throwable
{
Expand Down Expand Up @@ -62,10 +76,36 @@ public void shouldNotAllowSchemaWriteAccessInReadMode() throws Throwable
}

@Test
public void shouldNotAllowSchemaWriteAccessInWriteMode() throws Throwable
public void shouldNotAllowReadAccessInWriteOnlyMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE );
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE_ONLY );

// Expect
exception.expect( IllegalStateException.class );

// When
tx.acquireStatement().readOperations();
}

@Test
public void shouldAllowWriteAccessInWriteOnlyMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE_ONLY );

// When
DataWriteOperations writes = tx.acquireStatement().dataWriteOperations();

// Then
assertNotNull( writes );
}

@Test
public void shouldNotAllowSchemaWriteAccessInWriteOnlyMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE_ONLY );

// Expect
exception.expect( KernelException.class );
Expand All @@ -74,6 +114,19 @@ public void shouldNotAllowSchemaWriteAccessInWriteMode() throws Throwable
tx.acquireStatement().schemaWriteOperations();
}

@Test
public void shouldAllowReadsInWriteMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE );

// When
ReadOperations reads = tx.acquireStatement().readOperations();

// Then
assertNotNull( reads );
}

@Test
public void shouldAllowWritesInWriteMode() throws Throwable
{
Expand All @@ -87,6 +140,32 @@ public void shouldAllowWritesInWriteMode() throws Throwable
assertNotNull( writes );
}

@Test
public void shouldNotAllowSchemaWriteAccessInWriteMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.WRITE );

// Expect
exception.expect( KernelException.class );

// When
tx.acquireStatement().schemaWriteOperations();
}

@Test
public void shouldAllowReadsInFullMode() throws Throwable
{
// Given
KernelTransactionImplementation tx = newTransaction( AccessMode.FULL );

// When
ReadOperations reads = tx.acquireStatement().readOperations();

// Then
assertNotNull( reads );
}

@Test
public void shouldAllowWritesInFullMode() throws Throwable
{
Expand Down

0 comments on commit 61d4f07

Please sign in to comment.