package simpledb;

import java.lang.*;
import java.util.*;
import java.util.concurrent.*;

/**
 * Timeout-based deadlock detector. This detector operates by spawning
 * a thread that periodically checks the list of pending lock requests
 * for ones that have been running for longer than a specified
 * timeout, and aborts one.
 *
 * @author <a href="mailto:drkp@mit.edu">Dan R. K. Ports</a>
 */
public class TimeoutDeadlockDetector extends AbstractDeadlockDetector {

    private final long timeoutMillis;
    private final long checkIntervalMillis;
    
    public TimeoutDeadlockDetector(LockManager lm,
                                   long timeoutMillis_,
                                   long checkIntervalMillis_) {
        super(lm);
        this.timeoutMillis = timeoutMillis_;
        this.checkIntervalMillis = checkIntervalMillis_;

        Runnable runnable = new Runnable() {
                public void run() {
                    while (true) {
                        checkForDeadlock();
                        try {
                            Thread.sleep(checkIntervalMillis);
                        } catch (InterruptedException e) {
                            // ignore
                        }
                    }
                }
            };
        Thread t = new Thread(runnable);
        t.setDaemon(true);
        t.start();
    }

    private synchronized void checkForDeadlock() {
        for (List<LockRequest> reqs : lockRequestsByPid.values()) {
            for (LockRequest req : reqs) {
                if ((System.currentTimeMillis() - req.requestTime)
                    > timeoutMillis) {
                    // Lock request has been pending too long. Break
                    // deadlock.
                    breakDeadlock(req);
                }
            }
        }
    }
}
