示例#1
0
/* Identity node: forward all records as is.  */
static void SNetNodeIdentity(snet_stream_desc_t *desc, snet_record_t *rec)
{
    landing_identity_t    *land = DESC_LAND_SPEC(desc, identity);

    assert(land->outdesc);

    SNetWrite(&land->outdesc, rec, true);
}
示例#2
0
文件: xinput.c 项目: ra-one/snet-rts
void SNetCloseInput(node_t* node)
{
  input_arg_t           *iarg = NODE_SPEC(node, input);
  landing_input_t       *linp = DESC_LAND_SPEC(iarg->indesc, input);

  trace(__func__);
  assert(iarg->state == INPUT_terminating);
  iarg->state = INPUT_terminated;
  SNetDescDone(linp->outdesc);
  SNetInParserDestroy();
}
示例#3
0
static bool SNetInputAllowed(worker_t *worker)
{
  bool allowed = true;

  if (SNetInputThrottle()) {
    /* Check if output has advanced enough for us to input more. */
    size_t outs = NODE_SPEC(worker->output_node, output)->num_outputs;
    size_t ins = DESC_LAND_SPEC(worker->input_desc, input)->num_inputs;
    double limit = SNetInputOffset() + SNetInputFactor() * outs;
    allowed = (ins < limit);
  }

  return allowed;
}
示例#4
0
文件: xstream.c 项目: ra-one/snet-rts
/* Merge a stream to an identity landing with the subsequent stream. */
static snet_stream_desc_t *SNetMergeStreams(snet_stream_desc_t **desc_ptr)
{
  snet_stream_desc_t    *desc = *desc_ptr;
  snet_stream_desc_t    *next = DESC_LAND_SPEC(desc, identity)->outdesc;
  fifo_node_t           *fifo_tail_start;
  fifo_node_t           *fifo_tail_end;
  fifo_node_t           *node;
  int                    count = 0;

  /* Remove all data from the queue towards the garbage landing. */
  fifo_tail_start = SNetFifoGetTail(&desc->fifo, &fifo_tail_end);

  /* Count the number of data items in the captured list. */
  for (node = fifo_tail_start; node; node = node->next) {
    ++count;
  }

  /* Append the captured list onto the subsequent stream. */
  SNetFifoPutTail(&next->fifo, fifo_tail_start, fifo_tail_end);

  /* Reconnect the source landing of the next landing. */
  next->source = desc->source;

  /* Increase the reference count by the number of added records. */
  AAF(&(next->refs), count);

  /* Report statistics. */
  if (SNetDebug()) {
    printf("%s: collecting %d recs, %d drefs, %d nrefs\n",
            __func__, count, desc->refs, next->refs);
  }

  /* Convert the identity landing into garbage. */
  SNetBecomeGarbage(desc->landing);

  /* Make sure no one ever attempts to write to the dissolved stream. */
  *desc_ptr = next;

  /* Unlock the garbage landing: some worker todo items may still need it. */
  unlock_landing(desc->landing);

  /* Decrease reference count to the garbage collected stream. */
  SNetDescDone(desc);

  /* Return the subsequent stream. */
  return next;
}
示例#5
0
/* Star component: forward record to instance or to collector. */
void SNetNodeStar(snet_stream_desc_t *desc, snet_record_t *rec)
{
  const star_arg_t      *sarg = DESC_NODE_SPEC(desc, star);
  landing_star_t        *land = DESC_LAND_SPEC(desc, star);

  trace(__func__);

  switch (REC_DESCR(rec)) {
    case REC_data:
      if (land->star_leader && (sarg->is_det | sarg->is_detsup)) {
        SNetDetEnter(rec, &land->detenter, sarg->is_det, sarg->entity);
      }
      if (MatchesExitPattern( rec, sarg->exit_patterns, sarg->guards)) {
        StarWrite(WriteCollector, rec, desc);
      } else {
        StarWrite(WriteInstance, rec, desc);
      }
      break;

    case REC_detref:
      /* Forward record */
      StarWrite(WriteCollector, rec, desc);
      break;

    case REC_sync:
      SNetRecDestroy(rec);
      break;

    case REC_star_leader:
      land->star_leader = true;
      land->detenter.counter = LEADER_REC(rec, counter);
      land->detenter.seqnr   = LEADER_REC(rec, seqnr  );
      SNetRecDestroy(rec);
      break;

    default:
      SNetRecUnknownEnt(__func__, rec, sarg->entity);
  }
}
示例#6
0
文件: xinput.c 项目: ra-one/snet-rts
/* Create the node which reads records from an input file via the parser.
 * This is called from networkinterface.c to initialize the input module.
 */
void SNetInInputInit(
    FILE                *file,
    snetin_label_t      *labels,
    snetin_interface_t  *interfaces,
    snet_stream_t       *output)
{
  input_arg_t           *iarg;
  node_t                *node;
  landing_input_t       *linp;
  const int              first_worker_id = 1;
  
  trace(__func__);

  /* Create input node in the fixed network. */
  node = SNetNodeNew(NODE_input, (snet_stream_t **)NULL, 0, &output, 1,
                     SNetNodeInput, SNetStopInput, SNetTermInput);
  iarg = NODE_SPEC(node, input);
  iarg->output = output;
  iarg->state = INPUT_reading;

  /* Create an empty input descriptor: needed for SNetStreamOpen. */
  iarg->indesc = SNetNewAlign(snet_stream_desc_t);
  memset(iarg->indesc, 0, sizeof(snet_stream_desc_t));

  /* Create landing: needed for locking the input node before use. */
  iarg->indesc->landing = SNetNewLanding(node, NULL, LAND_input);
  linp = DESC_LAND_SPEC(iarg->indesc, input);
  linp->num_inputs = 0;

  /* Create output descriptor: needed by parser for writing. */
  iarg->indesc->landing->id = first_worker_id;
  linp->outdesc = SNetStreamOpen(output, iarg->indesc);
  iarg->indesc->landing->id = 0;

  /* Initialize the parser */
  SNetInParserInit(file, labels, interfaces, NULL, NULL);
}
示例#7
0
文件: xstream.c 项目: ra-one/snet-rts
/* 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;
}
示例#8
0
/* Work on an item.
 *
 * In case of a dissolved garbage stream update the source
 * stream of the work item.
 *
 * Return true iff a record was processed.
 *
 * If the contents of the item was merged with another item then
 * reset the item descriptor to NULL.
 */
static bool SNetWorkerWorkItem(work_item_t *const item, worker_t *worker)
{
  work_item_t           *lookup;

  /* Item must be owned and non-empty. */
  assert(item->lock == worker->id);
  assert(item->count > 0);

  /* Claim destination landing. */
  if (trylock_landing(item->desc->landing, worker) == false) {
    /* Nothing can be done. */
    return false;
  }

  /* Bring item descriptors past any garbage collectable landings. */
  while (item->desc->landing->type == LAND_garbage) {
    /* Get subsequent descriptor. */
    snet_stream_desc_t *next_desc = DESC_LAND_SPEC(item->desc, siso)->outdesc;

    /* Release landing claim. */
    unlock_landing(item->desc->landing);

    /* Decrease reference counts to descriptor. */
    SNetDescRelease(item->desc, item->count);

    /* Take item out of hash table. */
    SNetHashPtrRemove(worker->hash_ptab, item->desc);

    /* Update item descriptor. */
    item->desc = next_desc;

    /* Also advance past subsequent garbage landings. */
    while (next_desc->landing->type == LAND_garbage) {

      /* Get subsequent descriptor. */
      item->desc = DESC_LAND_SPEC(next_desc, siso)->outdesc;

      /* Test if current descriptor is also in our hash table. */
      lookup = (work_item_t *)SNetHashPtrLookup(worker->hash_ptab, next_desc);
      if (lookup && trylock_work_item(lookup, worker)) {
        /* Merge both descriptor counts into one. */
        item->count += lookup->count;
        lookup->count = 0;
        unlock_work_item(lookup, worker);
      }

      /* Decrease reference counts to garbage descriptor. */
      SNetDescRelease(next_desc, item->count);

      /* Advance to subsequent descriptor and repeat. */
      next_desc = item->desc;
    }

    /* The new descriptor may already exist in hash table. */
    lookup = (work_item_t *)SNetHashPtrLookup(worker->hash_ptab, next_desc);
    if (lookup) {
      /* Merge the two counts. */
      AAF(&lookup->count, item->count);
      /* Reset item. */
      item->count = 0;
      /* We already have this desciptor in lookup, so reset it. */
      item->desc = NULL;
      /* We made progress. */
      return true;
    }
    else /* (lookup == NULL) */ {

      /* Add new descriptor to hash table. */
      SNetHashPtrStore(worker->hash_ptab, item->desc, item);

      /* Claim destination landing. */
      if (trylock_landing(item->desc->landing, worker) == false) {
        /* We made progress anyway. */
        return true;
      }
    }
  }

  /* Subtract one read license. */
  --item->count;

  /* Unlock item so thieves can steal it while we work. */
  unlock_work_item(item, worker);

  /* Finally, do the work by delegating to the streams layer. */
  SNetStreamWork(item->desc, worker);

  /* We definitely made progress. */
  return true;
}
示例#9
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);
  }
}