/* * DBeaver - Universal Database Manager * Copyright (C) 2017 Andrew Khitrin (ahitrin@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jkiss.dbeaver.ext.oracle.model.lock; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.ext.oracle.editors.OracleLockEditor; import org.jkiss.dbeaver.ext.oracle.model.OracleDataSource; import org.jkiss.dbeaver.ext.ui.locks.manage.LockGraphManager; import org.jkiss.dbeaver.ext.ui.locks.manage.LockManagerViewer; import org.jkiss.dbeaver.model.DBPDataSource; import org.jkiss.dbeaver.model.admin.locks.DBAServerLockManager; import org.jkiss.dbeaver.model.exec.DBCSession; import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement; import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet; import org.jkiss.dbeaver.model.exec.jdbc.JDBCSession; public class OracleLockManager extends LockGraphManager<OracleLock,Integer> implements DBAServerLockManager<OracleLock,OracleLockItem>{ public static final String LOCK_QUERY = "select "+ "wsession.sid waiting_session, "+ "wsession.serial# serial, "+ "wsession.logon_time, "+ "wsession.blocking_session_status, "+ "wsession.event, "+ "wsession.username waiting_user, "+ "wprocess.pid wait_pid, "+ "nvl(obj.object_name,'-') oname, "+ "nvl(obj.owner,'-') owner, "+ "wsession.row_wait_block# row_lock, "+ "wsession.blocking_session holding_session, "+ "hprocess.pid hold_pid, "+ "hsession.username holding_user "+ "from "+ "v$session wsession "+ "join v$session hsession on wsession.blocking_session = hsession.sid "+ "join v$process wprocess on wprocess.addr = wsession.paddr "+ "join v$process hprocess on hprocess.addr = hsession.paddr "+ "left join dba_objects obj on obj.object_id = wsession.row_wait_obj# "+ "where "+ "wsession.blocking_session is not NULL "+ "union "+ "select "+ "wsession.sid waiting_session, "+ "wsession.serial# serial, "+ "wsession.logon_time, "+ "wsession.blocking_session_status, "+ "wsession.event, "+ "wsession.username waiting_user, "+ "wprocess.pid wait_pid, "+ "nvl(obj.object_name,'-') oname, "+ "nvl(obj.owner,'-') owner, "+ "wsession.row_wait_block# row_lock, "+ "nvl(wsession.blocking_session,0) holding_session, "+ "nvl(hprocess.pid,0) hold_pid, "+ "nvl(hsession.username,'-') holding_user "+ "from "+ "v$session wsession "+ "left join v$session hsession on wsession.blocking_session = hsession.sid "+ "join v$process wprocess on wprocess.addr = wsession.paddr "+ "left join v$process hprocess on hprocess.addr = hsession.paddr "+ "left join dba_objects obj on obj.object_id = wsession.row_wait_obj# "+ "where "+ "wsession.sid IN (SELECT blocking_session FROM v$session)"; public static final String LOCK_ITEM_QUERY = "select lock_type,mode_held,mode_requested,lock_id1,lock_id2,last_convert,blocking_others from dba_lock where session_id = ?"; private final OracleDataSource dataSource; public OracleLockManager(OracleDataSource dataSource) { this.dataSource = dataSource; } @Override public DBPDataSource getDataSource() { return dataSource; } @Override public Map<Integer,OracleLock> getLocks(DBCSession session, Map<String, Object> options) throws DBException { try { Map<Integer,OracleLock> locks = new HashMap<Integer,OracleLock>(10); try (JDBCPreparedStatement dbStat = ((JDBCSession) session).prepareStatement(LOCK_QUERY)) { try (JDBCResultSet dbResult = dbStat.executeQuery()) { while (dbResult.next()) { OracleLock l = new OracleLock(dbResult); locks.put(l.getId(), l); } } } super.buildGraphs(locks); return locks; } catch (SQLException e) { throw new DBException(e, session.getDataSource()); } } @Override public void alterSession(DBCSession session, OracleLock lock, Map<String, Object> options) throws DBException { try { StringBuilder sql = new StringBuilder("ALTER SYSTEM KILL SESSION "); sql.append("'").append(lock.getWait_sid()).append(',').append(lock.getSerial()).append("'"); sql.append(" IMMEDIATE"); try (JDBCPreparedStatement dbStat = ((JDBCSession) session).prepareStatement(sql.toString())) { dbStat.execute(); } } catch (SQLException e) { throw new DBException(e, session.getDataSource()); } } @Override public Class<OracleLock> getLocksType() { return OracleLock.class; } @Override public Collection<OracleLockItem> getLockItems(DBCSession session, Map<String, Object> options) throws DBException { try { List<OracleLockItem> locks = new ArrayList<>(); try (JDBCPreparedStatement dbStat = ((JDBCSession) session).prepareStatement(LOCK_ITEM_QUERY)) { String otype = (String) options.get(LockManagerViewer.keyType); switch (otype) { case LockManagerViewer.typeWait: dbStat.setInt(1, (int) options.get(OracleLockEditor.sidWait)); break; case LockManagerViewer.typeHold: dbStat.setInt(1, (int) options.get(OracleLockEditor.sidHold)); break; default: return locks; } try (JDBCResultSet dbResult = dbStat.executeQuery()) { while (dbResult.next()) { locks.add(new OracleLockItem(dbResult)); } } } return locks; } catch (SQLException e) { throw new DBException(e, session.getDataSource()); } } }