--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.diag.LockTable\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.diag;\r
+\r
+// temp\r
+import org.apache.derby.impl.services.locks.TableNameInfo;\r
+import org.apache.derby.iapi.services.locks.LockFactory;\r
+import org.apache.derby.iapi.services.locks.Latch;\r
+import org.apache.derby.iapi.services.locks.Lockable;\r
+import org.apache.derby.iapi.services.locks.VirtualLockTable;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.error.StandardException; \r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+import org.apache.derby.iapi.sql.conn.ConnectionUtil;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.iapi.error.PublicAPI;\r
+import org.apache.derby.iapi.sql.ResultColumnDescriptor;\r
+import org.apache.derby.impl.jdbc.EmbedResultSetMetaData;\r
+\r
+import java.util.Hashtable;\r
+import java.util.Enumeration;\r
+import java.util.Map;\r
+import java.io.InputStream;\r
+import java.io.Reader;\r
+import java.sql.NClob;\r
+import java.sql.ResultSetMetaData;\r
+import java.sql.RowId;\r
+import java.sql.SQLException;\r
+import java.sql.SQLXML;\r
+import java.sql.Types;\r
+\r
+import org.apache.derby.vti.VTITemplate;\r
+import org.apache.derby.vti.VTICosting;\r
+import org.apache.derby.vti.VTIEnvironment;\r
+\r
+/**\r
+ LockTable is a virtual table that shows all locks currently held in\r
+ the database.\r
+ \r
+ This virtual table can be invoked by calling it directly\r
+ <PRE> select * from SYSCS_DIAG.LOCK_TABLE </PRE>\r
+ \r
+ <P>The LockTable virtual table takes a snap shot of the lock table while\r
+ the system is in flux, so it is possible that some locks may be in\r
+ transition state while the snap shot is taken. We choose to do this rather\r
+ then impose extranous timing restrictions so that the use of this tool will\r
+ not alter the normal timing and flow of execution in the application.\r
+\r
+ <P>The LockTable virtual table has the following columns:\r
+ <UL><LI>XID varchar(15) - not nullable. The transaction id, this can be joined with the\r
+ TransactionTable virtual table's XID.</LI>\r
+ <LI>TYPE varchar(5) - nullable. The type of lock, ROW, TABLE, or LATCH</LI>\r
+ <LI>MODE varchar(4) - not nullable. The mode of the lock, "S", "U", "X", "IS", "IX".</LI>\r
+ <UL><LI>S is shared lock (N/A to Latch) </LI>\r
+ <LI>U is update lock (N/A to Latch) </LI>\r
+ <LI>X is exclusive lock </LI>\r
+ <LI>IS is intent shared lock (N/A to Latch or Row lock) </LI>\r
+ <LI>IX is intent exclusive lock (N/A to Latch or Row lock) </LI>\r
+ </UL>\r
+ <LI>TABLENAME varchar(128) - not nullable. The name of the base table the lock is for </LI>\r
+ <LI>LOCKNAME varchar(20) - not nullable. The name of the lock </LI>\r
+ <LI>STATE varchar(5) - nullable. GRANT or WAIT </LI>\r
+ <LI>TABLETYPE varchar(9) - not nullable. 'T' for user table, 'S' for system table </LI>\r
+ <LI>LOCKCOUNT varchar(5) - not nullable. Internal lock count.</LI>\r
+ <LI>INDEXNAME varchar(128) - normally null. If non-null, a lock is held on \r
+ the index, this can only happen if this is not a user transaction.</LI>\r
+ </UL>\r
+\r
+ */\r
+public class LockTable extends VTITemplate implements VTICosting {\r
+\r
+ /** return only latches */\r
+ public static final int LATCH = VirtualLockTable.LATCH;\r
+\r
+ /** return only table and row locks */\r
+ public static final int TABLE_AND_ROWLOCK = VirtualLockTable.TABLE_AND_ROWLOCK;\r
+\r
+ /** return all locks and latches */\r
+ public static final int ALL = VirtualLockTable.ALL;\r
+\r
+ /*\r
+ ** private \r
+ */\r
+ private TransactionController tc;\r
+ private Hashtable currentRow; // an entry in the lock table\r
+ private Enumeration lockTable; \r
+ private boolean wasNull;\r
+ private boolean initialized;\r
+ private final int flag;\r
+ private TableNameInfo tabInfo;\r
+\r
+ /**\r
+ The normal way of instantiating a LockTable, equivalent to\r
+ LockTable(org.apache.derby.diag.LockTable->TABLE_AND_ROWLOCK).\r
+ Only shows row and table lock and not latches. Latches are generally\r
+ held for very short duration and are not of interest to Derby \r
+ users. Only under abnormal circumstances will one be interested in\r
+ looking at latches.\r
+ */\r
+ public LockTable()\r
+ {\r
+ flag = TABLE_AND_ROWLOCK;\r
+ }\r
+\r
+ /**\r
+ This call is intrusive and should only be used under the supervision of\r
+ technical support. Create an instance of the lock table which\r
+ has transient latches as well as locks.\r
+ */\r
+ public LockTable(int flag)\r
+ {\r
+ this.flag = flag;\r
+ }\r
+\r
+ /**\r
+ @see java.sql.ResultSet#getMetaData\r
+ */\r
+ public ResultSetMetaData getMetaData()\r
+ {\r
+ return metadata;\r
+ }\r
+\r
+ /**\r
+ @see java.sql.ResultSet#next\r
+ @exception SQLException if no transaction context can be found, or other\r
+ Derby internal errors are encountered.\r
+ */\r
+ public boolean next() throws SQLException\r
+ {\r
+ try\r
+ {\r
+ if (!initialized)\r
+ {\r
+ LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();\r
+\r
+ tc = lcc.getTransactionExecute();\r
+ LockFactory lf = tc.getAccessManager().getLockFactory();\r
+ lockTable = lf.makeVirtualLockTable();\r
+ initialized = true;\r
+ tabInfo = new TableNameInfo(lcc, true);\r
+ }\r
+\r
+ currentRow = null;\r
+ if (lockTable != null) {\r
+ while (lockTable.hasMoreElements() && (currentRow == null)) {\r
+ currentRow = dumpLock((Latch) lockTable.nextElement());\r
+ }\r
+ }\r
+ }\r
+ catch (StandardException se)\r
+ {\r
+ throw PublicAPI.wrapStandardException(se);\r
+ }\r
+\r
+ return (currentRow != null);\r
+ }\r
+\r
+ /**\r
+ @see java.sql.ResultSet#close\r
+ */\r
+ public void close()\r
+ {\r
+ lockTable = null;\r
+ }\r
+\r
+ /**\r
+ All columns in TransactionTable VTI are of String type.\r
+ @see java.sql.ResultSet#getString\r
+ */\r
+ public String getString(int columnNumber)\r
+ { \r
+ String val = (String)currentRow.get(columnInfo[columnNumber-1].getName());\r
+ wasNull = (val == null);\r
+\r
+ return val;\r
+ }\r
+\r
+\r
+ /**\r
+ @see java.sql.ResultSet#wasNull\r
+ */\r
+ public boolean wasNull()\r
+ {\r
+ return wasNull;\r
+ }\r
+\r
+ /** VTI costing interface */\r
+ \r
+ /**\r
+ @see VTICosting#getEstimatedRowCount\r
+ */\r
+ public double getEstimatedRowCount(VTIEnvironment vtiEnvironment)\r
+ {\r
+ return VTICosting.defaultEstimatedRowCount;\r
+ }\r
+ \r
+ /**\r
+ @see VTICosting#getEstimatedCostPerInstantiation\r
+ */\r
+ public double getEstimatedCostPerInstantiation(VTIEnvironment vtiEnvironment)\r
+ {\r
+ return VTICosting.defaultEstimatedCost;\r
+ }\r
+ /**\r
+ @return false\r
+ @see VTICosting#supportsMultipleInstantiations\r
+ */\r
+ public boolean supportsMultipleInstantiations(VTIEnvironment vtiEnvironment)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ /*\r
+ ** Private methods\r
+ */\r
+\r
+ /**\r
+ Convert the lock information into a hashtable.\r
+ */\r
+ private Hashtable dumpLock(\r
+ Latch lock)\r
+ throws StandardException\r
+ {\r
+ Hashtable attributes = new Hashtable(17);\r
+ Object lock_type = lock.getQualifier();\r
+\r
+\r
+ // 4 things we are interested in from the lockable:\r
+ // containerId, segmentId, pageNum, recId\r
+\r
+ Lockable lockable = lock.getLockable();\r
+\r
+ // see if this lockable object wants to participate\r
+ if (!lockable.lockAttributes(flag, attributes))\r
+ return null; \r
+\r
+ // if it does, the lockable object must have filled in the following\r
+ // fields\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(attributes.get(VirtualLockTable.LOCKNAME) != null,\r
+ "lock table can only represent locks that have a LOCKNAME");\r
+\r
+ SanityManager.ASSERT(attributes.get(VirtualLockTable.LOCKTYPE) != null,\r
+ "lock table can only represent locks that have a LOCKTYPE");\r
+\r
+ if (attributes.get(VirtualLockTable.CONTAINERID) == null &&\r
+ attributes.get(VirtualLockTable.CONGLOMID) == null)\r
+ SanityManager.THROWASSERT(\r
+ "lock table can only represent locks that are associated with a container or conglomerate");\r
+ }\r
+\r
+ if (attributes.get(VirtualLockTable.LOCKNAME) == null ||\r
+ attributes.get(VirtualLockTable.LOCKTYPE) == null)\r
+ return null; // can't deal with this for now\r
+\r
+ // if the lock has zero count and is an instance of Lock then it\r
+ // is a lock that has just been released. Therefore do put it into\r
+ // the lock table. This occurs because the Lock object is the real\r
+ // live object in the LockTable. Thus when we copied the lock table\r
+ // it had a non-zero count, but since then it has been released\r
+ // (after we dropped the sync). Note if it is of type ActiveLock\r
+ // with zero count there is stil the chance it has been released.\r
+ // Less likely, but we still need to fix that at some time.\r
+ int lockCount = lock.getCount();\r
+ String state;\r
+ if (lockCount != 0)\r
+ state = "GRANT";\r
+ else if (!(lock instanceof org.apache.derby.impl.services.locks.ActiveLock))\r
+ return null;\r
+ else\r
+ state = "WAIT";\r
+\r
+ Long conglomId = (Long) attributes.get(VirtualLockTable.CONGLOMID);\r
+\r
+ if (conglomId == null)\r
+ {\r
+ // we need to figure this out\r
+ if (attributes.get(VirtualLockTable.CONTAINERID) == null)\r
+ return null; // can't deal with this for now\r
+\r
+ Long value = (Long)attributes.get(VirtualLockTable.CONTAINERID);\r
+ conglomId = new Long(tc.findConglomid(value.longValue()));\r
+ attributes.put(VirtualLockTable.CONGLOMID, conglomId);\r
+ }\r
+\r
+ attributes.put(VirtualLockTable.LOCKOBJ, lock);\r
+ Object owner = lock.getCompatabilitySpace().getOwner();\r
+ attributes.put(VirtualLockTable.XACTID,\r
+ (owner == null) ? "<null>" : owner.toString());\r
+ attributes.put(VirtualLockTable.LOCKMODE, lock_type.toString());\r
+\r
+ attributes.put(VirtualLockTable.LOCKCOUNT, Integer.toString(lockCount));\r
+\r
+ attributes.put(VirtualLockTable.STATE, state);\r
+\r
+ String tableName = tabInfo.getTableName(conglomId);\r
+\r
+ attributes.put(VirtualLockTable.TABLENAME, tableName);\r
+\r
+ String indexName = tabInfo.getIndexName(conglomId);\r
+\r
+ if (indexName != null)\r
+ attributes.put(VirtualLockTable.INDEXNAME, indexName);\r
+\r
+ String tableType = tabInfo.getTableType(conglomId);\r
+ attributes.put(VirtualLockTable.TABLETYPE, tableType);\r
+ return attributes;\r
+\r
+ }\r
+\r
+ /*\r
+ ** Metadata\r
+ */\r
+ private static final ResultColumnDescriptor[] columnInfo = {\r
+\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.XACTID, Types.VARCHAR, false, 15),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.LOCKTYPE, Types.VARCHAR, true, 5),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.LOCKMODE, Types.VARCHAR, false, 4),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.TABLENAME, Types.VARCHAR, false, 128),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.LOCKNAME, Types.VARCHAR, false, 20),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.STATE, Types.VARCHAR, true, 5),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.TABLETYPE, Types.VARCHAR, false, 9),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.LOCKCOUNT, Types.VARCHAR, false, 5),\r
+ EmbedResultSetMetaData.getResultColumnDescriptor(VirtualLockTable.INDEXNAME, Types.VARCHAR, true, 128)\r
+ };\r
+ \r
+ private static final ResultSetMetaData metadata = new EmbedResultSetMetaData(columnInfo);\r
+\r
+ public int getHoldability() throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return 0;\r
+ }\r
+\r
+ public Reader getNCharacterStream(int columnIndex) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public Reader getNCharacterStream(String columnLabel) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public NClob getNClob(int columnIndex) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public NClob getNClob(String columnLabel) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public String getNString(int columnIndex) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public String getNString(String columnLabel) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+\r
+\r
+ public RowId getRowId(int columnIndex) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public RowId getRowId(String columnLabel) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public SQLXML getSQLXML(int columnIndex) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public SQLXML getSQLXML(String columnLabel) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public boolean isClosed() throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return false;\r
+ }\r
+\r
+ public void updateAsciiStream(int columnIndex, InputStream x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateAsciiStream(String columnLabel, InputStream x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateAsciiStream(int columnIndex, InputStream x, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateAsciiStream(String columnLabel, InputStream x, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBinaryStream(int columnIndex, InputStream x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBinaryStream(String columnLabel, InputStream x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBinaryStream(int columnIndex, InputStream x, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBinaryStream(String columnLabel, InputStream x,\r
+ long length) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBlob(int columnIndex, InputStream inputStream)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBlob(String columnLabel, InputStream inputStream)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBlob(int columnIndex, InputStream inputStream, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateBlob(String columnLabel, InputStream inputStream,\r
+ long length) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateCharacterStream(int columnIndex, Reader x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateCharacterStream(String columnLabel, Reader reader)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateCharacterStream(int columnIndex, Reader x, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateCharacterStream(String columnLabel, Reader reader,\r
+ long length) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateClob(int columnIndex, Reader reader) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateClob(String columnLabel, Reader reader)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateClob(int columnIndex, Reader reader, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateClob(String columnLabel, Reader reader, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNCharacterStream(int columnIndex, Reader x)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNCharacterStream(String columnLabel, Reader reader)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNCharacterStream(int columnIndex, Reader x, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNCharacterStream(String columnLabel, Reader reader,\r
+ long length) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(int columnIndex, NClob clob) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(String columnLabel, NClob clob) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(int columnIndex, Reader reader) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(String columnLabel, Reader reader)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(int columnIndex, Reader reader, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNClob(String columnLabel, Reader reader, long length)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNString(int columnIndex, String string)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateNString(String columnLabel, String string)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateRowId(int columnIndex, RowId x) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateRowId(String columnLabel, RowId x) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public void updateSQLXML(String columnLabel, SQLXML xmlObject)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
+\r
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return false;\r
+ }\r
+\r
+ public <T> T unwrap(Class<T> iface) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public <T> T getObject(String columnLabel, Class<T> type)\r
+ throws SQLException {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+}\r
+\r