📄 objecttransferp.nc
字号:
/*
* "Copyright (c) 2000-2004 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2007 Johns Hopkins University.
* All rights reserved.
*/
/**
* @author Jonathan Hui <jwhui@cs.berkeley.edu>
* @author Chieh-Jan Mike Liang <cliang4@cs.jhu.edu>
* @author Razvan Musaloiu-E. <razvanm@cs.jhu.edu>
*/
#include "DelugePageTransfer.h"
#include "DelugeMsgs.h"
module ObjectTransferP
{
provides interface ObjectTransfer;
uses {
interface Random;
interface Timer<TMilli> as Timer;
interface DelugePageTransfer;
interface Crc;
interface AMSend as SendAdvMsg;
interface Receive as ReceiveAdvMsg;
interface BlockWrite[uint8_t img_num];
interface Leds;
// interface StatsCollector;
}
}
implementation
{
// States
enum {
S_ERASE,
S_SYNC,
S_INITIALIZING_PUB,
S_INITIALIZING_RECV,
S_STARTED,
S_STOPPED,
};
DelugeAdvTimer advTimers;
uint8_t state = S_STOPPED;
object_id_t cont_receive_new_objid;
object_size_t cont_receive_new_size;
uint8_t cont_receive_img_num;
message_t pMsgBuf;
bool isBusy_pMsgBuf = FALSE;
DelugeObjDesc curObjDesc;
void updateTimers()
{
//advTimers.timer = 0;
}
void setupAdvTimer()
{
advTimers.timer = (uint32_t)0x1 << (advTimers.periodLog2 - 1);
advTimers.timer += call Random.rand16() & (advTimers.timer - 1);
advTimers.overheard = 0;
call Timer.stop();
call Timer.startOneShot(advTimers.timer);
}
void resetTimer()
{
if (advTimers.periodLog2 != DELUGE_MIN_ADV_PERIOD_LOG2) {
advTimers.periodLog2 = DELUGE_MIN_ADV_PERIOD_LOG2;
setupAdvTimer();
}
}
task void signalObjRecvDone()
{
signal ObjectTransfer.receiveDone(SUCCESS);
}
void setNextPage()
{
if (curObjDesc.numPgsComplete < curObjDesc.numPgs) {
call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgsComplete);
advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;
advTimers.overheard = 0;
resetTimer();
} else {
call DelugePageTransfer.setWorkingPage(DELUGE_INVALID_OBJID, DELUGE_INVALID_PGNUM);
call ObjectTransfer.stop();
state = S_SYNC;
call BlockWrite.sync[cont_receive_img_num]();
}
}
bool isObjDescValid(DelugeObjDesc* tmpObjDesc)
{
return (tmpObjDesc->crc == call Crc.crc16(tmpObjDesc, sizeof(object_id_t) + sizeof(page_num_t))
&& tmpObjDesc->crc != 0);
}
void sendAdvMsg(uint16_t addr)
{
DelugeAdvMsg *pMsg = (DelugeAdvMsg *)(call SendAdvMsg.getPayload(&pMsgBuf, sizeof(DelugeAdvMsg)));
if (pMsg == NULL) {
return;
}
if (isBusy_pMsgBuf == FALSE) {
pMsg->sourceAddr = TOS_NODE_ID;
pMsg->version = DELUGE_VERSION;
pMsg->type = DELUGE_ADV_NORMAL;
memcpy(&(pMsg->objDesc), &curObjDesc, sizeof(DelugeObjDesc));
if (call SendAdvMsg.send(addr, &pMsgBuf, sizeof(DelugeAdvMsg)) == SUCCESS) {
//call StatsCollector.msg_bcastReq();
isBusy_pMsgBuf = TRUE;
}
}
}
/**
* Starts publisher
*/
command error_t ObjectTransfer.publish(object_id_t new_objid, object_size_t new_size, uint8_t img_num)
{
call ObjectTransfer.stop();
//call StatsCollector.startStatsCollector();
state = S_INITIALIZING_PUB;
curObjDesc.objid = new_objid;
curObjDesc.numPgs = ((new_size - 1) / DELUGET2_BYTES_PER_PAGE) + 1; // Number of pages to transmit
curObjDesc.numPgsComplete = curObjDesc.numPgs; // Publisher doesn't really care about this
curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
if (state == S_INITIALIZING_PUB) {
resetTimer();
}
state = S_STARTED;
call DelugePageTransfer.setImgNum(img_num);
call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgs);
return SUCCESS;
}
/**
* Resumes the process of preparing the receiver after the target volume is erased
*/
void cont_receive() {
state = S_INITIALIZING_RECV;
curObjDesc.objid = cont_receive_new_objid;
curObjDesc.numPgs = ((cont_receive_new_size - 1) / DELUGET2_BYTES_PER_PAGE) + 1; // Number of pages to receive
curObjDesc.numPgsComplete = 0;
curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
if (state == S_INITIALIZING_RECV) {
resetTimer();
}
state = S_STARTED;
call DelugePageTransfer.setImgNum(cont_receive_img_num);
setNextPage();
}
/**
* Starts receiver
*/
command error_t ObjectTransfer.receive(object_id_t new_objid, object_size_t new_size, uint8_t img_num)
{
error_t error;
call ObjectTransfer.stop();
//call StatsCollector.startStatsCollector();
cont_receive_new_objid = new_objid;
cont_receive_new_size = new_size;
cont_receive_img_num = img_num;
error = call BlockWrite.erase[cont_receive_img_num]();
if (error == SUCCESS) {
state = S_ERASE;
}
return error;
}
command error_t ObjectTransfer.stop()
{
call Timer.stop();
call DelugePageTransfer.stop();
state = S_STOPPED;
//call StatsCollector.stopStatsCollector();
curObjDesc.objid = DELUGE_INVALID_OBJID;
curObjDesc.numPgs = DELUGE_INVALID_PGNUM;
curObjDesc.numPgsComplete = DELUGE_INVALID_PGNUM;
advTimers.periodLog2 = 0;
return SUCCESS;
}
event void DelugePageTransfer.receivedPage(object_id_t new_objid, page_num_t new_pgNum)
{
// printf("R: %08lx %d\n", new_objid, new_pgNum);
if (new_objid == curObjDesc.objid && new_pgNum == curObjDesc.numPgsComplete) {
curObjDesc.numPgsComplete++;
curObjDesc.crc = call Crc.crc16(&curObjDesc, sizeof(object_id_t) + sizeof(page_num_t));
if (curObjDesc.numPgsComplete < curObjDesc.numPgs) {
setNextPage();
} else {
call DelugePageTransfer.setWorkingPage(curObjDesc.objid, curObjDesc.numPgsComplete);
state = S_SYNC;
if (call BlockWrite.sync[cont_receive_img_num]() != SUCCESS) {
post signalObjRecvDone();
}
}
}
}
event void BlockWrite.syncDone[uint8_t img_num](error_t error)
{
if (state == S_SYNC) {
post signalObjRecvDone();
}
}
event void DelugePageTransfer.suppressMsgs(object_id_t new_objid)
{
if (new_objid == curObjDesc.objid) {
advTimers.overheard = 1;
}
}
event void SendAdvMsg.sendDone(message_t* msg, error_t error)
{
isBusy_pMsgBuf = FALSE;
}
event message_t* ReceiveAdvMsg.receive(message_t* msg, void* payload, uint8_t len)
{
DelugeAdvMsg *rxAdvMsg = (DelugeAdvMsg*)payload;
DelugeObjDesc *cmpObjDesc = &(rxAdvMsg->objDesc);
bool isEqual = FALSE;
if (cmpObjDesc->objid != curObjDesc.objid) {
return msg;
}
if (rxAdvMsg->version != DELUGE_VERSION || state != S_STARTED) {
return msg;
}
if (isObjDescValid(&(rxAdvMsg->objDesc)) && state == S_STARTED) {
// Their image is larger (They have something we need)
if (cmpObjDesc->numPgsComplete > curObjDesc.numPgsComplete) {
if ( advTimers.newAdvs == 0 ) {
call DelugePageTransfer.dataAvailable(rxAdvMsg->sourceAddr);
}
}
// Their image is smaller (They need something we have)
else if (cmpObjDesc->numPgsComplete < curObjDesc.numPgsComplete) {
advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;
}
// image is the same
else {
advTimers.overheard = 1;
isEqual = TRUE;
}
if (!isEqual) {
resetTimer();
}
}
return msg;
}
event void Timer.fired()
{
updateTimers();
if (advTimers.overheard == 0) {
sendAdvMsg(AM_BROADCAST_ADDR);
}
if (call DelugePageTransfer.isTransferring())
advTimers.newAdvs = DELUGE_NUM_NEWDATA_ADVS_REQUIRED;
else if (advTimers.newAdvs > 0)
advTimers.newAdvs--;
if (advTimers.newAdvs == 0 &&
advTimers.periodLog2 < DELUGE_MAX_ADV_PERIOD_LOG2) {
advTimers.periodLog2++;
}
setupAdvTimer();
}
default command error_t BlockWrite.erase[uint8_t img_num]() { return FAIL; }
default command error_t BlockWrite.sync[uint8_t img_num]() { return FAIL; }
event void BlockWrite.writeDone[uint8_t img_num](storage_addr_t addr, void* buf, storage_len_t len, error_t error) {}
event void BlockWrite.eraseDone[uint8_t img_num](error_t error)
{
if (state == S_ERASE) {
cont_receive();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -