Exemple #1
0
static void FbCollReadFbi(struct fbcoll_state *state)
{
  snet_record_t *rec;

  assert( false == state->terminate );

  /* read from feedback stream */
  rec = SNetStreamRead( state->backstream);

  switch( SNetRecGetDescriptor( rec)) {

    case REC_data:
      /* relay data record */
      SNetStreamWrite( state->outstream, rec);
      /* mode switch to FB0 (there is a next iteration) */
      state->mode = FBCOLL_FB0;
      break;

    case REC_sort_end:
      assert( 0 == SNetRecGetLevel(rec) );
      switch(state->mode) {
        case FBCOLL_FB0:
          state->mode = FBCOLL_FB1;
          /* increase counter (non-functional) */
          SNetRecSetNum( rec, SNetRecGetNum(rec)+1);
          SNetStreamWrite( state->outstream, rec);
          break;
        case FBCOLL_FB1:
          state->mode = FBCOLL_IN;
          /* kill the sort record */
          SNetRecDestroy( rec);
          break;
        default: assert(0);
      }
      break;

    case REC_sync:
      SNetStreamReplace( state->backstream, SNetRecGetStream( rec));
      SNetRecDestroy( rec);
      break;

    case REC_terminate:
    case REC_collect:
    default:
      assert(0);
      /* if ignoring, at least destroy ... */
      SNetRecDestroy( rec);
      break;
  }
}
Exemple #2
0
/**
 * Process a sort record
 */
static void ProcessSortRecord(
    snet_entity_t *ent,
    snet_record_t *rec,
    snet_record_t **sort_rec,
    snet_stream_desc_t *cur_stream,
    snet_streamset_t *readyset,
    snet_streamset_t *waitingset)
{
  int res;
  assert( REC_sort_end == SNetRecGetDescriptor( rec) );

  /* sort record: place node in waitingset */
  /* remove node */
  res = SNetStreamsetRemove( readyset, cur_stream);
  assert(res == 0);
  /* put in waiting set */
  SNetStreamsetPut( waitingset, cur_stream);

  if (*sort_rec!=NULL) {
    /*
     * check that level & counter match
     */
    if( !SortRecEqual(rec, *sort_rec) ) {
      SNetUtilDebugNoticeEnt( ent,
          "[COLL] Warning: Received sort records do not match! "
          "expected (l%d,c%d) got (l%d,c%d) on %p", /* *trollface* PROBLEM? */
          SNetRecGetLevel(*sort_rec), SNetRecGetNum(*sort_rec),
          SNetRecGetLevel(rec),       SNetRecGetNum(rec),
          cur_stream
          );
    }
    /* destroy record */
    SNetRecDestroy( rec);
  } else {
    *sort_rec = rec;
  }
}
Exemple #3
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 */
Exemple #4
0
/**
 * Star component task
 */
static void StarBoxTask(void *arg)
{
  star_arg_t *sarg = arg;
  snet_record_t *rec;

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

  switch( SNetRecGetDescriptor( rec)) {

    case REC_data:
      if( MatchesExitPattern( rec, sarg->exit_patterns, sarg->guards)) {
        assert(!sarg->sync_cleanup);
#ifdef DEBUG_PRINT_GC
        SNetUtilDebugNoticeEnt( ent,
            "[STAR] Notice: Data leaves replication network.");
#endif
        /* send rec to collector */
        SNetStreamWrite( sarg->outstream, rec);
      } else {
        /* if instance has not been created yet, create it */
        if( sarg->nextstream == NULL) {
          CreateOperandNetwork(&sarg->nextstream, sarg, sarg->outstream);
        }
        /* send the record to the instance */
        SNetStreamWrite( sarg->nextstream, rec);
      } /* end if not matches exit pattern */

      /* deterministic non-incarnate has to append control records */
      if (sarg->is_det && !sarg->is_incarnate) {
        /* send new sort record to collector level=0, counter=0*/
        SNetStreamWrite( sarg->outstream,
            SNetRecCreate( REC_sort_end, 0, sarg->counter) );

        /* if has next instance, send new sort record */
        if (sarg->nextstream != NULL) {
          SNetStreamWrite( sarg->nextstream,
              SNetRecCreate( REC_sort_end, 0, sarg->counter) );
        }
        /* increment counter */
        sarg->counter++;

      }
#ifdef ENABLE_GC
      else if (sarg->sync_cleanup) {
        snet_record_t *term_rec;
        /*
         * If sync_cleanup is set, we decided to postpone termination
         * due to garbage collection triggered by a sync record until now.
         * Postponing was done in order not to create the operand network unnecessarily
         * only to be able to forward the sync record.
         */
        assert( sarg->nextstream != NULL);
        /* first send a sync record to the next instance */
        SNetStreamWrite( sarg->nextstream,
            SNetRecCreate( REC_sync, SNetStreamGet(sarg->instream)) );


        /* send a terminate record to collector, it will close and
           destroy the stream */
        term_rec = SNetRecCreate(REC_terminate);
        SNetRecSetFlag(term_rec);
        SNetStreamWrite( sarg->outstream, term_rec);

#ifdef DEBUG_PRINT_GC
        /* terminating due to GC */
        SNetUtilDebugNoticeEnt( ent,
            "[STAR] Notice: Destroying star dispatcher due to GC, "
            "delayed until new data record!"
            );
#endif
        SNetStreamClose(sarg->nextstream, false);
        SNetStreamClose(sarg->instream, false);
        TerminateStarBoxTask(sarg->outstream,sarg);
        return;
      }
#endif /* ENABLE_GC */
      break;

    case REC_sync:
      {
        snet_stream_t *newstream = SNetRecGetStream( rec);
#ifdef ENABLE_GC
        snet_locvec_t *loc = SNetStreamGetSource( newstream);
#ifdef DEBUG_PRINT_GC
        if (loc != NULL) {
          int size = SNetLocvecPrintSize(loc) + 1;
          char srecloc[size];
          srecloc[size - 1] = '\0';
          SNetLocvecPrint(srecloc, loc);
          SNetUtilDebugNoticeTask(
                "[STAR] Notice: Received sync record with a stream with source %s.",
                srecloc
                );
        }
#endif
        /* TODO
         * It is not necessary to carry the whole location vector in the
         * next stream of a star-entity, only a flag. As a prerequisite,
         * non_incarnates must not clean themselves up!
         */
        /*
         * Only incarnates are eligible for cleanup!
         * check if the source (location) of the stream and the own location are
         * (subsequent) star dispatcher entities of the same star combinator network
         * -> if so, we can clean-up ourselves
         */
        if ( sarg->is_incarnate && loc != NULL ) {
          assert( true == SNetLocvecEqualParent(loc, SNetLocvecGet(sarg->info)) );
          /* If the next instance is already created, we can forward the sync-record
           * immediately and terminate.
           * Otherwise we postpone termination to the point when a next data record
           * is received, as we create the operand network then.
           */
          if (sarg->nextstream != NULL) {
            snet_record_t *term_rec;
            /* forward the sync record  */
            SNetStreamWrite( sarg->nextstream, rec);
            /* send a terminate record to collector, it will close and
               destroy the stream */
            term_rec = SNetRecCreate(REC_terminate);
            SNetRecSetFlag(term_rec);
            SNetStreamWrite( sarg->outstream, term_rec);

#ifdef DEBUG_PRINT_GC
            /* terminating due to GC */
            SNetUtilDebugNoticeEnt( ent,
                "[STAR] Notice: Destroying star dispatcher due to GC, "
                "immediately on sync!"
                );
#endif
            SNetStreamClose(sarg->nextstream, false);
            SNetStreamClose(sarg->instream, true);
            TerminateStarBoxTask(sarg->outstream,sarg);
            return;
          } else {
            sarg->sync_cleanup = true;
#ifdef DEBUG_PRINT_GC
            SNetUtilDebugNoticeEnt( ent,
                "[STAR] Notice: Remembering delayed destruction.");
#endif
            /* handle sync record as usual */
            SNetStreamReplace( sarg->instream, newstream);
            SNetRecDestroy( rec);
          }
        } else
#endif /* ENABLE_GC */
        {
          /* handle sync record as usual */
          SNetStreamReplace( sarg->instream, newstream);
          SNetRecDestroy( rec);
        }
      }
      break;


    case REC_sort_end:
      {
        int rec_lvl = SNetRecGetLevel(rec);
        /* send a copy to the box, if exists */
        if( sarg->nextstream != NULL) {
          SNetStreamWrite(
              sarg->nextstream,
              SNetRecCreate( REC_sort_end,
                (!sarg->is_incarnate)? rec_lvl+1 : rec_lvl,
                SNetRecGetNum(rec) )
              );
        }

        /* send the original one to the collector */
        if (!sarg->is_incarnate) {
          /* if non-incarnate, we have to increase level */
          SNetRecSetLevel( rec, rec_lvl+1);
        }
        SNetStreamWrite( sarg->outstream, rec);
      }
      break;

    case REC_terminate:
      if( sarg->nextstream != NULL) {
        SNetStreamWrite( sarg->nextstream, SNetRecCopy( rec));
        SNetStreamClose( sarg->nextstream, false);
      }
      SNetStreamWrite( sarg->outstream, rec);
      /* note that no sort record has to be appended */
      SNetStreamClose(sarg->instream, true);
      TerminateStarBoxTask(sarg->outstream,sarg);

      return;

    case REC_collect:
    default:
      SNetUtilDebugFatal("Unknown record type!");
      /* if ignore, at least destroy ... */
      SNetRecDestroy( rec);
  }
  SNetThreadingRespawn(NULL);
}
Exemple #5
0
/**
 * @pre rec1 and rec2 are sort records
 */
static bool SortRecEqual( snet_record_t *rec1, snet_record_t *rec2)
{
  return (SNetRecGetLevel(rec1) == SNetRecGetLevel(rec2)) &&
         (SNetRecGetNum(  rec1) == SNetRecGetNum(  rec2));
}
Exemple #6
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 */