Revision d6a836f8

View differences:

nest/neighbor.c
254 254
static inline void
255 255
neigh_prune_one(neighbor *n)
256 256
{
257
  if (n->proto->core_state != FS_FLUSHING)
257
  if (n->proto->proto_state != PS_DOWN)
258 258
    return;
259 259
  rem_node(&n->n);
260 260
  if (n->iface)
nest/proto.c
552 552
  proto_feed_more(P);
553 553
}
554 554

  
555
static void
556
proto_schedule_flush(struct proto *p)
557
{
558
  /* Need to abort feeding */
559
  if (p->core_state == FS_FEEDING)
560
    rt_feed_baby_abort(p);
561

  
562
  DBG("%s: Scheduling flush\n", p->name);
563
  p->core_state = FS_FLUSHING;
564
  proto_relink(p);
565
  proto_flush_hooks(p);
566
  ev_schedule(proto_flush_event);
567
}
568

  
569
static void
570
proto_schedule_feed(struct proto *p)
571
{
572
  DBG("%s: Scheduling meal\n", p->name);
573
  p->core_state = FS_FEEDING;
574
  proto_relink(p);
575
  p->attn->hook = proto_feed;
576
  ev_schedule(p->attn);
577
}
578

  
555 579
/**
556 580
 * proto_notify_state - notify core about protocol state change
557 581
 * @p: protocol the state of which has changed
......
562 586
 * it should immediately notify the core about the change by calling
563 587
 * proto_notify_state() which will write the new state to the &proto
564 588
 * structure and take all the actions necessary to adapt to the new
565
 * state.
589
 * state. State change to PS_DOWN immediately frees resources of protocol
590
 * and might execute start callback of protocol; therefore,
591
 * it should be used at tail positions of protocol callbacks.
566 592
 */
567 593
void
568 594
proto_notify_state(struct proto *p, unsigned ps)
......
574 600
  if (ops == ps)
575 601
    return;
576 602

  
603
  p->proto_state = ps;
604

  
577 605
  switch (ps)
578 606
    {
579 607
    case PS_DOWN:
608
      neigh_prune(); // FIXME convert neighbors to resource?
609
      rfree(p->pool);
610
      p->pool = NULL;
611

  
580 612
      if (cs == FS_HUNGRY)		/* Shutdown finished */
581 613
	{
582
	  p->proto_state = ps;
583 614
	  proto_fell_down(p);
584 615
	  return;			/* The protocol might have ceased to exist */
585 616
	}
586
      else if (cs == FS_FLUSHING)	/* Still flushing... */
587
	;
588
      else
589
	{
590
	  if (cs == FS_FEEDING)		/* Need to abort feeding */
591
	    rt_feed_baby_abort(p);
592
	  goto schedule_flush;		/* Need to start flushing */
593
	}
617
      /* Otherwise, we have something to flush... */
618
      else if (cs != FS_FLUSHING)
619
	proto_schedule_flush(p);
594 620
      break;
595 621
    case PS_START:
596 622
      ASSERT(ops == PS_DOWN);
......
599 625
    case PS_UP:
600 626
      ASSERT(ops == PS_DOWN || ops == PS_START);
601 627
      ASSERT(cs == FS_HUNGRY);
602
      DBG("%s: Scheduling meal\n", p->name);
603
      cs = FS_FEEDING;
604
      p->attn->hook = proto_feed;
605
      ev_schedule(p->attn);
628
      proto_schedule_feed(p);
606 629
      break;
607 630
    case PS_STOP:
608
      if (ops != PS_DOWN)
609
	{
610
	schedule_flush:
611
	  DBG("%s: Scheduling flush\n", p->name);
612
	  proto_flush_hooks(p);
613
	  cs = FS_FLUSHING;
614
	  ev_schedule(proto_flush_event);
615
	}
631
      if ((cs = FS_FEEDING) || (cs == FS_HAPPY))
632
	proto_schedule_flush(p);
616 633
      break;
617 634
    default:
618 635
      bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]);
619 636
    }
620
  p->proto_state = ps;
621
  p->core_state = cs;
622
  proto_relink(p);
623 637
}
624 638

  
625 639
static void
......
628 642
  struct proto *p;
629 643

  
630 644
  rt_prune_all();
631
  neigh_prune();
632 645
  while ((p = HEAD(flush_proto_list))->n.next)
633 646
    {
634 647
      DBG("Flushing protocol %s\n", p->name);
635
      rfree(p->pool);
636
      p->pool = NULL;
637 648
      p->core_state = FS_HUNGRY;
638 649
      proto_relink(p);
639
      proto_fell_down(p);
650
      if (p->proto_state == PS_DOWN)
651
	proto_fell_down(p);
640 652
    }
641 653
}
642 654

  

Also available in: Unified diff