schema

## Class WriteOperations

- java.lang.Object
- - schema.WriteOperations

-      class WriteOperations
      extends Object

  Performs write operations and retries the operation when a `FaultException` occurs in order to handle transient network failures. While the `KVStore` read methods perform retries automatically when a network failure occurs, the `KVStore` write methods do not. Therefore, it is recommended that write operations are performed using the methods in this class, or using a similar retry mechanism in the application.

  The KVStore write methods are not defined to be strictly idempotent which means if they are performed more than once, the outcome may be different than if they were performed a single time. Repeating an operation may occur when it is retried after a network failure, if in fact the operation was successful the first time. Because of the network failure, the client is unaware of whether the first operation failed or succeeded.

  For example, if `KVStore.delete` throws a FaultException due to a network failure, it may or may not have succeeded. Imagine that it did succeed and the network failure occurred when receiving the operation reply message. When the KVStore.delete call is retried, it will return false because the previous attempt succeeded. Of course, this can also occur if another client deletes the record, even when no retries are necessary. Therefore, the semantics of the `delete` method in this class are slightly different than the semantics of `KVStore.delete`. The delete method here does not return an indication of whether it deleted the record. The record is guaranteed to be deleted when the delete method returns without an exception, but there is no way to know whether it was deleted by this method or another client. With this change in semantics, the delete method in this class is idempotent.

  Several methods in this class fall into the same category as the delete method in that they are idempotent, as they are defined here. These are: `put`, `delete` and `multiDelete`. When these methods return without an exception, their outcome is always the same, whether or not retries were necessary. For that reason, retrying these methods at the application level is not needed when no exception is thrown.

  Most of the other methods in this class -- `putIfAbsent`, `putIfPresent`, `putIfVersion` and `deleteIfVersion` -- fall into a different category. These methods are not idempotent, even as defined here, because the application needs to decide whether the operations need to be retried in the face of concurrent access.

  For example, say the application performs a `KVStore.get`, examines the record value and determines that it qualifies for deletion, and then calls `deleteIfVersion`. Say the call to KVStore.deleteIfVersion succeeds (when first called by the deleteIfVersion method here), but throws a FaultException due to a network failure. When the KVStore.deleteIfVersion call is retried, it returns false because the previous attempt succeeded and the record was deleted as a result; the deleteIfVersion method in this class will return false as well. Of course, this can also occur if another client has deleted or modified the record, even when no retries are necessary. Therefore, the meaning of a false return value from the deleteIfVersion method in this class is slightly different than for KVStore.deleteIfVersion. When false is returned by the deleteIfVersion method here, it may be because another client deleted or modified the record, or because this method itself unknowingly deleted the record and then retried the operation. Either way, the application should normally retry the higher level operation: call KVStore.get again (or use the prevValue parameter of the deleteIfVersion method) to get the current record value, and examine it again to see if the record still qualifies for deletion. In the example described, the record will no longer exist and the application should assume that it was deleted by another client or by this method itself; these two cases cannot be distinguished.

  As an illustration of the difference in semantics, imagine a store that is idle except for a single client thread that is performing KVStore.get and deleteIfVersion calls (the method in this class). We also guarantee that no data migration takes place in this test, since data migration changes record versions as if another client performed an update. In this test, one might assume that the deleteIfVersion method should always return true, since no other clients are accessing the store. However, this is an incorrect assumption. If the test is run for long enough, transient network failures will eventually occur, and deleteIfVersion will return false due to scenarios such as the one described above. This may be an unexpected outcome in such a test scenario, but should be expected in a real world application due to other client activity and data migration, as well as network failures.

  The following example is also noteworthy. Imagine that `putIfVersion` is used to increment or decrement a bank balance, or make another sort of incremental or conditional update. If null is returned by the putIfVersion method in this class (or if `KVStore.putIfVersion` throws a FaultException), this means the operation may or may not have succeeded. If performing the change exactly once is critical, as it would be when incrementing or decrementing a bank balance, the application must build in some means of determining whether the change succeeded or not. This explains why putIfVersion and similar methods in this class cannot simply compare the currently stored value to the value requested, to determine whether the operation succeeded. The test for success or failure must be left to the application in such cases.

  The execute method is a special case, since it doesn't fall neatly into one of the two categories defined: idempotent like delete, or non-idempotent like deleteIfVersion. This is because execute can be used to perform a combination of delete and deleteIfVersion, as well as other types of write operations. The execute method in this class will retry KVStore.execute when a FaultException is thrown, and the meaning of the individual operation results will depend on the type of operation, as defined by the other methods in this class.

  Note that this class does not do any exception handling, other than to retry the operation after any kind of FaultException is thrown. Up to `N_RETRIES` (currently two) retries are performed, and a FaultException that occurs in the last attempt is propagated to the caller. The caller should handle the exception as described in the `RunOperation` class in this example. In this example, calls to methods in this class are always made within the context of a RunOperation execution, and exceptions are handled by RunOperation in all cases.

  A known deficiency of this class is that a network failure is not distinguished from other types of FaultExceptions that might occur; a retry is performed when any type of FaultException is thrown. This is not considered a major problem for two reasons: a) other types of failures are likely to be persistent and will quickly occur again when retrying, and b) optimizing performance when handling FaultExceptions is not normally a concern.

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `(package private) class` | `WriteOperations.LobOp<R,E extends Exception>` Internal `abstract` class used to perform retries for a put or delete operation applied to a LOB.
    `static interface` | `WriteOperations.LOBStreamListener` For any entity that invokes one of the following methods of the `WriteOperations` utility class, that entity must supply an implementation of this interface: `putLOB putLOBIfAbsent putLOBIfPresent` The `getInputStream` method specified by this interface returns an instance of `InputStream` for the LOB to which the desired LOB operation is applied; where the stream that is returned can be either a new stream or a reset stream positioned at the first byte of the associated LOB.
    `(package private) class` | `WriteOperations.WriteOp<R,E extends Exception>` Internal class used to perform retries for a write operation.

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `WriteOperations(KVStore store, KVStoreConfig config)` Creates a WriteOperations wrapper for a given KVStore.

  - ### Method Summary

    Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `delete(Key key)` Calls `KVStore.delete` and performs retries if a FaultException is thrown.
    `void` | `delete(Key key, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.delete` and performs retries if a FaultException is thrown.
    `boolean` | `deleteIfVersion(Key key, Version matchVersion)` Calls `KVStore.deleteIfVersion` and performs retries if a FaultException is thrown.
    `boolean` | `deleteIfVersion(Key key, Version matchVersion, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.deleteIfVersion` and performs retries if a FaultException is thrown.
    `boolean` | `deleteLOB(Key lobKey, Durability durability, long lobTimeout, TimeUnit lobTimeoutUnit, long operationTimeout, TimeUnit operationTimeoutUnit)` Calls `KVLargeObject.deleteLOB` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered.
    `List<OperationResult>` | `execute(List<Operation> operations)` Calls `KVStore.execute` and performs retries if a FaultException is thrown.
    `List<OperationResult>` | `execute(List<Operation> operations, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.execute` and performs retries if a FaultException is thrown.
    `void` | `multiDelete(Key parentKey, KeyRange subRange, Depth depth)` Calls `KVStore.multiDelete` and performs retries if a FaultException is thrown.
    `void` | `multiDelete(Key parentKey, KeyRange subRange, Depth depth, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.multiDelete` and performs retries if a FaultException is thrown.
    `Version` | `put(Key key, Value value)` Calls `KVStore.put` and performs retries if a FaultException is thrown.
    `Version` | `put(Key key, Value value, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.put` and performs retries if a FaultException is thrown.
    `Version` | `putIfAbsent(Key key, Value value)` Calls `KVStore.putIfAbsent` and performs retries if a FaultException is thrown.
    `Version` | `putIfAbsent(Key key, Value value, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.putIfAbsent` and performs retries if a FaultException is thrown.
    `Version` | `putIfPresent(Key key, Value value)` Calls `KVStore.putIfPresent` and performs retries if a FaultException is thrown.
    `Version` | `putIfPresent(Key key, Value value, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.putIfPresent` and performs retries if a FaultException is thrown.
    `Version` | `putIfVersion(Key key, Value value, Version matchVersion)` Calls `KVStore.putIfVersion` and performs retries if a FaultException is thrown.
    `Version` | `putIfVersion(Key key, Value value, Version matchVersion, ReturnValueVersion prevValue, Durability durability, long timeout, TimeUnit timeoutUnit)` Calls `KVStore.putIfVersion` and performs retries if a FaultException is thrown.
    `Version` | `putLOB(Key lobKey, WriteOperations.LOBStreamListener lobStreamCallback, Durability durability, long lobTimeout, TimeUnit lobTimeoutUnit, long operationTimeout, TimeUnit operationTimeoutUnit)` Calls `KVLargeObject.putLOB` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered.
    `Version` | `putLOBIfAbsent(Key lobKey, WriteOperations.LOBStreamListener lobStreamCallback, Durability durability, long lobTimeout, TimeUnit lobTimeoutUnit, long operationTimeout, TimeUnit operationTimeoutUnit)` Calls `KVLargeObject.putLOBIfAbsent` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered.
    `Version` | `putLOBIfPresent(Key lobKey, WriteOperations.LOBStreamListener lobStreamCallback, Durability durability, long lobTimeout, TimeUnit lobTimeoutUnit, long operationTimeout, TimeUnit operationTimeoutUnit)` Calls `KVLargeObject.putLOBIfPresent` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered.

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

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

- - ### Constructor Detail

    - #### WriteOperations

          WriteOperations(KVStore store,
                         KVStoreConfig config)

      Creates a WriteOperations wrapper for a given KVStore.

  - ### Method Detail

    - #### put

          public Version put(Key key,
                    Value value)
                      throws DurabilityException,
                             RequestTimeoutException,
                             FaultException

      Calls `KVStore.put` and performs retries if a FaultException is thrown.

      This method is equivalent to `put(Key, Value, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### put

          public Version put(Key key,
                    Value value,
                    ReturnValueVersion prevValue,
                    Durability durability,
                    long timeout,
                    TimeUnit timeoutUnit)
                      throws DurabilityException,
                             RequestTimeoutException,
                             FaultException

      Calls `KVStore.put` and performs retries if a FaultException is thrown.

      This method is idempotent in the sense that if it is called multiple times and returns without throwing an exception, the outcome is always the same: the given Key/Value pair will have been stored.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfAbsent

          public Version putIfAbsent(Key key,
                            Value value)
                              throws DurabilityException,
                                     RequestTimeoutException,
                                     FaultException

      Calls `KVStore.putIfAbsent` and performs retries if a FaultException is thrown.

      This method is equivalent to `putIfAbsent(Key, Value, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfAbsent

          public Version putIfAbsent(Key key,
                            Value value,
                            ReturnValueVersion prevValue,
                            Durability durability,
                            long timeout,
                            TimeUnit timeoutUnit)
                              throws DurabilityException,
                                     RequestTimeoutException,
                                     FaultException

      Calls `KVStore.putIfAbsent` and performs retries if a FaultException is thrown.

      This method is not idempotent since if it is called multiple times, the outcome may be different because the key may or may not exist. When null is returned, the application is expected to take action, such as performing retries, at a higher level.

      When a retry is performed by this method and it returns null because the key is present, there is no returned indication of whether the key was inserted by an earlier attempt in the same method invocation, or by another client. The application must be prepared for either case.

      Because of this ambiguity, it can be difficult to use this method (instead of put) as a self-check when the key is expected to be absent, or as a way to prevent two clients from writing the same key. To do this reliably, each client must include a unique identifier in the value and check for that identifier (call KVStore.get or use the prevValue parameter of this method) when null is returned.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfPresent

          public Version putIfPresent(Key key,
                             Value value)
                               throws DurabilityException,
                                      RequestTimeoutException,
                                      FaultException

      Calls `KVStore.putIfPresent` and performs retries if a FaultException is thrown.

      This method is equivalent to `putIfPresent(Key, Value, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfPresent

          public Version putIfPresent(Key key,
                             Value value,
                             ReturnValueVersion prevValue,
                             Durability durability,
                             long timeout,
                             TimeUnit timeoutUnit)
                               throws DurabilityException,
                                      RequestTimeoutException,
                                      FaultException

      Calls `KVStore.putIfPresent` and performs retries if a FaultException is thrown.

      This method is not idempotent since if it is called multiple times, the outcome may be different because the key may or may not exist. When null is returned, the application is expected to take action, such as performing retries, at a higher level.

      This method is commonly used (instead of put) as a self-check, when the key is expected to be present.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfVersion

          public Version putIfVersion(Key key,
                             Value value,
                             Version matchVersion)
                               throws DurabilityException,
                                      RequestTimeoutException,
                                      FaultException

      Calls `KVStore.putIfVersion` and performs retries if a FaultException is thrown.

      This method is equivalent to `putIfVersion(Key, Value, Version, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### putIfVersion

          public Version putIfVersion(Key key,
                             Value value,
                             Version matchVersion,
                             ReturnValueVersion prevValue,
                             Durability durability,
                             long timeout,
                             TimeUnit timeoutUnit)
                               throws DurabilityException,
                                      RequestTimeoutException,
                                      FaultException

      Calls `KVStore.putIfVersion` and performs retries if a FaultException is thrown.

      This method is not idempotent since if it is called multiple times, the outcome may be different because the version may or may not match. When null is returned, the application is expected to take action, such as performing retries, at a higher level.

      When a retry is performed by this method and it returns null because the version does not match, there is no returned indication of whether the version was changed by an earlier attempt in the same method invocation, or by another client. The application must be prepared for either case.

      This method is commonly used (instead of put) as a way to avoid lost updates.

      WARNING: A putIfVersion operation should not be used to perform a self-check because the KVStore system may internally assign a new Version to a Key/Value pair when migrating data for better resource usage. One should never assume that only the application can change the Version of a Key/Value pair.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### delete

          public void delete(Key key)
                      throws DurabilityException,
                             RequestTimeoutException,
                             FaultException

      Calls `KVStore.delete` and performs retries if a FaultException is thrown.

      This method is equivalent to `delete(Key, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### delete

          public void delete(Key key,
                    ReturnValueVersion prevValue,
                    Durability durability,
                    long timeout,
                    TimeUnit timeoutUnit)
                      throws DurabilityException,
                             RequestTimeoutException,
                             FaultException

      Calls `KVStore.delete` and performs retries if a FaultException is thrown.

      This method is idempotent in the sense that if it is called multiple times and returns without throwing an exception, the outcome is always the same: the given Key/Value pair will have been deleted.

      Unlike `KVStore.delete`, this method does not return any indication of whether the Key/Value pair was deleted by this method or by another client.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### deleteIfVersion

          public boolean deleteIfVersion(Key key,
                                Version matchVersion)
                                  throws DurabilityException,
                                         RequestTimeoutException,
                                         FaultException

      Calls `KVStore.deleteIfVersion` and performs retries if a FaultException is thrown.

      This method is equivalent to `deleteIfVersion(Key, Version, ReturnValueVersion, Durability, long, TimeUnit)` except that the prevValue, durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### deleteIfVersion

          public boolean deleteIfVersion(Key key,
                                Version matchVersion,
                                ReturnValueVersion prevValue,
                                Durability durability,
                                long timeout,
                                TimeUnit timeoutUnit)
                                  throws DurabilityException,
                                         RequestTimeoutException,
                                         FaultException

      Calls `KVStore.deleteIfVersion` and performs retries if a FaultException is thrown.

      This method is not idempotent since if it is called multiple times, the outcome may be different because the version may or may not match. When false is returned, the application is expected to take action, such as performing retries, at a higher level.

      When a retry is performed by this method and it returns false because the version does not match, there is no returned indication of whether the version was changed by an earlier attempt in the same method invocation, or by another client. The application must be prepared for either case.

      This method is commonly used (instead of delete) as a way to avoid lost updates.

      WARNING: A deleteIfVersion operation should not be used to perform a self-check because the KVStore system may internally assign a new Version to a Key/Value pair when migrating data for better resource usage. One should never assume that only the application can change the Version of a Key/Value pair.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### multiDelete

          public void multiDelete(Key parentKey,
                         KeyRange subRange,
                         Depth depth)
                           throws DurabilityException,
                                  RequestTimeoutException,
                                  FaultException

      Calls `KVStore.multiDelete` and performs retries if a FaultException is thrown.

      This method is equivalent to `multiDelete(Key, KeyRange, Depth, Durability, long, TimeUnit)` except that the durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### multiDelete

          public void multiDelete(Key parentKey,
                         KeyRange subRange,
                         Depth depth,
                         Durability durability,
                         long timeout,
                         TimeUnit timeoutUnit)
                           throws DurabilityException,
                                  RequestTimeoutException,
                                  FaultException

      Calls `KVStore.multiDelete` and performs retries if a FaultException is thrown.

      This method is idempotent in the sense that if it is called multiple times and returns without throwing an exception, the outcome is always the same: the specified Key/Value pairs will have been deleted.

      Unlike `KVStore.multiDelete`, this method does not return any indication of how many Key/Value pairs were deleted by this method.

      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `FaultException`

    - #### execute

          public List<OperationResult> execute(List<Operation> operations)
                                        throws OperationExecutionException,
                                               DurabilityException,
                                               FaultException

      Calls `KVStore.execute` and performs retries if a FaultException is thrown.

      This method is equivalent to `execute(List, Durability, long, TimeUnit)` except that the durability, timeout and timeoutUnit parameters are not specified and take on default values.

      Throws:
        `OperationExecutionException`
        `DurabilityException`
        `FaultException`

    - #### execute

          public List<OperationResult> execute(List<Operation> operations,
                                      Durability durability,
                                      long timeout,
                                      TimeUnit timeoutUnit)
                                        throws OperationExecutionException,
                                               DurabilityException,
                                               FaultException

      Calls `KVStore.execute` and performs retries if a FaultException is thrown.

      This method may or may not be idempotent since the specified operations may or may not be idempotent. Care should be taken when multiple non-idempotent operations are included, because retries may cause some operations to fail.

      When a retry is performed by this method and an `OperationExecutionException` is thrown, there is no returned indication of whether the operation(s) failed due to an operation that succeeded in an earlier attempt in the same method invocation, or due to an operation by another client. The application must be prepared for either case.

      Throws:
        `OperationExecutionException`
        `DurabilityException`
        `FaultException`

    - #### putLOB

          public Version putLOB(Key lobKey,
                       WriteOperations.LOBStreamListener lobStreamCallback,
                       Durability durability,
                       long lobTimeout,
                       TimeUnit lobTimeoutUnit,
                       long operationTimeout,
                       TimeUnit operationTimeoutUnit)
                         throws DurabilityException,
                                RequestTimeoutException,
                                ConcurrentModificationException,
                                FaultException,
                                IOException

      Calls `KVLargeObject.putLOB` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered. Note that if a partial LOB is encountered by this method, the operation will overwrite that value.
      Parameters:
        `lobKey` - the key associated with the LOB to insert or update.
        `lobStreamCallback` - instance of the interface `WriteOperations.LOBStreamListener`; which specifies how the `InputStream` for the LOB should be created or reset when the insert or update operation performed by this method is retried as a result of a failure.
        `durability` - the durability associated with the insert or update operation performed by this method. If the value input for this parameter is `null`, then the value returned by `KVStoreConfig.getDurability()` will be used.
        `lobTimeout` - the timeout to use when attempting the insert or update operation on each LOB "chunk". The value input for this parameter is an upper bound on the time taken to perform the operation on each chunk. A best effort is made not to exceed the specified limit. If zero is input, then the value returned by `KVStoreConfig.getLOBTimeout(java.util.concurrent.TimeUnit)` is used. If the value input for this parameter is less than 0, then an `IllegalArgumentException` is thrown. Note that if a `RequestTimeoutException` is encountered while operating on a given chunk, then if the `operationTimeout` has not yet been exceeded, the operation may be retried, possibly on a different node in the store.
        `lobTimeoutUnit` - the unit of time on which the value input for the `lobTimeout` parameter is based; for example, `TimeUnit.MILLISECONDS`.
        `operationTimeout` - the timeout to use when attempting the insert or update operation on a given LOB (stream); that is, the sequence of chunks making up the LOB. The value input for this parameter is an upper bound on the time taken to perform the operation on the LOB as a whole. If zero is input, then the value returned by `KVStoreConfig.getRequestTimeout(java.util.concurrent.TimeUnit)` is used. If the value input for this parameter is less than 0 or greater than `Integer.MAX_VALUE`, an `IllegalArgumentException` is thrown. The reason this parameter must be less than or equal to `Integer.MAX_VALUE` is because a value greater than `Integer.MAX_VALUE` will result in overflow when constructing a `RequestTimeoutException`; which occurs when the requested operation timeout has been exceeded before a retry can be initiated.
        `operationTimeoutUnit` - the unit of time on which the value input for the `operationTimeout` parameter is based; for example, `TimeUnit.MILLISECONDS`.
      Returns:
        the `Version` associated with the newly inserted or updated LOB.
      Throws:
        ``DurabilityException`` - if the specified `Durability` cannot be satisfied.
        ``RequestTimeoutException`` - if the `lobTimeout` interval was exceeded during the insertion or update of a chunk or LOB metadata.
        ``ConcurrentModificationException`` - if it is detected that an attempt has been made to modify the LOB while the requested insertion or update was in progress.
        ``FaultException`` - if the requested insertion or update cannot be completed for any reason.
        ``IOException`` - if one is generated by the `lobStream`.
        `DurabilityException`
        `RequestTimeoutException`
        `ConcurrentModificationException`
        `FaultException`
        `IOException`
      See Also:
        `KVLargeObject.putLOB(oracle.kv.Key, java.io.InputStream, oracle.kv.Durability, long, java.util.concurrent.TimeUnit)`, `WriteOperations.LOBStreamListener`

    - #### putLOBIfAbsent

          public Version putLOBIfAbsent(Key lobKey,
                               WriteOperations.LOBStreamListener lobStreamCallback,
                               Durability durability,
                               long lobTimeout,
                               TimeUnit lobTimeoutUnit,
                               long operationTimeout,
                               TimeUnit operationTimeoutUnit)
                                 throws DurabilityException,
                                        RequestTimeoutException,
                                        ConcurrentModificationException,
                                        FaultException,
                                        IOException

      Calls `KVLargeObject.putLOBIfAbsent` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered. This method takes the same parameters and throws the same exceptions (for the same reasons) as the `putLOB` method.
      Returns:
        the `Version` of the new value, or `null` if an existing value is present and the insert opertion is unsuccessful.
      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `ConcurrentModificationException`
        `FaultException`
        `IOException`
      See Also:
        `KVLargeObject.putLOB(oracle.kv.Key, java.io.InputStream, oracle.kv.Durability, long, java.util.concurrent.TimeUnit)`, `putLOB(oracle.kv.Key, schema.WriteOperations.LOBStreamListener, oracle.kv.Durability, long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit)`, `WriteOperations.LOBStreamListener`

    - #### putLOBIfPresent

          public Version putLOBIfPresent(Key lobKey,
                                WriteOperations.LOBStreamListener lobStreamCallback,
                                Durability durability,
                                long lobTimeout,
                                TimeUnit lobTimeoutUnit,
                                long operationTimeout,
                                TimeUnit operationTimeoutUnit)
                                  throws DurabilityException,
                                         RequestTimeoutException,
                                         ConcurrentModificationException,
                                         FaultException,
                                         IOException

      Calls `KVLargeObject.putLOBIfPresent` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered. This method takes the same parameters and throws the same exceptions (for the same reasons) as the `putLOB` method.
      Returns:
        the `Version` of the new value, or `null` if no existing value is present and the update operation is unsuccessful.
      Throws:
        `DurabilityException`
        `RequestTimeoutException`
        `ConcurrentModificationException`
        `FaultException`
        `IOException`
      See Also:
        `KVLargeObject.putLOB(oracle.kv.Key, java.io.InputStream, oracle.kv.Durability, long, java.util.concurrent.TimeUnit)`, `putLOB(oracle.kv.Key, schema.WriteOperations.LOBStreamListener, oracle.kv.Durability, long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit)`, `WriteOperations.LOBStreamListener`

    - #### deleteLOB

          public boolean deleteLOB(Key lobKey,
                          Durability durability,
                          long lobTimeout,
                          TimeUnit lobTimeoutUnit,
                          long operationTimeout,
                          TimeUnit operationTimeoutUnit)
                            throws DurabilityException,
                                   RequestTimeoutException,
                                   ConcurrentModificationException,
                                   FaultException

      Calls `KVLargeObject.deleteLOB` and performs retries, at least until the specified timeout(s) have been exceeded, if a `FaultException` is encountered. Note that if the key corresponds to a partial LOB, this method will still attempt to remove the specified LOB from the store.
      Parameters:
        `lobKey` - the key associated with the LOB to delete.
        `durability` - the durability associated with the delete operation. If the value input for this parameter is `null`, then the value returned by `KVStoreConfig.getDurability()` will be used.
        `lobTimeout` - the timeout to use when attempting the delete operation on each LOB "chunk". The value input for this parameter is an upper bound on the time taken to perform the operation on each chunk. A best effort is made not to exceed the specified limit. If zero is input, then the value returned by `KVStoreConfig.getLOBTimeout(java.util.concurrent.TimeUnit)` is used. If the value input for this parameter is less than 0, then an `IllegalArgumentException` is thrown. Note that if a `RequestTimeoutException` is encountered while operating on a given chunk, then if the `operationTimeout` has not yet been exceeded, the operation may be retried, possibly on a different node in the store.
        `lobTimeoutUnit` - the unit of time on which the value input for the `lobTimeout` parameter is based; for example, `TimeUnit.MILLISECONDS`.
        `operationTimeout` - the timeout to use when attempting the delete operation on a given LOB; that is, the sequence of chunks making up the LOB. The value input for this parameter is an upper bound on the time taken to perform the operation on the LOB as a whole. If zero is input, then the value returned by `KVStoreConfig.getRequestTimeout(java.util.concurrent.TimeUnit)` is used. If the value input for this parameter is less than 0 or greater than `Integer.MAX_VALUE`, an `IllegalArgumentException` is thrown. The reason this parameter must be less than or equal to `Integer.MAX_VALUE` is because a value greater than `Integer.MAX_VALUE` will result in overflow when constructing a `RequestTimeoutException`; which occurs when the requested operation timeout has been exceeded before a retry can be initiated.
        `operationTimeoutUnit` - the unit of time on which the value input for the `operationTimeout` parameter is based; for example, `TimeUnit.MILLISECONDS`.
      Returns:
        `true` if the pair is successfully deleted, and `false` if the key is unknown to the store. Note that `true` is returned if a partial LOB is successfully deleted.
      Throws:
        ``DurabilityException`` - if the specified `Durability` cannot be satisfied.
        ``RequestTimeoutException`` - if the `lobTimeout` interval was exceeded during the deletion of a chunk.
        ``ConcurrentModificationException`` - if it is detected that an attempt has been made to modify the LOB while the deletion was in progress.
        ``FaultException`` - if the deletion cannot be completed for any reason.
        `DurabilityException`
        `RequestTimeoutException`
        `ConcurrentModificationException`
        `FaultException`
      See Also:
        `KVLargeObject.deleteLOB(oracle.kv.Key, oracle.kv.Durability, long, java.util.concurrent.TimeUnit)`

Copyright (c) 2011, 2014 Oracle and/or its affiliates. All rights reserved.