Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
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;
}
Пример #6
0
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;
}