Exemplo n.º 1
0
/* Terminate any kind of dripback landing. */
void SNetTermDripBack(landing_t *land, fifo_t *fifo)
{
  trace(__func__);

  if (land->type == LAND_dripback1) {
    landing_dripback1_t   *db1 = LAND_SPEC(land, dripback1);

    if (db1->controldesc) {
      snet_record_t *rec = SNetRecCreate(REC_terminate);
      land->worker = SNetThreadGetSelf();
      SNetWrite(&db1->controldesc, rec, false);
      SNetFifoPut(fifo, db1->controldesc);
    } else {
      SNetLandingDone(db1->dripback2);
    }
    SNetFreeLanding(land);
  }
  else if (land->type == LAND_dripback2) {
    landing_dripback2_t   *db2 = LAND_SPEC(land, dripback2);

    if (db2->instdesc) {
      fprintf(stderr, "%s: Premature termination of dripback2\n", __func__);
      SNetFifoPut(fifo, db2->instdesc);
      db2->instdesc = NULL;
    }
    if (db2->outdesc) {
      SNetFifoPut(fifo, db2->outdesc);
      db2->outdesc = NULL;
    }
    SNetFreeLanding(land);
  }
  else {
    assert(0);
  }
}
Exemplo n.º 2
0
/* Change an identity landing into a garbage landing. */
void SNetBecomeGarbage(landing_t *land)
{
  /* One static node for all garbage landings. */
  static node_t garbage_node = {
    NODE_garbage, SNetNodeGarbage, SNetStopGarbage, SNetTermGarbage
  };
  landing_identity_t    *ident = LAND_SPEC(land, identity);
  snet_stream_desc_t    *desc = ident->outdesc;

  /* Only identity landings can become a garbage landing. */
  assert(land->type == LAND_identity);

  if (SNetDebug()) {
    printf("%s: node %s land %s (prev %s)\n",
           __func__, SNetNodeName(land->node), SNetLandingName(land),
           SNetLandingTypeName(ident->prev_type));
  }

  /* Init new state to ``garbage'' */
  land->type = LAND_garbage;
  land->node = &garbage_node;

  /* Guarantee that destination stream persists until termination. */
  DESC_INCR(desc);
  LAND_INCR(desc->landing);
  assert(desc == LAND_SPEC(land, siso)->outdesc);
}
Exemplo n.º 3
0
/* Terminate any kind of feedback landing. */
void SNetTermFeedback(landing_t *land, fifo_t *fifo)
{
  trace(__func__);
  if (land->type == LAND_feedback1) {
    landing_feedback1_t   *fb1 = LAND_SPEC(land, feedback1);
    landing_feedback3_t   *fb3 = LAND_SPEC(fb1->feedback3, feedback3);

    assert(fb3->terminate == FeedbackInitial);
    if (fb1->outdesc) {
      SNetFifoPut(fifo, fb1->outdesc);
    }
    if (fb1->instdesc) {
      snet_record_t *recdet = SNetRecCreate(REC_detref, -1L, fb1->feedback3, NULL);
      land->worker = SNetThreadGetSelf();
      SNetWrite(&fb1->instdesc, recdet, false);
      SNetFifoPut(fifo, fb1->instdesc);
    }
    SNetLandingDone(fb1->feedback2);
    SNetLandingDone(fb1->feedback4);
    SNetLandingDone(fb1->feedback3);
    SNetFreeLanding(land);
  }
  else if (land->type == LAND_feedback2) {
    landing_feedback2_t   *fb2 = LAND_SPEC(land, feedback2);

    if (fb2->instdesc) {
      SNetFifoPut(fifo, fb2->instdesc);
    }
    SNetLandingDone(fb2->feedback3);
    SNetFreeLanding(land);
  }
  else if (land->type == LAND_feedback3) {
    landing_feedback3_t   *fb3 = LAND_SPEC(land, feedback3);

    SNetLandingDone(fb3->feedback4);
    SNetFreeLanding(land);
  }
  else if (land->type == LAND_feedback4) {
    landing_feedback4_t   *fb4 = LAND_SPEC(land, feedback4);

    if (fb4->outdesc) {
      SNetFifoPut(fifo, fb4->outdesc);
    }
    SNetFreeLanding(land);
  }
  else {
    assert(0);
  }
}
Exemplo n.º 4
0
/* Read one record from the parser. */
input_state_t SNetGetNextInputRecord(landing_t *land)
{
  landing_input_t       *linp = LAND_SPEC(land, input);
  input_arg_t           *iarg = NODE_SPEC(land->node, input);
  snet_record_t         *record = NULL;

  trace(__func__);
  assert(NODE_TYPE(land->node) == NODE_input);

  if (iarg->state == INPUT_reading) {
    // Ask parser for a new input record.
    while (SNetInParserGetNextRecord(&record) == SNET_PARSE_CONTINUE) {
      if (record) {
        break;
      }
    }
    if (record) {
      if (REC_DESCR(record) == REC_terminate) {
        SNetRecDestroy(record);
        iarg->state = INPUT_terminating;
      } else {
        linp->num_inputs += 1;
        SNetWrite(&linp->outdesc, record, false);
        return INPUT_reading;
      }
    } else {
      iarg->state = INPUT_terminating;
    }
    return iarg->state;
  } else {
    return INPUT_terminated;
  }
}
Exemplo n.º 5
0
/* Terminate a garbage landing: decrease references to subsequent resources. */
void SNetTermGarbage(landing_t *land, fifo_t *fifo)
{
  snet_stream_desc_t    *desc = LAND_SPEC(land, siso)->outdesc;
  trace(__func__);
  assert(desc);
  assert(desc->refs > 0);
  SNetLandingDone(desc->landing);
  SNetFifoPut(fifo, desc);
  SNetFreeLanding(land);
}
Exemplo n.º 6
0
/* Change a landing into an identity landing. */
void SNetBecomeIdentity(landing_t *land, snet_stream_desc_t *out)
{
    /* One static node for all identities. */
    static node_t identity_node = {
        NODE_identity, SNetNodeIdentity, SNetStopIdentity, SNetTermIdentity
    };
    landing_type_t prev_type = land->type;

    if (SNetDebugGC()) {
        printf("%s: node %s land %s\n",
               __func__, SNetNodeName(land->node), SNetLandingName(land));
    }

    /* Destroy old resources */
    SNetCleanupLanding(land);

    /* Init new state */
    land->type = LAND_identity;
    land->node = &identity_node;
    LAND_SPEC(land, identity)->outdesc = out;
    LAND_SPEC(land, identity)->prev_type = prev_type;

    assert(land->refs > 0);
}
Exemplo n.º 7
0
/* Terminate a star landing. */
void SNetTermStar(landing_t *land, fifo_t *fifo)
{
  landing_star_t        *lstar = LAND_SPEC(land, star);

  trace(__func__);

  if (lstar->instdesc) {
    SNetFifoPut(fifo, lstar->instdesc);
  }
  if (lstar->colldesc) {
    SNetFifoPut(fifo, lstar->colldesc);
  }
  if (lstar->instland) {
    SNetLandingDone(lstar->instland);
  }

  SNetLandingDone(lstar->collland);
  SNetFreeLanding(land);
}
Exemplo n.º 8
0
/* Terminate an identity landing. */
void SNetTermIdentity(landing_t *land, fifo_t *fifo)
{
    trace(__func__);
    SNetFifoPut(fifo, LAND_SPEC(land, identity)->outdesc);
    SNetFreeLanding(land);
}
Exemplo n.º 9
0
/* DripBack process a record. */
void SNetNodeDripBack(snet_stream_desc_t *desc, snet_record_t *rec)
{
  landing_t             *land = desc->landing;
  dripback_arg_t        *darg = LAND_NODE_SPEC(land, dripback);

  trace(__func__);

  if (land->type == LAND_dripback1) {
    landing_dripback1_t *db1 = LAND_SPEC(land, dripback1);
    landing_dripback2_t *db2 = LAND_SPEC(db1->dripback2, dripback2);
    SNetFifoPut(db1->recfifo, rec);
    if (FAA(&db2->queued, 1) == 0) {
      if (db1->controldesc == NULL) {
        SNetPushLanding(desc, db1->dripback2);
        db1->controldesc = SNetStreamOpen(darg->selfref, desc);
      }
      rec = SNetRecCreate(REC_wakeup);
      SNetWrite(&db1->controldesc, rec, true);
    }
  }
  else if (land->type == LAND_dripback2) {
    landing_dripback2_t *db2 = LAND_SPEC(land, dripback2);
    bool via_access = (DESC_STREAM(desc) == darg->selfref);

    assert(via_access || DESC_STREAM(desc) == darg->dripback);

    while (rec) {
      switch (REC_DESCR( rec)) {
        case REC_data:
          /* Test if record should go to the instance. */
          if (SNetFeedbackMatch( rec, darg->back_patterns, darg->guards)) {
            if (via_access) {
              /* Because record came from outside add a detref counter. */
              assert(db2->detfifo.head->next == NULL);
              SNetRecDetrefAdd(rec, ++(db2->entered), land, &db2->detfifo);
            } else {
              /* Record came from the instance. */
              assert(DATA_REC(rec, detref));
            }
            if (db2->instdesc == NULL) {
              /* Instance should come back to this landing. */
              if (SNetTopLanding(desc) != land) {
                SNetPushLanding(desc, land);
              }
              db2->instdesc = SNetStreamOpen(darg->instance, desc);
              if (SNetTopLanding(desc) == land) {
                SNetPopLanding(desc);
                SNetLandingDone(land);
              }
            }
            SNetWrite(&db2->instdesc, rec, false);
          } else {
            if (!via_access) {
              /* Record leaves the dripback loop. */
              assert(DATA_REC(rec, detref));
              SNetFeedbackLeave(rec, land, &db2->detfifo);
            }
            if (db2->outdesc == NULL) {
              db2->outdesc = SNetStreamOpen(darg->output, desc);
            }
            SNetWrite(&db2->outdesc, rec, false);
          }
          break;

        case REC_wakeup:
          assert(via_access);
          SNetRecDestroy(rec);
          break;

        case REC_terminate:
          assert(via_access);
          assert(db2->terminate == DripBackInitial);
          db2->terminate = DripBackDraining;
          SNetRecDestroy(rec);
          break;

        case REC_detref:
          if (DETREF_REC( rec, leave) == land &&
              DETREF_REC( rec, location) == SNetDistribGetNodeId())
          {
            assert(!via_access);
            SNetDetLeaveCheckDetref(rec, &db2->detfifo);
            if (DETREF_REC( rec, detref) == SNetFifoPeekFirst(&db2->detfifo)) {
              DripBackCheckBusy(db2);
            }
            SNetRecDestroy(rec);
          } else {
            assert(via_access);
            if (db2->outdesc == NULL) {
              db2->outdesc = SNetStreamOpen(darg->output, desc);
            }
            SNetWrite(&db2->outdesc, rec, false);
          }
          break;

        case REC_sync:
          SNetRecDestroy(rec);
          break;

        default:
          SNetRecUnknownEnt(__func__, rec, darg->entity);
      }
      rec = NULL;
      if (db2->state == DripBackBusy) {
        if (DripBackCheckBusy(db2) == false) {
          assert(db2->queued > 0);
          if (SAF(&db2->queued, 1) == 0) {
            db2->state = DripBackIdle;
          } else {
            rec = SNetFifoGet(&db2->recfifo);
            assert(rec);
            via_access = true;
          }
        }
      } else {
        assert(db2->state == DripBackIdle);
        assert(SNetFifoPeekFirst(&db2->detfifo) == NULL);
        if (db2->queued > 0) {
          rec = SNetFifoGet(&db2->recfifo);
          assert(rec);
          via_access = true;
          db2->state = DripBackBusy;
        }
      }
    }
    if (db2->terminate == DripBackDraining) {
      if (db2->state == DripBackIdle) {
        assert(db2->queued == 0 && DripBackCheckBusy(db2) == false);
        db2->terminate = DripBackTerminated;
      }
    }
    if (db2->terminate == DripBackTerminated) {
      if (db2->instdesc) {
        snet_stream_desc_t *desc = db2->instdesc;
        db2->instdesc = NULL;
        SNetDescDone(desc);
        SNetLandingDone(land);
      }
    }
  }
  else {
    assert(0);
  }
}
Exemplo n.º 10
0
/* Feedback forward a record. */
void SNetNodeFeedback(snet_stream_desc_t *desc, snet_record_t *rec)
{
  landing_t             *land = desc->landing;
  feedback_arg_t        *farg = LAND_NODE_SPEC(land, feedback);

  trace(__func__);

  if (land->type == LAND_feedback1) {
    landing_feedback1_t *fb1 = LAND_SPEC(land, feedback1);

    switch (REC_DESCR( rec)) {
      case REC_data:
        /* Test if record should go into the feedback loop. */
        if (SNetFeedbackMatch( rec, farg->back_patterns, farg->guards)) {
          /* Because record came from outside add a detref counter. */
          SNetRecDetrefAdd(rec, ++(fb1->counter), fb1->feedback3, fb1->detfifo);
          if (fb1->instdesc == NULL) {
            SNetPushLanding(desc, fb1->feedback2);
            fb1->instdesc = SNetStreamOpen(farg->selfref2, desc);
          }
          SNetWrite(&fb1->instdesc, rec, true);
        } else {
          if (fb1->outdesc == NULL) {
            SNetPushLanding(desc, fb1->feedback4);
            fb1->outdesc = SNetStreamOpen(farg->selfref4, desc);
          }
          SNetWrite(&fb1->outdesc, rec, true);
        }
        break;

      case REC_detref:
        if (fb1->outdesc == NULL) {
          SNetPushLanding(desc, fb1->feedback4);
          fb1->outdesc = SNetStreamOpen(farg->selfref4, desc);
        }
        SNetWrite(&fb1->outdesc, rec, true);
        break;

      case REC_sync:
        SNetRecDestroy(rec);
        break;

      default:
        SNetRecUnknownEnt(__func__, rec, farg->entity);
    }
  }
  else if (land->type == LAND_feedback2) {
    landing_feedback2_t *fb2 = LAND_SPEC(land, feedback2);
    if (fb2->instdesc == NULL) {
      SNetPushLanding(desc, fb2->feedback3);
      fb2->instdesc = SNetStreamOpen(farg->instance, desc);
    }
    switch (REC_DESCR( rec)) {
      case REC_data:
      case REC_detref:
        SNetWrite(&fb2->instdesc, rec, true);
        break;

      default:
        SNetRecUnknownEnt(__func__, rec, farg->entity);
    }
  }
  else if (land->type == LAND_feedback4) {
    landing_feedback4_t *fb4 = LAND_SPEC(land, feedback4);
    if (fb4->outdesc == NULL) {
      fb4->outdesc = SNetStreamOpen(farg->output, desc);
    }
    switch (REC_DESCR( rec)) {
      case REC_data:
      case REC_detref:
        SNetWrite(&fb4->outdesc, rec, true);
        break;

      default:
        SNetRecUnknownEnt(__func__, rec, farg->entity);
    }
  }
  else if (land->type == LAND_feedback3) {
    landing_feedback3_t *fb3 = LAND_SPEC(land, feedback3);
    if (fb3->terminate == FeedbackTerminated) {
      assert(REC_DESCR( rec) != REC_data);
      SNetRecDestroy(rec);
    } else {
      switch (REC_DESCR( rec)) {
        case REC_data:
          /* Test if record should go into the feedback loop. */
          if (SNetFeedbackMatch( rec, farg->back_patterns, farg->guards)) {
            if (fb3->instdesc == NULL) {
              SNetPushLanding(desc, fb3->feedback2);
              fb3->instdesc = SNetStreamOpen(farg->selfref2, desc);
            }
            /* send the record to the instance */
            SNetWrite(&fb3->instdesc, rec, false);
          } else {
            /* record leaves the feedback loop. */
            SNetFeedbackLeave(rec, land, &fb3->detfifo);
            if (fb3->outdesc == NULL) {
              SNetPushLanding(desc, fb3->feedback4);
              fb3->outdesc = SNetStreamOpen(farg->selfref4, desc);
            }
            /* forward record outwards */
            SNetWrite(&fb3->outdesc, rec, false);
            if (fb3->terminate) {
              assert(fb3->terminate == FeedbackDraining);
              FeedbackCheckBusy(fb3);
            }
          }
          break;

        case REC_detref:
          if (DETREF_REC( rec, leave) == land) {
            if (DETREF_REC( rec, seqnr) == -1L) {
              assert(fb3->terminate == FeedbackInitial);
              fb3->terminate = FeedbackDraining;
            }
            SNetRecDestroy(rec);
            FeedbackCheckBusy(fb3);
          }
          break;

        case REC_sync:
          SNetRecDestroy(rec);
          break;

        default:
          SNetRecUnknownEnt(__func__, rec, farg->entity);
      }
      if (fb3->terminate == FeedbackTerminating) {
        if (fb3->outdesc) {
          SNetDescDone(fb3->outdesc);
        }
        if (fb3->instdesc) {
          SNetDescDone(fb3->instdesc);
        }
        SNetLandingDone(fb3->feedback2);
        fb3->terminate = FeedbackTerminated;
      }
    }
  }
  else {
    assert(0);
  }
}