Package org.openrdf.sail.rdbms.util

Source Code of org.openrdf.sail.rdbms.util.DatabaseLockManager

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 2008.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.sail.rdbms.util;

import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import info.aduna.concurrent.locks.Lock;

import org.openrdf.sail.LockManager;
import org.openrdf.sail.SailLockedException;

/**
* @author James Leigh
*/
public class DatabaseLockManager implements LockManager {

  private static final String CREATE_LOCKED = "CREATE TABLE locked ( process VARCHAR(128) )";

  private static final String INSERT = "INSERT INTO locked VALUES ('";

  private static final String SELECT = "SELECT process FROM locked";

  private static final String DROP = "DROP TABLE locked";

  Logger logger = LoggerFactory.getLogger(DatabaseLockManager.class);

  private DataSource ds;

  private String user;

  private String password;

  public DatabaseLockManager(DataSource ds) {
    this.ds = ds;
  }

  public DatabaseLockManager(DataSource ds, String user, String password) {
    this.ds = ds;
    this.user = user;
    this.password = password;
  }

  public String getLocation() {
    try {
      // Both BasicDataSource and MysqlDataSource have getUrl
      Method getUrl = ds.getClass().getMethod("getUrl");
      return getUrl.invoke(ds).toString();
    }
    catch (Exception e) {
      // getUrl cannot be accessed
    }
    return ds.toString();
  }

  public boolean isDebugEnabled() {
    return logger.isDebugEnabled();
  }

  public boolean isLocked() {
    try {
      Connection con = getConnection();
      try {
        Statement st = con.createStatement();
        try {
          ResultSet rs = st.executeQuery(SELECT);
          try {
            return rs.next();
          }
          finally {
            rs.close();
          }
        }
        finally {
          st.close();
        }
      }
      finally {
        con.close();
      }
    }
    catch (SQLException exc) {
      logger.warn(exc.toString(), exc);
      return false;
    }
  }

  public Lock tryLock() {
    Lock lock = null;
    try {
      Connection con = getConnection();
      try {
        Statement st = con.createStatement();
        try {
          st.execute(CREATE_LOCKED);
          lock = createLock();
          st.execute(INSERT + getProcessName() + "')");
          return lock;
        }
        finally {
          st.close();
        }
      }
      finally {
        con.close();
      }
    }
    catch (SQLException exc) {
      logger.warn(exc.toString(), exc);
      if (lock != null) {
        lock.release();
      }
      return null;
    }
  }

  public Lock lockOrFail()
    throws SailLockedException
  {
    Lock lock = tryLock();
    if (lock != null) {
      return lock;
    }

    String requestedBy = getProcessName();
    String lockedBy = getLockedBy();
    if (lockedBy != null) {
      throw new SailLockedException(lockedBy, requestedBy, this);
    }

    lock = tryLock();
    if (lock != null) {
      return lock;
    }

    throw new SailLockedException(requestedBy);
  }

  /**
   * Revokes a lock owned by another process.
   *
   * @return <code>true</code> if a lock was successfully revoked.
   */
  public boolean revokeLock() {
    try {
      Connection con = getConnection();
      try {
        Statement st = con.createStatement();
        try {
          st.execute(DROP);
          return true;
        }
        finally {
          st.close();
        }
      }
      finally {
        con.close();
      }
    }
    catch (SQLException exc) {
      logger.warn(exc.toString(), exc);
      return false;
    }
  }

  Connection getConnection()
    throws SQLException
  {
    if (user == null) {
      return ds.getConnection();
    }

    return ds.getConnection(user, password);
  }

  private String getLockedBy() {
    try {
      Connection con = getConnection();
      try {
        Statement st = con.createStatement();
        try {
          ResultSet rs = st.executeQuery(SELECT);
          try {
            if (!rs.next()) {
              return null;
            }
            return rs.getString(1);
          }
          finally {
            rs.close();
          }
        }
        finally {
          st.close();
        }
      }
      finally {
        con.close();
      }
    }
    catch (SQLException exc) {
      logger.warn(exc.toString(), exc);
      return null;
    }
  }

  private String getProcessName() {
    return ManagementFactory.getRuntimeMXBean().getName();
  }

  private Lock createLock() {
    return new Lock() {

      private boolean active = true;

      public boolean isActive() {
        return active;
      }

      public void release() {
        active = false;
        try {
          Connection con = getConnection();
          try {
            Statement st = con.createStatement();
            try {
              st.execute(DROP);
            }
            finally {
              st.close();
            }
          }
          finally {
            con.close();
          }
        }
        catch (SQLException exc) {
          logger.error(exc.toString(), exc);
        }
      }

      @Override
      protected void finalize()
        throws Throwable
      {
        if (active) {
          release();
        }
        super.finalize();
      }
    };
  }
}
TOP

Related Classes of org.openrdf.sail.rdbms.util.DatabaseLockManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.