⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 writer.nc

📁 传感器网络中的嵌入式操作系统源代码
💻 NC
字号:
// $Id: Writer.nc,v 1.1.4.2 2003/08/18 22:09:47 cssharp Exp $/*									tab:4 * "Copyright (c) 2000-2003 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) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE      * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,  * 94704.  Attention:  Intel License Inquiry. */includes IFS;module Writer {  provides {    interface StdControl;    interface IFileWrite[uint8_t fd];    interface IFileWrite2[uint8_t fd];  }  uses {    interface IFileBlock;    interface IFileBlockErase;    interface IFileBlockMeta;    interface IFileFree;  }#include "massert.h"}implementation {  struct fileState {    fileblock_t first, block, nextBlock, blockPosition;    fileblockoffset_t lastOffset, offset;    bool check;  } fds[FS_NUM_WFDS];  fileblock_t newBlock, lastNewBlock, newCount;  fileblock_t lastBlock;  fileblockoffset_t lastBlockOffset;  uint8_t writefd;  char *writefrom;  filesize_t writeSize, requestedSize;  enum { s_creating, s_opening, s_seeking, s_truncating,	 s_reserving, s_reserving2,	 s_allocating, s_allocating2, s_syncing, s_writing,	 s_meta_sync, s_meta_sync_first };  uint8_t state;  command result_t StdControl.init() {    fds[0].first = fds[1].first = IFS_EOF_BLOCK;    return SUCCESS;  }  command result_t StdControl.start() {    return SUCCESS;  }  command result_t StdControl.stop() {    return SUCCESS;  }  void writeComplete(fileresult_t result) {    signal IFileWrite.writeDone[writefd](requestedSize - writeSize, result);  }  void syncComplete(fileresult_t result) {    signal IFileWrite.syncDone[writefd](result);  }  void seekComplete(fileresult_t result) {    signal IFileWrite2.seekDone[writefd](writeSize, result);  }  void reserveComplete(fileresult_t result) {    signal IFileWrite2.reserved[writefd](writeSize, result);  }  void allocateAbort(fileresult_t result) {    switch (state)      {      case s_creating: signal IFileWrite.newDone[writefd](result); break;      case s_reserving: reserveComplete(result); break;      default: writeComplete(result); break;      }  }  task void nospace() {    allocateAbort(FS_ERROR_NOSPACE);  }  void allocateNextNewBlock() {    lastNewBlock = newBlock;    newBlock = call IFileFree.allocate();    call IFileBlockErase.erase(newBlock);  }  void flushAndAllocateNextNewBlock() {    call IFileBlock.flush(newBlock);  }  void allocateNewBlocks(fileblock_t n) {    if (call IFileFree.nFreeBlocks() >= n)      {	newCount = n;	newBlock = IFS_EOF_BLOCK;	allocateNextNewBlock();      }    else      post nospace();  }  void allocateFail(fileresult_t result) {    call IFileFree.free(newBlock);    allocateAbort(result);  }  void readNextBlock() {    call IFileBlockMeta.read(fds[writefd].nextBlock, fds[writefd].check);  }  bool updateMeta() {    bool update = fds[writefd].check;    if (fds[writefd].offset > fds[writefd].lastOffset)      {	fds[writefd].lastOffset = fds[writefd].offset;	update = TRUE;      }    if (update)      call IFileBlockMeta.write(fds[writefd].block, fds[writefd].check, FALSE,				fds[writefd].nextBlock, fds[writefd].lastOffset);    return update;  }  event void IFileBlockErase.eraseDone(fileresult_t result) {    if (result == FS_OK)      call IFileBlockMeta.write(newBlock, fds[writefd].check,				FALSE, lastNewBlock, 0);    else      allocateFail(result);  }  command void IFileWrite.new[uint8_t fd](bool check) {    state = s_creating;     writefd = fd;    fds[fd].offset = 0;    fds[fd].lastOffset = 0;    fds[fd].check = check;    fds[fd].blockPosition = 0;    allocateNewBlocks(1);  }  command void IFileWrite2.open[uint8_t fd](fileblock_t first, bool check) {    state = s_opening;    writefd = fd;    fds[fd].first = fds[fd].block = first;    fds[fd].offset = 0;    fds[fd].blockPosition = 0;    fds[fd].check = check;    call IFileBlockMeta.read(first, check);  }  command fileblock_t IFileWrite.firstBlock[uint8_t fd]() {    return fds[fd].first;  }  command void IFileWrite.close[uint8_t fd]() {    fds[fd].first = IFS_EOF_BLOCK;  }  void continueWrite() {    fileblock_t block;    fileblockoffset_t count, offset;    // check if done    if (writeSize == 0)      {	writeComplete(FS_OK);	return;      }    block = fds[writefd].block;    offset = fds[writefd].offset;    if (writeSize >= IFS_PAGE_SIZE || writeSize + offset > IFS_PAGE_SIZE)      count = IFS_PAGE_SIZE - offset;    else      count = writeSize;    if (count > 0)      {	call IFileBlock.write(block, offset, writefrom, count);	fds[writefd].offset += count;	writefrom += count;	writeSize -= count;      }    else if (fds[writefd].nextBlock != IFS_EOF_BLOCK) // writing through a file      {	state = s_writing;	if (!updateMeta())	  readNextBlock();      }    else // need new block      {	state = s_allocating;	allocateNewBlocks(1);      }  }  void seekToEnd(fileblock_t nextBlock, fileblockoffset_t lastOffset);  void reserve(fileblock_t nextBlock, fileblockoffset_t lastOffset);  event void IFileBlockMeta.readDone(fileblock_t nextBlock,				     fileblockoffset_t lastByte,				     fileresult_t result) {    if (result == FS_OK)      switch (state)	{	case s_meta_sync_first:	  // setting root flag, we're not the only block or we wouldn't be	  // here (see metaSync)	  call IFileBlockMeta.write(fds[writefd].first, fds[writefd].check,				    TRUE, nextBlock, lastByte);	  break;	case s_opening:	  fds[writefd].nextBlock = nextBlock;	  fds[writefd].lastOffset = lastByte;	  signal IFileWrite2.openDone[writefd](result);	  break;	case s_seeking:	  seekToEnd(nextBlock, lastByte);	  break;	case s_reserving:	  reserve(nextBlock, lastByte);	  break;	case s_writing:	  call IFileBlock.flush(fds[writefd].block);	  fds[writefd].block = fds[writefd].nextBlock;	  fds[writefd].blockPosition++;	  fds[writefd].offset = 0;	  fds[writefd].nextBlock = nextBlock;	  fds[writefd].lastOffset = lastByte;	  break;	}    else      switch (state)	{	case s_opening: signal IFileWrite2.openDone[writefd](result); break;	case s_seeking: seekComplete(result); break;	case s_reserving: reserveComplete(result); break;	case s_meta_sync_first: syncComplete(result); break;	case s_writing: writeComplete(result); break;	}  }  event void IFileBlock.writeDone(fileresult_t result) {    if (result == FS_OK)      continueWrite();    else      writeComplete(result);  }  event void IFileBlockMeta.writeDone(fileresult_t result) {    if (result == FS_OK)      switch (state)	{	case s_truncating: {	  fileblock_t nowFree = fds[writefd].nextBlock;	  fds[writefd].nextBlock = IFS_EOF_BLOCK;	  fds[writefd].offset = fds[writefd].lastOffset = 0;	  signal IFileWrite2.truncated[writefd](nowFree, FS_OK);	  return;	}	case s_writing:	  readNextBlock();	  return;	case s_allocating: case s_reserving:	  if (--newCount)	    flushAndAllocateNextNewBlock();	  else	    call IFileBlock.sync(newBlock);	  return;	case s_creating:	  if (--newCount)	    flushAndAllocateNextNewBlock();	  else	    {	      fds[writefd].block = fds[writefd].first = newBlock;	      fds[writefd].nextBlock = lastNewBlock;	      signal IFileWrite.newDone[writefd](FS_OK);	    }	  return;	case s_allocating2:	  /* We've finished writing the old block */	  call IFileBlock.flush(fds[writefd].block);	  fds[writefd].block = newBlock;	  fds[writefd].blockPosition++;	  fds[writefd].nextBlock = lastNewBlock;	  fds[writefd].offset = fds[writefd].lastOffset = 0;	  break;	case s_reserving2:	  call IFileBlock.flush(lastBlock);	  if (lastBlock == fds[writefd].block)	    fds[writefd].nextBlock = newBlock;	  break;	case s_meta_sync:	  /* If metadata is more than 1 block we will need to set the root flag	     on the first block, so we just flush. */	  if (fds[writefd].block != fds[writefd].first)	    {	      state = s_meta_sync_first;	      call IFileBlock.flush(fds[writefd].block);	      fds[writefd].block = fds[writefd].first;	      return;	    }	  /* fall through */	case s_syncing: case s_meta_sync_first:	  call IFileBlock.sync(fds[writefd].block);	  return;	}    else      switch (state)	{	  // I'm not using allocateFail for failure in the s_allocating2	  // case as it's not clear whether the flash chip does or does not	  // contain the ptr to the new block. Better to leak until reboot.	case s_writing: case s_allocating2:	  writeComplete(result);	  return;	case s_creating: case s_allocating: case s_reserving:	  allocateFail(result);	  return;	case s_meta_sync: case s_syncing: case s_meta_sync_first:	  syncComplete(result);	  return;	case s_truncating:	  signal IFileWrite2.truncated[writefd](0, result);	  return;	}  }  task void writeCompleteTask() {    writeComplete(FS_OK);  }  command void IFileWrite.write[uint8_t fd](void *buffer, filesize_t n) {    writefd = fd;    writefrom = buffer;    requestedSize = writeSize = n;    if (n == 0)      post writeCompleteTask();    else      continueWrite();  }  command void IFileWrite.sync[uint8_t fd]() {    state = s_syncing;    writefd = fd;    if (!updateMeta())      call IFileBlock.sync(fds[fd].block);  }  command void IFileWrite.metaSync[uint8_t fd]() {    /* This assumes the MetaData component never rewinds and synchronises       once only, at the end. */    state = s_meta_sync;    writefd = fd;    call IFileBlockMeta.write(fds[fd].block, fds[fd].check, 			      fds[fd].block == fds[fd].first,			      IFS_EOF_BLOCK, fds[fd].offset);  }  event void IFileBlock.syncDone(fileresult_t result) {    switch (state)      {      case s_allocating:	/* We've synced the new block, now we can point to it from the	   old block */	if (result == FS_OK)	  {	    state = s_allocating2;	    call IFileBlockMeta.write(fds[writefd].block, fds[writefd].check,				      FALSE, newBlock, IFS_PAGE_SIZE);	  }	else	  allocateFail(result);	return;      case s_reserving:	if (result == FS_OK)	  {	    state = s_reserving2;	    call IFileBlockMeta.write(lastBlock, fds[writefd].check,				      FALSE, newBlock, lastBlockOffset);	  }	else	  allocateFail(result);	return;      case s_syncing: case s_meta_sync: case s_meta_sync_first:	signal IFileWrite.syncDone[writefd](result);	return;      }  }  event void IFileBlock.flushDone(fileresult_t result) {    switch (state)      {      case s_meta_sync_first:	if (result == FS_OK)	  call IFileBlockMeta.read(fds[writefd].first, fds[writefd].check);	else	  syncComplete(result);	break;      case s_allocating: case s_reserving: case s_creating:	if (result == FS_OK)	  allocateNextNewBlock();	else	  allocateFail(result);	break;      case s_reserving2:	reserveComplete(result);	break;      default:	if (result == FS_OK)	  continueWrite();	else	  writeComplete(result);	break;      }  }  void seekToEnd(fileblock_t nextBlock, fileblockoffset_t lastOffset) {    writeSize += lastOffset;    if (nextBlock == IFS_EOF_BLOCK || lastOffset < IFS_PAGE_SIZE)      {	fds[writefd].nextBlock = nextBlock;	fds[writefd].offset = fds[writefd].lastOffset = lastOffset;	seekComplete(FS_OK);      }    else      {	fds[writefd].block = nextBlock;	fds[writefd].blockPosition++;	call IFileBlockMeta.read(nextBlock, fds[writefd].check);      }  }  command void IFileWrite2.seekEnd[uint8_t fd]() {    state = s_seeking;    writefd = fd;    writeSize = 0;    seekToEnd(fds[fd].nextBlock, fds[fd].lastOffset);  }  command void IFileWrite2.truncate[uint8_t fd]() {    state = s_truncating;    writefd = fd;    call IFileBlockMeta.write(fds[fd].first, fds[fd].check, FALSE,			      IFS_EOF_BLOCK, 0);  }  task void reserveDoneTask() {    reserveComplete(FS_OK);  }  void reserve(fileblock_t nextBlock, fileblockoffset_t lastOffset) {    writeSize += IFS_PAGE_SIZE;    lastBlockOffset = lastOffset;    if (nextBlock == IFS_EOF_BLOCK)      {	if (writeSize > requestedSize)	  post reserveDoneTask();	else	  {	    fileblock_t nNewBlocks =	      (requestedSize - writeSize + IFS_PAGE_SIZE - 1) >> IFS_LOG2_PAGE_SIZE;	    writeSize += (filesize_t)nNewBlocks << IFS_LOG2_PAGE_SIZE;	    allocateNewBlocks(nNewBlocks);	  }      }    else      {	lastBlock = nextBlock;	call IFileBlockMeta.read(nextBlock, fds[writefd].check);      }  }  command void IFileWrite2.reserve[uint8_t fd](filesize_t newSize) {    state = s_reserving;    writefd = fd;    requestedSize = newSize;    writeSize = (filesize_t)fds[fd].blockPosition << IFS_LOG2_PAGE_SIZE;    lastBlock = fds[fd].block;    reserve(fds[fd].nextBlock, fds[fd].lastOffset);  }  default event void IFileWrite.newDone[uint8_t id](fileresult_t result) {    assert(0);  }  default event void IFileWrite.writeDone[uint8_t id](filesize_t nWritten, fileresult_t result) {    assert(0);  }  default event void IFileWrite.syncDone[uint8_t id](fileresult_t result) {    assert(0);  }  default event void IFileWrite2.openDone[uint8_t id](fileresult_t result) {    assert(0);  }  default event void IFileWrite2.seekDone[uint8_t id](filesize_t size, fileresult_t result) {    assert(0);  }  default event void IFileWrite2.reserved[uint8_t id](filesize_t size, fileresult_t result) {    assert(0);  }  default event void IFileWrite2.truncated[uint8_t id](fileblock_t nowFree, fileresult_t result) {    assert(0);  }  event void IFileBlock.readDone(fileresult_t result) {    assert(0);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -