Beispiel #1
0
/**
 * Create the instance of the operand network, including
 * routing component (star incarnate) at the end
 */
static void CreateOperandNetwork(snet_stream_desc_t **next,
    star_arg_t *sarg, snet_stream_desc_t *to_coll)
{
  /* info structure for network creation */
  /* The outstream to the collector from a newly created incarnate.
     Nothing is written to this stream, but it has to be registered
     at the collector. */
  snet_stream_t *starstream, *nextstream_addr;
  /* Create the stream to the instance */
  nextstream_addr = SNetStreamCreate(0);

  /* Set the source of the stream to support garbage collection */
  SNetStreamSetSource(nextstream_addr, SNetLocvecGet(sarg->info));

  /* open the stream for the caller */
  *next = SNetStreamOpen(nextstream_addr, 'w');

  /* use custom creation function for proper/easier update of locvec */
  starstream = SNetSerialStarchild(
      nextstream_addr,
      sarg->info,
      sarg->location,
      sarg->box,
      sarg->selffun
      );

  /* notify collector about the new instance */
  SNetStreamWrite( to_coll, SNetRecCreate(REC_collect, starstream));
}
Beispiel #2
0
static void FeedbackBufTask(snet_entity_t *, void *arg)
{
  fbbuf_arg_t *fbbarg = (fbbuf_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_record_t *rec;
  int out_counter = 0;
  int out_capacity;

  instream   = SNetStreamOpen(fbbarg->in,  'r');
  outstream  = SNetStreamOpen(fbbarg->out, 'w');
  out_capacity =  fbbarg->out_capacity;
  SNetMemFree( fbbarg);


  /* MAIN LOOP */
  while(1) {

    rec = SNetStreamRead(instream);
    if( SNetRecGetDescriptor(rec) == REC_terminate ) {
      /* this means, the outstream does not exist anymore! */
      SNetRecDestroy(rec);
      break; /* exit main loop */
    }

    if (out_counter+1 >= out_capacity) {
      /* new stream */
      snet_stream_t *new_stream = SNetStreamCreate(out_capacity);
      SNetStreamWrite(outstream,
          SNetRecCreate(REC_sync, new_stream)
          );

      SNetStreamClose(outstream, false);
      outstream = SNetStreamOpen(new_stream, 'w');
      out_counter = 0;
    }
    /* write the record to the stream */
    SNetStreamWrite(outstream, rec);
    out_counter++;
  } /* END OF MAIN LOOP */

  SNetStreamClose(instream,  true);
  SNetStreamClose(outstream, false);
}
Beispiel #3
0
/**
 * The feedback collector, the entry point of the
 * feedback combinator loop
 */
static void FeedbackCollTask(snet_entity_t *ent, void *arg)
{
  fbcoll_arg_t *fbcarg = (fbcoll_arg_t *)arg;
  struct fbcoll_state state;
  (void) ent; /* NOT USED */

  /* initialise state */
  state.terminate = false;
  state.mode = FBCOLL_IN;

  state.instream   = SNetStreamOpen(fbcarg->in,  'r');
  state.backstream = SNetStreamOpen(fbcarg->fbi, 'r');
  state.outstream  = SNetStreamOpen(fbcarg->out, 'w');
  SNetMemFree( fbcarg);

  /* MAIN LOOP */
  while( !state.terminate) {

    /* which stream to read from is mode dependent */
    switch(state.mode) {
      case FBCOLL_IN:
        FbCollReadIn(&state);
        break;
      case FBCOLL_FB1:
      case FBCOLL_FB0:
        FbCollReadFbi(&state);
        break;
      default: assert(0); /* should not be reached */
    }

  } /* END OF MAIN LOOP */

  SNetStreamClose(state.instream,   true);
  SNetStreamClose(state.backstream, true);
  SNetStreamClose(state.outstream,  false);

}
Beispiel #4
0
/**
 * This is the task doing the global input
 */
static void GlobInputTask(snet_entity_t *ent, void* data)
{
  handle_t *hnd = (handle_t *)data;

  if(hnd->buffer != NULL) {
    int i;
    snet_stream_desc_t *outstream = SNetStreamOpen(hnd->buffer, 'w');

    SNetInParserInit( hnd->file, hnd->labels, hnd->interfaces, outstream, ent);
    i = SNET_PARSE_CONTINUE;
    while(i != SNET_PARSE_TERMINATE){
      i = SNetInParserParse();
    }
    SNetInParserDestroy();

    SNetStreamClose( outstream, false);
  }

  SNetMemFree(hnd);
}
Beispiel #5
0
/* 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);
}
Beispiel #6
0
/**
 * Split box task.
 *
 * Implements both the non-deterministic and deterministic variants.
 */
static void SplitBoxTask(snet_entity_t *ent, void *arg)
{
  int i;
  split_arg_t *sarg = (split_arg_t *)arg;
  snet_stream_desc_t *initial, *instream;
  int ltag_val, utag_val;
  snet_info_t *info;
  snet_record_t *rec;
  snet_locvec_t *locvec;
  bool terminate = false;
  /* a list of all outstreams for all yet created instances */
  snet_streamset_t repos_set = NULL;
  snet_stream_iter_t *iter = SNetStreamIterCreate( &repos_set);
  /* a hashtable for fast lookup, initial capacity = 2^4 = 16 */
  hashtab_t *repos_tab = HashtabCreate( 4);
  (void) ent; /* NOT USED */

  /* for deterministic variant: */
  int counter = 0;

  initial = SNetStreamOpen(sarg->output, 'w');
  instream = SNetStreamOpen(sarg->input, 'r');

  /* MAIN LOOP START */
  while( !terminate) {
    /* read from input stream */
    rec = SNetStreamRead( instream);

    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* get lower and upper tag values */
        ltag_val = SNetRecGetTag( rec, sarg->ltag);
        utag_val = SNetRecGetTag( rec, sarg->utag);

        /* for all tag values */
        for( i = ltag_val; i <= utag_val; i++) {
          snet_stream_desc_t *outstream = HashtabGet( repos_tab, i);

          if( outstream == NULL) {
            snet_stream_t *temp_stream;
            snet_stream_t *newstream_addr = SNetStreamCreate(0);
            /* instance does not exist yet, create it */
            outstream = SNetStreamOpen(newstream_addr, 'w');
            /* add to lookup table */
            HashtabPut( repos_tab, i, outstream);
            /* add to list */
            SNetStreamsetPut( &repos_set, outstream);

            /* create info and location vector for creation of this replica */
            info = SNetInfoCopy(sarg->info);
            locvec = SNetLocvecSplitSpawn(SNetLocvecGet(sarg->info), i);
            SNetLocvecSet(info, locvec);

            if( sarg->is_byloc) {
              SNetRouteDynamicEnter(info, i, i, sarg->boxfun);
              temp_stream = sarg->boxfun(newstream_addr, info, i);
              temp_stream = SNetRouteUpdate(info, temp_stream, sarg->location);
              SNetRouteDynamicExit(info, i, i, sarg->boxfun);
            } else {
              SNetRouteDynamicEnter(info, i, sarg->location, sarg->boxfun);
              temp_stream = sarg->boxfun(newstream_addr, info, sarg->location);
              temp_stream = SNetRouteUpdate(info, temp_stream, sarg->location);
              SNetRouteDynamicExit(info, i, sarg->location, sarg->boxfun);
            }

            /* destroy info and location vector */
            SNetLocvecDestroy(locvec);
            SNetInfoDestroy(info);

            if(temp_stream != NULL) {
              /* notify collector about the new instance via initial */
              SNetStreamWrite( initial,
                  SNetRecCreate( REC_collect, temp_stream));
            }
          } /* end if (outstream==NULL) */

          /* multicast the record */
          SNetStreamWrite( outstream,
              /* copy record for all but the last tag value */
              (i!=utag_val) ? SNetRecCopy( rec) : rec
              );
        } /* end for all tags  ltag_val <= i <= utag_val */

        /* If deterministic, append a sort record to *all* registered
         * instances and the initial stream.
         */
        if( sarg->is_det ) {
          /* reset iterator */
          SNetStreamIterReset( iter, &repos_set);
          while( SNetStreamIterHasNext( iter)) {
            snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);

            SNetStreamWrite( cur_stream,
                SNetRecCreate( REC_sort_end, 0, counter));
          }
          /* Now also send a sort record to initial,
             after the collect records for new instances have been sent */
          SNetStreamWrite( initial,
              SNetRecCreate( REC_sort_end, 0, counter));
        }
        /* increment counter for deterministic variant */
        counter += 1;
        break;

      case REC_sync:
        {
          snet_stream_t *newstream = SNetRecGetStream( rec);
          SNetStreamReplace( instream, newstream);
          SNetRecDestroy( rec);
        }
        break;

      case REC_sort_end:
        /* broadcast the sort record */
        SNetStreamIterReset( iter, &repos_set);
        /* all instances receive copies of the record */
        while( SNetStreamIterHasNext( iter)) {
          snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);
          SNetStreamWrite( cur_stream,
              SNetRecCreate( REC_sort_end,
                /* we have to increase level */
                SNetRecGetLevel( rec)+1,
                SNetRecGetNum( rec))
              );
        }
        /* send the original record to the initial stream,
           but with increased level */
        SNetRecSetLevel( rec, SNetRecGetLevel( rec) + 1);
        SNetStreamWrite( initial, rec);
        break;

      case REC_terminate:

        SNetStreamIterReset( iter, &repos_set);
        /* all instances receive copies of the record */
        while( SNetStreamIterHasNext( iter)) {
          snet_stream_desc_t *cur_stream = SNetStreamIterNext( iter);
          SNetStreamWrite( cur_stream, SNetRecCopy( rec));

          SNetStreamIterRemove( iter);
          /* close  the stream to the instance */
          SNetStreamClose( cur_stream, false);
        }
        /* send the original record to the initial stream */
        SNetStreamWrite( initial, rec);
        /* note that no sort record has to be appended */
        terminate = true;
        break;

      case REC_collect:
        /* invalid control record */
      default:
        assert( 0);
        /* if ignore, at least destroy it */
        SNetRecDestroy( rec);
    }
  } /* MAIN LOOP END */

  /* destroy repository */
  HashtabDestroy( repos_tab);
  SNetStreamIterDestroy( iter);

  /* close and destroy initial stream */
  SNetStreamClose( initial, false);
  /* close instream */
  SNetStreamClose( instream, true);

  SNetLocvecDestroy(SNetLocvecGet(sarg->info));
  SNetInfoDestroy(sarg->info);
  /* destroy the argument */
  SNetMemFree( sarg);
} /* END of SPLIT BOX TASK */
Beispiel #7
0
/**
 * Convenience function for creating
 * Star, DetStar, StarIncarnate or DetStarIncarnate,
 * dependent on parameters is_incarnate and is_det
 */
static snet_stream_t *CreateStar( snet_stream_t *input,
    snet_info_t *info,
    int location,
    snet_variant_list_t *exit_patterns,
    snet_expr_list_t *guards,
    snet_startup_fun_t box_a,
    snet_startup_fun_t box_b,
    bool is_incarnate,
    bool is_det
    )
{
  snet_stream_t *output;
  star_arg_t *sarg;
  snet_stream_t *newstream;
  snet_locvec_t *locvec;

  locvec = SNetLocvecGet(info);
  if (!is_incarnate) {
    SNetLocvecStarEnter(locvec);
    input = SNetRouteUpdate(info, input, location);
  } else {
    input = SNetRouteUpdate(info, input, location);
  }

  if(SNetDistribIsNodeLocation(location)) {
    /* create the task argument */
    sarg = SNetMemAlloc( sizeof(star_arg_t));
    newstream = SNetStreamCreate(0);
    sarg->instream = SNetStreamOpen(input, 'r');
    sarg->outstream = SNetStreamOpen(newstream, 'w');
    sarg->nextstream = NULL;
    sarg->box = box_a;
    sarg->selffun = box_b;
    sarg->exit_patterns = exit_patterns;
    sarg->guards = guards;
    sarg->info = SNetInfoCopy(info);
    SNetLocvecSet(sarg->info, SNetLocvecCopy(locvec));
    sarg->is_incarnate = is_incarnate;
    sarg->is_det = is_det;
    sarg->location = location;
    sarg->sync_cleanup = false;
    sarg->counter = 0;

    SNetThreadingSpawn( ENTITY_star, location, locvec,
          "<star>", &StarBoxTask, sarg);

    /* creation function of top level star will return output stream
     * of its collector, the incarnates return their outstream
     */
    if (!is_incarnate) {
      /* the "top-level" star also creates a collector */
      output = CollectorCreateDynamic(newstream, location, info);
    } else {
      output = newstream;
    }

  } else {
    SNetExprListDestroy( guards);
    SNetVariantListDestroy(exit_patterns);
    output = input;
  }

  if (!is_incarnate) SNetLocvecStarLeave(SNetLocvecGet(info));

  return( output);
}
Beispiel #8
0
static void BoxTask(snet_entity_t *ent, void *arg)
{
#ifdef DBG_RT_TRACE_BOX_TIMINGS
  static struct timeval tv_in;
  static struct timeval tv_out;
#endif

#ifdef SNET_DEBUG_COUNTERS
  snet_time_t time_in;
  snet_time_t time_out;
  long mseconds;
#endif /* SNET_DEBUG_COUNTERS */

  box_arg_t *barg = (box_arg_t *)arg;
  snet_record_t *rec;
  snet_stream_desc_t *instream, *outstream;
  bool terminate = false;

  instream = SNetStreamOpen(barg->input, 'r');
  outstream =  SNetStreamOpen(barg->output, 'w');
  /* set out descriptor */
  barg->hnd.out_sd = outstream;
  /* set entity */
  barg->hnd.ent = ent;

  /* MAIN LOOP */
  while(!terminate) {
    /* read from input stream */
    rec = SNetStreamRead(instream);

    switch(SNetRecGetDescriptor(rec)) {
      case REC_trigger_initialiser:
      case REC_data:
      	barg->hnd.rec = rec;

#ifdef DBG_RT_TRACE_BOX_TIMINGS
        gettimeofday(&tv_in, NULL);
        SNetUtilDebugNoticeEnt(ent,
            "[BOX] Firing box function at %lf.",
            tv_in.tv_sec + tv_in.tv_usec / 1000000.0
            );
#endif
#ifdef SNET_DEBUG_COUNTERS
        SNetDebugTimeGetTime(&time_in);
#endif /* SNET_DEBUG_COUNTERS */

#ifdef USE_USER_EVENT_LOGGING
        /* Emit a monitoring message of a record read to be processed by a box */
        if (SNetRecGetDescriptor(rec) == REC_data) {
          SNetThreadingEventSignal(ent,
              SNetMonInfoCreate(EV_MESSAGE_IN, MON_RECORD, rec)
              );
        }
#endif

        /* execute box function and update execution realm */
        barg->hnd = *barg->boxfun(&barg->hnd);
        barg->hnd = *barg->exerealm_update(&barg->hnd);

        /*
         * Emit an event here?
         * SNetMonInfoEvent(EV_BOX_???, MON_RECORD, rec);
         */

#ifdef DBG_RT_TRACE_BOX_TIMINGS
        gettimeofday(&tv_out, NULL);
        SNetUtilDebugNoticeEnt(ent,
            "[BOX] Return from box function after %lf sec.",
            (tv_out.tv_sec - tv_in.tv_sec) + (tv_out.tv_usec - tv_in.tv_usec) / 1000000.0
            );
#endif


#ifdef SNET_DEBUG_COUNTERS
        SNetDebugTimeGetTime(&time_out);
        mseconds = SNetDebugTimeDifferenceInMilliseconds(&time_in, &time_out);
        SNetDebugCountersIncreaseCounter(mseconds, SNET_COUNTER_TIME_BOX);
#endif /* SNET_DEBUG_COUNTERS */

        SNetRecDestroy(rec);

        /* restrict to one data record per execution */
        //SNetThreadingYield();

        /* check the box task should be migrated after one record execution */
        SNetThreadingCheckMigrate();
        break;

      case REC_sync:
        {
          snet_stream_t *newstream = SNetRecGetStream(rec);
          SNetStreamReplace(instream, newstream);
          SNetRecDestroy(rec);
        }
        break;

      case REC_sort_end:
        /* forward the sort record */
        SNetStreamWrite(outstream, rec);
        break;

      case REC_terminate:
      	barg->hnd = *barg->exerealm_destroy(&barg->hnd);
        SNetStreamWrite(outstream, rec);
        terminate = true;
        break;

      case REC_collect:
      default:
        assert(0);
    }
  } /* MAIN LOOP END */
  barg->hnd = *barg->exerealm_destroy(&barg->hnd);
  SNetStreamClose(instream, true);
  SNetStreamClose(outstream, false);
 
  /* destroy box arg */
  SNetVariantListDestroy(barg->hnd.vars);
  SNetIntListListDestroy(barg->hnd.sign);
  SNetMemFree( barg);
}
Beispiel #9
0
/**
 * Collector task for dynamic combinators (star/split)
 * and the static parallel combinator
 */
void CollectorTask(snet_entity_t *ent, void *arg)
{
  coll_arg_t *carg = (coll_arg_t *)arg;
  snet_streamset_t readyset, waitingset;
  snet_stream_iter_t *wait_iter;
  snet_stream_desc_t *outstream;
  snet_stream_desc_t *curstream = NULL;
  snet_stream_desc_t *last = NULL;		// when the paired parallel terminate, it sends the sort_end record to the last branch
  snet_record_t *sort_rec = NULL;
  snet_record_t *term_rec = NULL;
  int incount;
  bool terminate = false;


  /* open outstream for writing */
  outstream = SNetStreamOpen(carg->output, 'w');

  readyset = waitingset = NULL;

  if (carg->is_static) {
    int i;
    incount = CARG_ST(carg, num);
    /* fill initial readyset of collector */
    for (i=0; i<incount; i++) {
      snet_stream_desc_t *tmp;
      /* open each stream in listening set for reading */
      tmp = SNetStreamOpen( CARG_ST(carg, inputs[i]), 'r');
      /* add each stream instreams[i] to listening set of collector */
      SNetStreamsetPut( &readyset, tmp);
    }
    SNetMemFree( CARG_ST(carg, inputs) );
  } else {
    incount = 1;
    /* Open initial stream and put into readyset */
    SNetStreamsetPut( &readyset,
        SNetStreamOpen(CARG_DYN(carg, input), 'r')
        );
  }

  /* create an iterator for waiting set, is reused within main loop*/
  wait_iter = SNetStreamIterCreate( &waitingset);

  /* MAIN LOOP */
  while( !terminate) {
    /* get a record */
    snet_record_t *rec = GetRecord(&readyset, incount, &curstream);
    /* process the record */
    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* data record: forward to output */
        SNetStreamWrite( outstream, rec);
        break;

      case REC_sort_end:
      	/* curstream == last, this is the last branch and the paired parallel already terminates
      	 * increase the level by one because it was not increased by the paired parallel as it should be
      	 * Also later when last becomes the only waiting branch, the collector should terminate. However before terminating, it should pretend that parallel has sent the sort end from all branches
      	 */
      	if (curstream == last) {			// imply last != NULL, this will be the last branch and the paired parallel already terminates
      		SNetRecSetLevel(rec, SNetRecGetLevel(rec) + 1);			// increase the level by one because it was not increased by the paired parallel as it should be
      	}
      	if (last == NULL && SNetRecGetLevel(rec) == 0 && SNetRecGetNum(rec) == -1) {		// if last was not set, and collector receives a sort_end (l0, c-1) --> set the curstream as last
      		last = curstream;																															// from now on, any sort_end from last will be increased level by 1
      		SNetRecDestroy( rec);
      		break;			// ignore the sort_end
      	}

        ProcessSortRecord(ent, rec, &sort_rec, curstream, &readyset, &waitingset);
        /* end processing this stream */
        curstream = NULL;
        break;

      case REC_sync:
        SNetStreamReplace( curstream, SNetRecGetStream( rec));
        SNetRecDestroy( rec);
        break;

      case REC_collect:
        /* only for dynamic collectors! */
        assert( false == carg->is_static );
        /* collect: add new stream to ready set */
#ifdef DESTROY_TERM_IN_WAITING_UPON_COLLECT
        /* but first, check if we can free resources by checking the
           waiting set for arrival of termination records */
        incount -= DestroyTermInWaitingSet(wait_iter, &waitingset);
        assert(incount > 0);
#endif
        /* finally, add new stream to ready set */
        SNetStreamsetPut(
            &readyset,
            SNetStreamOpen( SNetRecGetStream( rec), 'r')
            );
        /* update incoming counter */
        incount++;
        /* destroy collect record */
        SNetRecDestroy( rec);
        break;

      case REC_terminate:
        /* termination record: close stream and remove from ready set */
        ProcessTermRecord(rec, &term_rec, curstream, &readyset, &incount);
        /* stop processing this stream */
        curstream = NULL;
        break;

      default:
        assert(0);
        /* if ignore, at least destroy ... */
        SNetRecDestroy( rec);
    } /* end switch */

    /************* termination conditions *****************/
    if ( SNetStreamsetIsEmpty( &readyset)) {
      /* the streams which had a sort record are in the waitingset */
      if ( !SNetStreamsetIsEmpty( &waitingset)) {
        if ( carg->is_static && (1 == incount) ) {		// stat
          snet_stream_desc_t *in = (waitingset != NULL) ? waitingset : readyset;

          /* if last is the only one in the waitingset --> pretends that the already-terminated paired parallel has sent the sort end to all branches
           * Therefore restore the waitingset before terminating (so that a relevant sort_end is sent out) */
          if (in == last)
          	RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream);

          SNetStreamWrite( outstream,
              SNetRecCreate( REC_sync, SNetStreamGet(in))
              );
          SNetStreamClose( in, false);
          terminate = true;
#ifdef DEBUG_PRINT_GC
          /* terminating due to GC */
          SNetUtilDebugNoticeEnt( ent,
              "[COLL] Terminate static collector as only one branch left!"
              );
#endif
        } else
          RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream);
      } else {
        /* both ready set and waitingset are empty */
#ifdef DEBUG_PRINT_GC
        if (carg->is_static) {
          SNetUtilDebugNoticeEnt( ent,
              "[COLL] Terminate static collector as no inputs left!");
        }
#endif
        assert(term_rec != NULL);
        SNetStreamWrite( outstream, term_rec);
        term_rec = NULL;
        terminate = true;
      }
    }

     
    /************* end of termination conditions **********/
  } /* MAIN LOOP END */

  if (term_rec != NULL) {
    SNetRecDestroy(term_rec);
  }
  if (sort_rec != NULL) {
    SNetRecDestroy(sort_rec);
  }
  /* close outstream */
  SNetStreamClose( outstream, false);
  /* destroy iterator */
  SNetStreamIterDestroy( wait_iter);
  /* destroy argument */
  SNetMemFree( carg);
} /* END of DYNAMIC COLLECTOR TASK */
Beispiel #10
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);
  }
}
Beispiel #11
0
/**
 * The feedback buffer, in the back-loop
 */
static void FeedbackBufTask(snet_entity_t *ent, void *arg)
{
  fbbuf_arg_t *fbbarg = (fbbuf_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_queue_t *internal_buffer;
  snet_record_t *rec;
  int out_capacity;
  int max_read;
  (void) ent; /* NOT USED */

  instream   = SNetStreamOpen(fbbarg->in,  'r');
  outstream  = SNetStreamOpen(fbbarg->out, 'w');
  out_capacity =  fbbarg->out_capacity;
  SNetMemFree( fbbarg);

  internal_buffer = SNetQueueCreate();
  max_read = out_capacity; /* TODO better usual stream capacity */

  /* MAIN LOOP */
  while(1) {
    int n = 0;
    rec = NULL;

    /* STEP 1: read n=min(available,max_read) records from input stream */

    /* read first record of the actual dispatch */
    if (0 == SNetQueueSize(internal_buffer)) {
      rec = SNetStreamRead(instream);
      /* only in empty mode! */
      if( REC_terminate == SNetRecGetDescriptor( rec)) {
        /* this means, the outstream does not exist anymore! */
        SNetRecDestroy(rec);
        goto feedback_buf_epilogue;
      }
    } else {
      SNetThreadingYield();
      if ( SNetStreamPeek(instream) != NULL ) {
        rec = SNetStreamRead(instream);
        assert( REC_terminate != SNetRecGetDescriptor( rec) );
      }
    }

    if (rec != NULL) {
      n = 1;
      /* put record into internal buffer */
      (void) SNetQueuePut(internal_buffer, rec);
    }


    while ( n<=max_read && SNetStreamPeek(instream)!=NULL ) {
      rec = SNetStreamRead(instream);

      /* check if we will need a larger outstream, and if so,
       * create a larger stream
       */
      if (SNetQueueSize(internal_buffer)+1 >= out_capacity) {
        snet_stream_t *new_stream;
        out_capacity *= 2;

        new_stream = SNetStreamCreate(out_capacity);
        (void) SNetQueuePut(internal_buffer, SNetRecCreate(REC_sync, new_stream));
      }

      /* put record into internal buffer */
      (void) SNetQueuePut(internal_buffer, rec);
      n++;
    }

    /* STEP 2: try to empty the internal buffer */
    rec = SNetQueuePeek(internal_buffer);

    while (rec != NULL) {
      snet_stream_t *new_stream = NULL;
      if( REC_sync == SNetRecGetDescriptor( rec)) {
        new_stream = SNetRecGetStream(rec);
      }
      if (0 == SNetStreamTryWrite(outstream, rec)) {
        snet_record_t *rem;
        /* success, also remove from queue */
        rem = SNetQueueGet(internal_buffer);
        assert( rem == rec );

        if (new_stream != NULL) {
          /* written sync record, now change stream */
          SNetStreamClose(outstream, false);
          outstream = SNetStreamOpen(new_stream, 'w');
        }
      } else {
        /* there remain elements in the buffer */
        break;
      }
      /* for the next iteration */
      rec = SNetQueuePeek(internal_buffer);
    }
  } /* END OF MAIN LOOP */

feedback_buf_epilogue:

  SNetQueueDestroy(internal_buffer);

  SNetStreamClose(instream,   true);
  SNetStreamClose(outstream,  false);
}
Beispiel #12
0
/**
 * The feedback dispatcher, at the end of the
 * feedback combinator loop
 */
static void FeedbackDispTask(snet_entity_t *ent, void *arg)
{
  fbdisp_arg_t *fbdarg = (fbdisp_arg_t *)arg;

  snet_stream_desc_t *instream;
  snet_stream_desc_t *outstream;
  snet_stream_desc_t *backstream;
  bool terminate = false;
  snet_record_t *rec;
  (void) ent; /* NOT USED */

  instream   = SNetStreamOpen(fbdarg->in,  'r');
  outstream  = SNetStreamOpen(fbdarg->out, 'w');
  backstream = SNetStreamOpen(fbdarg->fbo, 'w');

  /* MAIN LOOP */
  while( !terminate) {

    /* read from input stream */
    rec = SNetStreamRead( instream);

    switch( SNetRecGetDescriptor( rec)) {

      case REC_data:
        /* route data record */
        if( MatchesBackPattern( rec, fbdarg->back_patterns, fbdarg->guards)) {
          /* send rec back into the loop */
          SNetStreamWrite( backstream, rec);
        } else {
          /* send to output */
          SNetStreamWrite( outstream, rec);
        }
        break;

      case REC_sort_end:
        {
          int lvl = SNetRecGetLevel(rec);
          if ( 0 == lvl ) {
            SNetStreamWrite( backstream, rec);
          } else {
            assert( lvl > 0 );
            SNetRecSetLevel( rec, lvl-1);
            SNetStreamWrite( outstream, rec);
          }
        }
        break;

      case REC_terminate:
        terminate = true;
#ifndef FEEDBACK_OMIT_BUFFER
        /* a terminate record is sent in the backloop for the buffer */
        SNetStreamWrite( backstream, SNetRecCopy( rec));
#endif
        SNetStreamWrite( outstream, rec);
        break;

      case REC_sync:
        SNetStreamReplace( instream, SNetRecGetStream( rec));
        SNetRecDestroy( rec);
        break;

      case REC_collect:
      default:
        assert(0);
        /* if ignoring, at least destroy ... */
        SNetRecDestroy( rec);
        break;
    }

  } /* END OF MAIN LOOP */

  SNetStreamClose(instream,   true);
  SNetStreamClose(outstream,  false);
  SNetStreamClose(backstream, false);

  SNetVariantListDestroy( fbdarg->back_patterns);
  SNetExprListDestroy( fbdarg->guards);
  SNetMemFree( fbdarg);
}
Beispiel #13
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);
  }
}
Beispiel #14
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);
  }
}