--- /dev/null
+/**
+ * DHV Logic Implementation.
+ *
+ * Define the interfaces and components.
+ *
+ * @author Thanh Dang
+ * @author Seungweon Park
+ *
+ * @modified 1/3/2009 Added meaningful documentation.
+ * @modified 8/28/2008 Defined DHV interfaces type.
+ * @modified 8/28/2008 Took the source code from DIP.
+ **/
+
+#include <Dhv.h>
+
+module DhvLogicP {
+ provides interface DisseminationUpdate<dhv_data_t>[dhv_key_t key];
+
+ provides interface Init;
+ provides interface StdControl;
+ provides interface DhvLogic as VectorLogic;
+ provides interface DhvLogic as DataLogic;
+ provides interface DhvStateLogic;
+
+ uses interface Boot;
+ uses interface DhvTrickleTimer;
+ uses interface DisseminationUpdate<dhv_data_t> as VersionUpdate[dhv_key_t key];
+
+ uses interface DhvDecision as DhvDataDecision;
+ uses interface DhvDecision as DhvVectorDecision;
+ uses interface DhvDecision as DhvSummaryDecision;
+ uses interface DhvDecision as DhvVBitDecision;
+ uses interface DhvDecision as DhvHSumDecision;
+
+ uses interface DhvCache as DhvDataCache;
+ uses interface DhvCache as DhvVectorCache;
+ uses interface DhvHelp;
+
+}
+
+implementation {
+ uint32_t windowSize;
+ uint8_t sendDecision();
+ uint8_t getState();
+ uint32_t bitIndex;
+ uint8_t hsum_status;
+ uint32_t diffHash;
+
+ command error_t Init.init() {
+ windowSize = DHV_TAU_LOW;
+ dbg("DhvLogicP","DHV ready\n");
+ return SUCCESS;
+ }
+
+ event void Boot.booted() {
+ hsum_status = 0;
+ bitIndex = 0;
+ }
+
+ command error_t StdControl.start() {
+ return call DhvTrickleTimer.start();
+ }
+
+ command error_t StdControl.stop() {
+ call DhvTrickleTimer.stop();
+ return SUCCESS;
+ }
+
+
+ /*Logic operation on the vector */
+ command error_t VectorLogic.setItem(dhv_key_t key){
+ call DhvVectorCache.addItem(key);
+ call DhvTrickleTimer.reset();
+ return SUCCESS;
+ }
+
+ command error_t VectorLogic.setReqItem(dhv_key_t key){
+ call DhvVectorCache.addReqItem(key);
+ call DhvTrickleTimer.reset();
+ return SUCCESS;
+ }
+
+ command error_t VectorLogic.unsetItem(dhv_key_t key){
+ call DhvVectorCache.removeItem(key);
+ call DhvStateLogic.setVBitState(0);
+ return SUCCESS;
+ }
+
+ command uint8_t * VectorLogic.allItem(){
+ return call DhvVectorCache.allItem();
+ }
+
+ command uint8_t VectorLogic.nextItem(){
+ return call DhvVectorCache.nextItem();
+ }
+
+ /*logic operations on the data*/
+ command error_t DataLogic.setItem(dhv_key_t key){
+ call DhvDataCache.addItem( key);
+ call DhvTrickleTimer.reset();
+ return SUCCESS;
+ }
+
+ command error_t DataLogic.setReqItem(dhv_key_t key){
+ call DhvDataCache.addReqItem( key);
+ call DhvTrickleTimer.reset();
+ return SUCCESS;
+ }
+
+ command error_t DataLogic.unsetItem(dhv_key_t key){
+ call DhvDataCache.removeItem(key);
+ call DhvStateLogic.setVBitState(0);
+ return SUCCESS;
+ }
+
+ command uint8_t* DataLogic.allItem(){
+ return call DhvDataCache.allItem();
+ }
+
+ command uint8_t DataLogic.nextItem(){
+ return call DhvDataCache.nextItem();
+ }
+
+ /*logic operation for the summary and vbit*/
+ command void DhvStateLogic.setHSumStatus(){
+ hsum_status = 1;
+ call DhvTrickleTimer.reset();
+ }
+
+ command void DhvStateLogic.unsetHSumStatus(){
+ hsum_status = 0;
+ }
+
+ command uint8_t DhvStateLogic.getHSumStatus(){
+ return hsum_status;
+ }
+
+ command void DhvStateLogic.setDiffSummary(){
+ if(bitIndex == 0){
+ bitIndex=1;
+ }
+
+ call DhvTrickleTimer.reset();
+ }
+
+ command void DhvStateLogic.setSameSummary(){
+ bitIndex = 0;
+ hsum_status = 0;
+ //reset all the vector and data status to avoid flooding
+ call DhvDataCache.removeAll();
+ call DhvVectorCache.removeAll();
+
+ }
+
+ command void DhvStateLogic.setVBitState(uint32_t state){
+ bitIndex = state;
+ if(state != 0){
+ call DhvTrickleTimer.reset();
+ }
+ }
+
+ command uint32_t DhvStateLogic.getVBitState(){
+ return bitIndex;
+ }
+
+ //unset one bit at index location
+ command void DhvStateLogic.unsetVBitIndex(uint8_t dindex){
+ uint32_t mask;
+ mask = 1;
+
+ mask = mask << (dindex-1);
+ dbg("TempDebug", "TempDebug: Before mask dindex bitIndex %d %d %d\n", mask, dindex, bitIndex);
+ if((bitIndex & mask) != 0){
+ bitIndex = bitIndex^mask;
+ }
+ dbg("TempDebug", "TempDebug: After bitIndex %d\n", bitIndex);
+ }
+
+ command void DhvStateLogic.setVBitIndex(uint8_t dindex){
+ uint32_t mask;
+ mask = 1;
+ mask = mask << (dindex-1);
+
+ bitIndex = bitIndex | mask;
+
+ call DhvTrickleTimer.reset();
+}
+
+//get the non-zero bit index to extract the vertical bits.
+command uint8_t DhvStateLogic.getVBitIndex(){
+
+ uint32_t mask;
+ uint8_t i;
+ uint32_t xor;
+
+ if(bitIndex == 0){
+ return 0;
+ }else
+ {
+ mask = 1;
+ for(i = 1; i <= 32; i++){
+ xor = bitIndex & mask;
+
+ dbg("TempDebug", "TempDebug: %d %d %d %d \n", i, bitIndex, mask, xor);
+ if(xor != 0){
+ return i;
+ }
+ mask = mask << 1;
+ }
+ return 0;
+ }
+}
+
+
+
+ command void DisseminationUpdate.change[dhv_key_t key](dhv_data_t* val) {
+
+ dbg("DhvLogicP","App notified key %x is new\n", key);
+
+ //update data: actual reprogramming job
+ call VersionUpdate.change[key](val);
+
+ //set data
+ call DhvDataCache.addItem(key);
+
+ //set to advertise its version
+ call DhvVectorCache.addItem(key);
+
+ //reset bindex
+ call DhvStateLogic.setVBitState(0);
+
+ dbg("DhvLogicP","Reset bindex to 0\n");
+ //reset timer
+ call DhvTrickleTimer.reset();
+ }
+
+ event uint32_t DhvTrickleTimer.requestWindowSize() {
+ //TODO: consider if this is neccessary
+ uint8_t decision;
+
+ decision = sendDecision();
+
+ if(decision == ID_DHV_SUMMARY){
+ windowSize = windowSize << 1;
+ if(windowSize > DHV_TAU_HIGH){
+ windowSize = DHV_TAU_HIGH;
+ }
+ }else{
+ if(decision != ID_DHV_INVALID){
+ windowSize = DHV_TAU_LOW;
+ }
+ }
+
+ /*if(decision == ID_DHV_DATA){
+ windowSize = DHV_TAU_LOW;
+ }else{
+ if(decision == ID_DHV_VBIT){
+ windowSize = DHV_TAU_LOW;
+ }else{
+ windowSize = windowSize << 1;
+ if(windowSize > DHV_TAU_HIGH){
+ windowSize = DHV_TAU_HIGH;
+ }
+ }
+ }
+ */
+ dbg("DhvLogicP", "Time window size requested, give %u : send decision %d \n", windowSize, decision);
+ return windowSize;
+ }
+
+ event void DhvTrickleTimer.fired() {
+ uint8_t decision;
+
+ dbg("DhvLogicP","Trickle Timer fired!\n");
+
+ decision = sendDecision();
+
+ switch(decision) {
+ case ID_DHV_INVALID:
+ dbg("DhvLogicP", "Decision to SUPPRESS\n");
+ break;
+ case ID_DHV_SUMMARY:
+ dbg("DhvLogicP", "Decision to SUMMARY\n");
+ call DhvSummaryDecision.send();
+ break;
+ case ID_DHV_VECTOR:
+ dbg("DhvLogicP", "Decision to VECTOR\n");
+ call DhvVectorDecision.send();
+ break;
+ case ID_DHV_DATA:
+ dbg("DhvLogicP", "Decision to DATA\n");
+ call DhvDataDecision.send();
+ break;
+ case ID_DHV_VBIT:
+ dbg("DhvLogicP", "Decision to VSUM\n");
+ call DhvVBitDecision.send();
+ break;
+ case ID_DHV_HSUM:
+ dbg("DhvLogicP", "Decision to HSUM\n");
+ call DhvHSumDecision.send();
+ break;
+ }
+ call DhvDataDecision.resetCommRate();
+ call DhvVectorDecision.resetCommRate();
+ call DhvSummaryDecision.resetCommRate();
+ call DhvVBitDecision.resetCommRate();
+ call DhvHSumDecision.resetCommRate();
+
+ //set bitstate to zero
+ call DhvStateLogic.setVBitState(0);
+ }
+
+
+ uint8_t getState() {
+ bool hasItemToSend;
+ uint32_t bindex;
+
+ hasItemToSend = FALSE;
+
+ hasItemToSend = call DhvDataCache.hasItemToSend();
+ if(hasItemToSend){
+ dbg("DhvLogicP", "has data to send? %u \n", hasItemToSend);
+ return ID_DHV_DATA;
+ }else{
+ hasItemToSend = call DhvVectorCache.hasItemToSend();
+ dbg("DhvLogicP", "has vector to send? %u \n", hasItemToSend);
+ if(hasItemToSend){
+ return ID_DHV_VECTOR;
+ }else{
+ bindex = call DhvStateLogic.getVBitState();
+ dbg("DhvLogicP", "send decision bindex %d \n", bindex);
+
+ if(bindex != 0){
+ return ID_DHV_VBIT;
+ }else{
+ if(hsum_status != 0){
+ return ID_DHV_HSUM;
+ }else {
+ return ID_DHV_SUMMARY;
+ }
+ }
+ }
+ }
+ }
+
+
+ uint8_t sendDecision() {
+
+ bool hasItemToSend;
+ uint32_t bindex;
+ uint8_t dataCommRate;
+ uint8_t vectorCommRate;
+ uint8_t summaryCommRate;
+ uint8_t vbitCommRate;
+ uint8_t hsumCommRate;
+
+ dataCommRate = call DhvDataDecision.getCommRate();
+ vectorCommRate = call DhvVectorDecision.getCommRate();
+ summaryCommRate = call DhvSummaryDecision.getCommRate();
+ vbitCommRate = call DhvVBitDecision.getCommRate();
+ hsumCommRate = call DhvHSumDecision.getCommRate();
+
+ hasItemToSend = FALSE;
+ hasItemToSend = call DhvDataCache.hasItemToSend();
+ if(hasItemToSend){
+ dbg("DhvLogicP", "has data to send? %u \n", hasItemToSend);
+ return ID_DHV_DATA;
+ }
+
+ bindex = call DhvStateLogic.getVBitState();
+ dbg("DhvLogicP", "send decision bindex %d \n", bindex);
+
+ if(bindex != 0){
+ return ID_DHV_VBIT;
+ }
+
+ if(hsum_status != 0){
+ return ID_DHV_HSUM;
+ }
+
+ if(dataCommRate > 1) {
+ dbg("DhvLogicP", "Heard data\n");
+ return ID_DHV_INVALID;
+ }
+
+
+ hasItemToSend = call DhvVectorCache.hasItemToSend();
+ dbg("DhvLogicP", "has vector to send? %u \n", hasItemToSend);
+
+ if(hasItemToSend){
+ return ID_DHV_VECTOR;
+ }
+
+ // didn't send or hear data at this point
+ if(vectorCommRate + summaryCommRate + vbitCommRate > 1) {
+ dbg("DhvLogicP", "Heard an advertisement\n");
+ return ID_DHV_INVALID;
+ }
+
+ return ID_DHV_SUMMARY;
+ }
+}