package uk.ac.ic.wlgitbridge.data;

import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by Winston on 20/11/14.
 */
public class ProjectLockImpl implements ProjectLock {

    private final Map<String, Lock> projectLocks;
    private final ReentrantReadWriteLock rwlock;
    private final Lock rlock;
    private final ReentrantReadWriteLock.WriteLock wlock;
    private LockAllWaiter waiter;
    private boolean waiting;

    public ProjectLockImpl() {
        projectLocks = new HashMap<String, Lock>();
        rwlock = new ReentrantReadWriteLock();
        rlock = rwlock.readLock();
        wlock = rwlock.writeLock();
        waiting = false;
    }

    public ProjectLockImpl(LockAllWaiter waiter) {
        this();
        setWaiter(waiter);
    }

    @Override
    public void lockForProject(String projectName) {
        getLockForProjectName(projectName).lock();
        rlock.lock();
    }

    @Override
    public void unlockForProject(String projectName) {
        getLockForProjectName(projectName).unlock();
        rlock.unlock();
        if (waiting) {
            trySignal();
        }
    }

    private void trySignal() {
        int threads = rwlock.getReadLockCount();
        if (waiter != null && threads > 0) {
            waiter.threadsRemaining(threads);
        }
    }

    public void lockAll() {
        waiting = true;
        trySignal();
        wlock.lock();
    }

    private synchronized Lock getLockForProjectName(String projectName) {
        Lock lock = projectLocks.get(projectName);
        if (lock == null) {
            lock = new ReentrantLock();
            projectLocks.put(projectName, lock);
        }
        return lock;
    }

    public void setWaiter(LockAllWaiter waiter) {
        this.waiter = waiter;
    }

}

@@ -277,16 +277,54 @@
 iteLock;
+%0Aimport uk.ac.ic.wlgitbridge.util.Log;
 %0A%0A/**%0A *
@@ -1079,248 +1079,679 @@
     
-getLockForProjectName(projectName).lock();%0A        rlock.lock();%0A    %7D%0A%0A    @Override%0A    public void unlockForProject(String projectName) %7B%0A        getLockForProjectName(projectName).unlock();%0A        rlock.unlock();%0A        if (waiting) %7B
+Log.debug(%22%5B%7B%7D%5D taking project lock%22, projectName);%0A        getLockForProjectName(projectName).lock();%0A        Log.debug(%22%5B%7B%7D%5D taking reentrant lock%22, projectName);%0A        rlock.lock();%0A        Log.debug(%22%5B%7B%7D%5D taken locks%22, projectName);%0A    %7D%0A%0A    @Override%0A    public void unlockForProject(String projectName) %7B%0A        Log.debug(%22%5B%7B%7D%5D releasing project lock%22, projectName);%0A        getLockForProjectName(projectName).unlock();%0A        Log.debug(%22%5B%7B%7D%5D releasing reentrant lock%22, projectName);%0A        rlock.unlock();%0A        Log.debug(%22%5B%7B%7D%5D released locks%22, projectName);%0A        if (waiting) %7B%0A            Log.debug(%22%5B%7B%7D%5D waiting for remaining threads%22, projectName);
 %0A   
@@ -1865,24 +1865,81 @@
 ockCount();%0A
+        Log.debug(%22-%3E waiting for %7B%7D threads%22, threads);%0A
         if (
@@ -2035,81 +2035,234 @@
     
-%7D%0A%0A    public void lockAll() %7B%0A        waiting = true;%0A        trySignal(
+    Log.debug(%22-%3E finished waiting for threads%22);%0A    %7D%0A%0A    public void lockAll() %7B%0A        Log.debug(%22-%3E locking all threads%22);%0A        waiting = true;%0A        trySignal();%0A        Log.debug(%22-%3E locking reentrant write lock%22
 );%0A 

Add debug logs to project lock mechanism