[JBoss JIRA] (ISPN-8069) Clustered Locks Embedded Mode
by Katia Aresti (JIRA)
[ https://issues.jboss.org/browse/ISPN-8069?page=com.atlassian.jira.plugin.... ]
Katia Aresti updated ISPN-8069:
-------------------------------
Description:
This issue will only supply an implementation for a Node Level Ownership and Non rentrant lock
h2. ClusteredLockManager and configuration
{code:java}
package org.infinispan.lock.api;
public class ClusteredLockManager {
boolean defineLock(String name);
ClusteredLock get(String name);
boolean isDefined(String name);
CompletableFuture<Boolean> remove(String name);
CompletableFuture<Void> reset(String name);
}
public class ClusteredLockConfiguration {
private final OwnershipLevel ownershipLevel; // default NODE
private final boolean rentrant; // default false
}
public enum OwnershipLevel {
NODE, // Node can lock if it owns the lock without blocking, only the owner node can unlock
INSTANCE, // Instance can lock multiple times if it owns the lock without blocking, only the owner instance can unlock
}
{code}
h4. ClusteredLock defineLock(String name, LockConfiguration configuration)
Defines a lock with the specific name and LockConfiguration. It does not overwrite existing configurations.
Returns true if successfully defined or false if the lock is already defined or any other failure. If silentFailover is false, then InfinispanLockException will be raised.
h4. ClusteredLock get(String name)
Get’s a InfinipanLock by it’s name and throws InfinispanLockException if the lock is not not defined. User must call defineLock before this method.
h4. boolean isDefined(String name)
True if the lock exists, false if it doesn’t
h4. CompletableFuture<Boolean> remove(String name)
Removes a Lock from the system. Returns true when it was removed, false when the lock does not exist. If any other Runtime problems appear, InfinispanLockException will be raised withe the reason. As Locks are not removed automatically, so this has to be done programatically when the Lock is no longer needed. Otherwise, OutOfMemoryException could happen.
Remove must be executed when the lock is locked, because running that without exclusive access should result in an exception. Internally, the implementation should contain generation number so that attempts to acquire a lock of a removed generation will result it exceptions in the other callers, too.
h4. CompletableFuture<Void> reset(String name)
Resets the lock to its initial state. If any parties are currently waiting at the lock, they will return with failure on the CompletableFuture
h2. ClusteredLock
When a cluster node holding a Lock dies, this lock is released and available for the others.
{code:java}
public interface ClusteredLock {
CompletableFuture<Void> lock();
CompletableFuture<Boolean> tryLock();
CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
CompletableFuture<Void> unlock();
}
{code}
h4. CompletableFuture<Void> lock();
CompletableFuture is completed successfully when the lock is acquired When a lock is aquired by a client, it will be automatically released after the maxLeaseTime specified. RenewalLeaseTime is the interval time is the time a client can aquire a lock consecutively User should set the timeouts to non-positive value The initial embedded implementation does not have to support positive values
h4. CompletableFuture<Boolean> tryLock();
Acquires the lock only if it is free at the time of invocation. Acquires the lock if it is available and returns with the value true. If the lock is not available then this method with the value false.
h4. CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
Acquires the lock if it is free within the given waiting time. If the lock is available this method returns with the value true.
Parameters: time - the maximum time to wait for the lock unit - the time unit of the time argument Returns: true if the lock was acquired and false if the waiting time elapsed before the lock was acquired
CompletableFuture fails with InfinispanLockException in case of error (InterruptedException, or any other non checked exceptions)
h4. CompletableFuture<Boolean> unlock();
If the lock is rentrant (Node or Instance), only the instance or node holding the lock will be able to unlock, otherwise, anybody can unlock and it will behave as a Semaphore with one permit. True answer will say that the operation was succesul and the lock has been released, false the lock has not been relased
was:
h2. ClusteredLockManager and configuration
{code:java}
package org.infinispan.lock.api;
public class ClusteredLockManager {
boolean defineLock(String name, LockConfiguration configuration);
InfinispanLock get(String name);
LockConfiguration getConfiguration(String name);
boolean isDefined(String name);
CompletableFuture<Boolean> remove(String name);
CompletableFuture<Void> reset(String name);
}
public class LockConfiguration {
private final RentrancyLevel lentrancyLevel; // default NOT_REENTRANT
private final boolean silentFailover; // default true
// The maximum length of time for which a client can hold and renew a lock aquisition
private final long maxLeaseTime;
// Maximum length of time a lock may be held without updating the lease,
// after that time any attempt to lock it will succeed
private final long renewalLeaseTime;
}
public enum RentrancyLevel {
NODE, // Node can lock if it owns the lock without blocking, only the owner node can unlock
INSTANCE, // Instance can lock multiple times if it owns the lock without blocking, only the owner instance can unlock
NOT_REENTRANT // Nobody can take the lock if already taken, but everybody can release it
}
{code}
h4. InfinispanLock defineLock(String name, LockConfiguration configuration)
Defines a lock with the specific name and LockConfiguration. It does not overwrite existing configurations.
Returns true if successfully defined or false if the lock is already defined or any other failure. If silentFailover is false, then InfinispanLockException will be raised.
h4. InfinispanLock get(String name)
Get’s a InfinipanLock by it’s name and throws InfinispanLockException if the lock is not not defined. User must call defineLock before this method.
h4. Optional<LockConfiguration> getConfiguration(String name);
Get’s the configuration for a Lock. If the Lock does not exist, Optional.empty() will be returned.
h4. boolean isDefined(String name)
True if the lock exists, false if it doesn’t
h4. CompletableFuture<Boolean> remove(String name)
Removes a Lock from the system. Returns true when it was removed, false when the lock does not exist. If any other Runtime problems appear, InfinispanLockException will be raised withe the reason. As Locks are not removed automatically, so this has to be done programatically when the Lock is no longer needed. Otherwise, OutOfMemoryException could happen.
Remove must be executed when the lock is locked, because running that without exclusive access should result in an exception. Internally, the implementation should contain generation number so that attempts to acquire a lock of a removed generation will result it exceptions in the other callers, too.
h4. CompletableFuture<Void> reset(String name)
Resets the lock to its initial state. If any parties are currently waiting at the lock, they will return with failure on the CompletableFuture
h2. InfinispanLock
When a cluster node holding a Lock dies, this lock is released and available for the others.
{code:java}
public interface InfinispanLock {
CompletableFuture<Void> lock();
CompletableFuture<Boolean> tryLock();
CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
CompletableFuture<Void> unlock();
}
{code}
h4. CompletableFuture<Void> lock();
CompletableFuture is completed successfully when the lock is acquired When a lock is aquired by a client, it will be automatically released after the maxLeaseTime specified. RenewalLeaseTime is the interval time is the time a client can aquire a lock consecutively User should set the timeouts to non-positive value The initial embedded implementation does not have to support positive values
h4. CompletableFuture<Boolean> tryLock();
Acquires the lock only if it is free at the time of invocation. Acquires the lock if it is available and returns with the value true. If the lock is not available then this method with the value false.
h4. CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
Acquires the lock if it is free within the given waiting time. If the lock is available this method returns with the value true.
Parameters: time - the maximum time to wait for the lock unit - the time unit of the time argument Returns: true if the lock was acquired and false if the waiting time elapsed before the lock was acquired
CompletableFuture fails with InfinispanLockException in case of error (InterruptedException, or any other non checked exceptions)
h4. CompletableFuture<Boolean> unlock();
If the lock is rentrant (Node or Instance), only the instance or node holding the lock will be able to unlock, otherwise, anybody can unlock and it will behave as a Semaphore with one permit. True answer will say that the operation was succesul and the lock has been released, false the lock has not been relased
h2. Demo
{code:java}
public static void main(String[] args) throws Exception {
EmbeddedCacheManager cm = Infinispan.createClustered();
CounterManager counterManager = EmbeddedCounterManagerFactory.asCounterManager(cm);
counterManager.defineCounter("counter", ...);
WeakCounter counter = counterManager.weakCounter("counter");
ClusteredLockManager lockManager = EmbeddedLockManagerFactory.asClusteredLockManager(cm);
lockManager.defineLock("lock", ...);
InfinispanLock lock = lockManager.get("lock");
for (int i = 0; i < 100; i++) {
System.out.println("Counter on " + i + " is => " + counter.getValue());
lock.lock()
.thenRun(new CounterExample(counter))
.whenComplete((nil, t) -> lock.unlock());
}
cm.stop();
}
static class CounterExample implements Runnable {
private WeakCounter counter;
public CounterExample(WeakCounter counter) {
this.counter = counter;
}
@Override
public void run() {
counter.increment();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
counter.decrement();
}
}
{code}
> Clustered Locks Embedded Mode
> -----------------------------
>
> Key: ISPN-8069
> URL: https://issues.jboss.org/browse/ISPN-8069
> Project: Infinispan
> Issue Type: Feature Request
> Reporter: Katia Aresti
> Assignee: Katia Aresti
>
> This issue will only supply an implementation for a Node Level Ownership and Non rentrant lock
> h2. ClusteredLockManager and configuration
> {code:java}
> package org.infinispan.lock.api;
> public class ClusteredLockManager {
> boolean defineLock(String name);
> ClusteredLock get(String name);
> boolean isDefined(String name);
> CompletableFuture<Boolean> remove(String name);
> CompletableFuture<Void> reset(String name);
> }
> public class ClusteredLockConfiguration {
> private final OwnershipLevel ownershipLevel; // default NODE
> private final boolean rentrant; // default false
> }
> public enum OwnershipLevel {
> NODE, // Node can lock if it owns the lock without blocking, only the owner node can unlock
> INSTANCE, // Instance can lock multiple times if it owns the lock without blocking, only the owner instance can unlock
> }
> {code}
> h4. ClusteredLock defineLock(String name, LockConfiguration configuration)
> Defines a lock with the specific name and LockConfiguration. It does not overwrite existing configurations.
> Returns true if successfully defined or false if the lock is already defined or any other failure. If silentFailover is false, then InfinispanLockException will be raised.
> h4. ClusteredLock get(String name)
> Get’s a InfinipanLock by it’s name and throws InfinispanLockException if the lock is not not defined. User must call defineLock before this method.
> h4. boolean isDefined(String name)
> True if the lock exists, false if it doesn’t
> h4. CompletableFuture<Boolean> remove(String name)
> Removes a Lock from the system. Returns true when it was removed, false when the lock does not exist. If any other Runtime problems appear, InfinispanLockException will be raised withe the reason. As Locks are not removed automatically, so this has to be done programatically when the Lock is no longer needed. Otherwise, OutOfMemoryException could happen.
> Remove must be executed when the lock is locked, because running that without exclusive access should result in an exception. Internally, the implementation should contain generation number so that attempts to acquire a lock of a removed generation will result it exceptions in the other callers, too.
> h4. CompletableFuture<Void> reset(String name)
> Resets the lock to its initial state. If any parties are currently waiting at the lock, they will return with failure on the CompletableFuture
> h2. ClusteredLock
>
> When a cluster node holding a Lock dies, this lock is released and available for the others.
> {code:java}
> public interface ClusteredLock {
> CompletableFuture<Void> lock();
> CompletableFuture<Boolean> tryLock();
> CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
> CompletableFuture<Void> unlock();
> }
> {code}
> h4. CompletableFuture<Void> lock();
> CompletableFuture is completed successfully when the lock is acquired When a lock is aquired by a client, it will be automatically released after the maxLeaseTime specified. RenewalLeaseTime is the interval time is the time a client can aquire a lock consecutively User should set the timeouts to non-positive value The initial embedded implementation does not have to support positive values
> h4. CompletableFuture<Boolean> tryLock();
> Acquires the lock only if it is free at the time of invocation. Acquires the lock if it is available and returns with the value true. If the lock is not available then this method with the value false.
> h4. CompletableFuture<Boolean> tryLock(long time, TimeUnit unit);
> Acquires the lock if it is free within the given waiting time. If the lock is available this method returns with the value true.
> Parameters: time - the maximum time to wait for the lock unit - the time unit of the time argument Returns: true if the lock was acquired and false if the waiting time elapsed before the lock was acquired
> CompletableFuture fails with InfinispanLockException in case of error (InterruptedException, or any other non checked exceptions)
> h4. CompletableFuture<Boolean> unlock();
> If the lock is rentrant (Node or Instance), only the instance or node holding the lock will be able to unlock, otherwise, anybody can unlock and it will behave as a Semaphore with one permit. True answer will say that the operation was succesul and the lock has been released, false the lock has not been relased
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months
[JBoss JIRA] (ISPN-8411) Add support for efficient removeAll
by Emond Papegaaij (JIRA)
[ https://issues.jboss.org/browse/ISPN-8411?page=com.atlassian.jira.plugin.... ]
Emond Papegaaij commented on ISPN-8411:
---------------------------------------
Well, the warning is not very clear in the outcome of the conflict, so we decided to be on the safe side and fix the warnings. Perhaps the warning should reflect the concurrency strategy used, like: _"Requesting TRANSACTIONAL cache concurrency strategy but the cache is not configured as transactional. The resulting cache will not be transactional."_
To fix the warnings, we had to change our {{persistence.xml}} to include the {{default_cache_concurrency_strategy}} and update all {{@Cache}} annotations on {{@OneToMany}} properties. {{org.hibernate.annotations.Cache}} has no default for the {{usage}} attribute, so to enable caching on a collection you must specify the concurrency strategy. On entities you can use {{@Cacheable(true)}} (or enable it globally, as we did). Perhaps the {{Cache.usage}} attribute could benefit from a {{DEFAULT}} concurrency strategy, which could also be the default value of the attribute.
> Add support for efficient removeAll
> -----------------------------------
>
> Key: ISPN-8411
> URL: https://issues.jboss.org/browse/ISPN-8411
> Project: Infinispan
> Issue Type: Feature Request
> Components: Hibernate Cache
> Affects Versions: 8.2.8.Final, 9.1.1.Final
> Environment: WildFly 10.1.0, WildFly 11.0.0.CR1, WildFly master, Hibernate 2LC
> Reporter: Emond Papegaaij
> Assignee: Galder Zamarreño
>
> Infinispan currently does not seem to implement an efficient way to clear an entire cache cluster-wide. This forces Hibernate to remove all entries one by one when a cache region needs to be cleared, for example when a buld CriteriaUpdate or CriteriaDelete is used.
> The behavior we are observing is:
> # All nodes in the cluster are queried for the keyset in a region
> # A lock seems to be in place for this region for the duration of the commit
> # The initiating node constructs a message with {{InvalidateCommands}} for all keys
> # This large message (230MB for 200k entries) is sent to all nodes in the cluster
> For large caches this can take very long. We had to increase the remote-timeout to 60 seconds to prevent timeouts. During this time, the entire cluster is locked an busy processing the cache invalidations. As you can understand, this is not a workable solution for us. On some places we can prevent the cache clear by updating the records one by one, but in other places this is not an option.
> The corresponding report at Hibernate can be found here: https://hibernate.atlassian.net/browse/HHH-12036
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months
[JBoss JIRA] (ISPN-8411) Add support for efficient removeAll
by Radim Vansa (JIRA)
[ https://issues.jboss.org/browse/ISPN-8411?page=com.atlassian.jira.plugin.... ]
Radim Vansa commented on ISPN-8411:
-----------------------------------
Good point, this should get inlined with the default configuration. Then all the people using transactional caches will get that warning, but at least it may push them in the right direction. Note that the original warning could be safely ignored, TRANSACTIONAL and READ_WRITE strategies offer the same guarantees in Infinispan (Hibernate later on specified that transactional means 'serializable' and read-write 'linearizable', but we're rather on the safe side).
I wonder what changes in your codebase are needed when you configure the server through WF's standalone(-ha).xml
> Add support for efficient removeAll
> -----------------------------------
>
> Key: ISPN-8411
> URL: https://issues.jboss.org/browse/ISPN-8411
> Project: Infinispan
> Issue Type: Feature Request
> Components: Hibernate Cache
> Affects Versions: 8.2.8.Final, 9.1.1.Final
> Environment: WildFly 10.1.0, WildFly 11.0.0.CR1, WildFly master, Hibernate 2LC
> Reporter: Emond Papegaaij
> Assignee: Galder Zamarreño
>
> Infinispan currently does not seem to implement an efficient way to clear an entire cache cluster-wide. This forces Hibernate to remove all entries one by one when a cache region needs to be cleared, for example when a buld CriteriaUpdate or CriteriaDelete is used.
> The behavior we are observing is:
> # All nodes in the cluster are queried for the keyset in a region
> # A lock seems to be in place for this region for the duration of the commit
> # The initiating node constructs a message with {{InvalidateCommands}} for all keys
> # This large message (230MB for 200k entries) is sent to all nodes in the cluster
> For large caches this can take very long. We had to increase the remote-timeout to 60 seconds to prevent timeouts. During this time, the entire cluster is locked an busy processing the cache invalidations. As you can understand, this is not a workable solution for us. On some places we can prevent the cache clear by updating the records one by one, but in other places this is not an option.
> The corresponding report at Hibernate can be found here: https://hibernate.atlassian.net/browse/HHH-12036
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months
[JBoss JIRA] (ISPN-8411) Add support for efficient removeAll
by Emond Papegaaij (JIRA)
[ https://issues.jboss.org/browse/ISPN-8411?page=com.atlassian.jira.plugin.... ]
Emond Papegaaij commented on ISPN-8411:
---------------------------------------
Thank you for the clear explanation. We are currently evaluating how to proceed. Changing the transaction mode requires some changes to our codebase (annotations) and a restart of our services.
While preparing our application to use read-write, we did get this warning:
{{13:29:03,808 WARN [org.hibernate.cache.infinispan.impl.BaseRegion] (ServerService Thread Pool -- 67) Requesting TRANSACTIONAL cache concurrency strategy but the cache is not configured as transactional.}}
It seems Hibernate 5.x still requests transactional caches by default for Infinispan: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-infinisp... . We've circumvented this problemen bij overriding the default using the {{hibernate.cache.default_cache_concurrency_strategy}} setting, which is documented as _This setting is very rarely required as the pluggable providers do specify the default strategy to use._
> Add support for efficient removeAll
> -----------------------------------
>
> Key: ISPN-8411
> URL: https://issues.jboss.org/browse/ISPN-8411
> Project: Infinispan
> Issue Type: Feature Request
> Components: Hibernate Cache
> Affects Versions: 8.2.8.Final, 9.1.1.Final
> Environment: WildFly 10.1.0, WildFly 11.0.0.CR1, WildFly master, Hibernate 2LC
> Reporter: Emond Papegaaij
> Assignee: Galder Zamarreño
>
> Infinispan currently does not seem to implement an efficient way to clear an entire cache cluster-wide. This forces Hibernate to remove all entries one by one when a cache region needs to be cleared, for example when a buld CriteriaUpdate or CriteriaDelete is used.
> The behavior we are observing is:
> # All nodes in the cluster are queried for the keyset in a region
> # A lock seems to be in place for this region for the duration of the commit
> # The initiating node constructs a message with {{InvalidateCommands}} for all keys
> # This large message (230MB for 200k entries) is sent to all nodes in the cluster
> For large caches this can take very long. We had to increase the remote-timeout to 60 seconds to prevent timeouts. During this time, the entire cluster is locked an busy processing the cache invalidations. As you can understand, this is not a workable solution for us. On some places we can prevent the cache clear by updating the records one by one, but in other places this is not an option.
> The corresponding report at Hibernate can be found here: https://hibernate.atlassian.net/browse/HHH-12036
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months
[JBoss JIRA] (ISPN-8412) Conflict resolution should utilise Merkle trees to improve performance
by Ryan Emerson (JIRA)
Ryan Emerson created ISPN-8412:
----------------------------------
Summary: Conflict resolution should utilise Merkle trees to improve performance
Key: ISPN-8412
URL: https://issues.jboss.org/browse/ISPN-8412
Project: Infinispan
Issue Type: Enhancement
Components: Core
Affects Versions: 9.2.0.Alpha1
Reporter: Ryan Emerson
Assignee: Ryan Emerson
Currently we detect conflicts between CacheEntry replicas by retrieving all entries for a cache segment and comparing their values on the node initiating the conflict resolution. This does not scale. Instead, we should generate a Merkle tree for each segment on the replica nodes. When initiating conflict resolution, it is then possible to retrieve a segments hash from each of its owners and determine if a conflict is present before requesting the conflicting entries.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months
[JBoss JIRA] (ISPN-8408) POM inheritance is broken
by Ryan Emerson (JIRA)
[ https://issues.jboss.org/browse/ISPN-8408?page=com.atlassian.jira.plugin.... ]
Ryan Emerson updated ISPN-8408:
-------------------------------
Status: Open (was: New)
> POM inheritance is broken
> -------------------------
>
> Key: ISPN-8408
> URL: https://issues.jboss.org/browse/ISPN-8408
> Project: Infinispan
> Issue Type: Bug
> Components: Build process
> Reporter: Tristan Tarrant
> Assignee: Ryan Emerson
> Fix For: 9.2.0.Final
>
>
> There are a number of problems with our project structure:
> - the parent pom uses the bom as its own parent: it should instead import it (i.e. revert ISPN-3998)
> - the server pom inherits from the wildfly pom. This was done at a time when the server build was a fork of the wildfly one. With the introduction of feature packs this is no longer necessary.
--
This message was sent by Atlassian JIRA
(v7.5.0#75005)
8 years, 5 months