int acsInitialize(long heapWords, int logLevel) { AcsDB acsdbBuf; unsigned long zero = 0; /* sdr_stow() wants this */ if (heapWords == 0) { /* Caller wants us to supply a default. */ heapWords = ACS_SDR_DEFAULT_HEAPWORDS; } if (ionAttach() < 0) { putErrmsg("Can't attach to ION.", NULL); return -1; } { Sdr sdr = getIonsdr(); IonDB iondb; char *pathname = iondb.parmcopy.pathName; CHKERR(sdr_begin_xn(sdr)); sdr_read(sdr, (char *) &iondb, getIonDbObject(), sizeof(IonDB)); sdr_exit_xn(sdr); #if 0 { char text[100]; sprintf( text, "ION parms pathname : %s", pathname ); writeMemo( text ); } #endif if (sdr_load_profile(acssdrName, SDR_IN_DRAM, heapWords, SM_NO_KEY, pathname, NULL) < 0) { putErrmsg("Unable to load SDR profile for ACS.", NULL); return -1; } else { writeMemo("ACS SDR profile loaded."); } } acsSdr = sdr_start_using(acssdrName); if (acsSdr == NULL) { putErrmsg("Can't start using SDR for ACS.", NULL); return -1; } if (getAcssdr() < 0) { putErrmsg("ACS can't find ACS SDR.", NULL); return -1; } CHKERR(sdr_begin_xn(acsSdr)); acsdbObject = sdr_find(acsSdr, acsDbName, NULL); switch (acsdbObject) { case -1: /* SDR error. */ sdr_cancel_xn(acsSdr); putErrmsg("Can't seek ACS database in SDR.", NULL); return -1; case 0: /* Not found must create new DB. */ memset((char *) &acsdbBuf, 0, sizeof(AcsDB)); acsdbBuf.pendingCusts = sdr_list_create(acsSdr); acsdbBuf.logLevel = logLevel; acsdbBuf.cidHash = sdr_hash_create(acsSdr, sizeof(AcsCustodyId), ACS_CIDHASH_ROWCOUNT, 1); acsdbBuf.bidHash = sdr_hash_create(acsSdr, sizeof(AcsBundleId), ACS_BIDHASH_ROWCOUNT, 1); acsdbBuf.id = sdr_stow(acsSdr, zero); acsdbObject = sdr_malloc(acsSdr, sizeof(AcsDB)); if (acsdbObject == 0) { sdr_cancel_xn(acsSdr); putErrmsg("No space for ACS database.", NULL); return -1; } sdr_write(acsSdr, acsdbObject, (char *) &acsdbBuf, sizeof(AcsDB)); sdr_catlg(acsSdr, acsDbName, 0, acsdbObject); if (sdr_end_xn(acsSdr)) { putErrmsg("Can't create ACS database.", NULL); return -1; } break; default: sdr_exit_xn(acsSdr); } acsConstants = &acsConstantsBuf; CHKERR(sdr_begin_xn(acsSdr)); sdr_read(acsSdr, (char *) acsConstants, acsdbObject, sizeof(AcsDB)); sdr_exit_xn(acsSdr); return 0; }
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; }
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; }
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; }
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; }