blob: e13d6013d950fbf13a4a846d116929a316491208 [file] [log] [blame]
/*
* 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;
}
}