Advertisement
Guest User

Untitled

a guest
Feb 19th, 2018
47
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.90 KB | None | 0 0
  1. package simpledb;
  2.  
  3. import java.util.*;
  4. import java.util.concurrent.ConcurrentHashMap;
  5.  
  6. public class LockManager {
  7.  
  8.     private Map<PageId, Set<TransactionId>> pageShLocks;
  9.     private Map<PageId, TransactionId> pageExLocks;
  10.     private Map<TransactionId, Set<PageId>> txLocks;
  11.     private Map<TransactionId, Set<TransactionId>> deadlockMap;
  12.  
  13.     public LockManager() {
  14.         this.pageExLocks = new ConcurrentHashMap<>();
  15.         this.pageShLocks = new ConcurrentHashMap();
  16.         this.txLocks = new ConcurrentHashMap<>();
  17.         this.deadlockMap = new ConcurrentHashMap<>();
  18.     }
  19.  
  20.     /**
  21.      * Acquires a shared/exclusive lock on a page for a given transaction
  22.      * Adds an entry mapping the tid -> {pid} reflecting the tx holds a lock on the page
  23.      * @param tid the transaction id
  24.      * @param pid the page id for which to lock
  25.      * @param perm the permissions to determine if the lock should be shared or exlcusive
  26.      */
  27.     public void acquirePageLock(TransactionId tid, PageId pid, Permissions perm) throws TransactionAbortedException, InterruptedException {
  28.         System.out.println("Tx" + tid + " acquiring " + perm + " lock");
  29.         if (perm == Permissions.READ_ONLY) {
  30.             acquireSharedLock(tid, pid);
  31.         } else {
  32.             acquireExclusiveLock(tid, pid);
  33.         }
  34.  
  35.         System.out.println("Tx" + tid + " acquired " + perm + " lock");
  36.         // acquired lock
  37.         this.deadlockMap.remove(tid);
  38.  
  39.         // Maintain the which tx -> page lock entry
  40.         if (!this.txLocks.containsKey(tid)) {
  41.             this.txLocks.put(tid, new HashSet<>());
  42.         }
  43.         this.txLocks.get(tid).add(pid);
  44.     }
  45.  
  46.     public synchronized void acquireSharedLock(TransactionId tid, PageId pid) throws InterruptedException, TransactionAbortedException {
  47.         if (this.pageShLocks.containsKey(pid) && this.pageShLocks.get(pid).contains(tid)) {
  48.             return;
  49.         }
  50.         while (this.pageExLocks.containsKey(pid) && !this.pageExLocks.get(pid).equals(tid)) {
  51.             Set<TransactionId> dependencies = new HashSet<>();
  52.             dependencies.add(this.pageExLocks.get(pid));
  53.             mapDependency(tid, pid, dependencies);
  54.             wait();
  55.         }
  56.         grabSharedLock(tid, pid);
  57.     }
  58.  
  59.     public synchronized void acquireExclusiveLock(TransactionId tid, PageId pid) throws TransactionAbortedException, InterruptedException {
  60.         if (this.pageExLocks.containsKey(pid) && this.pageExLocks.get(pid).equals(tid)) {
  61.             return;
  62.         }
  63.         Set<TransactionId> dependencies = new HashSet<>();
  64.  
  65.         while ((this.pageExLocks.containsKey(pid) && !this.pageExLocks.get(pid).equals(tid)) ||
  66.                 (this.pageShLocks.containsKey(pid) &&
  67.                         ((this.pageShLocks.get(pid).contains(tid) && this.pageShLocks.get(pid).size() > 1) ||
  68.                         (!this.pageShLocks.get(pid).contains(tid) && this.pageShLocks.get(pid).size() > 0)))) {
  69.  
  70.             if (this.pageExLocks.containsKey(pid) && !this.pageExLocks.get(pid).equals(tid)) {
  71.                 dependencies.add(this.pageExLocks.get(pid));
  72.             }
  73.             if (this.pageShLocks.containsKey(pid)) {
  74.                 for (TransactionId depIds : this.pageShLocks.get(pid)) {
  75.                     dependencies.add(depIds);
  76.                 }
  77.             }
  78.             mapDependency(tid, pid, dependencies);
  79.             wait();
  80.         }
  81.         grabExLock(tid, pid);
  82.  
  83.     }
  84.  
  85.     private void grabSharedLock(TransactionId tid, PageId pid) {
  86.         if (!this.pageShLocks.containsKey(pid)) {
  87.             this.pageShLocks.put(pid, new HashSet<>());
  88.         }
  89.         this.pageShLocks.get(pid).add(tid);
  90.     }
  91.  
  92.     private void grabExLock(TransactionId tid, PageId pid) {
  93.         if (!this.pageExLocks.containsKey(pid)) {
  94.             this.pageExLocks.put(pid, tid);
  95.         }
  96.     }
  97.     /**
  98.      * Releases a shared/exclusive lock on a page for a given transaction
  99.      * Removes the entry tid -> {pid} reflecting the tx no longer holds a lock on the page
  100.      * @param tid the transaction id
  101.      * @param pid the page id for which to release the lock
  102.      */
  103.     public synchronized void releasePageLock(TransactionId tid, PageId pid) {
  104.         if (this.pageExLocks.containsKey(pid) && this.pageExLocks.get(pid).equals(tid)) {
  105.             // release write lock
  106.             this.pageExLocks.remove(pid);
  107.         }
  108.         if (this.pageShLocks.containsKey(pid) && this.pageShLocks.get(pid).contains(tid)) {
  109.             this.pageShLocks.get(pid).remove(tid);
  110.         }
  111.  
  112.         // Remove the entry if empty
  113.         if (this.pageShLocks.containsKey(pid) && this.pageShLocks.get(pid).isEmpty()) {
  114.             this.pageShLocks.remove(pid);
  115.         }
  116.  
  117.         this.removeDependency(tid);
  118.  
  119.         // Remove the tx -> page entry
  120.         this.txLocks.get(tid).remove(pid);
  121.  
  122.         // If tx has no more locks, remove its entry
  123.         if (this.txLocks.get(tid).size() == 0) {
  124.             this.txLocks.remove(tid);
  125.         }
  126.  
  127.         System.out.println("Tx" + tid + " release " + " lock");
  128.         notifyAll();
  129.     }
  130.  
  131.     /**
  132.      * Returns true if the given transaction id holds a lock on the page associated with the specified page id
  133.      * @param tid the transaction id
  134.      * @param pid the page id
  135.      * @return true if given transaction id holds a lock on the page
  136.      */
  137.     public synchronized boolean txHoldsLock(TransactionId tid, PageId pid) {
  138.         if (this.pageExLocks.containsKey(pid) && this.pageExLocks.get(pid).equals(tid)) {
  139.             return true;
  140.         }
  141.         if (this.pageShLocks.containsKey(pid) && this.pageShLocks.get(pid).contains(tid)) {
  142.             return true;
  143.         }
  144.         return false;
  145.     }
  146.  
  147.     /**
  148.      * Returns a set of page ids that the given transaction has a lock on
  149.      * @param tid
  150.      * @return
  151.      */
  152.     public synchronized Set<PageId> txPages(TransactionId tid) {
  153.         HashSet<PageId> s = new HashSet<>();
  154.         if (this.txLocks.containsKey(tid)) {
  155.             s.addAll(this.txLocks.get(tid));
  156.         }
  157.         return s;
  158.     }
  159.  
  160.     /**
  161.      * Returns true if a deadlock is detected
  162.      * @param tid the tid of the acquiring transaction
  163.      * @return true if a deadlock exists, false otherwise
  164.      */
  165.     private synchronized boolean findDeadlock(TransactionId tid, PageId pid) {
  166.         Queue<TransactionId> q = new LinkedList<>();
  167.         Set<TransactionId> seen = new HashSet<>();
  168.         if (this.deadlockMap.containsKey(tid)) {
  169.             q.addAll(this.deadlockMap.get(tid));
  170.         }
  171.         while (!q.isEmpty()) {
  172.             TransactionId tx = q.remove();
  173.             if (!seen.contains(tx)) {
  174.                 seen.add(tx);
  175.                 if (tx.equals(tid)) {
  176.                     return true;
  177.                 }
  178.                 if (this.deadlockMap.containsKey(tx)) {
  179.                     q.addAll(this.deadlockMap.get(tx));
  180.                 }
  181.             }
  182.         }
  183.         return false;
  184.     }
  185.  
  186.     // Maps a Tx dependency such that TxA -> {TxB, TxC} TxA is waiting on B and C
  187.     // Will never map TxA -> itself
  188.     private synchronized void mapDependency(TransactionId tid, PageId pid, Set<TransactionId> txHolders) throws TransactionAbortedException {
  189.         if (!this.deadlockMap.containsKey(tid)) {
  190.             this.deadlockMap.put(tid, new HashSet<>());
  191.         }
  192.         txHolders.remove(tid);
  193.         this.deadlockMap.get(tid).addAll(txHolders);
  194.         if (findDeadlock(tid, pid)) {
  195.             System.out.println("Tx" + tid + " aborting due to deadlock ");
  196.             throw new TransactionAbortedException();
  197.         }
  198.     }
  199.  
  200.  
  201.     // Removes a tid from all dependencies so no transaction is waiting for it
  202.     private synchronized void removeDependency(TransactionId tid) {
  203.         this.deadlockMap.remove(tid);
  204.         for (TransactionId tx : this.deadlockMap.keySet()) {
  205.             this.deadlockMap.get(tx).remove(tid);
  206.         }
  207.     }
  208. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement