/* * Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved. * * 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 com.hazelcast.impl.management; import com.hazelcast.impl.base.DistributedLock; import com.hazelcast.nio.Data; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.List; import static com.hazelcast.nio.IOUtil.toData; import static com.hazelcast.nio.IOUtil.toObject; public class DetectDeadlockRequest implements ConsoleRequest { public int getType() { return ConsoleRequestConstants.REQUEST_TYPE_DETECT_DEADLOCK; } public Object readResponse(DataInput in) throws IOException { int size = in.readInt(); List<Edge> list = new ArrayList<Edge>(size); for (int i = 0; i < size; i++) { Data d = new Data(); d.readData(in); Edge e = (Edge) toObject(d); list.add(e); } return list; } public void writeResponse(ManagementCenterService mcs, DataOutput dos) throws Exception { List<Edge> list = mcs.detectDeadlock(); dos.writeInt(list == null ? 0 : list.size()); for (Edge edge : list) { Data data = toData(edge); data.writeData(dos); } } public void writeData(DataOutput out) throws IOException { } public void readData(DataInput in) throws IOException { } public static class Edge implements java.io.Serializable { Vertex from; Vertex to; Object key; String mapName; boolean globalLock; @Override public String toString() { return "Edge{" + "to=" + to.owner.getLockAddress() + to.owner.getLockThreadId() + ", key=" + key + '}'; } public boolean isGlobalLock() { return globalLock; } public void setGlobalLock(boolean globalLock) { this.globalLock = globalLock; } public String getMapName() { return mapName; } public void setMapName(String mapName) { this.mapName = mapName; } public Vertex getFrom() { return from; } public Vertex getTo() { return to; } public Object getKey() { return key; } public void setFrom(Vertex from) { this.from = from; } public void setTo(Vertex to) { this.to = to; } public void setKey(Object key) { this.key = key; } } public static class Vertex implements java.io.Serializable { int NOT_VISITED = 0; int BEING_VISITED = 1; int DONE_VISITED = 2; int visited = NOT_VISITED; DistributedLock owner; List<Edge> incomings = new ArrayList<Edge>(); List<Edge> outgoings = new ArrayList<Edge>(); Vertex(DistributedLock owner) { this.owner = owner; } public void addIncoming(Edge edge) { incomings.add(edge); } public void addOutgoing(Edge edge) { outgoings.add(edge); } public Vertex visit(List<Edge> list) { if (visited == BEING_VISITED) { return this; } if (visited == DONE_VISITED) { return null; } visited = BEING_VISITED; for (Edge edge : outgoings) { Vertex v2 = edge.to.visit(list); if (v2 != null) { list.add(edge); if (v2 == this) { throw new RuntimeException("Cycle is detected!"); } return v2; } } visited = DONE_VISITED; return null; } public int getVisited() { return visited; } public DistributedLock getOwner() { return owner; } public List<Edge> getIncomings() { return incomings; } public List<Edge> getOutgoings() { return outgoings; } public String name() { return owner.getLockAddress() + ":" + owner.getLockThreadId(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Vertex vertex = (Vertex) o; if (owner != null ? !(owner.getLockAddress().equals(vertex.owner.getLockAddress()) && owner.getLockThreadId() == vertex.owner.getLockThreadId()) : vertex.owner != null) return false; return true; } @Override public int hashCode() { return owner != null ? owner.hashCode() : 0; } @Override public String toString() { return "Vertex{" + "outgoings=" + outgoings + "," + owner + ", visited=" + visited + '}'; } } }