static void applyRateControl(Sdr sdr) { BpVdb *vdb = getBpVdb(); PsmPartition ionwm = getIonwm(); Throttle *throttle; PsmAddress elt; VInduct *induct; VOutduct *outduct; long capacityLimit; sdr_begin_xn(sdr); /* Just to lock memory. */ /* Recalculate limit on local bundle generation. */ manageProductionThrottle(vdb); /* Enable some bundle acquisition. */ for (elt = sm_list_first(ionwm, vdb->inducts); elt; elt = sm_list_next(ionwm, elt)) { induct = (VInduct *) psp(ionwm, sm_list_data(ionwm, elt)); throttle = &(induct->acqThrottle); capacityLimit = throttle->nominalRate << 1; throttle->capacity += throttle->nominalRate; if (throttle->capacity > capacityLimit) { throttle->capacity = capacityLimit; } if (throttle->capacity > 0) { sm_SemGive(throttle->semaphore); } } /* Enable some bundle transmission. */ for (elt = sm_list_first(ionwm, vdb->outducts); elt; elt = sm_list_next(ionwm, elt)) { outduct = (VOutduct *) psp(ionwm, sm_list_data(ionwm, elt)); throttle = &(outduct->xmitThrottle); capacityLimit = throttle->nominalRate << 1; throttle->capacity += throttle->nominalRate; if (throttle->capacity > capacityLimit) { throttle->capacity = capacityLimit; } if (throttle->capacity > 0) { sm_SemGive(throttle->semaphore); } } sdr_exit_xn(sdr); /* Unlock memory. */ }
static void infoProfile(int tokenCount, char **tokens) { DtpcVdb *vdb = getDtpcVdb(); Profile *vprofile; PsmAddress elt; PsmPartition wm = getIonwm(); unsigned int profileID; if (tokenCount != 3) { SYNTAX_ERROR; return; } profileID = atoi(tokens[2]); for (elt = sm_list_first(wm, vdb->profiles); elt; elt = sm_list_next(wm, elt)) { vprofile = (Profile *) psp(wm, sm_list_data(wm, elt)); if (vprofile->profileID == profileID) { break; } } if (elt == 0) { printText("Unknown profile."); return; } printProfile(vprofile); }
void sptrace_clear(PsmPartition trace) { PsmAddress traceHeaderAddress; TraceHeader *trh; PsmAddress elt; PsmAddress nextElt; PsmAddress itemAddress; TraceItem *item; if (!trace) return; traceHeaderAddress = psm_get_root(trace); trh = (TraceHeader *) psp(trace, traceHeaderAddress); CHKVOID(trh); for (elt = sm_list_first(trace, trh->log); elt; elt = nextElt) { nextElt = sm_list_next(trace, elt); itemAddress = sm_list_data(trace, elt); item = (TraceItem *) psp(trace, itemAddress); CHKVOID(item); if (item->opType == OP_ALLOCATE || item->opType == OP_FREE) { if (item->refOpNbr == 0) { continue; /* Not matched. */ } /* Delete matched activity from log. */ psm_free(trace, itemAddress); CHKVOID(sm_list_delete(trace, elt, NULL, NULL) == 0); } } }
void removeEmbargo(IonNode *node, uvast neighborNodeNbr) { PsmPartition ionwm = getIonwm(); PsmAddress elt; PsmAddress addr; Embargo *embargo; CHKVOID(node); for (elt = sm_list_first(ionwm, node->embargoes); elt; elt = sm_list_next(ionwm, elt)) { addr = sm_list_data(ionwm, elt); embargo = (Embargo *) psp(ionwm, addr); CHKVOID(embargo); if (embargo->nodeNbr < neighborNodeNbr) { continue; } if (embargo->nodeNbr > neighborNodeNbr) { return; /* Embargo not found. */ } break; /* Found the embargo to remove. */ } if (elt == 0) { return; /* Embargo not found. */ } oK(sm_list_delete(ionwm, elt, NULL, NULL)); psm_free(ionwm, addr); }
Object sdr_list_first(Sdr sdrv, Object list) { //TODO stub //SdrList listBuffer; //CHKZERO(sdrFetchSafe(sdrv)); CHKZERO(list); //sdrFetch(listBuffer, (Address) list); //return listBuffer.first; return sm_list_first(sdrv, list); }
void rfx_stop() { PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); int i; PsmAddress elt; PsmAddress nextElt; PsmAddress addr; Requisition *req; /* Safely shut down the ZCO flow control system. */ for (i = 0; i < 1; i++) { for (elt = sm_list_first(ionwm, vdb->requisitions[i]); elt; elt = nextElt) { nextElt = sm_list_next(ionwm, elt); addr = sm_list_data(ionwm, elt); req = (Requisition *) psp(ionwm, addr); sm_SemEnd(req->semaphore); psm_free(ionwm, addr); sm_list_delete(ionwm, elt, NULL, NULL); } } //zco_unregister_callback(); /* Stop the rfx clock if necessary. */ /* if (vdb->clockPid != ERROR) { sm_TaskKill(vdb->clockPid, SIGTERM); while (sm_TaskExists(vdb->clockPid)) { microsnooze(100000); } vdb->clockPid = ERROR; } */ /* Wipe out all red-black trees involved in routing, * for reconstruction on restart. */ sm_rbt_destroy(ionwm, vdb->contactIndex, rfx_erase_data, NULL); sm_rbt_destroy(ionwm, vdb->rangeIndex, rfx_erase_data, NULL); sm_rbt_destroy(ionwm, vdb->timeline, rfx_erase_data, NULL); vdb->contactIndex = sm_rbt_create(ionwm); vdb->rangeIndex = sm_rbt_create(ionwm); vdb->timeline = sm_rbt_create(ionwm); }
static void dropVdb(PsmPartition wm, PsmAddress vdbAddress) { IonVdb *vdb; int i; PsmAddress elt; PsmAddress nextElt; PsmAddress addr; Requisition *req; vdb = (IonVdb *) psp(wm, vdbAddress); /* Time-ordered list of probes can simply be destroyed. */ sm_list_destroy(wm, vdb->probes, rfx_erase_data, NULL); /* Three of the red-black tables in the Vdb are * emptied and recreated by rfx_stop(). Destroy them. */ sm_rbt_destroy(wm, vdb->contactIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->rangeIndex, NULL, NULL); sm_rbt_destroy(wm, vdb->timeline, NULL, NULL); /* cgr_stop clears all routing objects, so nodes and * neighbors themselves can now be deleted. */ sm_rbt_destroy(wm, vdb->nodes, destroyIonNode, NULL); sm_rbt_destroy(wm, vdb->neighbors, rfx_erase_data, NULL); /* Safely shut down the ZCO flow control system. */ for (i = 0; i < 1; i++) { for (elt = sm_list_first(wm, vdb->requisitions[i]); elt; elt = nextElt) { nextElt = sm_list_next(wm, elt); addr = sm_list_data(wm, elt); req = (Requisition *) psp(wm, addr); sm_SemEnd(req->semaphore); psm_free(wm, addr); sm_list_delete(wm, elt, NULL, NULL); } } //zco_unregister_callback(); }
static void listProfiles(int tokenCount, char **tokens) { PsmPartition wm = getIonwm(); PsmAddress elt; Profile *vprofile; if (tokenCount != 2) { SYNTAX_ERROR; return; } for (elt = sm_list_first(wm, (getDtpcVdb())->profiles); elt; elt = sm_list_next(wm, elt)) { vprofile = (Profile *) psp(wm, sm_list_data(wm, elt)); printProfile(vprofile); } }
static PsmAddress findFileName(PsmPartition trace, TraceHeader *trh, char *sourceFileName) { PsmAddress elt; PsmAddress filenameAddress; char *filename; int buflen; for (elt = sm_list_first(trace, trh->files); elt; elt = sm_list_next(trace, elt)) { filenameAddress = sm_list_data(trace, elt); filename = (char *) psp(trace, filenameAddress); if (strcmp(filename, sourceFileName) == 0) { return filenameAddress; } } /* This is a source file we haven't heard of before. */ buflen = strlen(sourceFileName) + 1; filenameAddress = psm_zalloc(trace, buflen); if (filenameAddress == 0) { discardEvent(trace); return 0; } /* Add this source file to the list for the trace. */ istrcpy((char *) psp(trace, filenameAddress), sourceFileName, buflen); if (sm_list_insert_last(trace, trh->files, filenameAddress) == 0) { discardEvent(trace); return 0; } return filenameAddress; }
static int adjustThrottles() { PsmPartition ionwm = getIonwm(); IonVdb *ionvdb = getIonVdb(); BpVdb *bpvdb = getBpVdb(); PsmAddress elt; VOutduct *outduct; unsigned long nodeNbr; IonNeighbor *neighbor; PsmAddress nextElt; int delta; VInduct *induct; /* Only the LTP induct and outduct throttles can be * dynamically adjusted in response to changes in data * rate between the local node and its neighbors, because * (currently) there is no mechanism for mapping neighbor * node number to duct name for any other CL protocol. * For LTP, duct name is LTP engine number which, by * convention, is identical to BP node number. For all * other CL protocols, duct nominal data rate is initially * set to the protocol's configured nominal data rate and * is never subsequently modified. * * So, first we find the LTP induct if any. */ for (elt = sm_list_first(ionwm, bpvdb->inducts); elt; elt = sm_list_next(ionwm, elt)) { induct = (VInduct *) psp(ionwm, sm_list_data(ionwm, elt)); if (strcmp(induct->protocolName, "ltp") == 0) { break; /* Found the LTP induct. */ } } if (elt == 0) /* No LTP induct; nothing to do. */ { return 0; } /* Now update all LTP outducts, and the induct as well, * inferring the existence of Neighbors in the process. */ for (elt = sm_list_first(ionwm, bpvdb->outducts); elt; elt = sm_list_next(ionwm, elt)) { outduct = (VOutduct *) psp(ionwm, sm_list_data(ionwm, elt)); if (strcmp(outduct->protocolName, "ltp") != 0) { continue; } nodeNbr = atol(outduct->ductName); neighbor = findNeighbor(ionvdb, nodeNbr, &nextElt); if (neighbor == NULL) { neighbor = addNeighbor(ionvdb, nodeNbr, nextElt); if (neighbor == NULL) { putErrmsg("Can't adjust outduct throttle.", NULL); return -1; } } if (neighbor->xmitRate != neighbor->prevXmitRate) { #ifndef ION_NOSTATS if (neighbor->nodeNbr != getOwnNodeNbr()) { /* We report and clear transmission * statistics as necessary. NOTE that * this procedure is based on the * assumption that the local node is * in LTP transmission contact with * AT MOST ONE neighbor at any time. * For more complex topologies it will * need to be redesigned. */ if (neighbor->xmitRate == 0) { /* End of xmit contact. */ reportAllStateStats(); clearAllStateStats(); } else if (neighbor->prevXmitRate == 0) { /* Start of xmit contact. */ reportAllStateStats(); clearAllStateStats(); } } #endif outduct->xmitThrottle.nominalRate = neighbor->xmitRate; neighbor->prevXmitRate = neighbor->xmitRate; } /* Note that the LTP induct is aggregate; the * duct's nominal rate is the sum of the rates * at which all neighbors are expected to be * transmitting to the local node at any given * moment. So we must add the change in rate * for each known neighbor to the aggregate * nominal reception rate for the induct. */ if (neighbor->recvRate != neighbor->prevRecvRate) { #ifndef ION_NOSTATS if (neighbor->nodeNbr != getOwnNodeNbr()) { /* We report and clear reception * statistics as necessary. NOTE that * this procedure is based on the * assumption that the local node is * in LTP reception contact with * AT MOST ONE neighbor at any time. * For more complex topologies it will * need to be redesigned. */ if (neighbor->recvRate == 0) { /* End of recv contact. */ reportAllStateStats(); clearAllStateStats(); } else if (neighbor->prevRecvRate == 0) { /* Start of recv contact. */ reportAllStateStats(); clearAllStateStats(); } } #endif delta = neighbor->recvRate - neighbor->prevRecvRate; induct->acqThrottle.nominalRate += delta; neighbor->prevRecvRate = neighbor->recvRate; } } return 0; }
static int manageLinks(Sdr sdr, time_t currentTime) { PsmPartition ionwm = getIonwm(); LtpVdb *ltpvdb = getLtpVdb(); IonVdb *ionvdb = getIonVdb(); PsmAddress elt; LtpVspan *vspan; Object obj; LtpSpan span; IonNeighbor *neighbor; PsmAddress nextElt; unsigned long priorXmitRate; sdr_begin_xn(sdr); for (elt = sm_list_first(ionwm, ltpvdb->spans); elt; elt = sm_list_next(ionwm, elt)) { vspan = (LtpVspan *) psp(ionwm, sm_list_data(ionwm, elt)); /* Finish aggregation as necessary. */ obj = sdr_list_data(sdr, vspan->spanElt); sdr_stage(sdr, (char *) &span, obj, sizeof(LtpSpan)); if (span.lengthOfBufferedBlock > 0) { span.ageOfBufferedBlock++; sdr_write(sdr, obj, (char *) &span, sizeof(LtpSpan)); if (span.ageOfBufferedBlock >= span.aggrTimeLimit) { sm_SemGive(vspan->bufFullSemaphore); } } /* Find Neighbor object encapsulating the current * known state of this LTP engine. */ neighbor = findNeighbor(ionvdb, vspan->engineId, &nextElt); if (neighbor == NULL) { neighbor = addNeighbor(ionvdb, vspan->engineId, nextElt); if (neighbor == NULL) { putErrmsg("Can't update span.", NULL); return -1; } } if (neighbor->xmitRate == 0) { if (vspan->localXmitRate > 0) { vspan->localXmitRate = 0; ltpStopXmit(vspan); } } else { if (vspan->localXmitRate == 0) { vspan->localXmitRate = neighbor->xmitRate; ltpStartXmit(vspan); } } if (neighbor->fireRate == 0) { if (vspan->remoteXmitRate > 0) { priorXmitRate = vspan->remoteXmitRate; vspan->remoteXmitRate = 0; if (ltpSuspendTimers(vspan, elt, currentTime, priorXmitRate)) { putErrmsg("Can't manage links.", NULL); return -1; } } } else { if (vspan->remoteXmitRate == 0) { vspan->remoteXmitRate = neighbor->fireRate; if (ltpResumeTimers(vspan, elt, currentTime, vspan->remoteXmitRate)) { putErrmsg("Can't manage links.", NULL); return -1; } } } if (neighbor->recvRate == 0) { vspan->receptionRate = 0; } else { vspan->receptionRate = neighbor->recvRate; } if (neighbor->owltInbound != vspan->owltInbound) { vspan->owltInbound = neighbor->owltInbound; } if (neighbor->owltOutbound != vspan->owltOutbound) { vspan->owltOutbound = neighbor->owltOutbound; } } if (sdr_end_xn(sdr) < 0) { putErrmsg("ltpclock failed managing links.", NULL); return -1; } return 0; }
void sptrace_report(PsmPartition trace, int verbose) { PsmAddress traceHeaderAddress; TraceHeader *trh; PsmAddress elt; TraceItem *item; char *fileName; char buffer[384]; int len; char buf2[256]; if (!trace) return; traceHeaderAddress = psm_get_root(trace); trh = (TraceHeader *) psp(trace, traceHeaderAddress); CHKVOID(trh); for (elt = sm_list_first(trace, trh->log); elt; elt = sm_list_next(trace, elt)) { item = (TraceItem *) psp(trace, sm_list_data(trace, elt)); CHKVOID(item); fileName = (char *) psp(trace, item->fileName); isprintf(buffer, sizeof buffer, "(%5d) at line %6d of %32.32s \ (pid %5d): ", item->opNbr, item->lineNbr, fileName, item->taskId); len = strlen(buffer); switch (item->opType) { case OP_ALLOCATE: isprintf(buf2, sizeof buf2, "allocated object %6ld of \ size %6d, ", item->objectAddress, item->objectSize); istrcpy(buffer + len, buf2, sizeof buffer - len); if (item->refOpNbr == 0) { len = strlen(buffer); istrcpy(buffer + len, "never freed", sizeof buffer - len); } else { if (!verbose) { continue; } len = strlen(buffer); fileName = (char *) psp(trace, item->refFileName); isprintf(buf2, sizeof buf2, "freed in (%5d) \ at line %6d of %32.32s (pid %5d)", item->refOpNbr, item->refLineNbr, fileName, item->refTaskId); istrcpy(buffer + len, buf2, sizeof buffer - len); } break; case OP_MEMO: isprintf(buf2, sizeof buf2, "re %6ld, '%.128s'", item->objectAddress, (char *) psp(trace, item->msg)); istrcpy(buffer + len, buf2, sizeof buffer - len); break; case OP_FREE: isprintf(buf2, sizeof buf2, "freed object %6ld, ", item->objectAddress); istrcpy(buffer + len, buf2, sizeof buffer - len); if (item->refOpNbr == 0) { len = strlen(buffer); istrcpy(buffer + len, "not currently allocated", sizeof buffer - len); } else { if (!verbose) { continue; } len = strlen(buffer); fileName = (char *) psp(trace, item->refFileName); CHKVOID(fileName); isprintf(buf2, sizeof buf2, "allocated in \ (%5d) at line %6d of %32.32s (pid %5d)", item->refOpNbr, item->refLineNbr, fileName, item->refTaskId); istrcpy(buffer + len, buf2, sizeof buffer - len); } break; } writeMemo(buffer); } }
static int enqueueToNeighbor(Bundle *bundle, Object bundleObj, unsigned long nodeNbr, unsigned long serviceNbr) { FwdDirective directive; char *decoration; char stationEid[64]; IonNode *stationNode; PsmAddress nextElt; PsmPartition ionwm; PsmAddress snubElt; IonSnub *snub; if (ipn_lookupPlanDirective(nodeNbr, bundle->id.source.c.serviceNbr, bundle->id.source.c.nodeNbr, &directive) == 0) { return 0; } /* The station node is a neighbor. */ #if BP_URI_RFC decoration = "dtn::"; #else decoration = ""; #endif isprintf(stationEid, sizeof stationEid, "%.5sipn:%lu.%lu", decoration, nodeNbr, serviceNbr); /* Is neighbor refusing to be a station for bundles? */ stationNode = findNode(getIonVdb(), nodeNbr, &nextElt); if (stationNode) { ionwm = getIonwm(); for (snubElt = sm_list_first(ionwm, stationNode->snubs); snubElt; snubElt = sm_list_next(ionwm, snubElt)) { snub = (IonSnub *) psp(ionwm, sm_list_data(ionwm, snubElt)); if (snub->nodeNbr < nodeNbr) { continue; } if (snub->nodeNbr > nodeNbr) { break; /* Not refusing bundles. */ } /* Neighbor is refusing bundles; give up. */ return 0; } } if (enqueueToDuct(&directive, bundle, bundleObj, stationEid) < 0) { putErrmsg("Can't enqueue bundle.", NULL); return -1; } return 0; }
int addEmbargo(IonNode *node, uvast neighborNodeNbr) { PsmPartition ionwm = getIonwm(); PsmAddress nextElt; PsmAddress elt; Embargo *embargo; PsmAddress addr; /* Find insertion point in embargoes list. */ CHKERR(node); nextElt = 0; for (elt = sm_list_first(ionwm, node->embargoes); elt; elt = sm_list_next(ionwm, elt)) { embargo = (Embargo *) psp(ionwm, sm_list_data(ionwm, elt)); CHKERR(embargo); if (embargo->nodeNbr < neighborNodeNbr) { continue; } if (embargo->nodeNbr > neighborNodeNbr) { nextElt = elt; break; /* Have found insertion point. */ } return 0; /* Embargo has already been added. */ } addr = psm_zalloc(ionwm, sizeof(Embargo)); if (addr == 0) { putErrmsg("Can't add embargo.", NULL); return -1; } if (nextElt) { elt = sm_list_insert_before(ionwm, nextElt, addr); } else { elt = sm_list_insert_last(ionwm, node->embargoes, addr); } if (elt == 0) { psm_free(ionwm, addr); putErrmsg("Can't add embargo.", NULL); return -1; } embargo = (Embargo *) psp(ionwm, addr); CHKERR(embargo); embargo->nodeNbr = neighborNodeNbr; embargo->probeIsDue = 0; postProbeEvent(node, embargo); /* Initial probe event. */ return 0; }
int main(int argc, char **argv) #endif { char *wmspace; int wmid; PsmPartition wm = NULL; PsmMgtOutcome outcome; PsmAddress testlist; sm_SemId semaphore; int cycleNbr = 1; char fileName[256]; int outputFile; PsmAddress lineListElt; PsmAddress lineAddress; char *line; if (sm_ipc_init() < 0) { return 0; } if (sm_ShmAttach(0x1108, 10000000, &wmspace, &wmid) < 0) { PERROR("can't attach to shared memory"); return 0; } if (psm_manage(wmspace, 10000000, "file2sm", &wm, &outcome) < 0 || outcome == Refused) { PUTS("can't manage shared memory"); return 0; } testlist = psm_get_root(wm); if (testlist == 0) { testlist = sm_list_create(wm); if (testlist == 0) { PUTS("can't create shared memory list"); return 0; } psm_set_root(wm, testlist); } semaphore = sm_SemCreate(0x1101, SM_SEM_FIFO); if (semaphore < 0) { PUTS("can't create semaphore"); return 0; } PUTMEMO("Working on cycle", utoa(cycleNbr)); isprintf(fileName, sizeof fileName, "file_copy_%d", cycleNbr); outputFile = iopen(fileName, O_WRONLY | O_APPEND, 0666); if (outputFile < 0) { PERROR("can't open output file"); return 0; } while (1) { while (sm_list_length(wm, testlist) == 0) { sm_SemTake(semaphore); /* Wait for line. */ } lineListElt = sm_list_first(wm, testlist); lineAddress = sm_list_data(wm, lineListElt); line = psp(wm, lineAddress); /* Process text of line. */ if (strcmp(line, "*** End of the file ***\n") == 0) { /* Close file, open next one. */ close(outputFile); cycleNbr++; PUTMEMO("Working on cycle", utoa(cycleNbr)); isprintf(fileName, sizeof fileName, "file_copy_%d", cycleNbr); outputFile = iopen(fileName, O_WRONLY | O_APPEND, 0666); if (outputFile < 0) { PERROR("Can't open output file"); return 0; } } else /* Just write line to output file. */ { if (iputs(outputFile, line) < 0) { close(outputFile); PERROR("Can't write to output file"); return 0; } } /* Delete line from shared memory list. */ psm_free(wm, lineAddress); CHKZERO(sm_list_delete(wm, lineListElt, (SmListDeleteFn) NULL, NULL) == 0); } }