[Tinyos-beta-commits] CVS: tinyos-1.x/beta/SystemCore/MementoMori CommonParams.h, NONE, 1.1 ExptM.nc, NONE, 1.1 ResultPacket.h, NONE, 1.1 ResultPkt.class, NONE, 1.1 ResultPkt.java, NONE, 1.1 RollCallIncrM.nc, NONE, 1.1 Roster.nc, NONE, 1.1 failureSched.h, NONE, 1.1 genFailureRoster.pl, NONE, 1.1 genRoster.sh, NONE, 1.1 AggressiveSendM.nc, 1.1, 1.2 CompressedSet.h, 1.2, 1.3 RollCall.h, 1.1, 1.2 RollCallC.nc, 1.2, 1.3 RollCallM.nc, 1.3, 1.4

Stan Rost stanrost at users.sourceforge.net
Fri Oct 8 13:50:24 PDT 2004


Update of /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4818

Modified Files:
	AggressiveSendM.nc CompressedSet.h RollCall.h RollCallC.nc 
	RollCallM.nc 
Added Files:
	CommonParams.h ExptM.nc ResultPacket.h ResultPkt.class 
	ResultPkt.java RollCallIncrM.nc Roster.nc failureSched.h 
	genFailureRoster.pl genRoster.sh 
Log Message:
- New testing/experiment code
- AggressiveSend now features a queue
- Added subtractSets() to CompressedSet.h
- Bugfixes in RollCall


--- NEW FILE: CommonParams.h ---
#ifndef _SR_COMMON__
#define _SR_COMMON__


enum {
  // Nodes awaken every ROLLCALL_PERIOD...
  ROLLCALL_PERIOD = 30 * 1024,

  // and wait for at most his long
  MAX_ROUND_WAIT = 3096,

  // but, actually, for MAX_ROUND_WAIT - WAIT_PER_LEVEL * treeLevel...
  WAIT_PER_LEVEL = 310,

  // before sending their reports, spread out randomly
  // over this interval
  STAGGER_INTERVAL = (WAIT_PER_LEVEL / 2),

  // The buffer which stores the bitmap is at most this long
  // max nodes = (MAX_LIVE_BITMAP_BYTES - 1) * 8
  MAX_LIVE_BITMAP_BYTES = 21,

  // The length of the history (for suppressing stray packets)
  MAX_LIVE_SET_HISTORY = 1,

  MAX_SEND_RETRIES = 2,

  MAX_NODES = ((MAX_LIVE_BITMAP_BYTES - sizeof(Set)) << 3),

  RADIO_POWER = 128
};

#endif

--- NEW FILE: ExptM.nc ---
/*
  This module parses many compile-time 
  options and parameters and sets up the experiment.

  The parameters include

  BASE_STATION_ADDRESS = which node is the base station in this expt

  RADIO_POWER = transmission power

  An include file <failureSched.h> which defines this array

  uint16_t *timeOutSched[2] = {
  {nodeId, secondsToTimeout},
  ...
  {0xFFFF, 0xFFFF}
  }

  EXPT_DURATION = xxx, duration of the experiment, in seconds
  In reality, the duration is 5 minutes more which we allow to collect
  results from nodes programmed at different times

  Any node mentioned in this array makes it into the node roster

  Any node whose secondsToTimeout = 0xFFFF never fails
  
  Any other node dies (i.e. turns off the radio) 
  after exactly secondsToTimeout seconds

*/
includes CommonParams;

module ExptM {
  uses {

    interface PowerArbiter;

    interface Timer;

#if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
    interface CC1000Control as CC1KControl;
#endif
  }
  provides {
    interface StdControl;

    interface Roster;
  }

}
implementation {

#include "failureSched.h"

  uint16_t timeOutSched[][2] = {
    TIME_OUT_SCHED
  };

  // The set itself
  uint8_t liveRoster[MAX_LIVE_BITMAP_BYTES];

  command result_t StdControl.init() {
    uint16_t i;
    Set *liveRSet;

    liveRSet = initSet(liveRoster, MAX_LIVE_BITMAP_BYTES);

    for (i = 0; ; i++) {

      if (timeOutSched[i][0] == 0xFFFF) {
	
	dbg(DBG_USR1, "EX Reached the end (%d th entry)\n", i);

	break;
      }

      setBit(liveRSet, timeOutSched[i][0]);

      if (timeOutSched[i][0] == TOS_LOCAL_ADDRESS &&
	  timeOutSched[i][1] != 0xFFFF) {

	dbg(DBG_USR1, "EX My timeout is %u\n", timeOutSched[i][1]);

	call Timer.start(TIMER_ONE_SHOT,
			 timeOutSched[i][1] * 1024);
      }
	
    }

    dbg(DBG_USR1, "EX In the end, the roster of network nodes is:\n");
    printSet(liveRSet);

    // Set the radio power
#ifdef PLATFORM_MICA2
#warning "Setting RADIO POWER..."
    call CC1KControl.SetRFPower(RADIO_POWER);
#endif

    return SUCCESS;
  }

  command result_t StdControl.start() {

    call PowerArbiter.useResource(PWR_RADIO);
  
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    return SUCCESS;
  }

  command Set *Roster.getRoster() {
    return (Set *)liveRoster;
  }

  event result_t Timer.fired() {

    dbg(DBG_USR1, "EX Node DED\n\n\n");

    call PowerArbiter.releaseResource(PWR_RADIO);

    return SUCCESS;
  }
}

--- NEW FILE: ResultPacket.h ---
#ifndef _SR_RESULTP__
#define _SR_RESULTP__

// Result of the protocol

typedef struct ResultPkt {

  // This one really only counts
  // at the root
  //2
  uint16_t numFailedNodes;

  // Amount number of bytes sent
  //6
  uint32_t bytesSent;

  // Number of rounds played so far
  // 8
  uint16_t numRounds;

  // Parent at the current iteration
  // 10
  uint16_t parentAddr;

  // Number of full updates sent
  // 12
  uint16_t numFullUpd;

  // -"- discovery updates sent
  // 14
  uint16_t numDiscUpd;

  // -"- failure updates sent
  // 16
  uint16_t numFailUpd;

} ResultPkt;

#endif

--- NEW FILE: ResultPkt.class ---
Êþº¾



























SourceFile


+¶
+¶
+¶
+¶
+¶
+¶
+¶

*¸




¬



--- NEW FILE: ResultPkt.java ---
/**
 * This class is automatically generated by mig. DO NOT EDIT THIS FILE.
 * This class implements a Java interface to the 'ResultPkt'
 * message type.
 */

public class ResultPkt extends net.tinyos.message.Message {

    /** The default size of this message type in bytes. */
    public static final int DEFAULT_MESSAGE_SIZE = 16;

    /** The Active Message type associated with this message. */
    public static final int AM_TYPE = 217;

    /** Create a new ResultPkt of size 16. */
    public ResultPkt() {
        super(DEFAULT_MESSAGE_SIZE);
        amTypeSet(AM_TYPE);
    }

    /** Create a new ResultPkt of the given data_length. */
    public ResultPkt(int data_length) {
        super(data_length);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt with the given data_length
     * and base offset.
     */
    public ResultPkt(int data_length, int base_offset) {
        super(data_length, base_offset);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt using the given byte array
     * as backing store.
     */
    public ResultPkt(byte[] data) {
        super(data);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt using the given byte array
     * as backing store, with the given base offset.
     */
    public ResultPkt(byte[] data, int base_offset) {
        super(data, base_offset);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt using the given byte array
     * as backing store, with the given base offset and data length.
     */
    public ResultPkt(byte[] data, int base_offset, int data_length) {
        super(data, base_offset, data_length);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt embedded in the given message
     * at the given base offset.
     */
    public ResultPkt(net.tinyos.message.Message msg, int base_offset) {
        super(msg, base_offset, DEFAULT_MESSAGE_SIZE);
        amTypeSet(AM_TYPE);
    }

    /**
     * Create a new ResultPkt embedded in the given message
     * at the given base offset and length.
     */
    public ResultPkt(net.tinyos.message.Message msg, int base_offset, int data_length) {
        super(msg, base_offset, data_length);
        amTypeSet(AM_TYPE);
    }

    /**
    /* Return a String representation of this message. Includes the
     * message type name and the non-indexed field values.
     */
    public String toString() {
      String s = "Message <ResultPkt> \n";
      try {
        s += "  [numFailedNodes=0x"+Long.toHexString(get_numFailedNodes())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [bytesSent=0x"+Long.toHexString(get_bytesSent())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [numRounds=0x"+Long.toHexString(get_numRounds())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [parentAddr=0x"+Long.toHexString(get_parentAddr())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [numFullUpd=0x"+Long.toHexString(get_numFullUpd())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [numDiscUpd=0x"+Long.toHexString(get_numDiscUpd())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      try {
        s += "  [numFailUpd=0x"+Long.toHexString(get_numFailUpd())+"]\n";
      } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }
      return s;
    }

    // Message-type-specific access methods appear below.

    /////////////////////////////////////////////////////////
    // Accessor methods for field: numFailedNodes
    //   Field type: int, unsigned
    //   Offset (bits): 0
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'numFailedNodes' is signed (false).
     */
    public static boolean isSigned_numFailedNodes() {
        return false;
    }

    /**
     * Return whether the field 'numFailedNodes' is an array (false).
     */
    public static boolean isArray_numFailedNodes() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'numFailedNodes'
     */
    public static int offset_numFailedNodes() {
        return (0 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'numFailedNodes'
     */
    public static int offsetBits_numFailedNodes() {
        return 0;
    }

    /**
     * Return the value (as a int) of the field 'numFailedNodes'
     */
    public int get_numFailedNodes() {
        return (int)getUIntElement(offsetBits_numFailedNodes(), 16);
    }

    /**
     * Set the value of the field 'numFailedNodes'
     */
    public void set_numFailedNodes(int value) {
        setUIntElement(offsetBits_numFailedNodes(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'numFailedNodes'
     */
    public static int size_numFailedNodes() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'numFailedNodes'
     */
    public static int sizeBits_numFailedNodes() {
        return 16;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: bytesSent
    //   Field type: long, unsigned
    //   Offset (bits): 16
    //   Size (bits): 32
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'bytesSent' is signed (false).
     */
    public static boolean isSigned_bytesSent() {
        return false;
    }

    /**
     * Return whether the field 'bytesSent' is an array (false).
     */
    public static boolean isArray_bytesSent() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'bytesSent'
     */
    public static int offset_bytesSent() {
        return (16 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'bytesSent'
     */
    public static int offsetBits_bytesSent() {
        return 16;
    }

    /**
     * Return the value (as a long) of the field 'bytesSent'
     */
    public long get_bytesSent() {
        return (long)getUIntElement(offsetBits_bytesSent(), 32);
    }

    /**
     * Set the value of the field 'bytesSent'
     */
    public void set_bytesSent(long value) {
        setUIntElement(offsetBits_bytesSent(), 32, value);
    }

    /**
     * Return the size, in bytes, of the field 'bytesSent'
     */
    public static int size_bytesSent() {
        return (32 / 8);
    }

    /**
     * Return the size, in bits, of the field 'bytesSent'
     */
    public static int sizeBits_bytesSent() {
        return 32;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: numRounds
    //   Field type: int, unsigned
    //   Offset (bits): 48
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'numRounds' is signed (false).
     */
    public static boolean isSigned_numRounds() {
        return false;
    }

    /**
     * Return whether the field 'numRounds' is an array (false).
     */
    public static boolean isArray_numRounds() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'numRounds'
     */
    public static int offset_numRounds() {
        return (48 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'numRounds'
     */
    public static int offsetBits_numRounds() {
        return 48;
    }

    /**
     * Return the value (as a int) of the field 'numRounds'
     */
    public int get_numRounds() {
        return (int)getUIntElement(offsetBits_numRounds(), 16);
    }

    /**
     * Set the value of the field 'numRounds'
     */
    public void set_numRounds(int value) {
        setUIntElement(offsetBits_numRounds(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'numRounds'
     */
    public static int size_numRounds() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'numRounds'
     */
    public static int sizeBits_numRounds() {
        return 16;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: parentAddr
    //   Field type: int, unsigned
    //   Offset (bits): 64
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'parentAddr' is signed (false).
     */
    public static boolean isSigned_parentAddr() {
        return false;
    }

    /**
     * Return whether the field 'parentAddr' is an array (false).
     */
    public static boolean isArray_parentAddr() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'parentAddr'
     */
    public static int offset_parentAddr() {
        return (64 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'parentAddr'
     */
    public static int offsetBits_parentAddr() {
        return 64;
    }

    /**
     * Return the value (as a int) of the field 'parentAddr'
     */
    public int get_parentAddr() {
        return (int)getUIntElement(offsetBits_parentAddr(), 16);
    }

    /**
     * Set the value of the field 'parentAddr'
     */
    public void set_parentAddr(int value) {
        setUIntElement(offsetBits_parentAddr(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'parentAddr'
     */
    public static int size_parentAddr() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'parentAddr'
     */
    public static int sizeBits_parentAddr() {
        return 16;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: numFullUpd
    //   Field type: int, unsigned
    //   Offset (bits): 80
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'numFullUpd' is signed (false).
     */
    public static boolean isSigned_numFullUpd() {
        return false;
    }

    /**
     * Return whether the field 'numFullUpd' is an array (false).
     */
    public static boolean isArray_numFullUpd() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'numFullUpd'
     */
    public static int offset_numFullUpd() {
        return (80 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'numFullUpd'
     */
    public static int offsetBits_numFullUpd() {
        return 80;
    }

    /**
     * Return the value (as a int) of the field 'numFullUpd'
     */
    public int get_numFullUpd() {
        return (int)getUIntElement(offsetBits_numFullUpd(), 16);
    }

    /**
     * Set the value of the field 'numFullUpd'
     */
    public void set_numFullUpd(int value) {
        setUIntElement(offsetBits_numFullUpd(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'numFullUpd'
     */
    public static int size_numFullUpd() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'numFullUpd'
     */
    public static int sizeBits_numFullUpd() {
        return 16;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: numDiscUpd
    //   Field type: int, unsigned
    //   Offset (bits): 96
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'numDiscUpd' is signed (false).
     */
    public static boolean isSigned_numDiscUpd() {
        return false;
    }

    /**
     * Return whether the field 'numDiscUpd' is an array (false).
     */
    public static boolean isArray_numDiscUpd() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'numDiscUpd'
     */
    public static int offset_numDiscUpd() {
        return (96 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'numDiscUpd'
     */
    public static int offsetBits_numDiscUpd() {
        return 96;
    }

    /**
     * Return the value (as a int) of the field 'numDiscUpd'
     */
    public int get_numDiscUpd() {
        return (int)getUIntElement(offsetBits_numDiscUpd(), 16);
    }

    /**
     * Set the value of the field 'numDiscUpd'
     */
    public void set_numDiscUpd(int value) {
        setUIntElement(offsetBits_numDiscUpd(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'numDiscUpd'
     */
    public static int size_numDiscUpd() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'numDiscUpd'
     */
    public static int sizeBits_numDiscUpd() {
        return 16;
    }

    /////////////////////////////////////////////////////////
    // Accessor methods for field: numFailUpd
    //   Field type: int, unsigned
    //   Offset (bits): 112
    //   Size (bits): 16
    /////////////////////////////////////////////////////////

    /**
     * Return whether the field 'numFailUpd' is signed (false).
     */
    public static boolean isSigned_numFailUpd() {
        return false;
    }

    /**
     * Return whether the field 'numFailUpd' is an array (false).
     */
    public static boolean isArray_numFailUpd() {
        return false;
    }

    /**
     * Return the offset (in bytes) of the field 'numFailUpd'
     */
    public static int offset_numFailUpd() {
        return (112 / 8);
    }

    /**
     * Return the offset (in bits) of the field 'numFailUpd'
     */
    public static int offsetBits_numFailUpd() {
        return 112;
    }

    /**
     * Return the value (as a int) of the field 'numFailUpd'
     */
    public int get_numFailUpd() {
        return (int)getUIntElement(offsetBits_numFailUpd(), 16);
    }

    /**
     * Set the value of the field 'numFailUpd'
     */
    public void set_numFailUpd(int value) {
        setUIntElement(offsetBits_numFailUpd(), 16, value);
    }

    /**
     * Return the size, in bytes, of the field 'numFailUpd'
     */
    public static int size_numFailUpd() {
        return (16 / 8);
    }

    /**
     * Return the size, in bits, of the field 'numFailUpd'
     */
    public static int sizeBits_numFailUpd() {
        return 16;
    }

}

--- NEW FILE: RollCallIncrM.nc ---
includes CompressedSet;
includes PowerArbiter;
includes TimeSync;
includes ResultPacket;

module RollCallIncrM {
  provides {
    interface StdControl;
  }
  uses {
    interface RouteControl;

    interface SendMsg as SendReport;
    interface ReceiveMsg as ReceiveReport;

    interface AggressiveSendControl;

    interface EpochScheduler;
    interface PowerArbiter;

    interface Timer;
    interface Time;

    interface Random;

    interface HeartBeatHandler;

    interface Leds;
  }
}
implementation {

  // Nodes awaken every ROLLCALL_PERIOD...
#define ROLLCALL_PERIOD 10240
  
  // and wait for at most his long
#define MAX_ROUND_WAIT 3096

  // but, actually, for MAX_ROUND_WAIT - WAIT_PER_LEVEL * treeLevel...
#define WAIT_PER_LEVEL 205

  // before sending their reports, spread out randomly
  // over this interval
#define STAGGER_INTERVAL (WAIT_PER_LEVEL / 2)

  // The buffer which stores the bitmap is at most this long
  // max nodes = (MAX_LIVE_BITMAP_BYTES - 1) * 8
#define MAX_LIVE_BITMAP_BYTES 21

  // The length of the history (for suppressing stray packets)
#define MAX_LIVE_SET_HISTORY 1

#define MAX_SEND_RETRIES 2

#define MAX_NODES ((MAX_LIVE_BITMAP_BYTES - sizeof(Set)) << 3)

  // Forward decls ----------------------------

  // Clean up after sending your report
  void finishRound();

  enum {
    // Sending the full bitmap of live and dead nodes
    UPDATE_FULL = 0,
    // Sending the bitmap of just the newly discovered nodes
    UPDATE_DISC,
    // Sending the bitmap of just the failed nodes
    UPDATE_FAIL,
    // Sending the bitmap of just the failed nodes,
    // need a node to disprove that these nodes have failed
    UPDATE_QUERY
  };

  typedef struct {
    // Round of this communication
    uint16_t round:14;

    // Type of the roster message
    uint16_t type:2;

    // Set of nodes that we consider alive
    Set alive;
  } RosterMsg;

  uint32_t rollCallRound = 0;

  // A circular buffer of sets maintaining 
  // history
  uint8_t liveSetHistory[MAX_LIVE_SET_HISTORY][MAX_LIVE_BITMAP_BYTES];
  int8_t curLiveSet = 0;

  // Buffer for the liveness bitmap
  // To be recast into Set
  uint8_t lastLiveSet[MAX_LIVE_BITMAP_BYTES];
  bool lastLSValid = FALSE;

  void initLiveSets() {
    for (curLiveSet = 0; 
	 curLiveSet < MAX_LIVE_SET_HISTORY; 
	 curLiveSet++) {
      initSet(&liveSetHistory[curLiveSet][0], 
	      MAX_LIVE_BITMAP_BYTES);
    }

    initSet(lastLiveSet, MAX_LIVE_BITMAP_BYTES);

    curLiveSet = 0;
  }

  // Get the pointer to the current live Set
  Set *getLiveSet() {
    return (Set *)&liveSetHistory[curLiveSet][0];
  }
  
  // Fast forward the live set to the next one
  void switchLiveSet() {
    int8_t oldLiveSet = curLiveSet;

    if (++curLiveSet == MAX_LIVE_SET_HISTORY) {
      curLiveSet = 0;
    }

    // Invalidate the last live set
    lastLSValid = FALSE;

    // Carry over to the next round
    copySet((Set *)&liveSetHistory[curLiveSet][0], 
	    (Set *)&liveSetHistory[oldLiveSet][0]);
  }

  void aggregateHistory() {
    int8_t temp;
    uint8_t idx;

    // If the cached set value is invalid, need to recompute
    if (!lastLSValid) {
      initSet(lastLiveSet, MAX_LIVE_BITMAP_BYTES);
      
      for (temp = curLiveSet - MAX_LIVE_SET_HISTORY,
	     idx = curLiveSet - MAX_LIVE_SET_HISTORY; 
	   temp < curLiveSet;
	   temp++, idx++) {
	unionSets((Set *)lastLiveSet, 
		  (Set *)&liveSetHistory[idx %  MAX_LIVE_SET_HISTORY][0]);
      }

      lastLSValid = TRUE;
    }
  }

  bool liveSetChanged() {
    aggregateHistory();

    return !setsEqual((Set *)lastLiveSet,
		      (Set *)&liveSetHistory[curLiveSet][0]);
  }

  bool collectDiscoveredNodes(Set *newNodeSet) {
    aggregateHistory();

    copySet(newNodeSet, 
	    (Set *)&liveSetHistory[curLiveSet][0]);

    subtractSets((Set *)newNodeSet,
		 (Set *)lastLiveSet);

    return (newNodeSet->len == 0);
  }

  bool collectFailedNodes(Set *failedNodeSet) {
    aggregateHistory();

    copySet(failedNodeSet, 
	    (Set *)lastLiveSet);

    subtractSets((Set *)failedNodeSet,
		 (Set *)lastLiveSet);

    return (failedNodeSet->len == 0);
  }

  // Remember my old tree level so if that
  // changes, will need to adjust the epoch
  // scheduling and initial full update
  uint8_t treeLevel = 0xFF;

  TOS_Msg rollCallMsg;
  // Try to send again if busy
  uint8_t sendRetries = 0;

  command result_t StdControl.init() {

    call Leds.init();

    initLiveSets();

    return SUCCESS;
  }
  command result_t StdControl.start() {

    // Init the round timing
    call EpochScheduler.addSchedule(ROLLCALL_PERIOD,
				    MAX_ROUND_WAIT);

    // Prime the bitmap
    {
      Set *aliveBitmap = getLiveSet();

      // Note that I am alive :)
      setBit(aliveBitmap, TOS_LOCAL_ADDRESS);

      dbg(DBG_USR3, "^^ Alive bitmap is now\n");
      printSet(aliveBitmap);
    }

    call EpochScheduler.start();

    return SUCCESS;
  }
  command result_t StdControl.stop() {
    return SUCCESS;
  }

  event TOS_MsgPtr ReceiveReport.receive(TOS_MsgPtr msg) {
    RosterMsg *aMsg = (RosterMsg *)msg->data;
    uint8_t buf2[MAX_LIVE_BITMAP_BYTES];
    Set *aliveSet = getLiveSet();
    Set *newSet = initSet(buf2, MAX_LIVE_BITMAP_BYTES);

    /*
     * Uncomment to reject packets to others

     if (msg->addr == TOS_LOCAL_ADDRESS)
     return msg;

     *
     */

    // Add -1 here to allow aggregates of two rounds
    if (aMsg->round != rollCallRound) {
      // Stale

      return msg;
    }

    dbg(DBG_USR3, "^^ Node %u reports set:\n", 
	call RouteControl.getSender(msg));
    printSetBits(&aMsg->alive);

    decompressSet(&aMsg->alive, newSet);

    if (aMsg->type == UPDATE_FULL ||
	aMsg->type == UPDATE_DISC) {

      dbg(DBG_USR3, "^^ A node reports these are alive (type=%s):\n",
	  aMsg->type == UPDATE_FULL ? "FULL" : "DISC");
      printSet(newSet);

      // This node is alive
      unionSets(aliveSet, newSet);
    } else {

      dbg(DBG_USR3, "^^ A node reports these have failed:\n");
      printSet(newSet);
      printSetBits(newSet);

      // Update type is "failure"
      subtractSets(aliveSet, newSet);
    }

    dbg(DBG_USR3, "^^ After union my set is:\n");
    printSet(aliveSet);
    printSetBits(aliveSet);

    return msg;
  }

  event void EpochScheduler.beginEpoch() {
    TimeStamp ts;

    //    call PowerArbiter.useResource(PWR_RADIO);

    tos2timeStamp(call Time.get(), ts);

    rollCallRound = timeStampDiv32(ts, ROLLCALL_PERIOD);

  }


  event void EpochScheduler.epochOver() {
    uint8_t curTreeLevel = call RouteControl.getDepth();

    // Check if our attachments have changed, change our schedule
    // if so
    if (curTreeLevel != treeLevel) {
      uint32_t waitingTime = curTreeLevel * WAIT_PER_LEVEL;

      dbg(DBG_USR1, "^^^^ Tree level change: from %u to %u!!!\n", 
	  treeLevel, curTreeLevel);

      if (waitingTime > MAX_ROUND_WAIT) {
	waitingTime = MAX_ROUND_WAIT;      
      }

      dbg(DBG_USR1, "^^^^ Tree level sets wait to %u\n", waitingTime);;

      treeLevel = curTreeLevel;

      call EpochScheduler.stop();

      call EpochScheduler.addSchedule(ROLLCALL_PERIOD,
				      MAX_ROUND_WAIT - 
				      waitingTime);

      call EpochScheduler.start();
    }

    call Timer.start(TIMER_ONE_SHOT,
		     (TOS_LOCAL_ADDRESS * (uint32_t)STAGGER_INTERVAL) / 
		     (uint32_t)MAX_NODES);
  }

  event result_t Timer.fired() {
    uint16_t maxLen;
    RosterMsg *aliveMsg = 
      (RosterMsg *)rollCallMsg.data;
    Set *aliveSet = (Set *)getLiveSet();
    // Variables for compression of the bitmap
    uint8_t projLen, idxLen;

    bool isGateway = (call RouteControl.getDepth() == 0);

    dbg(DBG_USR3, "^^ Round %u over, reporting these as alive to %u\n", 
	rollCallRound,
	call RouteControl.getParent());
    printSet(aliveSet);

    if (!liveSetChanged()) {
      // Not doing anything, absolutely
      dbg(DBG_USR3, "^^ UPDATE DECISION:  Idle this round\n");

      finishRound();

    } else {
      // Determine what has changed
      uint8_t buf2[MAX_LIVE_BITMAP_BYTES];
      
      if (collectFailedNodes((Set *)buf2)) {
	// Some nodes have failed
	dbg(DBG_USR3, "^^ UPDATE DECISION:  These nodes have failed\n");
	printSet((Set *)buf2);

	// Engage in local reconciliation

      } else {

      }
      
    }

    // Submit the report
    aliveMsg->round = rollCallRound;

    // XXX: Projected length might exceed
    // the size of the packet
    if (!isGateway &&
	preprocessSet(aliveSet, &projLen, &idxLen)) {
      
      // Compress the set
      compressSet(aliveSet, &aliveMsg->alive, idxLen);
    } else {
      // Copy the set
      copySet(&aliveMsg->alive, aliveSet);
    }
    

    dbg(DBG_USR3, "neighbor message SIZE OF ALIVE SET = %u, maxLen is %u\n", 
	sizeOfSet(aliveSet),
	maxLen);

    {
      uint16_t tgtAddr = TOS_BCAST_ADDR;
      
      dbg(DBG_USR3, "^^ level %d READY TO SHIP %d bytes to parent: %u%s", 
	  call RouteControl.getDepth(),
	  sizeof(RosterMsg) - sizeof(Set) +
	  sizeOfSet(&aliveMsg->alive),
	  call RouteControl.getParent(),
	  (call RouteControl.getDepth() == 0 ? "-------\n" : "\n"));
      printSet(&aliveMsg->alive);
      
      if (!isGateway) {
	tgtAddr = call RouteControl.getParent();
      } else {
	tgtAddr = TOS_UART_ADDR;
      }

      dbg(DBG_USR3, "^^ SHIPPING!!!\n");
      fflush(stdout);
      
      if (call SendReport.send(tgtAddr,
			       sizeof(RosterMsg) - sizeof(Set) +
			       sizeOfSet(&aliveMsg->alive),
			       &rollCallMsg) == FAIL) {

	call Leds.greenToggle();

	dbg(DBG_USR3, "^^ send FAILED to SHIP!\n");
	fflush(stdout);
	
	if (sendRetries > MAX_SEND_RETRIES) {
	  sendRetries = 0;

	  finishRound();
	} else {
	  sendRetries++;

	  call Timer.start(TIMER_ONE_SHOT,
			   WAIT_PER_LEVEL >> 1);
	}
      } else {
	dbg(DBG_USR3, "^^ send SHIPPED successfully!\n");	
	fflush(stdout);
      }
      
    }

    return SUCCESS;
  }

  event result_t SendReport.sendDone(TOS_MsgPtr msg,
				     result_t status) {

    dbg(DBG_USR3, "^^ sendDone\n");    

    finishRound();

    return SUCCESS;
  }

  void finishRound() {
    Set *aliveBitmap;

    switchLiveSet();

    // Note:  this function clears the live set
    aliveBitmap = getLiveSet();

    //    call PowerArbiter.releaseResource(PWR_RADIO);

    // Note that I am alive :)
    setBit(aliveBitmap, TOS_LOCAL_ADDRESS);

    dbg(DBG_USR3, "^^ After finishround, my alive set is\n");
    printSet(aliveBitmap);
  }

  event void HeartBeatHandler.receiveHeartBeat(uint16_t srcAddr,
					       VitalStats *vStats) {
    Set *aliveBitmap = getLiveSet();

    dbg(DBG_USR1, "Overheard heartbeat from %u as alive\n\n", srcAddr);

    setBit(aliveBitmap, srcAddr);

  }


}

--- NEW FILE: Roster.nc ---
includes CompressedSet;

interface Roster {

  /**
   * Obtain the roster of nodes within the network
   *
   * @returns The set representation of live nodes
   **/
  command Set *getRoster();

}

--- NEW FILE: failureSched.h ---
#define TIME_OUT_SCHED \
{1, 0xFFFF}, \
{3, 0xFFFF}, \
{4, 0xFFFF}, \
{5, 0xFFFF}, \
{6, 0xFFFF}, \
{7, 0xFFFF}, \
{8, 0xFFFF}, \
{9, 0xFFFF}, \
{11, 0xFFFF}, \
{13, 0xFFFF}, \
{14, 0xFFFF}, \
{15, 0xFFFF}, \
{16, 0xFFFF}, \
{18, 0xFFFF}, \
{2, 0xFFFF}, \
{19, 0xFFFF}, \
{20, 0xFFFF}, \
{21, 0xFFFF}, \
{22, 0xFFFF}, \
{23, 0xFFFF}, \
{27, 0xFFFF}, \
{28, 0xFFFF}, \
{29, 0xFFFF}, \
{30, 0xFFFF}, \
{31, 0xFFFF}, \
{32, 0xFFFF}, \
{33, 0xFFFF}, \
{34, 0xFFFF}, \
{35, 0xFFFF}, \
{36, 0xFFFF}, \
{39, 0xFFFF}, \
{43, 0xFFFF}, \
{44, 0xFFFF}, \
{45, 0xFFFF}, \
{46, 0xFFFF}, \
{47, 0xFFFF}, \
{48, 0xFFFF}, \
{49, 0xFFFF}, \
{50, 0xFFFF}, \
{51, 0xFFFF}, \
{53, 0xFFFF}, \
{52, 0xFFFF}, \
{56, 0xFFFF}, \
{ 0xFFFF, 0xFFFF }

--- NEW FILE: genFailureRoster.pl ---
#!/usr/bin/perl -w

use DBI;
use strict;
use POSIX qw(ceil floor);

# database information
my $db="auth";
#my $host="mist.csail.mit.edu";
my $host="127.0.0.1";
my $port="3306";
my $userid="stanrost";
my $passwd="stanr";
my $connectionInfo="DBI:mysql:database=$db;$host:$port";
my $exptTable = $ARGV[0];

#if (scalar @ARGV != 1) {
#    print "Usage: ./genFailureRoster.pl <name of the experiment file>\n";
#    exit;
#}

open(OUTF, ">failureSched.h");

print OUTF "#define TIME_OUT_SCHED \\\n";

# make connection to database
my $dbh = DBI->connect($connectionInfo,$userid,$passwd);

my $query = "select moteid from motes where active != 0 and platform != 'cricket'";

my $sth = $dbh->prepare($query);

$sth->execute();

my @res;

while (@res = $sth->fetchrow()) {
    print OUTF "{$res[0], 0xFFFF}, \\\n";
}

# disconnect from database
$dbh->disconnect;

print OUTF "{ 0xFFFF, 0xFFFF }\n";

close(OUTF);

--- NEW FILE: genRoster.sh ---
#!/bin/bash

mysql -B -N -h 127.0.0.1 -P 3306 -u stanrost -pstanr -e "select moteid from auth.motes where active !=0 and platform != 'cricket'" | awk 'BEGIN { print "#define TIME_OUT_SCHED \\" } { print "{" $0 ", 0xFFFF} \\"} END {print "{ 0xFFFF, 0xFFFF }"}' > failureSched.h 

Index: AggressiveSendM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori/AggressiveSendM.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** AggressiveSendM.nc	20 Sep 2004 16:44:36 -0000	1.1
--- AggressiveSendM.nc	8 Oct 2004 20:50:19 -0000	1.2
***************
*** 6,9 ****
--- 6,11 ----
    }
    uses {
+     interface Leds;
+ 
      interface SendMsg as SendExt[uint8_t id];
    }
***************
*** 11,21 ****
--- 13,110 ----
  implementation {
  
+  // This data structure is imposed onto TOS_Msg
+   // following the portion of it that actually
+   // gets transmitted.
+ 
+   // This saves precious resources, as these fields
+   // such as the CRC, and signal strength are not even
+   // used until the packet enters the
+   typedef struct {    
+     TOS_Msg *next;
+ 
+     uint8_t retriesLeft;
+     
+   } MsgStub;
+   
+   // Recast the portion of TOS_Msg not used
+   // prior to sending the packet into a useful data structure
+   MsgStub *getStub(TOS_MsgPtr msg) {
+     return (MsgStub *)(((uint8_t *)msg) + MSG_DATA_SIZE);
+   }
+ 
+   // Heads of the queue
+   // The queues store freshest items eraliest to be
+   // removed first (i.e. headFifoQ points to the next
+   // item to be dequeued)
+   
+   // Head of the FIFO queue fo packets
+   TOS_MsgPtr headFifoQ = NULL;
+ 
+ 
  #define AGGRESSIVE_INIT_RETRIES 3
  
    uint8_t maxRetries = AGGRESSIVE_INIT_RETRIES;
  
+   // Data essage being set, currently
    uint8_t retriesLeft = 0;
    TOS_MsgPtr _msg = NULL;
  
+   void printPacket(TOS_MsgPtr msg) {
+     MsgStub *stub = getStub(msg);
+     
+     // Pointer:AM type:ptr to next:timeout
+     dbg_clear(DBG_USR2, "[%p:%d:%u:%p]",
+ 	      msg, msg->type, stub->retriesLeft, stub->next);
+   }
+  
+  void printQueue() {
+    TOS_MsgPtr head = headFifoQ;
+ 
+    dbg(DBG_USR2, "SendQ: head is %p (of type %u)",
+        _msg,
+        (_msg == NULL ? 0 : _msg->type)
+        );  
+  
+    if (head == NULL) {
+      dbg_clear(DBG_USR2, "[EMPTY]\n");
+    } else {
+      TOS_MsgPtr cur = head;
+      
+      while (cur != NULL) {
+        printPacket(cur);
+        
+        cur = getStub(cur)->next;
+      }
+    }
+    dbg_clear(DBG_USR2, "\n");
+  }
+ 
+   task void doSend() {
+ 
+     dbg(DBG_USR1, "doSend()\n");
+     printQueue();
+ 
+     // If we are currently not sending any message,
+     // popo another one from the queue
+     if (_msg == NULL) {
+       if (headFifoQ == NULL)
+ 	return;
+       else {
+ 	MsgStub *stub = getStub(headFifoQ);
+ 
+ 	_msg = headFifoQ;
+ 	retriesLeft = stub->retriesLeft;
+ 
+ 	headFifoQ = stub->next;
+       }
+     }
+ 
+     // Msg is all set
+     call SendExt.send[_msg->type](_msg->addr,
+ 				  _msg->length,
+ 				  _msg);
+ 
+   }
+ 
    command void AggressiveSendControl.setRetries(uint8_t numRetries) {
      maxRetries = numRetries;
***************
*** 25,47 ****
  					    uint8_t length,
  					    TOS_MsgPtr msg) {
!     if (_msg != NULL)
        return FAIL;
-     else {
-       result_t res;
  
!       dbg(DBG_USR1, "^^^ SHIPPING 2!!!\n");
  
!       if ((res = call SendExt.send[id](addr, length, msg)) == SUCCESS) {
  
! 	retriesLeft = maxRetries;
! 	_msg = msg;
! 	_msg->ack = 0;
  
!       } 
  
!       dbg(DBG_USR1, "^^^ SHIPPED 2!!!\n");
  
!       return res;
      }
    }
  
--- 114,165 ----
  					    uint8_t length,
  					    TOS_MsgPtr msg) {
!     MsgStub *stub;
! 
!     // Assure uniqueness in the queue
!     TOS_MsgPtr cur = headFifoQ;
! 
!     if (msg == _msg)
        return FAIL;
  
!     while (cur != NULL &&
! 	   (stub = getStub(cur))) {
!       if (cur == msg)
! 	return FAIL;
  
!       cur = stub->next;
!     }
  
!     call Leds.yellowToggle();
  
!     stub = getStub(msg);
  
!     // Enqueue
!     msg->addr = addr;
!     msg->length = length;
!     msg->type = id;
  
!     msg->ack = 0;
! 
!     stub->next = NULL;
!     stub->retriesLeft = maxRetries;
! 
!     // Enqueue to tail
!     if (headFifoQ == NULL)
!       headFifoQ = msg;
!     else {
!       cur = headFifoQ;
!       
!       while (cur != NULL &&
! 	     (stub = getStub(cur)) &&
! 	     (stub->next != NULL)) {
! 	cur = stub->next;
!       }
! 
!       stub->next = msg;
      }
+ 
+     post doSend();
+ 
+     return SUCCESS;
    }
  
***************
*** 49,53 ****
  
      _msg = NULL;
!     retriesLeft = 0;
  
      return signal SendMsg.sendDone[id](msg, success);
--- 167,172 ----
  
      _msg = NULL;
! 
!     post doSend();
  
      return signal SendMsg.sendDone[id](msg, success);
***************
*** 74,103 ****
  					      result_t success) {
  
!     if (msg != _msg)
        return signal SendMsg.sendDone[id](msg, success);
!     else if (msg->addr == TOS_BCAST_ADDR ||
! 	     msg->addr == TOS_UART_ADDR) {
!       dbg(DBG_USR1, "*** RETRIES RESET: BROADCAST\n");
  
        return finish(id, msg, success);
  
!     } else if (!msg->ack) {
        if (retriesLeft == 0) {
  
! 	dbg(DBG_USR1, "*** FAILED AFTER %d RETRIES\n", maxRetries);
  	
! 	return finish(id, msg, FAIL);
  	
        } else {
  	--retriesLeft;
  
! 	//	dbg(DBG_USR1, "*** RETRIES LEFT: %d\n", retriesLeft);
! 
! 	// Cannot return FAIL here
! 	if (call SendExt.send[id](msg->addr,
! 				  msg->length,
! 				  msg) == FAIL) {
! 	  dbg(DBG_USR1, "*** RETRIES RESEND FAILED!!!\n");
! 	}
  
  	return SUCCESS;
--- 193,225 ----
  					      result_t success) {
  
!     if (msg != _msg) {
!       // Another process finished, we should now try
!       post doSend();
! 
!       call Leds.greenToggle();
!       
!       dbg(DBG_USR1, "*** ANOTHER: type %d\n", id);
! 
        return signal SendMsg.sendDone[id](msg, success);
!     } else if (msg->addr == TOS_UART_ADDR) {
!       dbg(DBG_USR1, "*** RETRIES RESET: UART\n");
  
        return finish(id, msg, success);
  
!     } else if (msg->addr == TOS_BCAST_ADDR ||
! 	       !msg->ack) {
!       
!       call Leds.redToggle();
! 
        if (retriesLeft == 0) {
  
! 	dbg(DBG_USR1, "*** FAILED/BROADCAST AFTER %d RETRIES\n", maxRetries);
  	
! 	return finish(id, msg, msg->addr == TOS_BCAST_ADDR ? SUCCESS : FAIL);
  	
        } else {
  	--retriesLeft;
  
! 	post doSend();
  
  	return SUCCESS;

Index: CompressedSet.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori/CompressedSet.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** CompressedSet.h	4 Oct 2004 23:24:44 -0000	1.2
--- CompressedSet.h	8 Oct 2004 20:50:19 -0000	1.3
***************
*** 149,153 ****
  void subtractSet(Set *s1,
  		 Set *s2) {
!   uint8_t i, minLen;
  
    if (s1 == NULL ||
--- 149,153 ----
  void subtractSet(Set *s1,
  		 Set *s2) {
!   uint8_t i, maxLen;
  
    if (s1 == NULL ||
***************
*** 155,162 ****
      return;
  
!   minLen = (s1->len < s2->len ? 
! 	    s1->len : s2->len);
  
!   for (i = 0; i < minLen; i++) {
      if ((s1->data[i] &= ~(s2->data[i])) != 0)
        s1->len = i+1;
--- 155,162 ----
      return;
  
!   maxLen = s1->len;
!   s1->len = 0;
  
!   for (i = 0; i < maxLen; i++) {
      if ((s1->data[i] &= ~(s2->data[i])) != 0)
        s1->len = i+1;
***************
*** 221,224 ****
--- 221,225 ----
  
    for (i = 0; i < s->len; i++) {
+ 
      res += countBits(s->data[i]);
    }
***************
*** 387,390 ****
--- 388,403 ----
  }
  
+ void clearBit(Set *s, uint16_t loc) {
+   markBitArray(s->data, loc, FALSE);
+ 
+   while (loc > 0 &&
+ 	 testBitArray(s->data, loc) == FALSE) loc--;
+ 
+   // Scan left until hit a set bit
+   if (s->len > (loc / 8 + 1)) {
+     s->len = loc / 8 + 1;
+   }
+ }
+ 
  bool testBit(Set *s, uint16_t loc) {
  

Index: RollCall.h
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori/RollCall.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** RollCall.h	27 Aug 2004 22:48:50 -0000	1.1
--- RollCall.h	8 Oct 2004 20:50:19 -0000	1.2
***************
*** 5,9 ****
  enum {
    ROLLCALL_AM = 215,
!   ROLLCALL_ACT_AM = 216
  };
  
--- 5,11 ----
  enum {
    ROLLCALL_AM = 215,
!   
!   // Reporting the total statistics
!   ROLLCALL_STATS_REP_AM = 217
  };
  

Index: RollCallC.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori/RollCallC.nc,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** RollCallC.nc	20 Sep 2004 16:44:37 -0000	1.2
--- RollCallC.nc	8 Oct 2004 20:50:19 -0000	1.3
***************
*** 15,20 ****
      TimerC, GenericCommPromiscuous as Comm,
      RollCallM, UsefulTimeC, RandomLFSR,
!     AggressiveSendM;
!   
  
    StdControl = Comm;
--- 15,25 ----
      TimerC, GenericCommPromiscuous as Comm,
      RollCallM, UsefulTimeC, RandomLFSR,
!     AggressiveSendM, LedsC, NoLeds,
! 
! #if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
!     CC1000ControlM,
! #endif
! 
!     ExptM;
  
    StdControl = Comm;
***************
*** 23,26 ****
--- 28,36 ----
    StdControl = RollCallM;
  
+   StdControl = ExptM;
+ #if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
+   StdControl = CC1000ControlM;
+ #endif
+ 
    HeartBeatHandler = RollCallM.HeartBeatHandler;
  
***************
*** 29,46 ****
    RollCallM.RouteControl = RouteControl;
  
-   /*
-     Non-aggressive reliability
-   
-   RollCallM.SendReport -> Comm.SendMsg[ROLLCALL_AM];
-   */
- 
    RollCallM.ReceiveReport -> Comm.ReceiveMsg[ROLLCALL_AM];
  
    RollCallM.SendReport -> AggressiveSendM.SendMsg[ROLLCALL_AM];
!   AggressiveSendM.SendExt[ROLLCALL_AM] -> Comm.SendMsg[ROLLCALL_AM];
  
!   //  RollCallM.SendReport = Send[ROLLCALL_AM];
  
!   RollCallM.AggressiveSendControl -> AggressiveSendM;
  
    RollCallM.EpochScheduler -> 
--- 39,55 ----
    RollCallM.RouteControl = RouteControl;
  
    RollCallM.ReceiveReport -> Comm.ReceiveMsg[ROLLCALL_AM];
  
+   RollCallM.AggressiveSendControl -> AggressiveSendM;
    RollCallM.SendReport -> AggressiveSendM.SendMsg[ROLLCALL_AM];
!   RollCallM.SendStats -> AggressiveSendM.SendMsg[ROLLCALL_STATS_REP_AM];
!   AggressiveSendM.SendExt -> Comm.SendMsg;
  
!   AggressiveSendM.Leds -> LedsC;
  
!   /*
!   RollCallM.SendReport -> Comm.SendMsg[ROLLCALL_AM];
!   RollCallM.SendStats -> Comm.SendMsg[ROLLCALL_STATS_REP_AM];
!   */
  
    RollCallM.EpochScheduler -> 
***************
*** 52,54 ****
--- 61,75 ----
  
    RollCallM.Timer -> TimerC.Timer[unique("Timer")];
+ 
+   RollCallM.Leds -> NoLeds;
+ 
+   RollCallM.Roster -> ExptM.Roster;
+ 
+   ExptM.PowerArbiter ->
+     PowerArbiterC.PowerArbiter[unique("PowerArbiter")];
+   ExptM.Timer -> TimerC.Timer[unique("Timer")];
+ 
+ #if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
+   ExptM.CC1KControl -> CC1000ControlM;
+ #endif
  }

Index: RollCallM.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-1.x/beta/SystemCore/MementoMori/RollCallM.nc,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** RollCallM.nc	4 Oct 2004 23:24:44 -0000	1.3
--- RollCallM.nc	8 Oct 2004 20:50:19 -0000	1.4
***************
*** 2,5 ****
--- 2,8 ----
  includes PowerArbiter;
  includes TimeSync;
+ includes ResultPacket;
+ 
+ includes CommonParams;
  
  module RollCallM {
***************
*** 24,50 ****
  
      interface HeartBeatHandler;
-   }
- }
- implementation {
- 
-   // Nodes awaken every ROLLCALL_PERIOD...
- #define ROLLCALL_PERIOD 10240
-   
-   // and wait for at most his long
- #define MAX_ROUND_WAIT 2048
  
!   // but, actually, for MAX_ROUND_WAIT - WAIT_PER_LEVEL * treeLevel...
! #define WAIT_PER_LEVEL 205
! 
!   // before sending their reports, spread out randomly
!   // over this interval
! #define STAGGER_INTERVAL (WAIT_PER_LEVEL / 2)
  
!   // The buffer which stores the bitmap is at most this long
!   // max nodes = (MAX_LIVE_BITMAP_BYTES - 1) * 8
! #define MAX_LIVE_BITMAP_BYTES 20
  
!   // The length of the history (for suppressing stray packets)
! #define MAX_LIVE_SET_HISTORY 1
  
    // Forward decls ----------------------------
--- 27,40 ----
  
      interface HeartBeatHandler;
  
!     interface Leds;
  
!     // For sending the stats to the UART
!     interface SendMsg as SendStats;
  
!     interface Roster;
!   }
! }
! implementation {
  
    // Forward decls ----------------------------
***************
*** 52,55 ****
--- 42,46 ----
    // Clean up after sending your report
    void finishRound();
+   void sendReport();
  
    typedef struct {
***************
*** 66,69 ****
--- 57,61 ----
    // To be recast into Set
    uint8_t lastLiveSet[MAX_LIVE_BITMAP_BYTES];
+   bool lastLSValid = FALSE;
  
    uint8_t liveSetHistory[MAX_LIVE_SET_HISTORY][MAX_LIVE_BITMAP_BYTES];
***************
*** 74,78 ****
  	 curLiveSet < MAX_LIVE_SET_HISTORY; 
  	 curLiveSet++) {
!       initSet(liveSetHistory[curLiveSet], 
  	      MAX_LIVE_BITMAP_BYTES);
      }
--- 66,70 ----
  	 curLiveSet < MAX_LIVE_SET_HISTORY; 
  	 curLiveSet++) {
!       initSet(&liveSetHistory[curLiveSet][0], 
  	      MAX_LIVE_BITMAP_BYTES);
      }
***************
*** 93,96 ****
--- 85,92 ----
        curLiveSet = 0;
      }
+ 
+     // Invalidate the last live set
+     lastLSValid = FALSE;
+ 
      initSet(&liveSetHistory[curLiveSet][0], 
  	    MAX_LIVE_BITMAP_BYTES);
***************
*** 101,146 ****
      uint8_t idx;
  
!     initSet(lastLiveSet, MAX_LIVE_BITMAP_BYTES);
  
!     for (temp = curLiveSet - MAX_LIVE_SET_HISTORY,
! 	   idx = curLiveSet - MAX_LIVE_SET_HISTORY; 
! 	 temp < curLiveSet;
! 	 temp++, idx++) {
!       unionSets((Set *)lastLiveSet, 
! 		(Set *)&liveSetHistory[idx %  MAX_LIVE_SET_HISTORY][0]);
      }
    }
  
-   bool liveSetChanged() {
-     aggregateHistory();
- 
-     return !setsEqual((Set *)lastLiveSet,
- 		      (Set *)&liveSetHistory[curLiveSet][0]);
-   }
- 
-   bool collectDiscoveredNodes(Set *newNodeSet) {
-     aggregateHistory();
- 
-     copySet(newNodeSet, 
- 	    (Set *)&liveSetHistory[curLiveSet][0]);
- 
-     subtractSets((Set *)newNodeSet,
- 		 (Set *)lastLiveSet);
- 
-     return (newNodeSet->len == 0);
-   }
- 
-   bool collectFailedNodes(Set *failedNodeSet) {
-     aggregateHistory();
- 
-     copySet(failedNodeSet, 
- 	    (Set *)lastLiveSet);
- 
-     subtractSets((Set *)failedNodeSet,
- 		 (Set *)lastLiveSet);
- 
-     return (failedNodeSet->len == 0);
-   }
- 
    // Remember my old tree level so if that
    // changes, will need to adjust the epoch
--- 97,116 ----
      uint8_t idx;
  
!     // If the cached set value is invalid, need to recompute
!     if (!lastLSValid) {
!       initSet(lastLiveSet, MAX_LIVE_BITMAP_BYTES);
!       
!       for (temp = curLiveSet - MAX_LIVE_SET_HISTORY,
! 	     idx = curLiveSet - MAX_LIVE_SET_HISTORY; 
! 	   temp < curLiveSet;
! 	   temp++, idx++) {
! 	unionSets((Set *)lastLiveSet, 
! 		  (Set *)&liveSetHistory[idx %  MAX_LIVE_SET_HISTORY][0]);
!       }
  
!       lastLSValid = TRUE;
      }
    }
  
    // Remember my old tree level so if that
    // changes, will need to adjust the epoch
***************
*** 149,156 ****
--- 119,139 ----
  
    TOS_Msg rollCallMsg;
+   // Try to send again if busy
+   uint8_t sendRetries = 0;
+ 
+   TOS_Msg statsMsg;
+   ResultPkt *statsPkt = NULL;
  
    command result_t StdControl.init() {
  
+     call Leds.init();
+ 
      initLiveSets();
+     
+     {
+       statsPkt = (ResultPkt *)statsMsg.data;
+ 
+       memset(statsPkt, 0, sizeof(ResultPkt));
+     }
  
      return SUCCESS;
***************
*** 187,191 ****
      Set *newSet = initSet(buf2, MAX_LIVE_BITMAP_BYTES);
  
!     if (aMsg->round < rollCallRound - 1) {
        // Stale
  
--- 170,184 ----
      Set *newSet = initSet(buf2, MAX_LIVE_BITMAP_BYTES);
  
!     /*
!      * Uncomment to reject packets to others
! 
!      if (msg->addr == TOS_LOCAL_ADDRESS)
!      return msg;
! 
!      *
!      */
! 
!     // Add -1 here to allow aggregates of two rounds
!     if (aMsg->round != rollCallRound) {
        // Stale
  
***************
*** 193,197 ****
      }
  
!     dbg(DBG_USR3, "^^ Node %u reports set:\n", 
  	call RouteControl.getSender(msg));
      printSetBits(&aMsg->alive);
--- 186,190 ----
      }
  
!     dbg(DBG_USR3, "^^ Node reports set:\n", 
  	call RouteControl.getSender(msg));
      printSetBits(&aMsg->alive);
***************
*** 215,218 ****
--- 208,213 ----
      TimeStamp ts;
  
+     call Leds.yellowOn();
+ 
      //    call PowerArbiter.useResource(PWR_RADIO);
  
***************
*** 227,230 ****
--- 222,227 ----
      uint8_t curTreeLevel = call RouteControl.getDepth();
  
+     call Leds.yellowOff();
+ 
      // Check if our attachments have changed, change our schedule
      // if so
***************
*** 254,291 ****
  
      call Timer.start(TIMER_ONE_SHOT,
! 		     (call Random.rand() * (uint32_t)STAGGER_INTERVAL) >> 16);
    }
  
    event result_t Timer.fired() {
!     uint16_t maxLen;
      RosterMsg *aliveMsg = 
        (RosterMsg *)rollCallMsg.data;
!     Set *aliveSet = (Set *)getLiveSet();
!     // Variables for compression of the bitmap
      uint8_t projLen, idxLen;
  
!     dbg(DBG_USR3, "^^ Round %u over, reporting these as alive\n", 
! 	rollCallRound);
      printSet(aliveSet);
! 
      // Submit the report
      aliveMsg->round = rollCallRound;
! 
      // XXX: Projected length might exceed
      // the size of the packet
!     if (preprocessSet(aliveSet, &projLen, &idxLen)) {
!       
!       // Compress the set
!       compressSet(aliveSet, &aliveMsg->alive, idxLen);
      } else {
!       // Copy the set
!       copySet(&aliveMsg->alive, aliveSet);
!     }
!     
  
!     dbg(DBG_USR3, "neighbor message SIZE OF ALIVE SET = %u, maxLen is %u\n", 
! 	sizeOfSet(aliveSet),
! 	maxLen);
  
      {
        uint16_t tgtAddr = TOS_BCAST_ADDR;
--- 251,304 ----
  
      call Timer.start(TIMER_ONE_SHOT,
! 		     (TOS_LOCAL_ADDRESS * (uint32_t)STAGGER_INTERVAL) / 
! 		     (uint32_t)MAX_NODES);
    }
  
    event result_t Timer.fired() {
!     Set *aliveSet = (Set *)getLiveSet();
!     bool isGateway = (call RouteControl.getDepth() == 0) &&
!       (call RouteControl.getParent() != TOS_BCAST_ADDR);
      RosterMsg *aliveMsg = 
        (RosterMsg *)rollCallMsg.data;
!     
!     // Variables for the compression of the bitmap
      uint8_t projLen, idxLen;
  
!     dbg(DBG_USR3, "^^ Round %u over, reporting these as alive to %u\n", 
! 	rollCallRound,
! 	call RouteControl.getParent());
      printSet(aliveSet);
!       
      // Submit the report
      aliveMsg->round = rollCallRound;
!     
      // XXX: Projected length might exceed
      // the size of the packet
!     if (!isGateway) {
! 
!       if (preprocessSet(aliveSet, &projLen, &idxLen)) {
! 	
! 	// Compress the set
! 	compressSet(aliveSet, &aliveMsg->alive, idxLen);
!       } else {
! 	// Copy the set
! 	copySet(&aliveMsg->alive, aliveSet);
!       }
      } else {
!       // Report just the dead nodes
!       copySet(&aliveMsg->alive, call Roster.getRoster());
  
!       subtractSet(&aliveMsg->alive, aliveSet);
! 
!       dbg(DBG_USR3, "~~ Gateway node reports these have died\n");
!       printSet(&aliveMsg->alive);
! 
!       statsPkt->numFailedNodes = setLength(&aliveMsg->alive);
!     }
  
+     
+     dbg(DBG_USR3, "neighbor message SIZE OF ALIVE SET = %u\n", 
+ 	sizeOfSet(aliveSet));
+     
      {
        uint16_t tgtAddr = TOS_BCAST_ADDR;
***************
*** 299,328 ****
        printSet(&aliveMsg->alive);
        
!       if (call RouteControl.getDepth() > 0) {
! 	tgtAddr = call RouteControl.getParent();
!       } else {
  	tgtAddr = TOS_UART_ADDR;
!       }
! 
        dbg(DBG_USR3, "^^ SHIPPING!!!\n");
-       fflush(stdout);
  
-       
        if (call SendReport.send(tgtAddr,
  			       sizeof(RosterMsg) - sizeof(Set) +
  			       sizeOfSet(&aliveMsg->alive),
  			       &rollCallMsg) == FAIL) {
! 	
  	dbg(DBG_USR3, "^^ send FAILED to SHIP!\n");
- 	fflush(stdout);
  	
! 	finishRound();
        } else {
  	dbg(DBG_USR3, "^^ send SHIPPED successfully!\n");	
- 	fflush(stdout);
        }
        
      }
! 
      return SUCCESS;
    }
--- 312,346 ----
        printSet(&aliveMsg->alive);
        
!       if (isGateway)
  	tgtAddr = TOS_UART_ADDR;
!       else
! 	tgtAddr = call RouteControl.getParent();
!       
        dbg(DBG_USR3, "^^ SHIPPING!!!\n");
  
        if (call SendReport.send(tgtAddr,
  			       sizeof(RosterMsg) - sizeof(Set) +
  			       sizeOfSet(&aliveMsg->alive),
  			       &rollCallMsg) == FAIL) {
! 	call Leds.redToggle();
! 		
  	dbg(DBG_USR3, "^^ send FAILED to SHIP!\n");
  	
! 	if (sendRetries > MAX_SEND_RETRIES) {
! 	  sendRetries = 0;
! 	  
! 	  finishRound();
! 	} else {
! 	  sendRetries++;
! 	  
! 	  call Timer.start(TIMER_ONE_SHOT,
! 			   WAIT_PER_LEVEL);
! 	}
        } else {
  	dbg(DBG_USR3, "^^ send SHIPPED successfully!\n");	
        }
        
      }
!     
      return SUCCESS;
    }
***************
*** 333,336 ****
--- 351,363 ----
      dbg(DBG_USR3, "^^ sendDone\n");    
  
+     if (status == SUCCESS) { 
+       statsPkt->bytesSent = 5 + msg->length;
+       
+       statsPkt->numFullUpd = 1;
+  
+       call Leds.greenToggle();
+     } else
+       call Leds.redToggle();
+ 
      finishRound();
  
***************
*** 341,344 ****
--- 368,373 ----
      Set *aliveBitmap;
  
+     sendReport();
+ 
      switchLiveSet();
  
***************
*** 353,356 ****
--- 382,386 ----
      dbg(DBG_USR3, "^^ After finishround, my alive set is\n");
      printSet(aliveBitmap);
+ 
    }
  
***************
*** 365,367 ****
--- 395,426 ----
  
  
+   void sendReport() {
+     // Form and send a report
+     
+     // bytesSent, numFailedNodes and numFillUpd are already set
+     
+     statsPkt->numRounds = rollCallRound;
+ 
+     statsPkt->parentAddr = call RouteControl.getParent();
+ 
+     dbg(DBG_USR1, 
+ 	"REPORT #failed: %u bytes: %u rounds: %u parent: %u fullUpd: %u\n",
+ 	statsPkt->numFailedNodes,
+ 	statsPkt->bytesSent,
+ 	statsPkt->numRounds,
+ 	statsPkt->parentAddr,
+ 	statsPkt->numFullUpd);
+ 
+     call SendStats.send(TOS_UART_ADDR,
+ 			sizeof(ResultPkt),
+ 			&statsMsg);
+   }
+ 
+   event result_t SendStats.sendDone(TOS_MsgPtr msg,
+ 				    result_t status) {
+ 
+     return SUCCESS;
+   }
+ 
+ 
  }



More information about the Tinyos-beta-commits mailing list