Hi,

I have committed the attached patch, which although a little kludgy, adds the ability for the VM to send multiple events in a single packet (what events to send and whether they are legal to send together is the responsibility of the VM).

We should not need a queue to deal with this: the VM *should* know when it is appropriate to use this. Right now, as far as I can tell, that means with MethodEntry/Exit, SingleStep, and Breakpoint. One is supposed to be able to send multiple ThreadStart/End, ClassPrepare, and other events together (as long as they're all the same thread and class), but Sun's HotSpot VM does not do it this way. It sends a packet for each event.

Largely it is a refactoring of the old code.

Keith

ChangeLog
2007-05-03  Keith Seitz  <[EMAIL PROTECTED]>

        * gnu/classpath/jdwp/Jdwp.java (notify): Rewrite to call
        new array-based method.
        (notify): New function.
        (sendEvent): Rewrite to use sendEvents.
        (sendEvents): New method.
        * gnu/classpath/jdwp/event/Event.java (toPacket): Make static.
        Change parameters to use arrays for events and requests.
        Add suspendPolicy parameter.
        Move per-event data transformation to...
        (_toData): ... here.
        * gnu/classpath/jdwp/transport/JdwpConnection.java
        (sendEvent): Renamed to ...
        (sendEvents): ... this.
        Change parameters to use arrays for events and requests.
        Add suspendPolicy parameter.
Index: gnu/classpath/jdwp/Jdwp.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/Jdwp.java,v
retrieving revision 1.9
diff -u -p -r1.9 Jdwp.java
--- gnu/classpath/jdwp/Jdwp.java	27 Apr 2007 21:30:59 -0000	1.9
+++ gnu/classpath/jdwp/Jdwp.java	3 May 2007 22:46:21 -0000
@@ -51,6 +51,7 @@ import gnu.classpath.jdwp.transport.Tran
 
 import java.io.IOException;
 import java.security.AccessController;
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -207,7 +208,6 @@ public class Jdwp
    * The event is filtered through the event manager before being
    * sent.
    *
-   * FIXME: Probably need logic to send multiple (different) events
    * @param event the event to report
    */
   public static void notify(Event event)
@@ -235,6 +235,62 @@ public class Jdwp
   }
   
   /**
+   * Notify the debugger of "co-located" events. This method should
+   * not be called if debugging is not active (but it would not
+   * cause any harm). Places where event notifications occur
+   * should check isDebugging before doing anything.
+   *
+   * The events are filtered through the event manager before being
+   * sent.
+   *
+   * @param events the events to report
+   */
+  public static void notify(Event[] events)
+  {
+    Jdwp jdwp = getDefault();
+    
+    if (jdwp != null)
+      {
+	byte suspendPolicy = JdwpConstants.SuspendPolicy.NONE;
+	EventManager em = EventManager.getDefault();
+	ArrayList allEvents = new ArrayList ();
+	ArrayList allRequests = new ArrayList ();
+	for (int i = 0; i < events.length; ++i)
+	  {
+	    EventRequest[] r = em.getEventRequests(events[i]);
+	    for (int j = 0; j < r.length; ++j)
+	      {
+		/* This is hacky, but it's not clear whether this
+		   can really happen, and if it does, what should
+		   occur. */
+		allEvents.add (events[i]);
+		allRequests.add (r[j]);
+
+		// Perhaps this is overkill?
+		if (r[j].getSuspendPolicy() > suspendPolicy)
+		  suspendPolicy = r[j].getSuspendPolicy();
+	      }
+	  }
+
+	try
+	  {
+	    Event[] e = new Event[allEvents.size()];
+	    allEvents.toArray(e);
+	    EventRequest[] r = new EventRequest[allRequests.size()];
+	    allRequests.toArray(r);
+	    sendEvents(r, e, suspendPolicy);
+	    jdwp._enforceSuspendPolicy(suspendPolicy);
+	  }
+	catch (Exception e)
+	  {
+	    /* Really not much we can do. For now, just print out
+	       a warning to the user. */
+	    System.out.println ("Jdwp.notify: caught exception: " + e);
+	  }
+      }
+  }
+
+  /**
    * Sends the event to the debugger.
    *
    * This method bypasses the event manager's filtering.
@@ -246,13 +302,30 @@ public class Jdwp
   public static void sendEvent (EventRequest request, Event event)
       throws IOException
   {
-    Jdwp jdwp = getDefault ();
+    sendEvents (new EventRequest[] { request }, new Event[] { event },
+		request.getSuspendPolicy());
+  }
+
+  /**
+   * Sends the events to the debugger.
+   *
+   * This method bypasses the event manager's filtering.
+   *
+   * @param  requests  list of debugger requests for the events
+   * @param  events    the events to send
+   * @param  suspendPolicy the suspendPolicy enforced by the VM
+   * @throws IOException if a communications failure occurs
+   */
+  public static void sendEvents (EventRequest[] requests, Event[] events,
+				 byte suspendPolicy)
+    throws IOException
+  {
+    Jdwp jdwp = getDefault();
     if (jdwp != null)
       {
-	// !! May need to implement send queue?
 	synchronized (jdwp._connection)
 	  {
-	    jdwp._connection.sendEvent (request, event);
+	    jdwp._connection.sendEvents (requests, events, suspendPolicy);
 	  }
       }
   }
Index: gnu/classpath/jdwp/event/Event.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/event/Event.java,v
retrieving revision 1.2
diff -u -p -r1.2 Event.java
--- gnu/classpath/jdwp/event/Event.java	12 Jun 2006 19:43:26 -0000	1.2
+++ gnu/classpath/jdwp/event/Event.java	3 May 2007 22:46:21 -0000
@@ -1,5 +1,5 @@
 /* Event.java -- a base class for all event types
-   Copyright (C) 2005 Free Software Foundation
+   Copyright (C) 2005, 2007 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -135,25 +135,30 @@ public abstract class Event
   public abstract Object getParameter (int type);
 
   /**
-   * Converts this event into to a JDWP packet
+   * Converts the events into to a single JDWP Event.COMPOSITE packet
    *
    * @param dos     the stream to which to write data
-   * @param request the request the wanted this notification
+   * @param events  the events to package into the packet
+   * @param requests the corresponding event requests
+   * @param suspendPolicy the suspend policy enforced by the VM
    * @returns a <code>JdwpPacket</code> of the events
    */
-  public JdwpPacket toPacket (DataOutputStream dos, EventRequest request)
+  public static JdwpPacket toPacket (DataOutputStream dos,
+				     Event[] events,
+				     EventRequest[] requests,
+				     byte suspendPolicy)
   {
     JdwpPacket pkt;
     try
       {
-	dos.writeByte (request.getSuspendPolicy ());
-	dos.writeInt (1);
-	dos.writeByte (_eventKind);
-	dos.writeInt (request.getId ());
-	_writeData (dos);
-
-	pkt = new JdwpCommandPacket (JdwpConstants.CommandSet.Event.CS_VALUE,
-				     JdwpConstants.CommandSet.Event.COMPOSITE);
+	dos.writeByte (suspendPolicy);
+	dos.writeInt (events.length);
+	for (int i = 0; i < events.length; ++i)
+	  _toData (dos, events[i], requests[i]);
+
+	pkt
+	  = new JdwpCommandPacket (JdwpConstants.CommandSet.Event.CS_VALUE,
+				   JdwpConstants.CommandSet.Event.COMPOSITE);
       }
     catch (IOException ioe)
       {
@@ -162,4 +167,14 @@ public abstract class Event
 
     return pkt;
   }
+
+  // Helper function for toPacket
+  private static void _toData (DataOutputStream dos, Event event,
+			       EventRequest request)
+    throws IOException
+  {
+    dos.writeByte (event._eventKind);
+    dos.writeInt (request.getId ());
+    event._writeData (dos);
+  }
 }
Index: gnu/classpath/jdwp/transport/JdwpConnection.java
===================================================================
RCS file: /sources/classpath/classpath/gnu/classpath/jdwp/transport/JdwpConnection.java,v
retrieving revision 1.6
diff -u -p -r1.6 JdwpConnection.java
--- gnu/classpath/jdwp/transport/JdwpConnection.java	16 Jun 2006 18:32:49 -0000	1.6
+++ gnu/classpath/jdwp/transport/JdwpConnection.java	3 May 2007 22:46:21 -0000
@@ -1,5 +1,5 @@
 /* JdwpConnection.java -- A JDWP-speaking connection
-   Copyright (C) 2005, 2006 Free Software Foundation
+   Copyright (C) 2005, 2006, 2007 Free Software Foundation
 
 This file is part of GNU Classpath.
 
@@ -267,13 +267,17 @@ public class JdwpConnection
   }
 
   /**
-   * Send an event notification to the debugger
+   * Send an event notification to the debugger. Note that this
+   * method will only send out one notification: all the events
+   * are passed in a single Event.COMPOSITE packet.
    *
-   * @param request  the debugger request that wanted this event
-   * @param event    the event
+   * @param requests  debugger requests for events
+   * @param events    the events to send
+   * @param suspendPolicy  the suspend policy enforced by the VM
    * @throws IOException
    */
-  public void sendEvent (EventRequest request, Event event)
+  public void sendEvents(EventRequest[] requests, Event[] events,
+			 byte suspendPolicy)
     throws IOException
   {
     JdwpPacket pkt;
@@ -281,7 +285,7 @@ public class JdwpConnection
     synchronized (_bytes)
       {
 	_bytes.reset ();
-	pkt = event.toPacket (_doStream, request);
+	pkt = Event.toPacket (_doStream, events, requests, suspendPolicy);
 	pkt.setData (_bytes.toByteArray ());
       }
 

Reply via email to