You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ignite.apache.org by GitBox <gi...@apache.org> on 2020/12/02 10:59:38 UTC

[GitHub] [ignite] akalash commented on a change in pull request #8516: IGNITE-13775 checkpointRWLock wrapper refactoring.

akalash commented on a change in pull request #8516:
URL: https://github.com/apache/ignite/pull/8516#discussion_r534074704



##########
File path: modules/core/src/main/java/org/apache/ignite/internal/util/ReentrantReadWriteLockWithTracking.java
##########
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.util.IgniteUtils.nl;
+
+/** */
+public class ReentrantReadWriteLockWithTracking implements ReadWriteLock {
+    /** Lock hold message. */
+    public static final String LOCK_HOLD_MESSAGE = "ReadLock held the lock more than ";
+
+    /** Lock print threshold. */
+    private long readLockThreshold;
+
+    /** Delegate instance. */
+    private final ReentrantReadWriteLock delegate = new ReentrantReadWriteLock();
+
+    /** Read lock holder. */
+    private ReentrantReadWriteLockWithTracking.ReadLock readLock;
+
+    /** Write lock holder. */
+    private ReentrantReadWriteLockWithTracking.WriteLock writeLock = new ReentrantReadWriteLockWithTracking.WriteLock(delegate);
+
+    /**
+     * ReentrantRWLock wrapper, provides additional trace info on {@link ReadLockWithTracking#unlock()} method, if someone
+     * holds the lock more than {@code readLockThreshold}.
+     *
+     * @param log Ignite logger.
+     * @param readLockThreshold ReadLock threshold timeout.
+     */
+    public ReentrantReadWriteLockWithTracking(IgniteLogger log, long readLockThreshold) {
+        readLock = new ReadLockWithTracking(delegate, log, readLockThreshold);
+
+        this.readLockThreshold = readLockThreshold;
+    }
+
+    /** Delegator implementation. */
+    public ReentrantReadWriteLockWithTracking() {
+        readLock = new ReentrantReadWriteLockWithTracking.ReadLock(delegate);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.ReadLock readLock() {

Review comment:
       Do you really need ReentrantReadWriteLockWithTracking.ReadLock here? Maybe it makes sense to change it to java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock?

##########
File path: modules/core/src/main/java/org/apache/ignite/internal/util/ReentrantReadWriteLockWithTracking.java
##########
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.util.IgniteUtils.nl;
+
+/** */
+public class ReentrantReadWriteLockWithTracking implements ReadWriteLock {
+    /** Lock hold message. */
+    public static final String LOCK_HOLD_MESSAGE = "ReadLock held the lock more than ";
+
+    /** Lock print threshold. */
+    private long readLockThreshold;
+
+    /** Delegate instance. */
+    private final ReentrantReadWriteLock delegate = new ReentrantReadWriteLock();
+
+    /** Read lock holder. */
+    private ReentrantReadWriteLockWithTracking.ReadLock readLock;
+
+    /** Write lock holder. */
+    private ReentrantReadWriteLockWithTracking.WriteLock writeLock = new ReentrantReadWriteLockWithTracking.WriteLock(delegate);
+
+    /**
+     * ReentrantRWLock wrapper, provides additional trace info on {@link ReadLockWithTracking#unlock()} method, if someone
+     * holds the lock more than {@code readLockThreshold}.
+     *
+     * @param log Ignite logger.
+     * @param readLockThreshold ReadLock threshold timeout.
+     */
+    public ReentrantReadWriteLockWithTracking(IgniteLogger log, long readLockThreshold) {
+        readLock = new ReadLockWithTracking(delegate, log, readLockThreshold);
+
+        this.readLockThreshold = readLockThreshold;
+    }
+
+    /** Delegator implementation. */
+    public ReentrantReadWriteLockWithTracking() {
+        readLock = new ReentrantReadWriteLockWithTracking.ReadLock(delegate);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.ReadLock readLock() {
+        return readLock;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.WriteLock writeLock() {
+        return writeLock;
+    }
+
+    /** */
+    public long lockWaitThreshold() {
+        return readLockThreshold;
+    }
+
+    /**
+     * Queries if the write lock is held by the current thread.
+     *
+     * @return {@code true} if the current thread holds the write lock and
+     *         {@code false} otherwise
+     */
+    public boolean isWriteLockedByCurrentThread() {
+        return delegate.isWriteLockedByCurrentThread();
+    }
+
+    /**
+     * Queries the number of reentrant read holds on this lock by the
+     * current thread.  A reader thread has a hold on a lock for
+     * each lock action that is not matched by an unlock action.
+     *
+     * @return the number of holds on the read lock by the current thread,
+     *         or zero if the read lock is not held by the current thread
+     */
+    public int getReadHoldCount() {
+        return delegate.getReadHoldCount();
+    }
+
+    /**
+     * Queries the number of read locks held for this lock. This
+     * method is designed for use in monitoring system state, not for
+     * synchronization control.
+     * @return the number of read locks held
+     */
+    public int getReadLockCount() {
+        return delegate.getReadLockCount();
+    }
+
+    /** */
+    public static class WriteLock implements Lock {
+        /** Delegate instance. */
+        private final ReentrantReadWriteLock delegate;
+
+        /** */
+        public WriteLock(ReentrantReadWriteLock lock) {
+            delegate = lock;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lock() {
+            delegate.writeLock().lock();
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lockInterruptibly() throws InterruptedException {
+            delegate.writeLock().lockInterruptibly();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock() {
+            return delegate.writeLock().tryLock();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException {
+            return delegate.writeLock().tryLock(time, unit);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void unlock() {
+            delegate.writeLock().unlock();
+        }
+
+        /** {@inheritDoc} */
+        @NotNull @Override public Condition newCondition() {
+            return delegate.writeLock().newCondition();
+        }
+
+        /**
+         * Queries if this write lock is held by the current thread.
+         * Identical in effect to {@link
+         * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
+         *
+         * @return {@code true} if the current thread holds this lock and
+         *         {@code false} otherwise
+         */
+        public boolean isHeldByCurrentThread() {
+            return delegate.writeLock().isHeldByCurrentThread();
+        }
+    }
+
+    /** Tracks long rlock holders. */
+    public static class ReadLockWithTracking extends ReadLock {
+        /**
+         * Delegate instance.
+         */
+        private final ReentrantReadWriteLock delegate;
+
+        /** */
+        private static final ThreadLocal<T2<Integer, Long>> READ_LOCK_HOLDER_TS =
+            ThreadLocal.withInitial(() -> new T2<>(0, 0L));
+
+        /** */
+        private IgniteLogger log;
+
+        /** */
+        private long readLockThreshold;
+
+        /** */
+        protected ReadLockWithTracking(ReentrantReadWriteLock lock, @Nullable IgniteLogger log, long readLockThreshold) {
+            super(lock);
+
+            delegate = lock;
+
+            this.log = log;
+
+            this.readLockThreshold = readLockThreshold;
+        }
+
+        /** */
+        private void inc() {
+            T2<Integer, Long> val = READ_LOCK_HOLDER_TS.get();
+
+            int cntr = val.get1();
+
+            if (cntr == 0)
+                val.set2(U.currentTimeMillis());
+
+            val.set1(++cntr);
+
+            READ_LOCK_HOLDER_TS.set(val);
+        }
+
+        /** */
+        private void dec() {
+            T2<Integer, Long> val = READ_LOCK_HOLDER_TS.get();
+
+            int cntr = val.get1();
+
+            if (--cntr == 0) {
+                long timeout = U.currentTimeMillis() - val.get2();
+
+                if (timeout > readLockThreshold) {
+                    GridStringBuilder sb = new GridStringBuilder();
+
+                    sb.a(LOCK_HOLD_MESSAGE + timeout + " ms." + nl());
+
+                    U.printStackTrace(Thread.currentThread().getId(), sb);
+
+                    U.warn(log, sb.toString());
+                }
+            }
+
+            val.set1(cntr);
+
+            READ_LOCK_HOLDER_TS.set(val);
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lock() {
+            delegate.readLock().lock();
+
+            inc();
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lockInterruptibly() throws InterruptedException {
+            delegate.readLock().lockInterruptibly();
+
+            inc();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock() {
+            if (delegate.readLock().tryLock()) {
+                inc();
+
+                return true;
+            }
+            else
+                return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+            if (delegate.readLock().tryLock(timeout, unit)) {
+                inc();
+
+                return true;
+            }
+            else
+                return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void unlock() {
+            delegate.readLock().unlock();
+
+            dec();
+        }
+    }
+
+    /** Default implementation. */
+    public static class ReadLock implements Lock {

Review comment:
       Can be removed if we will change the return type in the method above.

##########
File path: modules/core/src/main/java/org/apache/ignite/internal/util/ReentrantReadWriteLockWithTracking.java
##########
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.util.IgniteUtils.nl;
+
+/** */
+public class ReentrantReadWriteLockWithTracking implements ReadWriteLock {
+    /** Lock hold message. */
+    public static final String LOCK_HOLD_MESSAGE = "ReadLock held the lock more than ";
+
+    /** Lock print threshold. */
+    private long readLockThreshold;
+
+    /** Delegate instance. */
+    private final ReentrantReadWriteLock delegate = new ReentrantReadWriteLock();
+
+    /** Read lock holder. */
+    private ReentrantReadWriteLockWithTracking.ReadLock readLock;
+
+    /** Write lock holder. */
+    private ReentrantReadWriteLockWithTracking.WriteLock writeLock = new ReentrantReadWriteLockWithTracking.WriteLock(delegate);
+
+    /**
+     * ReentrantRWLock wrapper, provides additional trace info on {@link ReadLockWithTracking#unlock()} method, if someone
+     * holds the lock more than {@code readLockThreshold}.
+     *
+     * @param log Ignite logger.
+     * @param readLockThreshold ReadLock threshold timeout.
+     */
+    public ReentrantReadWriteLockWithTracking(IgniteLogger log, long readLockThreshold) {
+        readLock = new ReadLockWithTracking(delegate, log, readLockThreshold);
+
+        this.readLockThreshold = readLockThreshold;
+    }
+
+    /** Delegator implementation. */
+    public ReentrantReadWriteLockWithTracking() {
+        readLock = new ReentrantReadWriteLockWithTracking.ReadLock(delegate);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.ReadLock readLock() {
+        return readLock;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.WriteLock writeLock() {

Review comment:
       Do you really need ReentrantReadWriteLockWithTracking.WriteLock here? Maybe it makes sense to change it to java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock?

##########
File path: modules/core/src/main/java/org/apache/ignite/internal/util/ReentrantReadWriteLockWithTracking.java
##########
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.util.IgniteUtils.nl;
+
+/** */
+public class ReentrantReadWriteLockWithTracking implements ReadWriteLock {
+    /** Lock hold message. */
+    public static final String LOCK_HOLD_MESSAGE = "ReadLock held the lock more than ";
+
+    /** Lock print threshold. */
+    private long readLockThreshold;
+
+    /** Delegate instance. */
+    private final ReentrantReadWriteLock delegate = new ReentrantReadWriteLock();
+
+    /** Read lock holder. */
+    private ReentrantReadWriteLockWithTracking.ReadLock readLock;
+
+    /** Write lock holder. */
+    private ReentrantReadWriteLockWithTracking.WriteLock writeLock = new ReentrantReadWriteLockWithTracking.WriteLock(delegate);
+
+    /**
+     * ReentrantRWLock wrapper, provides additional trace info on {@link ReadLockWithTracking#unlock()} method, if someone
+     * holds the lock more than {@code readLockThreshold}.
+     *
+     * @param log Ignite logger.
+     * @param readLockThreshold ReadLock threshold timeout.
+     */
+    public ReentrantReadWriteLockWithTracking(IgniteLogger log, long readLockThreshold) {
+        readLock = new ReadLockWithTracking(delegate, log, readLockThreshold);
+
+        this.readLockThreshold = readLockThreshold;
+    }
+
+    /** Delegator implementation. */
+    public ReentrantReadWriteLockWithTracking() {
+        readLock = new ReentrantReadWriteLockWithTracking.ReadLock(delegate);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.ReadLock readLock() {
+        return readLock;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.WriteLock writeLock() {
+        return writeLock;
+    }
+
+    /** */
+    public long lockWaitThreshold() {
+        return readLockThreshold;
+    }
+
+    /**
+     * Queries if the write lock is held by the current thread.
+     *
+     * @return {@code true} if the current thread holds the write lock and
+     *         {@code false} otherwise
+     */
+    public boolean isWriteLockedByCurrentThread() {
+        return delegate.isWriteLockedByCurrentThread();
+    }
+
+    /**
+     * Queries the number of reentrant read holds on this lock by the
+     * current thread.  A reader thread has a hold on a lock for
+     * each lock action that is not matched by an unlock action.
+     *
+     * @return the number of holds on the read lock by the current thread,
+     *         or zero if the read lock is not held by the current thread
+     */
+    public int getReadHoldCount() {
+        return delegate.getReadHoldCount();
+    }
+
+    /**
+     * Queries the number of read locks held for this lock. This
+     * method is designed for use in monitoring system state, not for
+     * synchronization control.
+     * @return the number of read locks held
+     */
+    public int getReadLockCount() {
+        return delegate.getReadLockCount();
+    }
+
+    /** */
+    public static class WriteLock implements Lock {
+        /** Delegate instance. */
+        private final ReentrantReadWriteLock delegate;
+
+        /** */
+        public WriteLock(ReentrantReadWriteLock lock) {
+            delegate = lock;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lock() {
+            delegate.writeLock().lock();
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lockInterruptibly() throws InterruptedException {
+            delegate.writeLock().lockInterruptibly();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock() {
+            return delegate.writeLock().tryLock();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean tryLock(long time, @NotNull TimeUnit unit) throws InterruptedException {
+            return delegate.writeLock().tryLock(time, unit);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void unlock() {
+            delegate.writeLock().unlock();
+        }
+
+        /** {@inheritDoc} */
+        @NotNull @Override public Condition newCondition() {
+            return delegate.writeLock().newCondition();
+        }
+
+        /**
+         * Queries if this write lock is held by the current thread.
+         * Identical in effect to {@link
+         * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
+         *
+         * @return {@code true} if the current thread holds this lock and
+         *         {@code false} otherwise
+         */
+        public boolean isHeldByCurrentThread() {
+            return delegate.writeLock().isHeldByCurrentThread();
+        }
+    }
+
+    /** Tracks long rlock holders. */
+    public static class ReadLockWithTracking extends ReadLock {
+        /**
+         * Delegate instance.
+         */
+        private final ReentrantReadWriteLock delegate;
+
+        /** */
+        private static final ThreadLocal<T2<Integer, Long>> READ_LOCK_HOLDER_TS =
+            ThreadLocal.withInitial(() -> new T2<>(0, 0L));
+
+        /** */
+        private IgniteLogger log;
+
+        /** */
+        private long readLockThreshold;
+
+        /** */
+        protected ReadLockWithTracking(ReentrantReadWriteLock lock, @Nullable IgniteLogger log, long readLockThreshold) {
+            super(lock);
+
+            delegate = lock;
+
+            this.log = log;
+
+            this.readLockThreshold = readLockThreshold;
+        }
+
+        /** */
+        private void inc() {
+            T2<Integer, Long> val = READ_LOCK_HOLDER_TS.get();
+
+            int cntr = val.get1();
+
+            if (cntr == 0)
+                val.set2(U.currentTimeMillis());
+
+            val.set1(++cntr);
+
+            READ_LOCK_HOLDER_TS.set(val);
+        }
+
+        /** */
+        private void dec() {
+            T2<Integer, Long> val = READ_LOCK_HOLDER_TS.get();
+
+            int cntr = val.get1();
+
+            if (--cntr == 0) {
+                long timeout = U.currentTimeMillis() - val.get2();
+
+                if (timeout > readLockThreshold) {
+                    GridStringBuilder sb = new GridStringBuilder();
+
+                    sb.a(LOCK_HOLD_MESSAGE + timeout + " ms." + nl());
+
+                    U.printStackTrace(Thread.currentThread().getId(), sb);
+
+                    U.warn(log, sb.toString());
+                }
+            }
+
+            val.set1(cntr);
+
+            READ_LOCK_HOLDER_TS.set(val);
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("LockAcquiredButNotSafelyReleased")
+        @Override public void lock() {
+            delegate.readLock().lock();

Review comment:
       As I understand here and in other methods super.{method} should be used.

##########
File path: modules/core/src/main/java/org/apache/ignite/internal/util/ReentrantReadWriteLockWithTracking.java
##########
@@ -0,0 +1,330 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.util.IgniteUtils.nl;
+
+/** */
+public class ReentrantReadWriteLockWithTracking implements ReadWriteLock {
+    /** Lock hold message. */
+    public static final String LOCK_HOLD_MESSAGE = "ReadLock held the lock more than ";
+
+    /** Lock print threshold. */
+    private long readLockThreshold;
+
+    /** Delegate instance. */
+    private final ReentrantReadWriteLock delegate = new ReentrantReadWriteLock();
+
+    /** Read lock holder. */
+    private ReentrantReadWriteLockWithTracking.ReadLock readLock;
+
+    /** Write lock holder. */
+    private ReentrantReadWriteLockWithTracking.WriteLock writeLock = new ReentrantReadWriteLockWithTracking.WriteLock(delegate);
+
+    /**
+     * ReentrantRWLock wrapper, provides additional trace info on {@link ReadLockWithTracking#unlock()} method, if someone
+     * holds the lock more than {@code readLockThreshold}.
+     *
+     * @param log Ignite logger.
+     * @param readLockThreshold ReadLock threshold timeout.
+     */
+    public ReentrantReadWriteLockWithTracking(IgniteLogger log, long readLockThreshold) {
+        readLock = new ReadLockWithTracking(delegate, log, readLockThreshold);
+
+        this.readLockThreshold = readLockThreshold;
+    }
+
+    /** Delegator implementation. */
+    public ReentrantReadWriteLockWithTracking() {
+        readLock = new ReentrantReadWriteLockWithTracking.ReadLock(delegate);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.ReadLock readLock() {
+        return readLock;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ReentrantReadWriteLockWithTracking.WriteLock writeLock() {
+        return writeLock;
+    }
+
+    /** */
+    public long lockWaitThreshold() {
+        return readLockThreshold;
+    }
+
+    /**
+     * Queries if the write lock is held by the current thread.
+     *
+     * @return {@code true} if the current thread holds the write lock and
+     *         {@code false} otherwise
+     */
+    public boolean isWriteLockedByCurrentThread() {
+        return delegate.isWriteLockedByCurrentThread();
+    }
+
+    /**
+     * Queries the number of reentrant read holds on this lock by the
+     * current thread.  A reader thread has a hold on a lock for
+     * each lock action that is not matched by an unlock action.
+     *
+     * @return the number of holds on the read lock by the current thread,
+     *         or zero if the read lock is not held by the current thread
+     */
+    public int getReadHoldCount() {
+        return delegate.getReadHoldCount();
+    }
+
+    /**
+     * Queries the number of read locks held for this lock. This
+     * method is designed for use in monitoring system state, not for
+     * synchronization control.
+     * @return the number of read locks held
+     */
+    public int getReadLockCount() {
+        return delegate.getReadLockCount();
+    }
+
+    /** */
+    public static class WriteLock implements Lock {

Review comment:
       Perhaps this class won't make any sense if we change the return type to java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock in the method above.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org