All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.hajdbc.lock.distributed.DistributedLock Maven / Gradle / Ivy

There is a newer version: 3.6.61
Show newest version
package net.sf.hajdbc.lock.distributed;

import net.sf.hajdbc.distributed.CommandDispatcher;
import net.sf.hajdbc.distributed.Member;
import net.sf.hajdbc.lock.WriteLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

class DistributedLock implements Lock {
  static final Logger LOG = LoggerFactory.getLogger(DistributedLock.class);
  public static final int DEFAULT_LOCK_TIMEOUT = 3;
  private final RemoteLockDescriptor descriptor;
  private final Lock lock;
  /**
   * 获取分布式读写锁的分布式互斥锁,必须先获取分布式互斥锁才能获取分布式读写锁。
   * 无论是否获取读写锁成功或失败,结束后都必须要释放该互斥锁
   */
  private final Lock masterLock;
  private final CommandDispatcher dispatcher;

  DistributedLock(RemoteLockDescriptor descriptor, Lock lock, Lock masterLock, CommandDispatcher dispatcher) {
    this.descriptor = descriptor;
    this.lock = lock;
    this.masterLock = masterLock;
    this.dispatcher = dispatcher;
  }

  @Override
  public void lock() {
    boolean locked = false;
    while (!locked) {
      locked = tryLock();
      if (!locked) {
        if (lock instanceof LockObject) {
          Object lockObject = ((LockObject) lock).getLockObject();

          synchronized (lockObject) {
            try {
              lockObject.wait(1000);
            } catch (InterruptedException e) {
              //e.printStackTrace();
              Thread.yield();
            }
          }
        }
        //Thread.yield();
      }
    }
  }

  @Override
  public void lockInterruptibly() throws InterruptedException {
    boolean locked = false;

    while (!locked) {
      locked = tryLock();

      if (Thread.currentThread().isInterrupted()) {
        throw new InterruptedException();
      }

      if (!locked) {
        if (lock instanceof LockObject) {
          Object lockObject = ((LockObject) lock).getLockObject();

          synchronized (lockObject) {
            lockObject.wait(1000);
          }
        }
        Thread.yield();
      }
    }
  }

  @Override
  public boolean tryLock() {
    boolean locked = false;

    try {
      locked = this.tryLock(DEFAULT_LOCK_TIMEOUT, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      //ignore e.printStackTrace();
      // LOG.warn(null,e);
    }

    return locked;
  }

  private String getKey(){
    StringBuilder key = new StringBuilder();
    if(lock instanceof WriteLock){
      key.append("write");
    }else{
      key.append("read");
    }
    if(lock instanceof LockObject){
      key.append("("+((LockObject)lock).getLockObject()+")");
    }else{
      key.append("()");
    }
    return key.toString();
  }

  /**
   *
   * @param time
   * @param unit
   * @return
   * @throws InterruptedException
   */
  @Override
  public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
    boolean locked = false;

//    获取分布式读写锁的分布式互斥锁,必须先获取分布式互斥锁才能获取分布式读写锁。
//    无论是否获取读写锁成功或失败,结束后都必须要释放该互斥锁
    String key = getKey();

    if (masterLock.tryLock(2, TimeUnit.SECONDS)) {
      try {
        if (this.lock.tryLock(time, unit)) {
          logInfo("Lock local ok. key:{}", key);
          try {
            locked = this.lockMembers();
          } finally {
            if (!locked) {
              this.lock.unlock();
            }
          }
        }
      } finally {
        this.masterLock.unlock();
      }
    }
    logInfo("tryLock end {} key:{} locked:{}", descriptor.getMember().toString(), key, locked);
    return locked;
  }

  private void logInfo(String msg, Object... arguments) {
    if(isTrace()){
      LOG.info(msg,arguments);
    }
  }

  private boolean isTrace(){
    return Files.exists(Paths.get("/etc/ha-jdbc/trace/lock"));
  }

  private boolean lockMembers() {
    boolean locked = true;
    logInfo("lockMembers begin {}", descriptor.getMember().toString());

    Map results = this.dispatcher.executeAll(new MemberAcquireLockCommand(this.descriptor), descriptor.getMember());
    logInfo("lockMembers results:{}", results);
    for (Map.Entry entry : results.entrySet()) {
      locked &= Optional.ofNullable(entry.getValue()).orElse(false);
    }
    logInfo("lockMembers end  {} locked:{}", descriptor.getMember().toString(), locked);

    if (!locked) {
      this.unlockMembers();
    }

    return locked;
  }

  @Override
  public void unlock() {
    this.lock.unlock();
    this.unlockMembers();
  }

  private void unlockMembers() {
    this.dispatcher.executeAll(new MemberReleaseLockCommand(this.descriptor), descriptor.getMember());
  }

  @Override
  public Condition newCondition() {
    throw new UnsupportedOperationException();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy