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

📄 p30logp.nc

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

  /*
   * Invariant should be that everytime after an append completes,
   * nextFreeRecord should point to a valid free record slot. Uses
   * nextFreeRecord to append.
   */
  command error_t Write.append[ storage_volume_t block ](void* buf, storage_len_t len) {
    record_meta_t recordMeta;

    myMount(block);
    
    // error check
    if(len > L_RECORD_DATA_SIZE)
      return EINVAL;

    // if non circular log, fail
    if((!call Circular.get[block]()) &&
       (lastBlock[block] == (L_PARTITIONS(block) - 1)) &&
       (nextFreeRecord[block] == (L_MAX_RECORDS_PER_BLOCK - 1)))
      return FAIL;

    m_state = S_APPEND;
    clientId = block;
    clientBuf = buf;
    clientLen = len;

    // if you try to log 0, just immediately succeed, this really shouldn't happen
    if(len == 0) {
      clientResult = SUCCESS;
      post signalDoneTask();
      return SUCCESS;
    }

    // if readCookie was on SEEK_EOL, adjust it back to here
    if(readCookieOffset[block] == SEEK_EOL)
      readCookieOffset[block] = L_RAW_OFFSET(block, lastBlock[block], nextFreeRecord[block]) + sizeof(record_meta_t);
      
    // use next free record, write the INVALID, write the data, write the VALID
    recordMeta.status = RECORD_INVALID;
    recordMeta.length = len;
    call Flash.write(L_RAW_OFFSET(block, lastBlock[block], nextFreeRecord[block]),
		     (uint8_t*) &recordMeta,
		     sizeof(record_meta_t));
    call Flash.write(L_RAW_OFFSET(block, lastBlock[block], nextFreeRecord[block]) +
		     sizeof(record_meta_t),
		     (uint8_t*) buf, len);
    recordMeta.status = RECORD_VALID;
    call Flash.write(L_RAW_OFFSET(block, lastBlock[block], nextFreeRecord[block]),
		     (uint8_t*) &recordMeta,
		     sizeof(record_meta_t));
    nextFreeRecord[block]++;
    // see if you need to adjust blocks or shuffle
    if(nextFreeRecord[block] == L_MAX_RECORDS_PER_BLOCK)
      shuffleBlocks(block);

    clientResult = SUCCESS;
    post signalDoneTask();
    
    return SUCCESS;
  }

  /*
   * We use nextFreeRecord to get the cookie
   */
  command storage_cookie_t Write.currentOffset[ storage_volume_t block ]() {
    myMount(block);

    return L_RAW_OFFSET(block, lastBlock[block], nextFreeRecord[block]) +
      sizeof(record_meta_t);
  }

  /*
   * First we erase all the log data blocks so that they can be
   * reused. Then we zero the cookies and then write them to our
   * partitions like the append operation. If we crash in the middle,
   * you may have to erase again. However, if an erase does fail, at
   * least all your data will still be there, so that you can try
   * again.
   */
  command error_t Write.erase[storage_volume_t block]() {
    uint32_t i;

    for(i = 0; i < L_PARTITIONS(block); i++) {
      call Flash.erase(L_BASE_BLOCK(block) + (i * P30_BLOCK_SIZE));
    }

    mountBits[block] = 0;
    myMount(block);

    // ... starting block implicitly written by mount

    m_state = S_ERASE;
    clientId = block;
    clientResult = SUCCESS;
    post signalDoneTask();

    return SUCCESS;
  }

  /*
   * Sync does nothing really because unlike the AT45DB, Intel P30
   * writes directly through.
   */
  command error_t Write.sync[storage_volume_t block]() {
    myMount(block);

    m_state = S_SYNC;
    
    clientId = block;
    clientResult = SUCCESS;
    
    post signalDoneTask();
    return SUCCESS;

  }

  /*
   * Sanity check the read cookie and adjust for any other special
   * cookies. Because you can seek to the byte, must it is saved in
   * flash as records, you have to do a lot of tricky seeking, but
   * it's done here. Also has to handle any pages that are spilled
   * over.
   */
  command error_t Read.read[ storage_volume_t block ](void* buf, storage_len_t len) {
    record_meta_t recordMeta;
    uint32_t recordCounter;
    uint32_t pageCounter;
    uint32_t offset;

    clientId = block;
    clientBuf = buf;
    clientResult = SUCCESS;

    myMount(block);

    m_state = S_READ;
    
    if(len == 0 || readCookieOffset[block] == SEEK_EOL) {
      clientResult = SUCCESS;
      clientLen = 0;
      post signalDoneTask();
      return SUCCESS;
    }
    
    // adjust SEEK_BEGINNING to a real offset
    if(readCookieOffset[block] == SEEK_BEGINNING) {
      readCookieOffset[block] = L_RAW_OFFSET(block, firstBlock[block], 1) +
	sizeof(record_meta_t);
    }
    
    // convert the cookie to something useful
    cookieToTuple(readCookieOffset[block], block, &pageCounter, &recordCounter, &offset);
    // sanity check readCookie
    call Flash.read(L_RAW_OFFSET(block, pageCounter, recordCounter),
		    (uint8_t*) &recordMeta,
		    sizeof(record_meta_t));
    if((recordMeta.status == RECORD_VALID) && (offset > len)) {
      readCookieOffset[block] = L_RAW_OFFSET(block, firstBlock[block], 0) + sizeof(record_meta_t);
      cookieToTuple(readCookieOffset[block], block, &pageCounter, &recordCounter, &offset);
    }

    clientLen = 0; // reset how much actually read and count up

    
    while(len != 0) {
      call Flash.read(L_RAW_OFFSET(block, pageCounter, recordCounter),
		      (uint8_t*) &recordMeta,
		      sizeof(record_meta_t));
      if(recordMeta.status == RECORD_INVALID) {
	goto advance_counter;
      }
      if(recordMeta.status == RECORD_EMPTY) {
	readCookieOffset[block] = SEEK_EOL;
	post signalDoneTask();
	return SUCCESS;
      }
      // read partial block and finish
      if(len < recordMeta.length + offset) {
	call Flash.read(L_RAW_OFFSET(block, pageCounter, recordCounter) +
			offset + sizeof(record_meta_t),
			buf,
			len);
	offset = len;
	buf = buf + len;
	len = 0;
      }
      else {
	call Flash.read(L_RAW_OFFSET(block, pageCounter, recordCounter) + 
			offset + sizeof(record_meta_t),
			buf,
			recordMeta.length - offset);
	clientLen = clientLen + recordMeta.length - offset;
	len -= recordMeta.length - offset;
	buf = buf + recordMeta.length - offset;
	offset = 0;
      
      advance_counter:
	recordCounter++;
	if((recordCounter >= L_MAX_RECORDS_PER_BLOCK) && (pageCounter == lastBlock[block])) {
	  readCookieOffset[block] = SEEK_EOL;
	  post signalDoneTask();
	  return SUCCESS;
	}
	// need to adjust page possibly if spills
	// also need to check if reached end of log (lastBlock[block] or RECORD_AVAILABLE)
	if(recordCounter >= L_MAX_RECORDS_PER_BLOCK) {
	  pageCounter = (pageCounter + 1) % L_PARTITIONS(block);
	  recordCounter = 1;
	}
      }
    }

    readCookieOffset[block] = L_RAW_OFFSET(block, pageCounter, recordCounter) +
      sizeof(record_meta_t) + offset;
    post signalDoneTask();
    return SUCCESS;
  }
    
  command storage_cookie_t Read.currentOffset[ storage_volume_t block ]() {
    myMount(block);
    return readCookieOffset[block];
  }

  /*
   * Just set the cookie. If you seek into an invalid area, just set
   * it at SEEK_BEGINNING.
   */
  command error_t Read.seek[ storage_volume_t block ](storage_cookie_t offset) {
    uint32_t page;
    uint32_t record;
    uint32_t recordOffset;
    record_meta_t recordMeta;
    myMount(block);

    clientId = block;
    clientResult = SUCCESS;

    m_state = S_SEEK;

    readCookieOffset[block] = offset;

    post signalDoneTask();      
    
    return SUCCESS;
  }

  /*
   * Go through all the pages, if it's a free page, count whatever is
   * available left. Add them all up.
   */
  command storage_len_t Read.getSize[ storage_volume_t block ]() {
    storage_len_t len = 0;
    uint32_t i;
    uint32_t j;
    page_meta_t pageMeta;
    record_meta_t recordMeta;
    
    myMount(block);
    
    for(i = 0; i < L_PARTITIONS(block); i++) {
      call Flash.read(L_RAW_OFFSET(block, i, j),
		      (uint8_t*) &pageMeta,
		      sizeof(page_meta_t));
      if(pageMeta.header != PAGE_AVAILABLE) {
	len = len + (sizeof(record_data_t) * L_MAX_RECORDS_PER_BLOCK);
	continue;
      }
      for(j = 1; j < L_MAX_RECORDS_PER_BLOCK; j++) {
	call Flash.read(L_RAW_OFFSET(block, i, j),
			(uint8_t*) &recordMeta,
			sizeof(record_meta_t));
	if(recordMeta.status == RECORD_EMPTY) {
	  len = len + ((L_MAX_RECORDS_PER_BLOCK - j) * sizeof(record_meta_t));
	  break;
	}
      }
    }
    
    return len;
  }

  default event void Read.readDone[ storage_volume_t block ](void* buf, storage_len_t len, error_t error) {}
  default event void Read.seekDone[ storage_volume_t block ](error_t error) {}
  default event void Write.appendDone[ storage_volume_t block ](void* buf, storage_len_t len, bool recordsLost, error_t error) {}

  default event void Write.eraseDone[ storage_volume_t block ](error_t error) {}
  default event void Write.syncDone[ storage_volume_t block ](error_t error) {}

  default command bool Circular.get[ uint8_t id ]() { return FALSE; }
}

⌨️ 快捷键说明

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