snet_handle_t *SNetOutRawArray( snet_handle_t *hnd, int if_id, snet_variant_t *variant, void **fields, int *tags, int *btags) { int i, name; snet_record_t *out_rec, *old_rec; #ifdef DBG_RT_TRACE_OUT_TIMINGS struct timeval tv_in; struct timeval tv_out; gettimeofday( &tv_in, NULL); SNetUtilDebugNoticeEnt( hnd->ent, "[BOX] SNetOut called at %lf.", tv_in.tv_sec + tv_in.tv_usec / 1000000.0 ); #endif // set values from box out_rec = SNetRecCreate( REC_data); SNetRecSetInterfaceId( out_rec, if_id); i = 0; VARIANT_FOR_EACH_FIELD(variant, name) { SNetRecSetField( out_rec, name, SNetRefCreate(fields[i], if_id)); i++; }
snet_record_t *SNetRecCopy( snet_record_t *rec) { snet_record_t *new_rec; switch (REC_DESCR( rec)) { case REC_data: new_rec = SNetMemAlloc( sizeof( snet_record_t)); REC_DESCR( new_rec) = REC_data; RECPTR( new_rec) = SNetMemAlloc( sizeof( snet_record_types_t)); RECORD( new_rec, data_rec) = SNetMemAlloc( sizeof( data_rec_t)); DATA_REC( new_rec, fields) = SNetRefMapCopy(DATA_REC(rec, fields)); DATA_REC( new_rec, tags) = SNetIntMapCopy( DATA_REC( rec, tags)); DATA_REC( new_rec, btags) = SNetIntMapCopy( DATA_REC( rec, btags)); SNetRecSetInterfaceId( new_rec, SNetRecGetInterfaceId( rec)); SNetRecSetDataMode( new_rec, SNetRecGetDataMode( rec)); DATA_REC( new_rec, parent_rids) = NULL; /* (DATA_REC( rec, parent_rids)==NULL) ? NULL : SNetRecIdListCopy(DATA_REC( rec, parent_rids)); */ break; case REC_sort_end: new_rec = SNetRecCreate( REC_DESCR( rec), SORT_E_REC( rec, level), SORT_E_REC( rec, num)); break; case REC_terminate: new_rec = SNetRecCreate( REC_terminate); TERM_REC(new_rec, local) = TERM_REC(rec, local); break; default: new_rec = NULL; SNetUtilDebugFatal("Can't copy record of type %d", REC_DESCR( rec)); break; } return new_rec; }
/* 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); } }
/* helper functions to handle mode the feedback collector is in */ static void FbCollReadIn(struct fbcoll_state *state) { snet_record_t *rec; assert( false == state->terminate ); /* read from input stream */ rec = SNetStreamRead( state->instream); switch( SNetRecGetDescriptor( rec)) { case REC_data: /* relay data record */ SNetStreamWrite( state->outstream, rec); /* append a sort record */ SNetStreamWrite( state->outstream, SNetRecCreate( REC_sort_end, 0, 1 ) /*type, lvl, num*/ ); /* mode switch to FB1 */ state->mode = FBCOLL_FB1; break; case REC_sort_end: /* increase the level and forward */ SNetRecSetLevel( rec, SNetRecGetLevel(rec)+1); SNetStreamWrite( state->outstream, rec); break; case REC_terminate: state->terminate = true; SNetStreamWrite( state->outstream, rec); /* note that no sort record has to be appended */ break; case REC_sync: SNetStreamReplace( state->instream, SNetRecGetStream( rec)); SNetRecDestroy( rec); break; case REC_collect: default: assert(0); /* if ignoring, at least destroy ... */ SNetRecDestroy( rec); break; } }
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); }
/** * 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 */
/** * 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); }
/** * 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 */
/* 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); } }
/** * 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); }
void *Feeder( void *buf) { snet_buffer_t *inbuf = (snet_buffer_t*)buf; snet_record_t *rec1; snet_variantencoding_t *type1; SACarg *in_key; int *key, str_len; int i, j; key = malloc( 16 * sizeof( int)); for( i=0; i<16; i++) { key[i] = i; } desboxes__genKey1( &in_key,SACARGconvertFromIntPointer( key, 1, 16)); // Text { SACarg *in_bits, *in_string; int *current_block, *bit_array; char *plaintext; plaintext = malloc( MAX_PT_LEN * sizeof( char)); fprintf(stderr, "\n\nText to be enciphered: "); fgets( plaintext, MAX_PT_LEN, stdin); str_len = strlen( plaintext); desboxes__to_string1( &in_string, SACARGconvertFromCharPointer( plaintext, 1, str_len-1)); desboxes__string2bitBlocks1( &in_bits, in_string); bit_array = SACARGconvertToIntArray( SACARGnewReference( in_bits)); fprintf(stderr, "\nInput:\n"); for( i=0; i<SACARGgetShape( in_bits, 0); i++) { current_block = SNetMemAlloc( 64 * sizeof( int)); fprintf(stderr, "Block %d:\n", i); for( j=0; j<64; j++) { current_block[j]= bit_array[(i*64)+j]; fprintf(stderr, "%d ", current_block[j]); } if( DECIPHER) { type1 = SNetTencVariantEncode( SNetTencCreateVector( 2 , F__des__Pt, F__des__Key), SNetTencCreateVector( 1, T__des__Decipher), SNetTencCreateVector( 0)); } else { type1 = SNetTencVariantEncode( SNetTencCreateVector( 2 , F__des__Pt, F__des__Key), SNetTencCreateVector( 0), SNetTencCreateVector( 0)); } rec1 = SNetRecCreate( REC_data, type1); SNetRecSetField( rec1, F__des__Pt, SACARGconvertFromIntPointer( current_block, 1, 64)); SNetRecSetField( rec1, F__des__Key, SACARGnewReference( in_key)); SNetRecSetInterfaceId( rec1, 0); SNetBufPut( inbuf, rec1); fprintf(stderr, "\n"); } } SNetBufPut( inbuf, SNetRecCreate( REC_terminate)); return( NULL); }
/* 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); } }