001: package de.ixdb.squirrel_sql.plugins.cache;
002:
003: import java.sql.ResultSet;
004: import java.sql.SQLException;
005: import java.util.HashMap;
006: import java.util.ArrayList;
007:
008: public class ProcessData {
009: public int pid;
010: public Integer blockedByPid;
011: public String deadLockChain;
012: public int lockCount;
013: public String locks;
014: public String nspace;
015: public String routine;
016: public long lines;
017: public long globals;
018: public String state;
019: public String userName;
020: public String clientName;
021: public String exeName;
022: public String ipAdress;
023: public String device;
024: public int job;
025:
026: public static String[] getColumns() {
027: return new String[] { "Pid", "Blocked by Pid",
028: "Deadlock chain (Pids)", "Lock count", "Locks",
029: "Nspace", "Routine", "Lines", "Globals", "State",
030: "Username", "Client Name", "EXE Name", "IP Address",
031: "Device", "Job#" };
032: }
033:
034: private ProcessData blockedBy;
035:
036: public ProcessData(ResultSet procList) {
037: try {
038: job = procList.getInt("Job#");
039: pid = procList.getInt("Pid");
040: device = procList.getString("Device");
041: nspace = procList.getString("Nspace");
042: routine = procList.getString("Routine");
043: lines = procList.getLong("Lines");
044: globals = procList.getLong("Globals");
045: state = procList.getString("State");
046: userName = procList.getString("Username");
047: clientName = procList.getString("Client Name");
048: exeName = procList.getString("EXE Name");
049: ipAdress = procList.getString("IP Address");
050: } catch (SQLException e) {
051: throw new RuntimeException(e);
052: }
053:
054: }
055:
056: public void fillBlocks(ProcessData[] allProcData) {
057: int[] blockedPids = parseBlockedPidsFromLocks();
058:
059: for (int i = 0; i < allProcData.length; i++) {
060: for (int j = 0; j < blockedPids.length; j++) {
061: if (blockedPids[j] == allProcData[i].pid) {
062: allProcData[i].blockedBy = this ;
063: allProcData[i].blockedByPid = new Integer(this .pid);
064: }
065: }
066: }
067: }
068:
069: private int[] parseBlockedPidsFromLocks() {
070: // pid 25493, lock examples:
071: // 5 [" /db1/shd_data_4_3/"]User.ygwaBvbPosKorrD(1) 25493 1D, 25499 X E
072: // 5 [" /db1/shd_data_4_3/"]User.ygwaBvbPosKorrD(1) 25493 1D, 25499,25506 X,X E,E
073: // 5 [" /db1/shd_data_4_3/"]User.ygwaBvbPosKorrD(1) 25493 1D, 25499,25506,25508 X,X,X E,E,E
074: //
075: // oder
076: //
077: //6 [" d:\db\shd_data_lov\"]User.WLagerartikelD(76) 5544 1D,
078: //7 [" d:\db\shd_data_lov\"]User.WLagerartikelD(77) 5544 1D, 3804 S E
079: //8 [" d:\db\shd_data_lov\"]User.WVorgangD(24) 5544 1D,
080: //
081: // oder für kein Lock:
082: //
083: //3 [" f:\db\shd_data\"]User.ygwaTestD(989) 3792 1D,
084: //4 [" f:\db\shd_data\"]User.ygwaTestD(990) 3792 1D,
085: //5 [" f:\db\shd_data\"]User.ygwaTestD(991) 3792 1D,
086: //6 [" f:\db\shd_data\"]User.ygwaTestD(992) 3792 1D,
087: //7 [" f:\db\shd_data\"]User.ygwaTestD(993) 3792 1D,
088: //8 [" f:\db\shd_data\"]User.ygwaTestD(994) 3792 1D,
089: //9 [" f:\db\shd_data\"]User.ygwaTestD(995) 3792 1D,
090: //
091: //
092:
093: if (null == locks) {
094: return new int[0];
095: }
096:
097: HashMap blockedPids = new HashMap();
098: String[] splits = locks.split("\n");
099:
100: for (int i = 0; i < splits.length; i++) {
101: String[] splits2 = splits[i].split(",");
102:
103: if (2 > splits2.length) {
104: continue;
105: }
106:
107: for (int j = 1; j < splits2.length; j++) {
108: String[] splits3 = splits2[j].replaceAll("\t", " ")
109: .split(" ");
110:
111: for (int k = 0; k < splits3.length; k++) {
112: String[] splits4 = splits3[k].split(",");
113:
114: for (int l = 0; l < splits4.length; l++) {
115: try {
116: Integer pidBuf = new Integer(splits4[l]
117: .trim());
118:
119: // Es mach nichts, wenn es die PID nicht gäbe.
120: // Sie wird dann einfach oben nicht zugeordnet.
121: if (pidBuf.intValue() != pid) {
122: blockedPids.put(pidBuf, pidBuf);
123: }
124: } catch (NumberFormatException e) {
125: }
126: }
127:
128: }
129: }
130:
131: }
132:
133: Integer[] blockedPidsBuf = (Integer[]) blockedPids.keySet()
134: .toArray(new Integer[0]);
135:
136: int[] ret = new int[blockedPidsBuf.length];
137:
138: for (int i = 0; i < ret.length; i++) {
139: ret[i] = blockedPidsBuf[i].intValue();
140: }
141:
142: return ret;
143: }
144:
145: public void fillDeadLockChain() {
146:
147: ProcessData blocker = blockedBy;
148:
149: ArrayList chain = new ArrayList();
150:
151: HashMap blockers = new HashMap();
152:
153: while (null != blocker) {
154: chain.add(new Integer(blocker.pid));
155:
156: if (blocker.pid == pid) {
157: deadLockChain = getChainAsSting(chain);
158: break;
159: }
160:
161: if (null != blockers.get(blocker)) {
162: // If we are blocked by a member of a deadlock chain
163: // but do not belong to the deadlock chain ourselves
164: // this prevents a forever loop.
165: break;
166: }
167:
168: blockers.put(blocker, blocker);
169: blocker = blocker.blockedBy;
170: }
171: }
172:
173: private String getChainAsSting(ArrayList chain) {
174: ///////////////////////////////////////////////////////////////////////////////
175: // A deadlock chain is circular and does not have a defined beginning Pid.
176: // In order to make the string representation of a deadlock chain unique
177: // we put the smallest Pid at the beginning of the chain.
178: Integer minPid = (Integer) chain.get(0);
179: int ixOfMinPid = 0;
180:
181: for (int i = 0; i < chain.size(); i++) {
182: Integer buf = ((Integer) chain.get(i));
183: if (minPid.intValue() > buf.intValue()) {
184: minPid = buf;
185: ixOfMinPid = i;
186: }
187: }
188:
189: for (int i = 0; i < ixOfMinPid; ++i) {
190: chain.add(chain.remove(0));
191: }
192: //
193: /////////////////////////////////////////////////////////////////////////////
194:
195: String ret = "" + chain.get(0);
196: for (int i = 1; i < chain.size(); i++) {
197: ret += "-->" + chain.get(i);
198: }
199: ret += "-->" + chain.get(0);
200:
201: return ret;
202: }
203: }
|