Ejemplo n.º 1
0
/* Open a descriptor to an output stream.
 *
 * The source landing which opens the stream is determined by parameter 'prev'.
 * The new descriptor holds a pointer to a landing which instantiates
 * the destination node as determined by the stream parameter 'stream'.
 *
 * Special cases:
 * (1) Dispatchers should create an additional landing for a future collector
 * and push this landing onto a stack of future landings.
 * (2) Collectors should retrieve their designated landing from this stack
 * and verify that it is theirs.
 */
snet_stream_desc_t *SNetStreamOpen(
    snet_stream_t *stream,
    snet_stream_desc_t *prev)
{
  snet_stream_desc_t    *desc;

  trace(__func__);

  desc = SNetNewAlign(snet_stream_desc_t);
  DESC_STREAM(desc) = stream;
  desc->source = prev->landing;
  desc->refs = 1;
  SNetFifoInit(&desc->fifo);

  switch (NODE_TYPE(stream->dest)) {

    case NODE_filter:
    case NODE_nameshift:
    case NODE_output:
      desc->landing = SNetNewLanding(DESC_DEST(desc), prev, LAND_siso);
      DESC_LAND_SPEC(desc, siso)->outdesc = NULL;
      break;

    case NODE_box:
      SNetNewBoxLanding(desc, prev);
      break;

    case NODE_parallel:
      SNetNewParallelLanding(desc, prev);
      break;

    case NODE_star:
      SNetNewStarLanding(desc, prev);
      break;

    case NODE_split:
      SNetNewSplitLanding(desc, prev);
      break;

    case NODE_feedback:
      SNetNewFeedbackLanding(desc, prev);
      break;

    case NODE_dripback:
      SNetNewDripBackLanding(desc, prev);
      break;

    case NODE_sync:
      desc->landing = SNetNewLanding(STREAM_DEST(stream), prev, LAND_sync);
      SNetSyncInitDesc(desc, stream);
      break;

    case NODE_zipper:
      /* Init the landing state of a fused sync-star node */
      desc->landing = SNetNewLanding(STREAM_DEST(stream), prev, LAND_zipper);
      DESC_LAND_SPEC(desc, zipper)->outdesc = NULL;
      DESC_LAND_SPEC(desc, zipper)->head = NULL;
      break;

    case NODE_collector:
      /* Collectors receive the previously created landing from the stack */
      desc->landing = SNetPopLanding(prev);
      assert(desc->landing);
      assert(desc->landing->type == LAND_collector);
      assert(DESC_NODE(desc) == STREAM_DEST(stream));
      assert(desc->landing->refs > 0);
      break;

    case NODE_observer:
      desc->landing = SNetNewLanding(DESC_DEST(desc), prev, LAND_observer);
      DESC_LAND_SPEC(desc, observer)->outdesc = NULL;
      DESC_LAND_SPEC(desc, observer)->oid = 0;
      break;

    case NODE_observer2:
      desc->landing = SNetPopLanding(prev);
      assert(desc->landing);
      assert(desc->landing->type == LAND_empty);
      break;

    case NODE_input:
    case NODE_identity:
    case NODE_garbage:
    default:
      desc->landing = NULL;
      assert(0);
      break;
  }

  /* if (SNetVerbose() && SNetNodeGetWorkerCount() <= 1) {
    printf("%s: %s, %s\n", __func__,
           SNetNodeName(desc->landing->node), SNetLandingName(desc->landing));
  } */

  return desc;
}
Ejemplo n.º 2
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);
  }
}
Ejemplo n.º 3
0
/* Send a record to a stream which may need to be opened */
static void StarWrite(star_write_t kind, snet_record_t *rec, 
                      snet_stream_desc_t *desc)
{
  const star_arg_t      *sarg = DESC_NODE_SPEC(desc, star);
  landing_star_t        *land = DESC_LAND_SPEC(desc, star);

  switch (kind) {

    case WriteCollector:
      /* check if open */
      if (!land->colldesc) {
        /* first landing must be collector */
        if (SNetTopLanding(desc) != land->collland) {
          SNetPushLanding(desc, land->collland);
        }
        land->colldesc = SNetStreamOpen(sarg->collector, desc);
      }
      SNetWrite(&land->colldesc, rec, true);
      break;

    case WriteInstance:
      /* check if open */
      if (!land->instdesc) {
        /* first landing must be instance */
        if (SNetTopLanding(desc) != land->instland) {
          SNetPushLanding(desc, land->instland);
        }
        land->instdesc = SNetStreamOpen(sarg->instance, desc);
        /* remove instance landing */
        if (SNetTopLanding(desc) == land->instland) {
          SNetPopLanding(desc);
          SNetLandingDone(land->instland);
        }
        /* prevent double deallocation */
        land->instland = NULL;
        /* emit output record to instance */
        SNetWrite(&land->instdesc, rec, true);
      } else {
        /* A star is superfluous when the next landing is its incarnation. */
        bool superfluous = (desc->landing->node == land->instdesc->landing->node);

        /* emit output record to instance */
        SNetWrite(&land->instdesc, rec, (superfluous == false));

        /* If instance has been garbage collected then dissolve. */
        if (superfluous) {
          /* Possibly forward leader status to next incarnation. */
          rec = (land->star_leader && (sarg->is_det | sarg->is_detsup)) ?
                SNetRecCreate(REC_star_leader, land->detenter.counter,
                                               land->detenter.seqnr) : NULL;
          land->star_leader = false;

          /* Discard stream towards collector. */
          if (land->colldesc) {
            SNetDescDone(land->colldesc);
          }

          /* Discard collector landing. */
          SNetLandingDone(land->collland);

          /* Change landing into identity, which can be garbage collected. */
          SNetBecomeIdentity(desc->landing, land->instdesc);

          /* Finally, notify incarnation of new leader status. */
          if (rec) {
            SNetWrite(&(DESC_LAND_SPEC(desc, identity)->outdesc), rec, true);
          }
        }
      }
      break;

    default:
      assert(0);
  }
}