| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 flash.tools.debugger.concrete; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import flash.tools.debugger.Isolate; |
| |
| /** |
| * This class can be to count the number of messages |
| * received during a debug session. |
| * |
| */ |
| public class DMessageCounter implements DProtocolNotifierIF |
| { |
| long[] m_inCounts; |
| long[] m_outCounts; |
| long m_lastIsolate; |
| Object m_isolateLock; |
| boolean m_isolate; |
| |
| Map<Long, DMessageCounter> m_isolateCounterMap; |
| |
| public DMessageCounter() |
| { |
| m_inCounts = new long[DMessage.InSIZE+1]; |
| m_outCounts = new long[DMessage.OutSIZE+1]; |
| m_lastIsolate = 1; |
| m_isolateCounterMap = new HashMap<Long, DMessageCounter>(); |
| m_isolateLock = new Object(); |
| clearArray(m_inCounts); |
| clearArray(m_outCounts); |
| } |
| |
| public void disconnected() |
| { |
| // We're being notified (via the DProtocolNotifierIF interface) that |
| // the socket connection has been broken. If anyone is waiting for |
| // a message to come in, they ain't gonna get one. So, we'll notify() |
| // them so that they can wake up and realize that the connection has |
| // been broken. |
| Object inLock = getInLock(); |
| synchronized (inLock) { inLock.notifyAll(); } |
| Object outLock = getOutLock(); |
| synchronized (outLock) { outLock.notifyAll(); } |
| } |
| |
| /** |
| * Returns the object on which external code can call "wait" in order |
| * to block until a message is received. |
| */ |
| public Object getInLock() { return m_inCounts; } |
| |
| /** |
| * Returns the object on which external code can call "wait" in order |
| * to block until a message is sent. |
| */ |
| public Object getOutLock() { return m_outCounts; } |
| |
| /** |
| * Collect stats on outgoing messages |
| */ |
| public void messageSent(DMessage msg) |
| { |
| int type = msg.getType(); |
| if (type < 0 || type >=DMessage.OutSIZE) |
| type = DMessage.OutSIZE; |
| long targetIsolate = msg.getTargetIsolate(); |
| Object outLock = getOutLock(); |
| if (!m_isolate) { |
| synchronized (m_isolateLock) { |
| if (m_lastIsolate != Isolate.DEFAULT_ID) { |
| DMessageCounter counter = m_isolateCounterMap.get(m_lastIsolate); |
| outLock = counter.getOutLock(); |
| } |
| } |
| } |
| synchronized (outLock) { |
| |
| if (!m_isolate && targetIsolate != Isolate.DEFAULT_ID) { |
| // if (m_isolateCounterMap.containsKey(targetIsolate)) { |
| DMessageCounter counter = m_isolateCounterMap.get(targetIsolate); |
| counter.messageSent(msg); |
| m_outCounts[type] += 1; |
| outLock.notifyAll(); // tell anyone who is waiting that a message has been sent |
| //counter.getOutLock().notifyAll(); |
| // } |
| // else { |
| // System.out.println("No counter for worker " + targetIsolate); |
| // m_outCounts[type] += 1; |
| // outLock.notifyAll(); // tell anyone who is waiting that a message has been sent |
| // } |
| } |
| else { |
| m_outCounts[type] += 1; |
| outLock.notifyAll(); // tell anyone who is waiting that a message has been sent |
| } |
| } |
| } |
| |
| public void setIsolate(boolean value) { |
| m_isolate = value; |
| } |
| |
| /** |
| * Collect stats on the messages |
| */ |
| public void messageArrived(DMessage msg, DProtocol which) |
| { |
| /* extract type */ |
| int type = msg.getType(); |
| |
| // System.out.println("msg counter ="+type); |
| |
| /* anything we don't know about goes in a special slot at the end of the array. */ |
| if (type < 0 || type >= DMessage.InSIZE) |
| type = DMessage.InSIZE; |
| Object inLock = getInLock(); |
| if (!m_isolate) { |
| synchronized (m_isolateLock) { |
| if (m_lastIsolate != Isolate.DEFAULT_ID) { |
| DMessageCounter counter = m_isolateCounterMap.get(m_lastIsolate); |
| inLock = counter.getInLock(); |
| } |
| } |
| } |
| |
| synchronized (inLock) { |
| if (type == DMessage.InIsolate) { |
| long isolate = msg.getDWord(); |
| if (isolate != Isolate.DEFAULT_ID) { |
| /** Check if our map has a counter for this isolate */ |
| if (!m_isolateCounterMap.containsKey(isolate)) { |
| DMessageCounter isolateCounter = new DMessageCounter(); |
| isolateCounter.setIsolate(true); |
| m_isolateCounterMap.put(isolate, isolateCounter); |
| } |
| } |
| synchronized (m_isolateLock) { |
| m_lastIsolate = isolate; |
| } |
| m_inCounts[type] += 1; |
| inLock.notifyAll(); // tell anyone who is waiting that a message has been received |
| } |
| else if (!m_isolate && m_lastIsolate != Isolate.DEFAULT_ID) { |
| DMessageCounter counter = m_isolateCounterMap.get(m_lastIsolate); |
| counter.messageArrived(msg, which); |
| synchronized (counter.getInLock()) { |
| counter.getInLock().notifyAll(); |
| } |
| |
| } |
| else { |
| m_inCounts[type] += 1; |
| inLock.notifyAll(); // tell anyone who is waiting that a message has been received |
| } |
| } |
| } |
| |
| /* getters */ |
| public long getInCount(int type) { synchronized (getInLock()) { return m_inCounts[type]; } } |
| public long getOutCount(int type) { synchronized (getOutLock()) { return m_outCounts[type]; } } |
| |
| public long getIsolateInCount(long isolate, int type) { |
| DMessageCounter counter = m_isolateCounterMap.get(isolate); |
| return counter.getInCount(type); |
| } |
| |
| public long getIsolateOutCount(long isolate, int type) { |
| DMessageCounter counter = m_isolateCounterMap.get(isolate); |
| return counter.getOutCount(type); |
| } |
| |
| public Object getIsolateInLock(long isolate) { |
| DMessageCounter counter = m_isolateCounterMap.get(isolate); |
| return counter.getInLock(); |
| } |
| |
| |
| /* setters */ |
| public void clearInCounts() { synchronized (getInLock()) { clearArray(m_inCounts); } } |
| public void clearOutCounts() { synchronized (getOutLock()) { clearArray(m_outCounts); } } |
| |
| /** |
| * Clear out the array |
| */ |
| void clearArray(long[] ar) |
| { |
| for(int i=0; i<ar.length; i++) |
| ar[i] = 0; |
| } |
| } |