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

📄 logstoragep.nc

📁 tinyos-2.x.rar
💻 NC
📖 第 1 页 / 共 2 页
字号:

    readMetadata(firstPage);
  }

  void located() {
    metaState = META_LOCATELAST;
    /* firstPage is one after last valid page, but the last page with
       a record end may be some pages earlier. Search for it. */
    lastPage = lastVolumePage() - 1;
    locateLastRecord();
  }

  at45page_t locateCurrentPage() {
    return firstPage + ((lastPage - firstPage) >> 1);
  }

  void locateBinarySearch() {
    if (lastPage <= firstPage)
      located();
    else
      readMetadata(locateCurrentPage());
  }

  void locateGreaterThan() {
    firstPage = locateCurrentPage() + 1;
    locateBinarySearch();
  }

  void locateLessThan() {
    lastPage = locateCurrentPage();
    locateBinarySearch();
  }

  void locateCrcDone(uint16_t crc) {
    if (crc == metadata.crc)
      {
	s[client].wpos = metadata.pos;
	locateGreaterThan();
      }
    else
      locateLessThan();
  }

  void locateReadDone() {
    if (metadata.magic == PERSISTENT_MAGIC && s[client].wpos < metadata.pos)
      crcPage(locateCurrentPage());
    else
      locateLessThan();
  }

  void locateFirstCrcDone(uint16_t crc) {
    if (metadata.magic == PERSISTENT_MAGIC && crc == metadata.crc)
      s[client].wpos = metadata.pos;
    else
      s[client].wpos = 0;

    metaState = META_LOCATE;
    locateBinarySearch();
  }

  void locateFirstReadDone() {
    crcPage(lastPage);
  }

  /* Locate log beginning and ending. See description at top of file. */
  void locateStart() {
    metaState = META_LOCATEFIRST;
    firstPage = firstVolumePage();
    lastPage = lastVolumePage() - 1;
    readMetadata(lastPage);
  }

  /* ------------------------------------------------------------------ */
  /* Append								*/
  /* ------------------------------------------------------------------ */

  void appendContinue() {
    uint8_t *buf = s[client].buf + pos;
    at45pageoffset_t offset = s[client].woffset, count;
    storage_len_t len = s[client].len - pos;
    
    if (len == 0)
      {
	endRequest(SUCCESS);
	return;
      }

    if (s[client].wpage == lastVolumePage())
      {
	/* We reached the end of a linear log */
	endRequest(ESIZE);
	return;
      }

    if (offset + len <= PAGE_SIZE)
      count = len;
    else
      count = PAGE_SIZE - offset;

    s[client].wpos += count;
    s[client].woffset += count;
    pos += count;

    /* We normally lose data at the point we make the first write to a
       page in a log that has circled. */
    if (offset == 0 && s[client].circled)
      recordsLost = TRUE;

    call At45db.write(s[client].wpage, offset, buf, count);
  }
  
  void appendWriteDone() {
    if (s[client].woffset == PAGE_SIZE) /* Time to write metadata */
      wmetadataStart();
    else
      endRequest(SUCCESS);
  }

  void appendMetadataDone() { // metadata of previous page flushed
    /* Setup metadata in case we overflow this page too */
    metadata.flags = 0;
    appendContinue();
  }

  void appendSyncDone() {
    s[client].wpos = metadata.pos + PAGE_SIZE;
    appendStart();
  }

  void appendStart() {
    storage_len_t len = s[client].len - pos;
    storage_len_t vlen = (storage_len_t)npages() * PAGE_SIZE;

    recordsLost = FALSE;

    /* If request would span the end of the flash, sync, to maintain the
       invariant that the last flash page is synced and that either
       the first or last pages are valid.

       Note that >= in the if below means we won't write a record that
       would end on the last byte of the last page, as this would mean that
       we would not sync the last page, breaking the log volume
       invariant */
    if ((s[client].wpos - PAGE_SIZE) % vlen >= vlen - len)
      sync();
    else
      {
	/* Set lastRecordOffset in case we need to write metadata (see
	   wmetadataStart) */
	metadata.lastRecordOffset = s[client].woffset;
	metadata.flags = F_LASTVALID;
	appendContinue();
      }
  }

  /* ------------------------------------------------------------------ */
  /* Sync								*/
  /* ------------------------------------------------------------------ */

  void syncStart() {
    if (s[client].woffset == 0) /* we can't lose any writes */
      endRequest(SUCCESS);
    else
      sync();
  }

  void syncMetadataDone() {
    /* Write position reflect the absolute position in the flash, not
       user-bytes written. So update wpos to reflect sync effects. */
    s[client].wpos = metadata.pos + PAGE_SIZE;
    endRequest(SUCCESS);
  }

  /* ------------------------------------------------------------------ */
  /* Write block metadata						*/
  /* ------------------------------------------------------------------ */

  void wmetadataStart() {
    /* The caller ensures that metadata.flags (except F_CIRCLED) and
       metadata.lastRecordOffset are set correctly. */
    metaState = META_WRITE;
    firstPage = s[client].wpage; // remember page to commit
    metadata.pos = s[client].wpos - s[client].woffset;
    metadata.magic = PERSISTENT_MAGIC;
    if (s[client].circled)
      metadata.flags |= F_CIRCLED;

    call At45db.computeCrc(firstPage, 0, PAGE_SIZE, 0);

    /* We move to the next page now. If writing the metadata fails, we'll
       simply leave the invalid page in place. Trying to recover seems
       complicated, and of little benefit (note that in practice, At45dbC
       shuts down after a failed write, so nothing is really going to
       happen after that anyway). */
    setWritePage(s[client].wpage + 1);

    /* Invalidate read pointer if we reach it's page */
    if (s[client].wpage == s[client].rpage)
      invalidateReadPointer();
  }

  void wmetadataCrcDone(uint16_t crc) {
    uint8_t i, *md;

    // Include metadata in crc
    md = (uint8_t *)&metadata;
    for (i = 0; i < offsetof(nx_struct pageinfo, crc); i++)
      crc = crcByte(crc, md[i]);
    metadata.crc = crc;

    // And save it
    writeMetadata(firstPage);
  }

  void wmetadataWriteDone() {
    metaState = META_IDLE;
    if (metadata.flags & F_SYNC)
      call At45db.sync(firstPage);
    else
      call At45db.flush(firstPage);
  }

  /* ------------------------------------------------------------------ */
  /* Read 								*/
  /* ------------------------------------------------------------------ */

  void readContinue() {
    uint8_t *buf = s[client].buf + pos;
    at45pageoffset_t offset = s[client].roffset, count;
    at45pageoffset_t end = s[client].rend;
    storage_len_t len = s[client].len - pos;
    
    if (len == 0)
      {
	endRequest(SUCCESS);
	return;
      }

    if (!s[client].rvalid)
      {
	if (s[client].circled)
	  /* Find a valid page after wpage, skipping invalid pages */
	  s[client].rpage = s[client].wpage;
	else
	  {
	    /* resume reading at the beginning of the first page */
	    s[client].rvalid = TRUE;
	    s[client].rpage = lastVolumePage() - 1;
	  }

	rmetadataStart();
	return;
      }

    if (s[client].rpage == s[client].wpage)
      end = s[client].woffset;

    if (offset == end)
      {
	if ((s[client].rpage + 1 == lastVolumePage() && !s[client].circular) ||
	    s[client].rpage == s[client].wpage)
	  endRequest(SUCCESS); // end of log
	else
	  rmetadataStart();
	return;
      }

    if (offset + len <= end)
      count = len;
    else
      count = end - offset;

    pos += count;
    s[client].rpos += count;
    s[client].roffset = offset + count;

    call At45db.read(s[client].rpage, offset, buf, count);
  }

  void readStart() {
    readContinue();
  }

  /* ------------------------------------------------------------------ */
  /* Read block metadata						*/
  /* ------------------------------------------------------------------ */

  void continueReadAt(at45pageoffset_t roffset) {
    /* Resume reading at firstPage whose metadata is currently available
       in the metadata variable */
    metaState = META_IDLE;
    s[client].rpos = metadata.pos + roffset;
    s[client].rpage = firstPage;
    s[client].roffset = roffset;
    s[client].rend =
      metadata.flags & F_SYNC ? metadata.lastRecordOffset : PAGE_SIZE;
    s[client].rvalid = TRUE;
    readContinue();
  }

  void rmetadataContinue() {
    if (++firstPage == lastVolumePage())
      firstPage = firstVolumePage();
    if (firstPage == s[client].wpage)
      if (!s[client].rvalid)
	/* We cannot find a record boundary to start at (we've just
	   walked through the whole log...). Give up. */
	endRequest(SUCCESS);
      else
	{
	  /* The current write page has no metadata yet, so we fake it */
	  metadata.flags = 0;
	  metadata.pos = s[client].wpos - s[client].woffset;
	  continueReadAt(0);
	}
    else
      readMetadata(firstPage);
  }

  void rmetadataReadDone() {
    if (metadata.magic == PERSISTENT_MAGIC)
      crcPage(firstPage);
    else
      endRequest(SUCCESS);
  }

  void rmetadataCrcDone(uint16_t crc) {
    if (!s[client].rvalid)
      if (crc == metadata.crc && metadata.flags & F_LASTVALID)
	continueReadAt(metadata.lastRecordOffset);
      else
	rmetadataContinue();
    else 
      if (crc == metadata.crc)
	continueReadAt(0);
      else
	endRequest(SUCCESS);
  }

  void rmetadataStart() {
    metaState = META_READ;
    firstPage = s[client].rpage;
    rmetadataContinue();
  }

  /* ------------------------------------------------------------------ */
  /* Seek.								*/
  /* ------------------------------------------------------------------ */

  void seekCrcDone(uint16_t crc) {
    if (metadata.magic == PERSISTENT_MAGIC && crc == metadata.crc &&
	metadata.pos == s[client].rpos - s[client].roffset)
      {
	s[client].rvalid = TRUE;
	if (metadata.flags & F_SYNC)
	  s[client].rend = metadata.lastRecordOffset;
      }
    endRequest(SUCCESS);
  }

  void seekReadDone() {
    crcPage(s[client].rpage);
  }

  /* Move to position specified by cookie. */
  void seekStart() {
    uint32_t offset = (uint32_t)(uint16_t)s[client].buf << 16 | s[client].len;

    invalidateReadPointer(); // default to beginning of log

    /* The write positions are offset by PAGE_SIZE (see emptyLog) */

    if (offset == SEEK_BEGINNING)
      offset = PAGE_SIZE;

    if (offset > s[client].wpos || offset < PAGE_SIZE)
      {
	endRequest(EINVAL);
	return;
      }

    /* Cookies are just flash positions which continue incrementing as
       you circle around and around. So we can just check the requested
       page's metadata.pos field matches the cookie's value */
    s[client].rpos = offset;
    s[client].roffset = (offset - PAGE_SIZE) % PAGE_SIZE;
    s[client].rpage = firstVolumePage() + ((offset - PAGE_SIZE) / PAGE_SIZE) % npages();
    s[client].rend = PAGE_SIZE; // default to no sync flag

    // The last page's metadata isn't written to flash yet. Special case it.
    if (s[client].rpage == s[client].wpage)
      {
	/* If we're seeking within the current write page, just go there.
	   Otherwise, we're asking for an old version of the current page
	   so just keep the invalidated read pointer, i.e., read from
	   the beginning. */
	if (offset >= s[client].wpos - s[client].woffset)
	  s[client].rvalid = TRUE;
	endRequest(SUCCESS);
      }
    else
      {
	metaState = META_SEEK;
	readMetadata(s[client].rpage);
      }
  }

  /* ------------------------------------------------------------------ */
  /* Dispatch HAL operations to current user op				*/
  /* ------------------------------------------------------------------ */

  event void At45db.eraseDone(error_t error) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else
	eraseEraseDone();
  }

  event void At45db.writeDone(error_t error) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else
	switch (metaState)
	  {
	  case META_WRITE: wmetadataWriteDone(); break;
	  case META_IDLE: appendWriteDone(); break;
	  }
  }

  event void At45db.syncDone(error_t error) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else switch (s[client].request)
	{
	case R_ERASE: eraseMetadataDone(); break;
	case R_APPEND: appendSyncDone(); break;
	case R_SYNC: syncMetadataDone(); break;
	}
  }

  event void At45db.flushDone(error_t error) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else
	appendMetadataDone();
  }

  event void At45db.readDone(error_t error) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else
	switch (metaState)
	  {
	  case META_LOCATEFIRST: locateFirstReadDone(); break;
	  case META_LOCATE: locateReadDone(); break;
	  case META_LOCATELAST: locateLastReadDone(); break;
	  case META_SEEK: seekReadDone(); break;
	  case META_READ: rmetadataReadDone(); break;
	  case META_IDLE: readContinue(); break;
	  }					    
  }

  event void At45db.computeCrcDone(error_t error, uint16_t crc) {
    if (client != NO_CLIENT)
      if (error != SUCCESS)
	endRequest(FAIL);
      else
	switch (metaState)
	  {
	  case META_LOCATEFIRST: locateFirstCrcDone(crc); break;
	  case META_LOCATE: locateCrcDone(crc); break;
	  case META_LOCATELAST: locateLastCrcDone(crc); break;
	  case META_SEEK: seekCrcDone(crc); break;
	  case META_WRITE: wmetadataCrcDone(crc); break;
	  case META_READ: rmetadataCrcDone(crc); break;
	  }
  }

  event void At45db.copyPageDone(error_t error) { }

  default event void LogWrite.appendDone[uint8_t logId](void* buf, storage_len_t l, bool rLost, error_t error) { }
  default event void LogWrite.eraseDone[uint8_t logId](error_t error) { }
  default event void LogWrite.syncDone[uint8_t logId](error_t error) { }
  default event void LogRead.readDone[uint8_t logId](void* buf, storage_len_t l, error_t error) { }
  default event void LogRead.seekDone[uint8_t logId](error_t error) {}

  default command at45page_t At45dbVolume.remap[uint8_t logId](at45page_t volumePage) {return 0;}
  default command at45page_t At45dbVolume.volumeSize[uint8_t logId]() {return 0;}
  default async command error_t Resource.request[uint8_t logId]() {return SUCCESS;}
  default async command error_t Resource.release[uint8_t logId]() { return FAIL; }
}

⌨️ 快捷键说明

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