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); }
void ionDropVdb() { PsmPartition wm = getIonwm(); char *ionvdbName = _ionvdbName(); PsmAddress vdbAddress; PsmAddress elt; char *stop = NULL; if (psm_locate(wm, ionvdbName, &vdbAddress, &elt) < 0) { putErrmsg("Failed searching for vdb.", NULL); return; } if (elt) { dropVdb(wm, vdbAddress); /* Destroy Vdb. */ psm_free(wm, vdbAddress); if (psm_uncatlg(wm, ionvdbName) < 0) { putErrmsg("Failed uncataloging vdb.", NULL); } } oK(_ionvdb(&stop)); /* Forget old Vdb. */ }
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); }
IonNode *addNode(IonVdb *ionvdb, uvast nodeNbr) { PsmPartition ionwm = getIonwm(); PsmAddress addr; PsmAddress elt; IonNode *node; addr = psm_zalloc(ionwm, sizeof(IonNode)); if (addr == 0) { putErrmsg("Can't add node.", NULL); return NULL; } node = (IonNode *) psp(ionwm, addr); CHKNULL(node); memset((char *) node, 0, sizeof(IonNode)); node->nodeNbr = nodeNbr; elt = sm_rbt_insert(ionwm, ionvdb->nodes, addr, rfx_order_nodes, node); if (elt == 0) { psm_free(ionwm, addr); putErrmsg("Can't add node.", NULL); return NULL; } node->embargoes = sm_list_create(ionwm); return node; }
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. */ }
PsmAddress postProbeEvent(IonNode *node, Embargo *embargo) { PsmPartition ionwm = getIonwm(); PsmAddress addr; IonProbe *probe; IonVdb *ionvdb; IonNeighbor *neighbor; PsmAddress nextElt; unsigned int rtlt; /* Round-trip light time. */ int interval = 6; /* Minimum 6-sec interval. */ PsmAddress elt; IonProbe *pr; CHKZERO(node); CHKZERO(embargo); addr = psm_zalloc(ionwm, sizeof(IonProbe)); if (addr == 0) { putErrmsg("Can't create probe event.", NULL); return 0; } probe = (IonProbe *) psp(ionwm, addr); CHKZERO(probe); probe->time = getUTCTime(); probe->destNodeNbr = node->nodeNbr; probe->neighborNodeNbr = embargo->nodeNbr; /* Schedule next probe of this embargoed neighbor for the * time that is the current time plus 2x the round-trip * light time from the local node to the neighbor (but * at least 6 seconds). */ ionvdb = getIonVdb(); neighbor = findNeighbor(ionvdb, embargo->nodeNbr, &nextElt); if (neighbor) { rtlt = (neighbor->owltOutbound + neighbor->owltInbound) << 1; if (rtlt > interval) { interval = rtlt; } } probe->time += interval; for (elt = sm_list_last(ionwm, ionvdb->probes); elt; elt = sm_list_prev(ionwm, elt)) { pr = (IonProbe *) psp(ionwm, sm_list_data(ionwm, elt)); CHKZERO(pr); if (pr->time <= probe->time) { return sm_list_insert_after(ionwm, elt, addr); } } return sm_list_insert_first(ionwm, ionvdb->probes, addr); }
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 executeList(int tokenCount, char **tokens) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); PsmAddress elt; PsmAddress addr; char buffer[RFX_NOTE_LEN]; if (tokenCount < 2) { printText("List what?"); return; } if (strcmp(tokens[1], "contact") == 0) { CHKVOID(sdr_begin_xn(sdr)); for (elt = sm_rbt_first(ionwm, vdb->contactIndex); elt; elt = sm_rbt_next(ionwm, elt)) { addr = sm_rbt_data(ionwm, elt); rfx_print_contact(addr, buffer); printText(buffer); } sdr_exit_xn(sdr); return; } if (strcmp(tokens[1], "range") == 0) { CHKVOID(sdr_begin_xn(sdr)); for (elt = sm_rbt_first(ionwm, vdb->rangeIndex); elt; elt = sm_rbt_next(ionwm, elt)) { addr = sm_rbt_data(ionwm, elt); rfx_print_range(addr, buffer); printText(buffer); } sdr_exit_xn(sdr); return; } SYNTAX_ERROR; }
char *rfx_print_range(PsmAddress rxaddr, char *buffer) { IonRXref *range; char fromTimeBuffer[TIMESTAMPBUFSZ]; char toTimeBuffer[TIMESTAMPBUFSZ]; CHKNULL(rxaddr); CHKNULL(buffer); range = (IonRXref *) psp(getIonwm(), rxaddr); writeTimestampUTC(range->fromTime, fromTimeBuffer); writeTimestampUTC(range->toTime, toTimeBuffer); isprintf(buffer, RFX_NOTE_LEN, "From %20s to %20s the OWLT from \ node " UVAST_FIELDSPEC " to node " UVAST_FIELDSPEC " is %10u seconds.", fromTimeBuffer, toTimeBuffer, range->fromNode, range->toNode, range->owlt); return buffer; }
char *rfx_print_contact(PsmAddress cxaddr, char *buffer) { IonCXref *contact; char fromTimeBuffer[TIMESTAMPBUFSZ]; char toTimeBuffer[TIMESTAMPBUFSZ]; CHKNULL(cxaddr); CHKNULL(buffer); contact = (IonCXref *) psp(getIonwm(), cxaddr); writeTimestampUTC(contact->fromTime, fromTimeBuffer); writeTimestampUTC(contact->toTime, toTimeBuffer); snprintf(buffer, RFX_NOTE_LEN, "From %20s to %20s the xmit rate from \ node " UVAST_FIELDSPEC " to node " UVAST_FIELDSPEC " is %10lu bytes/sec, \ probability %f.", fromTimeBuffer, toTimeBuffer, contact->fromNode, contact->toNode, (unsigned long) contact->xmitRate, contact->prob); return buffer; }
IonNode *findNode(IonVdb *ionvdb, uvast nodeNbr, PsmAddress *nextElt) { PsmPartition ionwm = getIonwm(); IonNode arg; PsmAddress elt; CHKNULL(ionvdb); CHKNULL(nextElt); memset((char *) &arg, 0, sizeof(IonNode)); arg.nodeNbr = nodeNbr; elt = sm_rbt_search(ionwm, ionvdb->nodes, rfx_order_nodes, &arg, nextElt); if (elt) { return (IonNode *) psp(ionwm, sm_rbt_data(ionwm, elt)); } return NULL; }
IonNeighbor *addNeighbor(IonVdb *ionvdb, uvast nodeNbr) { PsmPartition ionwm = getIonwm(); IonNode *node; PsmAddress nextElt; PsmAddress addr; PsmAddress elt; IonNeighbor *neighbor; node = findNode(ionvdb, nodeNbr, &nextElt); if (node == NULL) { node = addNode(ionvdb, nodeNbr); if (node == NULL) { putErrmsg("Can't add neighboring node.", NULL); return NULL; } } addr = psm_zalloc(ionwm, sizeof(IonNeighbor)); if (addr == 0) { putErrmsg("Can't add neighbor.", NULL); return NULL; } neighbor = (IonNeighbor *) psp(ionwm, addr); CHKNULL(neighbor); memset((char *) neighbor, 0, sizeof(IonNeighbor)); neighbor->nodeNbr = nodeNbr; neighbor->node = psa(ionwm, node); elt = sm_rbt_insert(ionwm, ionvdb->neighbors, addr, rfx_order_neighbors, neighbor); if (elt == 0) { psm_free(ionwm, addr); putErrmsg("Can't add neighbor.", NULL); return NULL; } return neighbor; }
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 void ionDropVdb(char * vdbName) { PsmPartition wm = getIonwm(); char *ionvdbName = vdbName; PsmAddress vdbAddress; PsmAddress elt; if (psm_locate(wm, ionvdbName, &vdbAddress, &elt) < 0) { putErrmsg("Failed searching for vdb.", NULL); return; } if (elt) { dropVdb(wm, vdbAddress); /* Destroy Vdb. */ if (psm_uncatlg(wm, ionvdbName) < 0) { putErrmsg("Failed uncataloging vdb.", NULL); } psm_free(wm, vdbAddress); } }
static void deleteRange(PsmAddress rxaddr, int conditional) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); time_t currentTime = getUTCTime(); IonRXref *rxref; Object obj; IonEvent event; IonNeighbor *neighbor; PsmAddress nextElt; rxref = (IonRXref *) psp(ionwm, rxaddr); /* Delete range from non-volatile database. */ if (rxref->rangeElt) /* An asserted range. */ { if (conditional) /* Delete only if imputed. */ { return; /* Retain asserted range. */ } /* Unconditional deletion; remove range from DB. */ obj = sdr_list_data(sdr, rxref->rangeElt); sdr_free(sdr, obj); sdr_list_delete(sdr, rxref->rangeElt, NULL, NULL); } /* Delete range events from timeline. */ event.ref = rxaddr; event.time = rxref->fromTime; if (rxref->rangeElt) { event.type = IonStartAssertedRange; } else { event.type = IonStartImputedRange; } sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); event.time = rxref->toTime; if (rxref->rangeElt) { event.type = IonStopAssertedRange; } else { event.type = IonStopImputedRange; } sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); /* Apply to current state as necessary. */ if (currentTime >= rxref->fromTime && currentTime <= rxref->toTime) { if (rxref->fromNode == getOwnNodeNbr()) { neighbor = findNeighbor(vdb, rxref->toNode, &nextElt); if (neighbor) { neighbor->owltOutbound = 0; } } if (rxref->toNode == getOwnNodeNbr()) { neighbor = findNeighbor(vdb, rxref->fromNode, &nextElt); if (neighbor) { neighbor->owltInbound = 0; } } } /* Delete range from index. */ if (rxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } sm_rbt_delete(ionwm, vdb->rangeIndex, rfx_order_ranges, rxref, rfx_erase_data, NULL); }
Object rfx_insert_range(time_t fromTime, time_t toTime, uvast fromNode, uvast toNode, unsigned int owlt) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonRXref arg1; PsmAddress rxelt; PsmAddress nextElt; PsmAddress rxaddr; IonRXref *rxref; IonEvent arg2; PsmAddress prevElt; char rangeIdString[128]; IonRange range; Object iondbObj; IonDB iondb; Object obj; Object elt; /* Note that ranges are normally assumed to be symmetrical, * i.e., the signal propagation time from B to A is normally * assumed to be the same as the signal propagation time * from A to B. For this reason, normally only the A->B * range (where A is a node number that is less than node * number B) need be entered; when ranges are applied to * the IonNeighbor objects in the ION database, the A->B * range is stored as the OWLT for transmissions from A to * B and also as the OWLT for transmissions from B to A. * * However, it is possible to insert asymmetric ranges, as * would apply when the forward and return traffic between * some pair of nodes travels by different transmission * paths that introduce different latencies. When this is * the case, both the A->B and B->A ranges must be entered. * The A->B range is initially processed as a symmetric * range as described above, but when the B->A range is * subsequently noted it overrides the default OWLT for * transmissions from B to A. */ CHKZERO(fromTime); CHKZERO(toTime > fromTime); CHKZERO(fromNode); CHKZERO(toNode); CHKZERO(sdr_begin_xn(sdr)); /* Make sure range doesn't overlap with any pre-existing * ranges. */ memset((char *) &arg1, 0, sizeof(IonRXref)); arg1.fromNode = fromNode; arg1.toNode = toNode; arg1.fromTime = fromTime; arg1.toTime = toTime; arg1.owlt = owlt; rxelt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg1, &nextElt); if (rxelt) /* Range is in database already. */ { rxaddr = sm_rbt_data(ionwm, rxelt); rxref = (IonRXref *) psp(ionwm, rxaddr); if (rxref->rangeElt == 0) /* Imputed. */ { /* The existing range for the same nodes * and time is merely an imputed range, * which is being overridden by a non- * canonical range assertion indicating * an override of the normal symmetry in * the owlt between nodes. Must delete * that imputed range, together with the * associated events, after which there * is no duplication. */ sm_rbt_delete(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg1, rfx_erase_data, NULL); arg2.ref = rxaddr; arg2.time = rxref->fromTime; arg2.type = IonStartImputedRange; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &arg2, rfx_erase_data, NULL); arg2.time = rxref->toTime; arg2.type = IonStopImputedRange; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &arg2, rfx_erase_data, NULL); } else /* Overriding an asserted range. */ { /* This is an attempt to replace an * existing asserted range with another * asserted range, which is prohibited. */ if (rxref->owlt == owlt) { sdr_exit_xn(sdr); return rxaddr; /* Idempotent. */ } isprintf(rangeIdString, sizeof rangeIdString, "from %lu, %llu->%llu", fromTime, fromNode, toNode); writeMemoNote("[?] Range OWLT not revised", rangeIdString); sdr_exit_xn(sdr); return 0; } } /* Check for overlap, which is not allowed. */ if (nextElt) { prevElt = sm_rbt_prev(ionwm, nextElt); rxref = (IonRXref *) psp(ionwm, sm_rbt_data(ionwm, nextElt)); if (fromNode == rxref->fromNode && toNode == rxref->toNode && toTime > rxref->fromTime) { writeMemoNote("[?] Overlapping range", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } else { prevElt = sm_rbt_last(ionwm, vdb->rangeIndex); } if (prevElt) { rxref = (IonRXref *) psp(ionwm, sm_rbt_data(ionwm, prevElt)); if (fromNode == rxref->fromNode && toNode == rxref->toNode && fromTime < rxref->toTime) { writeMemoNote("[?] Overlapping range", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } /* Range isn't already in database; okay to add. */ rxaddr = 0; range.fromTime = fromTime; range.toTime = toTime; range.fromNode = fromNode; range.toNode = toNode; range.owlt = owlt; obj = sdr_malloc(sdr, sizeof(IonRange)); if (obj) { sdr_write(sdr, obj, (char *) &range, sizeof(IonRange)); iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); elt = sdr_list_insert_last(sdr, iondb.ranges, obj); if (elt) { arg1.rangeElt = elt; rxaddr = insertRXref(&arg1); if (rxaddr == 0) { sdr_cancel_xn(sdr); } } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't insert range.", NULL); return 0; } return rxaddr; }
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; }
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; }
int rfx_remove_range(time_t fromTime, uvast fromNode, uvast toNode) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonRXref arg; PsmAddress rxelt; PsmAddress nextElt; PsmAddress rxaddr; IonRXref *rxref; /* Note: when the fromTime passed to ionadmin is '*' * a fromTime of zero is passed to rfx_remove_range, * where it is interpreted as "all ranges between * these two nodes". */ memset((char *) &arg, 0, sizeof(IonRXref)); arg.fromNode = fromNode; arg.toNode = toNode; CHKERR(sdr_begin_xn(sdr)); if (fromTime) /* Not a wild-card deletion. */ { arg.fromTime = fromTime; rxelt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg, &nextElt); if (rxelt) /* Found it. */ { rxaddr = sm_rbt_data(ionwm, rxelt); deleteRange(rxaddr, 0); } } else /* Wild-card deletion, start at time zero. */ { while (1) { /* Get first remaining range for this * to/from node pair. */ oK(sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg, &rxelt)); if (rxelt == 0) { break; /* No more ranges. */ } rxaddr = sm_rbt_data(ionwm, rxelt); rxref = (IonRXref *) psp(ionwm, rxaddr); if (rxref->fromNode > arg.fromNode || rxref->toNode > arg.toNode) { break; /* No more matches. */ } deleteRange(rxaddr, 0); } } if (fromNode > toNode) { /* This is either an imputed range or else * a non-canonical range assertion, * indicating an override of the normal * symmetry in the owlt between nodes. The * reverse range assertion does *not* hold. */ if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't remove range(s).", NULL); return -1; } return 0; } /* Canonical range assertion(s); delete corresponding * imputed range(s) as well. */ arg.fromNode = toNode; /* Reverse direction. */ arg.toNode = fromNode; /* Reverse direction. */ if (fromTime) /* Not a wild-card deletion. */ { arg.fromTime = fromTime; rxelt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg, &nextElt); if (rxelt) /* Found it. */ { rxaddr = sm_rbt_data(ionwm, rxelt); deleteRange(rxaddr, 1); } } else /* Wild-card deletion, start at time zero. */ { while (1) { /* Get first remaining range for this * to/from node pair. */ oK(sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg, &rxelt)); if (rxelt == 0) { break; /* No more ranges. */ } rxaddr = sm_rbt_data(ionwm, rxelt); rxref = (IonRXref *) psp(ionwm, rxaddr); if (rxref->fromNode > arg.fromNode || rxref->toNode > arg.toNode) { break; /* No more matches. */ } deleteRange(rxaddr, 1); } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't remove range(s).", NULL); return -1; } return 0; }
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 rfx_remove_contact(time_t fromTime, uvast fromNode, uvast toNode) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonCXref arg; PsmAddress cxelt; PsmAddress nextElt; PsmAddress cxaddr; IonCXref *cxref; /* Note: when the fromTime passed to ionadmin is '*' * a fromTime of zero is passed to rfx_remove_contact, * where it is interpreted as "all contacts between * these two nodes". */ memset((char *) &arg, 0, sizeof(IonCXref)); arg.fromNode = fromNode; arg.toNode = toNode; CHKERR(sdr_begin_xn(sdr)); if (fromTime) /* Not a wild-card deletion. */ { arg.fromTime = fromTime; cxelt = sm_rbt_search(ionwm, vdb->contactIndex, rfx_order_contacts, &arg, &nextElt); if (cxelt) /* Found it. */ { cxaddr = sm_rbt_data(ionwm, cxelt); deleteContact(cxaddr); } } else /* Wild-card deletion, start at time zero. */ { while (1) { /* Get first remaining contact for this * to/from node pair. */ oK(sm_rbt_search(ionwm, vdb->contactIndex, rfx_order_contacts, &arg, &cxelt)); if (cxelt == 0) { break; /* No more contacts. */ } cxaddr = sm_rbt_data(ionwm, cxelt); cxref = (IonCXref *) psp(ionwm, cxaddr); if (cxref->fromNode > fromNode || cxref->toNode > toNode) { break; /* No more matches. */ } deleteContact(cxaddr); } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't remove contact(s).", NULL); return -1; } return 0; }
static void executeInfo(int tokenCount, char **tokens) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); time_t refTime; time_t timestamp; uvast fromNode; uvast toNode; IonCXref arg1; PsmAddress elt; PsmAddress addr; PsmAddress nextElt; char buffer[RFX_NOTE_LEN]; IonRXref arg2; if (tokenCount < 2) { printText("Information on what?"); return; } if (tokenCount != 5) { SYNTAX_ERROR; return; } refTime = _referenceTime(NULL); timestamp = readTimestampUTC(tokens[2], refTime); fromNode = strtouvast(tokens[3]); toNode = strtouvast(tokens[4]); if (strcmp(tokens[1], "contact") == 0) { memset((char *) &arg1, 0, sizeof(IonCXref)); arg1.fromNode = fromNode; arg1.toNode = toNode; arg1.fromTime = timestamp; CHKVOID(sdr_begin_xn(sdr)); elt = sm_rbt_search(ionwm, vdb->contactIndex, rfx_order_contacts, &arg1, &nextElt); if (elt) { addr = sm_rbt_data(ionwm, elt); oK(rfx_print_contact(addr, buffer)); printText(buffer); } else { printText("Contact not found in database."); } sdr_exit_xn(sdr); return; } if (strcmp(tokens[1], "range") == 0) { memset((char *) &arg2, 0, sizeof(IonRXref)); arg2.fromNode = fromNode; arg2.toNode = toNode; arg2.fromTime = timestamp; CHKVOID(sdr_begin_xn(sdr)); elt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg2, &nextElt); if (elt) { addr = sm_rbt_data(ionwm, elt); oK(rfx_print_range(addr, buffer)); printText(buffer); } else { printText("Range not found in database."); } sdr_exit_xn(sdr); return; } SYNTAX_ERROR; }
int rfx_start() { PsmPartition ionwm = getIonwm(); Sdr sdr = getIonsdr(); IonVdb *vdb = getIonVdb(); Object iondbObj; IonDB iondb; Object elt; iondbObj = getIonDbObject(); CHKERR(sdr_begin_xn(sdr)); /* To lock memory. */ sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); /* Destroy and re-create volatile contact and range * databases. This prevents contact/range duplication * as a result of adds before starting ION. */ sm_rbt_destroy(ionwm, vdb->contactIndex, rfx_erase_data, NULL); sm_rbt_destroy(ionwm, vdb->rangeIndex, rfx_erase_data, NULL); vdb->contactIndex = sm_rbt_create(ionwm); vdb->rangeIndex = sm_rbt_create(ionwm); /* Load range index for all asserted ranges. In so * doing, load the nodes for which ranges are known * and load events for all predicted changes in range. */ for (elt = sdr_list_first(sdr, iondb.ranges); elt; elt = sdr_list_next(sdr, elt)) { if (loadRange(elt) < 0) { putErrmsg("Can't load range.", NULL); sdr_exit_xn(sdr); return -1; } } /* Load contact index for all contacts. In so doing, * load the nodes for which contacts are planned (as * necessary) and load events for all planned changes * in data rate affecting the local node. */ iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); for (elt = sdr_list_first(sdr, iondb.contacts); elt; elt = sdr_list_next(sdr, elt)) { if (loadContact(elt) < 0) { putErrmsg("Can't load contact.", NULL); sdr_exit_xn(sdr); return -1; } } /* Start the rfx clock if necessary. */ /* if (vdb->clockPid == ERROR || sm_TaskExists(vdb->clockPid) == 0) { vdb->clockPid = pseudoshell("rfxclock"); } */ sdr_exit_xn(sdr); /* Unlock memory. */ return 0; }
static void deleteContact(PsmAddress cxaddr) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); time_t currentTime = getUTCTime(); IonCXref *cxref; Object obj; IonEvent event; IonNeighbor *neighbor; PsmAddress nextElt; cxref = (IonCXref *) psp(ionwm, cxaddr); /* Delete contact events from timeline. */ event.ref = cxaddr; if (cxref->startXmit) { event.time = cxref->startXmit; event.type = IonStartXmit; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopXmit) { event.time = cxref->stopXmit; event.type = IonStopXmit; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->startFire) { event.time = cxref->startFire; event.type = IonStartFire; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopFire) { event.time = cxref->stopFire; event.type = IonStopFire; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->startRecv) { event.time = cxref->startRecv; event.type = IonStartRecv; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->stopRecv) { event.time = cxref->stopRecv; event.type = IonStopRecv; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } if (cxref->purgeTime) { event.time = cxref->purgeTime; event.type = IonPurgeContact; sm_rbt_delete(ionwm, vdb->timeline, rfx_order_events, &event, rfx_erase_data, NULL); } /* Apply to current state as necessary. */ if (currentTime >= cxref->startXmit && currentTime <= cxref->stopXmit) { neighbor = findNeighbor(vdb, cxref->toNode, &nextElt); if (neighbor) { neighbor->xmitRate = 0; } } if (currentTime >= cxref->startFire && currentTime <= cxref->stopFire) { neighbor = findNeighbor(vdb, cxref->fromNode, &nextElt); if (neighbor) { neighbor->fireRate = 0; } } if (currentTime >= cxref->startRecv && currentTime <= cxref->stopRecv) { neighbor = findNeighbor(vdb, cxref->fromNode, &nextElt); if (neighbor) { neighbor->recvRate = 0; } } /* Delete contact from index. */ if (cxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } sm_rbt_delete(ionwm, vdb->contactIndex, rfx_order_contacts, cxref, rfx_erase_data, NULL); /* Delete contact from non-volatile database. */ obj = sdr_list_data(sdr, cxref->contactElt); sdr_list_delete(sdr, cxref->contactElt, NULL, NULL); sdr_free(sdr, obj); }
PsmAddress rfx_insert_contact(time_t fromTime, time_t toTime, uvast fromNode, uvast toNode, unsigned int xmitRate, float prob) { Sdr sdr = getIonsdr(); PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonCXref arg; PsmAddress cxelt; PsmAddress nextElt; PsmAddress cxaddr; IonCXref *cxref; PsmAddress prevElt; char contactIdString[128]; IonContact contact; Object iondbObj; IonDB iondb; Object obj; Object elt; CHKZERO(fromTime); CHKZERO(toTime > fromTime); CHKZERO(fromNode); CHKZERO(toNode); CHKZERO(prob > 0.0 && prob <= 1.0); CHKZERO(sdr_begin_xn(sdr)); /* Make sure contact doesn't overlap with any pre-existing * contacts. */ memset((char *) &arg, 0, sizeof(IonCXref)); arg.fromNode = fromNode; arg.toNode = toNode; arg.fromTime = fromTime; arg.toTime = toTime; arg.xmitRate = xmitRate; arg.routingObject = 0; cxelt = sm_rbt_search(ionwm, vdb->contactIndex, rfx_order_contacts, &arg, &nextElt); //cxelt = 0; if (cxelt) /* Contact is in database already. */ { cxaddr = sm_rbt_data(ionwm, cxelt); cxref = (IonCXref *) psp(ionwm, cxaddr); if (cxref->xmitRate == xmitRate) { sdr_exit_xn(sdr); return cxaddr; } isprintf(contactIdString, sizeof contactIdString, "at %lu, %llu->%llu", fromTime, fromNode, toNode); writeMemoNote("[?] Contact data rate not revised", contactIdString); sdr_exit_xn(sdr); return 0; } else /* Check for overlap, which is not allowed. */ { if (nextElt) { prevElt = sm_rbt_prev(ionwm, nextElt); cxref = (IonCXref *) psp(ionwm, sm_rbt_data(ionwm, nextElt)); if (fromNode == cxref->fromNode && toNode == cxref->toNode && toTime > cxref->fromTime) { writeMemoNote("[?] Overlapping contact", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } else { prevElt = sm_rbt_last(ionwm, vdb->contactIndex); } if (prevElt) { cxref = (IonCXref *) psp(ionwm, sm_rbt_data(ionwm, prevElt)); if (fromNode == cxref->fromNode && toNode == cxref->toNode && fromTime < cxref->toTime) { writeMemoNote("[?] Overlapping contact", utoa(fromNode)); sdr_exit_xn(sdr); return 0; } } } /* Contact isn't already in database; okay to add. */ cxaddr = 0; contact.fromTime = fromTime; contact.toTime = toTime; contact.fromNode = fromNode; contact.toNode = toNode; contact.xmitRate = xmitRate; contact.prob = prob; obj = sdr_malloc(sdr, sizeof(IonContact)); if (obj) { sdr_write(sdr, obj, (char *) &contact, sizeof(IonContact)); iondbObj = getIonDbObject(); sdr_read(sdr, (char *) &iondb, iondbObj, sizeof(IonDB)); elt = sdr_list_insert_last(sdr, iondb.contacts, obj); if (elt) { arg.contactElt = elt; cxaddr = insertCXref(&arg); if (cxaddr == 0) { sdr_cancel_xn(sdr); } } } if (sdr_end_xn(sdr) < 0) { putErrmsg("Can't insert contact.", NULL); return 0; } return cxaddr; }
static PsmAddress insertCXref(IonCXref *cxref) { PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonNode *node; PsmAddress nextElt; PsmAddress cxaddr; Object iondbObj; IonDB iondb; PsmAddress cxelt; PsmAddress addr; IonEvent *event; time_t currentTime = getUTCTime(); /* Load the affected nodes. */ node = findNode(vdb, cxref->toNode, &nextElt); if (node == NULL) { node = addNode(vdb, cxref->toNode); if (node == NULL) { return 0; } } node = findNode(vdb, cxref->fromNode, &nextElt); if (node == NULL) { node = addNode(vdb, cxref->fromNode); if (node == NULL) { return 0; } } /* Construct the contact index entry. */ cxaddr = psm_zalloc(ionwm, sizeof(IonCXref)); if (cxaddr == 0) { return 0; } /* Compute times of relevant events. */ iondbObj = getIonDbObject(); sdr_read(getIonsdr(), (char *) &iondb, iondbObj, sizeof(IonDB)); if (cxref->fromNode == getOwnNodeNbr()) { /* Be a little slow to start transmission, and * a little quick to stop, to ensure that * segments arrive only when neighbor is * expecting them. */ cxref->startXmit = cxref->fromTime + iondb.maxClockError; cxref->stopXmit = cxref->toTime - iondb.maxClockError; } if (cxref->toNode == getOwnNodeNbr()) { /* Be a little slow to resume timers, and a * little quick to suspend them, to minimize the * chance of premature timeout. */ cxref->startFire = cxref->fromTime + iondb.maxClockError; cxref->stopFire = cxref->toTime - iondb.maxClockError; } else /* Not a transmission to the local node. */ { cxref->purgeTime = cxref->toTime; } memcpy((char *) psp(ionwm, cxaddr), (char *) cxref, sizeof(IonCXref)); cxelt = sm_rbt_insert(ionwm, vdb->contactIndex, cxaddr, rfx_order_contacts, cxref); if (cxelt == 0) { psm_free(ionwm, cxaddr); return 0; } /* Insert relevant timeline events. */ if (cxref->startXmit) { addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = cxref->startXmit; event->type = IonStartXmit; event->ref = cxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } } if (cxref->stopXmit) { addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = cxref->stopXmit; event->type = IonStopXmit; event->ref = cxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } } if (cxref->startFire) { addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = cxref->startFire; event->type = IonStartFire; event->ref = cxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } } if (cxref->stopFire) { addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = cxref->stopFire; event->type = IonStopFire; event->ref = cxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } } if (cxref->purgeTime) { addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = cxref->purgeTime; event->type = IonPurgeContact; event->ref = cxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } } if (cxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } return cxaddr; }
static PsmAddress insertRXref(IonRXref *rxref) { PsmPartition ionwm = getIonwm(); IonVdb *vdb = getIonVdb(); IonNode *node; PsmAddress nextElt; IonRXref arg; PsmAddress rxaddr; PsmAddress rxelt; PsmAddress addr; IonEvent *event; PsmAddress rxaddr2; IonRXref *rxref2; time_t currentTime = getUTCTime(); /* Load the affected nodes. */ node = findNode(vdb, rxref->toNode, &nextElt); if (node == NULL) { node = addNode(vdb, rxref->toNode); if (node == NULL) { return 0; } } node = findNode(vdb, rxref->fromNode, &nextElt); if (node == NULL) { node = addNode(vdb, rxref->fromNode); if (node == NULL) { return 0; } } /* Construct the range index entry. */ rxaddr = psm_zalloc(ionwm, sizeof(IonRXref)); if (rxaddr == 0) { return 0; } memcpy((char *) psp(ionwm, rxaddr), (char *) rxref, sizeof(IonRXref)); rxelt = sm_rbt_insert(ionwm, vdb->rangeIndex, rxaddr, rfx_order_ranges, rxref); if (rxelt == 0) { psm_free(ionwm, rxaddr); return 0; } /* Insert relevant asserted timeline events. */ addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = rxref->fromTime; event->type = IonStartAssertedRange; event->ref = rxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { return 0; } addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = rxref->toTime; event->type = IonStopAssertedRange; event->ref = rxaddr; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { return 0; } if (rxref->toTime > currentTime) /* Affects routes. */ { vdb->lastEditTime = currentTime; } if (rxref->fromNode > rxref->toNode) { /* This is a non-canonical range assertion, * indicating an override of the normal * symmetry in the owlt between nodes. The * reverse range assertion does *not* hold. */ return rxaddr; } /* This is a canonical range assertion, so we may need * to insert the imputed (symmetrical) reverse range * assertion as well. Is the reverse range already * asserted? */ arg.fromNode = rxref->toNode; arg.toNode = rxref->fromNode; arg.fromTime = rxref->fromTime; rxelt = sm_rbt_search(ionwm, vdb->rangeIndex, rfx_order_ranges, &arg, &nextElt); if (rxelt) /* Asserted range exists; we're done. */ { return rxaddr; } /* Reverse range is not asserted, so it must be imputed. * * First, load index entry for the imputed range. */ rxaddr2 = psm_zalloc(ionwm, sizeof(IonRXref)); if (rxaddr2 == 0) { return 0; } rxref2 = (IonRXref *) psp(ionwm, rxaddr2); rxref2->fromNode = rxref->toNode; /* Reversed. */ rxref2->toNode = rxref->fromNode; /* Reversed. */ rxref2->fromTime = rxref->fromTime; rxref2->toTime = rxref->toTime; rxref2->owlt = rxref->owlt; rxref2->rangeElt = 0; /* Indicates "imputed". */ memcpy((char *) psp(ionwm, rxaddr2), (char *) rxref2, sizeof(IonRXref)); rxelt = sm_rbt_insert(ionwm, vdb->rangeIndex, rxaddr2, rfx_order_ranges, rxref2); if (rxelt == 0) { psm_free(ionwm, rxaddr2); return 0; } /* Then insert relevant imputed timeline events. */ addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = rxref->fromTime; event->type = IonStartImputedRange; event->ref = rxaddr2; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } addr = psm_zalloc(ionwm, sizeof(IonEvent)); if (addr == 0) { return 0; } event = (IonEvent *) psp(ionwm, addr); event->time = rxref->toTime; event->type = IonStopImputedRange; event->ref = rxaddr2; if (sm_rbt_insert(ionwm, vdb->timeline, addr, rfx_order_events, event) == 0) { psm_free(ionwm, addr); return 0; } return rxaddr; }
IonVdb * createIonVdb(char * ionvdbName) { IonVdb *vdb = NULL; PsmAddress vdbAddress; PsmAddress elt; Sdr sdr; PsmPartition ionwm; IonDB iondb; char * name = ionvdbName; /* Attaching to volatile database. */ ionwm = getIonwm(); if (psm_locate(ionwm, name, &vdbAddress, &elt) < 0) { putErrmsg("Failed searching for vdb.", name); return NULL; } if (elt) { vdb = (IonVdb *) psp(ionwm, vdbAddress); } if (vdb != NULL) return vdb; /* ION volatile database doesn't exist yet. */ sdr = getIonsdr(); CHKNULL(sdr_begin_xn(sdr)); /* To lock memory. */ vdbAddress = psm_zalloc(ionwm, sizeof(IonVdb)); if (vdbAddress == 0) { sdr_exit_xn(sdr); putErrmsg("No space for volatile database.", name); return NULL; } vdb = (IonVdb *) psp(ionwm, vdbAddress); memset((char *) vdb, 0, sizeof(IonVdb)); if ((vdb->nodes = sm_rbt_create(ionwm)) == 0 || (vdb->neighbors = sm_rbt_create(ionwm)) == 0 || (vdb->contactIndex = sm_rbt_create(ionwm)) == 0 || (vdb->rangeIndex = sm_rbt_create(ionwm)) == 0 || (vdb->timeline = sm_rbt_create(ionwm)) == 0 || (vdb->probes = sm_list_create(ionwm)) == 0 || (vdb->requisitions[0] = sm_list_create(ionwm)) == 0 || (vdb->requisitions[1] = sm_list_create(ionwm)) == 0 || psm_catlg(ionwm, name, vdbAddress) < 0) { sdr_exit_xn(sdr); putErrmsg("Can't initialize volatile database.", name); return NULL; } vdb->clockPid = ERROR; /* None yet. */ sdr_read(sdr, (char *) &iondb, getIonDbObject(), sizeof(IonDB)); vdb->deltaFromUTC = iondb.deltaFromUTC; sdr_exit_xn(sdr); /* Unlock memory. */ //fprintf(stderr, "ionVdb created: %d\n", getOwnNodeNbr()); return vdb; }
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; }