/* Notification to GDB.
   Copyright (C) 1989-2013 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* Async notifications to GDB.  When the state of remote target is
   changed or something interesting to GDB happened, async
   notifications are used to tell GDB.

   Each type of notification is represented by an object
   'struct notif_server', in which there is a queue for events to GDB
   represented by 'struct notif_event'.  GDBserver writes (by means of
   'write' field) each event in the queue into the buffer and send the
   contents in buffer to GDB.  The contents in buffer is specified in
   RSP.  See more in the comments to field 'queue' of
   'struct notif_server'.

   Here is the workflow of sending events and managing queue:
   1.  At any time, when something interesting FOO happens, a object
   of 'struct notif_event' or its sub-class EVENT is created for FOO.

   2.  Enque EVENT to the 'queue' field of 'struct notif_server' for
   FOO and send corresponding notification packet to GDB if EVENT is
   the first one.
   #1 and #2 are done by function 'notif_push'.

   3.  EVENT is not deque'ed until the ack of FOO from GDB arrives.
   Before ack of FOO arrives, FOO happens again, a new object of
   EVENT is created and enque EVENT silently.
   Once GDB has a chance to ack to FOO, it sends an ack to GDBserver,
   and GDBserver repeatedly sends events to GDB and gets ack of FOO,
   until queue is empty.  Then, GDBserver sends 'OK' to GDB that all
   queued notification events are done.

   # 3 is done by function 'handle_notif_ack'.  */

#include "notif.h"

static struct notif_server *notifs[] =
{
  &notif_stop,
};

/* Write another event or an OK, if there are no more left, to
   OWN_BUF.  */

void
notif_write_event (struct notif_server *notif, char *own_buf)
{
  if (!QUEUE_is_empty (notif_event_p, notif->queue))
    {
      struct notif_event *event
	= QUEUE_peek (notif_event_p, notif->queue);

      notif->write (event, own_buf);
    }
  else
    write_ok (own_buf);
}

/* Handle the ack in buffer OWN_BUF,and packet length is PACKET_LEN.
   Return 1 if the ack is handled, and return 0 if the contents
   in OWN_BUF is not a ack.  */

int
handle_notif_ack (char *own_buf, int packet_len)
{
  int i = 0;
  struct notif_server *np = NULL;

  for (i = 0; i < ARRAY_SIZE (notifs); i++)
    {
      np = notifs[i];
      if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0
	  && packet_len == strlen (np->ack_name))
	break;
    }

  if (np == NULL)
    return 0;

  /* If we're waiting for GDB to acknowledge a pending event,
     consider that done.  */
  if (!QUEUE_is_empty (notif_event_p, np->queue))
    {
      struct notif_event *head
	= QUEUE_deque (notif_event_p, np->queue);

      if (remote_debug)
	fprintf (stderr, "%s: acking %d\n", np->ack_name,
		 QUEUE_length (notif_event_p, np->queue));

      xfree (head);
    }

  notif_write_event (np, own_buf);

  return 1;
}

/* Put EVENT to the queue of NOTIF.  */

void
notif_event_enque (struct notif_server *notif,
		   struct notif_event *event)
{
  QUEUE_enque (notif_event_p, notif->queue, event);

  if (remote_debug)
    fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
	     QUEUE_length (notif_event_p, notif->queue));

}

/* Push one event NEW_EVENT of notification NP into NP->queue.  */

void
notif_push (struct notif_server *np, struct notif_event *new_event)
{
  int is_first_event = QUEUE_is_empty (notif_event_p, np->queue);

  /* Something interesting.  Tell GDB about it.  */
  notif_event_enque (np, new_event);

  /* If this is the first stop reply in the queue, then inform GDB
     about it, by sending a corresponding notification.  */
  if (is_first_event)
    {
      char buf[PBUFSIZ];
      char *p = buf;

      xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
      p += strlen (p);

      np->write (new_event, p);
      putpkt_notif (buf);
    }
}

static void
notif_event_xfree (struct notif_event *event)
{
  xfree (event);
}

void
initialize_notif (void)
{
  int i = 0;

  for (i = 0; i < ARRAY_SIZE (notifs); i++)
    notifs[i]->queue
      = QUEUE_alloc (notif_event_p, notif_event_xfree);
}
