{"action":"created","comment":{"url":"https://api.github.com/repos/infinispan/infinispan/pulls/comments/35968352","id":35968352,"diff_hunk":"@@ -0,0 +1,378 @@\n+package org.infinispan.util.concurrent.locks.impl;\n+\n+import org.infinispan.commons.util.Util;\n+import org.infinispan.configuration.cache.Configuration;\n+import org.infinispan.context.InvocationContext;\n+import org.infinispan.factories.KnownComponentNames;\n+import org.infinispan.factories.annotations.ComponentName;\n+import org.infinispan.factories.annotations.Inject;\n+import org.infinispan.jmx.annotations.DataType;\n+import org.infinispan.jmx.annotations.MBean;\n+import org.infinispan.jmx.annotations.ManagedAttribute;\n+import org.infinispan.util.concurrent.TimeoutException;\n+import org.infinispan.util.concurrent.locks.DeadlockChecker;\n+import org.infinispan.util.concurrent.locks.DeadlockDetectedException;\n+import org.infinispan.util.concurrent.locks.ExtendedLockPromise;\n+import org.infinispan.util.concurrent.locks.KeyAwareLockListener;\n+import org.infinispan.util.concurrent.locks.KeyAwareLockPromise;\n+import org.infinispan.util.concurrent.locks.LockContainer;\n+import org.infinispan.util.concurrent.locks.LockListener;\n+import org.infinispan.util.concurrent.locks.LockManager;\n+import org.infinispan.util.concurrent.locks.LockPromise;\n+import org.infinispan.util.concurrent.locks.LockState;\n+import org.infinispan.util.logging.Log;\n+import org.infinispan.util.logging.LogFactory;\n+\n+import java.util.ArrayList;\n+import java.util.Collection;\n+import java.util.HashSet;\n+import java.util.List;\n+import java.util.Objects;\n+import java.util.Set;\n+import java.util.concurrent.CompletableFuture;\n+import java.util.concurrent.ScheduledExecutorService;\n+import java.util.concurrent.ScheduledFuture;\n+import java.util.concurrent.TimeUnit;\n+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;\n+\n+/**\n+ * The default {@link LockManager} implementation for transactional and non-transactional caches.\n+ *\n+ * @author Pedro Ruivo\n+ * @since 8.0\n+ */\n+@MBean(objectName = \"LockManager\", description = \"Manager that handles MVCC locks for entries\")\n+public class DefaultLockManager implements LockManager {\n+\n+   private static final Log log = LogFactory.getLog(DefaultLockManager.class);\n+   private static final boolean trace = log.isTraceEnabled();\n+   protected LockContainer lockContainer;\n+   protected Configuration configuration;\n+   protected ScheduledExecutorService scheduler;\n+\n+   @Inject\n+   public void inject(LockContainer container, Configuration configuration,\n+                      @ComponentName(KnownComponentNames.TIMEOUT_SCHEDULE_EXECUTOR) ScheduledExecutorService executorService) {\n+      this.lockContainer = container;\n+      this.configuration = configuration;\n+      this.scheduler = executorService;\n+   }\n+\n+\n+   @Override\n+   public KeyAwareLockPromise lock(Object key, Object lockOwner, long time, TimeUnit unit) {\n+      Objects.requireNonNull(key, \"Key must be non null\");\n+      Objects.requireNonNull(lockOwner, \"Lock owner must be non null\");\n+      Objects.requireNonNull(unit, \"Time unit must be non null\");\n+\n+      if (trace) {\n+         log.tracef(\"Lock key=%s for owner=%s. timeout=%s (%s)\", key, lockOwner, time, unit);\n+      }\n+\n+      ExtendedLockPromise promise = lockContainer.acquire(key, lockOwner, time, unit);\n+      scheduleLockPromise(promise, time, unit);\n+      return new KeyAwareExtendedLockPromise(promise, key, unit.toMillis(time));\n+   }\n+\n+   @Override\n+   public KeyAwareLockPromise lockAll(Collection<?> keys, Object lockOwner, long time, TimeUnit unit) {\n+      Objects.requireNonNull(keys, \"Keys must be non null\");\n+      Objects.requireNonNull(lockOwner, \"Lock owner must be non null\");\n+      Objects.requireNonNull(unit, \"Time unit must be non null\");\n+\n+      if (keys.isEmpty()) {\n+         if (trace) {\n+            log.tracef(\"Lock all: no keys found for owner=%s\", lockOwner);\n+         }\n+         return KeyAwareLockPromise.NO_OP;\n+      } else if (keys.size() == 1) {\n+         //although will have the cost of creating an iterator, at least, we don't need to enter the synchronized section.\n+         return lock(keys.iterator().next(), lockOwner, time, unit);\n+      }\n+\n+      final Set<Object> uniqueKeys = filterDistinctKeys(keys);\n+\n+      if (uniqueKeys.isEmpty()) {\n+         if (trace) {\n+            log.tracef(\"Lock all: no keys found for owner=%s\", lockOwner);\n+         }\n+         return KeyAwareLockPromise.NO_OP;\n+      } else if (uniqueKeys.size() == 1) {\n+         //although will have the cost of creating an iterator, at least, we don't need to enter the synchronized section.\n+         return lock(uniqueKeys.iterator().next(), lockOwner, time, unit);\n+      }\n+\n+      if (trace) {\n+         log.tracef(\"Lock all keys=%s for owner=%s. timeout=%s (%s)\", uniqueKeys, lockOwner, time, unit);\n+      }\n+\n+      final CompositeLockPromise compositeLockPromise = new CompositeLockPromise(uniqueKeys.size());\n+      synchronized (this) {","path":"core/src/main/java/org/infinispan/util/concurrent/locks/impl/DefaultLockManager.java","position":110,"original_position":110,"commit_id":"90fbc251fd23ff7c352ff06f6e73ded5b2e2f711","original_commit_id":"90fbc251fd23ff7c352ff06f6e73ded5b2e2f711","user":{"login":"danberindei","id":504907,"avatar_url":"https://avatars.githubusercontent.com/u/504907?v=3","gravatar_id":"","url":"https://api.github.com/users/danberindei","html_url":"https://github.com/danberindei","followers_url":"https://api.github.com/users/danberindei/followers","following_url":"https://api.github.com/users/danberindei/following{/other_user}","gists_url":"https://api.github.com/users/danberindei/gists{/gist_id}","starred_url":"https://api.github.com/users/danberindei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danberindei/subscriptions","organizations_url":"https://api.github.com/users/danberindei/orgs","repos_url":"https://api.github.com/users/danberindei/repos","events_url":"https://api.github.com/users/danberindei/events{/privacy}","received_events_url":"https://api.github.com/users/danberindei/received_events","type":"User","site_admin":false},"body":"A comment on why we need the synchronization would be nice.","created_at":"2015-07-31T12:20:46Z","updated_at":"2015-07-31T12:20:46Z","html_url":"https://github.com/infinispan/infinispan/pull/3606#discussion_r35968352","pull_request_url":"https://api.github.com/repos/infinispan/infinispan/pulls/3606","_links":{"self":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/comments/35968352"},"html":{"href":"https://github.com/infinispan/infinispan/pull/3606#discussion_r35968352"},"pull_request":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/3606"}}},"pull_request":{"url":"https://api.github.com/repos/infinispan/infinispan/pulls/3606","id":40779538,"html_url":"https://github.com/infinispan/infinispan/pull/3606","diff_url":"https://github.com/infinispan/infinispan/pull/3606.diff","patch_url":"https://github.com/infinispan/infinispan/pull/3606.patch","issue_url":"https://api.github.com/repos/infinispan/infinispan/issues/3606","number":3606,"state":"open","locked":false,"title":"ISPN-2849 Don't keep threads blocked when waiting for locks to be rel…","user":{"login":"pruivo","id":1492066,"avatar_url":"https://avatars.githubusercontent.com/u/1492066?v=3","gravatar_id":"","url":"https://api.github.com/users/pruivo","html_url":"https://github.com/pruivo","followers_url":"https://api.github.com/users/pruivo/followers","following_url":"https://api.github.com/users/pruivo/following{/other_user}","gists_url":"https://api.github.com/users/pruivo/gists{/gist_id}","starred_url":"https://api.github.com/users/pruivo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pruivo/subscriptions","organizations_url":"https://api.github.com/users/pruivo/orgs","repos_url":"https://api.github.com/users/pruivo/repos","events_url":"https://api.github.com/users/pruivo/events{/privacy}","received_events_url":"https://api.github.com/users/pruivo/received_events","type":"User","site_admin":false},"body":"…eased\r\n\r\nhttps://issues.jboss.org/browse/ISPN-2849\r\n\r\nanother huge PR unfortunately :( ","created_at":"2015-07-24T14:21:04Z","updated_at":"2015-07-31T12:20:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c77873c9034836940336103f36cee646f7ef965b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/infinispan/infinispan/pulls/3606/commits","review_comments_url":"https://api.github.com/repos/infinispan/infinispan/pulls/3606/comments","review_comment_url":"https://api.github.com/repos/infinispan/infinispan/pulls/comments{/number}","comments_url":"https://api.github.com/repos/infinispan/infinispan/issues/3606/comments","statuses_url":"https://api.github.com/repos/infinispan/infinispan/statuses/90fbc251fd23ff7c352ff06f6e73ded5b2e2f711","head":{"label":"pruivo:ISPN-2849/remote_locks_v3","ref":"ISPN-2849/remote_locks_v3","sha":"90fbc251fd23ff7c352ff06f6e73ded5b2e2f711","user":{"login":"pruivo","id":1492066,"avatar_url":"https://avatars.githubusercontent.com/u/1492066?v=3","gravatar_id":"","url":"https://api.github.com/users/pruivo","html_url":"https://github.com/pruivo","followers_url":"https://api.github.com/users/pruivo/followers","following_url":"https://api.github.com/users/pruivo/following{/other_user}","gists_url":"https://api.github.com/users/pruivo/gists{/gist_id}","starred_url":"https://api.github.com/users/pruivo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pruivo/subscriptions","organizations_url":"https://api.github.com/users/pruivo/orgs","repos_url":"https://api.github.com/users/pruivo/repos","events_url":"https://api.github.com/users/pruivo/events{/privacy}","received_events_url":"https://api.github.com/users/pruivo/received_events","type":"User","site_admin":false},"repo":{"id":3626075,"name":"infinispan","full_name":"pruivo/infinispan","owner":{"login":"pruivo","id":1492066,"avatar_url":"https://avatars.githubusercontent.com/u/1492066?v=3","gravatar_id":"","url":"https://api.github.com/users/pruivo","html_url":"https://github.com/pruivo","followers_url":"https://api.github.com/users/pruivo/followers","following_url":"https://api.github.com/users/pruivo/following{/other_user}","gists_url":"https://api.github.com/users/pruivo/gists{/gist_id}","starred_url":"https://api.github.com/users/pruivo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pruivo/subscriptions","organizations_url":"https://api.github.com/users/pruivo/orgs","repos_url":"https://api.github.com/users/pruivo/repos","events_url":"https://api.github.com/users/pruivo/events{/privacy}","received_events_url":"https://api.github.com/users/pruivo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pruivo/infinispan","description":"Infinispan is an open source data grid platform and highly scalable NoSQL cloud data store.","fork":true,"url":"https://api.github.com/repos/pruivo/infinispan","forks_url":"https://api.github.com/repos/pruivo/infinispan/forks","keys_url":"https://api.github.com/repos/pruivo/infinispan/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pruivo/infinispan/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pruivo/infinispan/teams","hooks_url":"https://api.github.com/repos/pruivo/infinispan/hooks","issue_events_url":"https://api.github.com/repos/pruivo/infinispan/issues/events{/number}","events_url":"https://api.github.com/repos/pruivo/infinispan/events","assignees_url":"https://api.github.com/repos/pruivo/infinispan/assignees{/user}","branches_url":"https://api.github.com/repos/pruivo/infinispan/branches{/branch}","tags_url":"https://api.github.com/repos/pruivo/infinispan/tags","blobs_url":"https://api.github.com/repos/pruivo/infinispan/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pruivo/infinispan/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pruivo/infinispan/git/refs{/sha}","trees_url":"https://api.github.com/repos/pruivo/infinispan/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pruivo/infinispan/statuses/{sha}","languages_url":"https://api.github.com/repos/pruivo/infinispan/languages","stargazers_url":"https://api.github.com/repos/pruivo/infinispan/stargazers","contributors_url":"https://api.github.com/repos/pruivo/infinispan/contributors","subscribers_url":"https://api.github.com/repos/pruivo/infinispan/subscribers","subscription_url":"https://api.github.com/repos/pruivo/infinispan/subscription","commits_url":"https://api.github.com/repos/pruivo/infinispan/commits{/sha}","git_commits_url":"https://api.github.com/repos/pruivo/infinispan/git/commits{/sha}","comments_url":"https://api.github.com/repos/pruivo/infinispan/comments{/number}","issue_comment_url":"https://api.github.com/repos/pruivo/infinispan/issues/comments{/number}","contents_url":"https://api.github.com/repos/pruivo/infinispan/contents/{+path}","compare_url":"https://api.github.com/repos/pruivo/infinispan/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pruivo/infinispan/merges","archive_url":"https://api.github.com/repos/pruivo/infinispan/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pruivo/infinispan/downloads","issues_url":"https://api.github.com/repos/pruivo/infinispan/issues{/number}","pulls_url":"https://api.github.com/repos/pruivo/infinispan/pulls{/number}","milestones_url":"https://api.github.com/repos/pruivo/infinispan/milestones{/number}","notifications_url":"https://api.github.com/repos/pruivo/infinispan/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pruivo/infinispan/labels{/name}","releases_url":"https://api.github.com/repos/pruivo/infinispan/releases{/id}","created_at":"2012-03-05T10:40:21Z","updated_at":"2015-05-08T17:30:13Z","pushed_at":"2015-07-29T13:28:12Z","git_url":"git://github.com/pruivo/infinispan.git","ssh_url":"git@github.com:pruivo/infinispan.git","clone_url":"https://github.com/pruivo/infinispan.git","svn_url":"https://github.com/pruivo/infinispan","homepage":"http://www.infinispan.org","size":77621,"stargazers_count":3,"watchers_count":3,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6,"mirror_url":null,"open_issues_count":0,"forks":6,"open_issues":0,"watchers":3,"default_branch":"master"}},"base":{"label":"infinispan:master","ref":"master","sha":"8122b30e87cdcccf559dce7cf1bdee9e7eabeb1f","user":{"login":"infinispan","id":458093,"avatar_url":"https://avatars.githubusercontent.com/u/458093?v=3","gravatar_id":"","url":"https://api.github.com/users/infinispan","html_url":"https://github.com/infinispan","followers_url":"https://api.github.com/users/infinispan/followers","following_url":"https://api.github.com/users/infinispan/following{/other_user}","gists_url":"https://api.github.com/users/infinispan/gists{/gist_id}","starred_url":"https://api.github.com/users/infinispan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/infinispan/subscriptions","organizations_url":"https://api.github.com/users/infinispan/orgs","repos_url":"https://api.github.com/users/infinispan/repos","events_url":"https://api.github.com/users/infinispan/events{/privacy}","received_events_url":"https://api.github.com/users/infinispan/received_events","type":"Organization","site_admin":false},"repo":{"id":1050944,"name":"infinispan","full_name":"infinispan/infinispan","owner":{"login":"infinispan","id":458093,"avatar_url":"https://avatars.githubusercontent.com/u/458093?v=3","gravatar_id":"","url":"https://api.github.com/users/infinispan","html_url":"https://github.com/infinispan","followers_url":"https://api.github.com/users/infinispan/followers","following_url":"https://api.github.com/users/infinispan/following{/other_user}","gists_url":"https://api.github.com/users/infinispan/gists{/gist_id}","starred_url":"https://api.github.com/users/infinispan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/infinispan/subscriptions","organizations_url":"https://api.github.com/users/infinispan/orgs","repos_url":"https://api.github.com/users/infinispan/repos","events_url":"https://api.github.com/users/infinispan/events{/privacy}","received_events_url":"https://api.github.com/users/infinispan/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/infinispan/infinispan","description":"Infinispan is an open source data grid platform and highly scalable NoSQL cloud data store.","fork":false,"url":"https://api.github.com/repos/infinispan/infinispan","forks_url":"https://api.github.com/repos/infinispan/infinispan/forks","keys_url":"https://api.github.com/repos/infinispan/infinispan/keys{/key_id}","collaborators_url":"https://api.github.com/repos/infinispan/infinispan/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/infinispan/infinispan/teams","hooks_url":"https://api.github.com/repos/infinispan/infinispan/hooks","issue_events_url":"https://api.github.com/repos/infinispan/infinispan/issues/events{/number}","events_url":"https://api.github.com/repos/infinispan/infinispan/events","assignees_url":"https://api.github.com/repos/infinispan/infinispan/assignees{/user}","branches_url":"https://api.github.com/repos/infinispan/infinispan/branches{/branch}","tags_url":"https://api.github.com/repos/infinispan/infinispan/tags","blobs_url":"https://api.github.com/repos/infinispan/infinispan/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/infinispan/infinispan/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/infinispan/infinispan/git/refs{/sha}","trees_url":"https://api.github.com/repos/infinispan/infinispan/git/trees{/sha}","statuses_url":"https://api.github.com/repos/infinispan/infinispan/statuses/{sha}","languages_url":"https://api.github.com/repos/infinispan/infinispan/languages","stargazers_url":"https://api.github.com/repos/infinispan/infinispan/stargazers","contributors_url":"https://api.github.com/repos/infinispan/infinispan/contributors","subscribers_url":"https://api.github.com/repos/infinispan/infinispan/subscribers","subscription_url":"https://api.github.com/repos/infinispan/infinispan/subscription","commits_url":"https://api.github.com/repos/infinispan/infinispan/commits{/sha}","git_commits_url":"https://api.github.com/repos/infinispan/infinispan/git/commits{/sha}","comments_url":"https://api.github.com/repos/infinispan/infinispan/comments{/number}","issue_comment_url":"https://api.github.com/repos/infinispan/infinispan/issues/comments{/number}","contents_url":"https://api.github.com/repos/infinispan/infinispan/contents/{+path}","compare_url":"https://api.github.com/repos/infinispan/infinispan/compare/{base}...{head}","merges_url":"https://api.github.com/repos/infinispan/infinispan/merges","archive_url":"https://api.github.com/repos/infinispan/infinispan/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/infinispan/infinispan/downloads","issues_url":"https://api.github.com/repos/infinispan/infinispan/issues{/number}","pulls_url":"https://api.github.com/repos/infinispan/infinispan/pulls{/number}","milestones_url":"https://api.github.com/repos/infinispan/infinispan/milestones{/number}","notifications_url":"https://api.github.com/repos/infinispan/infinispan/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/infinispan/infinispan/labels{/name}","releases_url":"https://api.github.com/repos/infinispan/infinispan/releases{/id}","created_at":"2010-11-04T12:33:19Z","updated_at":"2015-07-29T13:47:37Z","pushed_at":"2015-07-31T09:25:17Z","git_url":"git://github.com/infinispan/infinispan.git","ssh_url":"git@github.com:infinispan/infinispan.git","clone_url":"https://github.com/infinispan/infinispan.git","svn_url":"https://github.com/infinispan/infinispan","homepage":"http://www.infinispan.org","size":155703,"stargazers_count":391,"watchers_count":391,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":297,"mirror_url":null,"open_issues_count":16,"forks":297,"open_issues":16,"watchers":391,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/3606"},"html":{"href":"https://github.com/infinispan/infinispan/pull/3606"},"issue":{"href":"https://api.github.com/repos/infinispan/infinispan/issues/3606"},"comments":{"href":"https://api.github.com/repos/infinispan/infinispan/issues/3606/comments"},"review_comments":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/3606/comments"},"review_comment":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/infinispan/infinispan/pulls/3606/commits"},"statuses":{"href":"https://api.github.com/repos/infinispan/infinispan/statuses/90fbc251fd23ff7c352ff06f6e73ded5b2e2f711"}}}}