com.thinkaurelius.titan.diskstorage.locking.consistentkey

## Class ExpectedValueCheckingStore

- java.lang.Object
- - com.thinkaurelius.titan.diskstorage.keycolumnvalue.KCVSProxy
  - - com.thinkaurelius.titan.diskstorage.locking.consistentkey.ExpectedValueCheckingStore

- All Implemented Interfaces:
    KeyColumnValueStore

      public class ExpectedValueCheckingStore
      extends KCVSProxy

  A `KeyColumnValueStore` wrapper intended for nontransactional stores that forwards all but these two methods to an encapsulated store instance:

  - `acquireLock(StaticBuffer, StaticBuffer, StaticBuffer, StoreTransaction)`
  - `mutate(StaticBuffer, List, List, StoreTransaction)`

  This wrapper adds some logic to both of the overridden methods before calling the encapsulated store's version.

  This class, along with its collaborator class `ExpectedValueCheckingTransaction`, track all `expectedValue` arguments passed to `acquireLock` for each `StoreTransaction`. When the transaction first `mutate(...)`s, the these classes cooperate to check that all previously provided expected values match actual values, throwing an exception and preventing mutation if a mismatch is detected.

  This relies on a `Locker` instance supplied during construction for locking.

- - ### Field Summary

    - ### Fields inherited from class com.thinkaurelius.titan.diskstorage.keycolumnvalue.KCVSProxy

      `store`

    - ### Fields inherited from interface com.thinkaurelius.titan.diskstorage.keycolumnvalue.KeyColumnValueStore

      `NO_ADDITIONS, NO_DELETIONS`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `ExpectedValueCheckingStore(KeyColumnValueStore store, Locker locker)`

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `acquireLock(StaticBuffer key, StaticBuffer column, StaticBuffer expectedValue, StoreTransaction txh)` Attempts to claim a lock on the value at the specified `key` and `column` pair.
    `void` | `mutate(StaticBuffer key, List<Entry> additions, List<StaticBuffer> deletions, StoreTransaction txh)` Verifies acquisition of locks `txh` from previous calls to `KeyColumnValueStore.acquireLock(StaticBuffer, StaticBuffer, StaticBuffer, StoreTransaction)` , then writes supplied `additions` and/or `deletions` to `key` in the underlying data store.
    `protected StoreTransaction` | `unwrapTx(StoreTransaction t)`

    - ### Methods inherited from class com.thinkaurelius.titan.diskstorage.keycolumnvalue.KCVSProxy

      `close, getKeys, getKeys, getName, getSlice, getSlice`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### ExpectedValueCheckingStore

          public ExpectedValueCheckingStore(KeyColumnValueStore store,
                                    Locker locker)

  - ### Method Detail

    - #### mutate

          public void mutate(StaticBuffer key,
                    List<Entry> additions,
                    List<StaticBuffer> deletions,
                    StoreTransaction txh)
                      throws BackendException

      Verifies acquisition of locks `txh` from previous calls to `KeyColumnValueStore.acquireLock(StaticBuffer, StaticBuffer, StaticBuffer, StoreTransaction)` , then writes supplied `additions` and/or `deletions` to `key` in the underlying data store. Deletions are applied strictly before additions. In other words, if both an addition and deletion are supplied for the same column, then the column will first be deleted and then the supplied Entry for the column will be added.

      Implementations which don't support locking should skip the initial lock verification step but otherwise behave as described above.

      This implementation supports locking when `lockStore` is non-null.
      Specified by:
        `mutate` in interface `KeyColumnValueStore`
      Overrides:
        `mutate` in class `KCVSProxy`
      Parameters:
        `key` - the key under which the columns in `additions` and `deletions` will be written
        `additions` - the list of Entry instances representing column-value pairs to create under `key`, or null to add no column-value pairs
        `deletions` - the list of columns to delete from `key`, or null to delete no columns
        `txh` - the transaction to use
      Throws:
        `PermanentLockingException` - if locking is supported by the implementation and at least one lock acquisition attempted by `KeyColumnValueStore.acquireLock(StaticBuffer, StaticBuffer, StaticBuffer, StoreTransaction)` has failed
        `BackendException`

    - #### acquireLock

          public void acquireLock(StaticBuffer key,
                         StaticBuffer column,
                         StaticBuffer expectedValue,
                         StoreTransaction txh)
                           throws BackendException

      Attempts to claim a lock on the value at the specified `key` and `column` pair. These locks are discretionary.

      If locking fails, implementations of this method may, but are not required to, throw `PermanentLockingException`. This method is not required to determine whether locking actually succeeded and may return without throwing an exception even when the lock can't be acquired. Lock acquisition is only only guaranteed to be verified by the first call to `KeyColumnValueStore.mutate(StaticBuffer, List, List, StoreTransaction)` on any given `txh`.

      The `expectedValue` must match the actual value present at the `key` and `column` pair. If the true value does not match the `expectedValue`, the lock attempt fails and `LockingException` is thrown. This method may check `expectedValue`. The `mutate()` mutate is required to check it.

      When this method is called multiple times on the same `key`, `column`, and `txh`, calls after the first have no effect.

      Locks acquired by this method must be automatically released on transaction `commit()` or `rollback()`.

      Implementations which don't support locking should throw `UnsupportedOperationException`.

      This implementation supports locking when `lockStore` is non-null.

      Consider the following scenario. This method is called twice with identical key, column, and txh arguments, but with different expectedValue arguments in each call. In testing, it seems titan's graphdb requires that implementations discard the second expectedValue and, when checking expectedValues vs actual values just prior to mutate, only the initial expectedValue argument should be considered.
      Specified by:
        `acquireLock` in interface `KeyColumnValueStore`
      Overrides:
        `acquireLock` in class `KCVSProxy`
      Parameters:
        `key` - the key on which to lock
        `column` - the column on which to lock
        `expectedValue` - the expected value for the specified key-column pair on which to lock (null means the pair must have no value)
        `txh` - the transaction to use
      Throws:
        `PermanentLockingException` - the lock could not be acquired due to contention with other transactions or a locking-specific storage problem
        `BackendException`

    - #### unwrapTx

          protected StoreTransaction unwrapTx(StoreTransaction t)

      Overrides:
        `unwrapTx` in class `KCVSProxy`

Copyright © 2012–2014. All rights reserved.