Пример #1
0
int Store::read(char *buf, uint size)
{
   STORE_ASSERT(m_state == Reading);
   //printf("%x: Store::read total=%d\n",(int)portable_ftell(m_file),size);
   do {
#if USE_FTELL
      portable_off_t curPos = portable_ftell(m_file);
#else
      portable_off_t curPos = m_cur;
#endif
      int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE - 1)));
      int bytesLeft    = bytesInBlock < (int)size ? (int)size - bytesInBlock : 0;
      int numBytes     = size - bytesLeft;
      //printf("  Store::read: pos=%x num=%d left=%d\n",(int)curPos,numBytes,bytesLeft);

      if (numBytes > 0) {
         //printf("%x: Store::read: %d out of %d bytes\n",(int)portable_ftell(m_file),numBytes,size);
         if ((int)fread(buf, 1, numBytes, m_file) != numBytes) {
            fprintf(stderr, "Error reading from store: %s\n", strerror(errno));
            exit(1);
         }
         m_cur += numBytes;
         m_reads++;
      }
      if (bytesLeft > 0) {
         portable_off_t newPos;
         // read offset of the next block
#if USE_FTELL
         STORE_ASSERT(((portable_ftell(m_file) + BLOCK_POINTER_SIZE) & (BLOCK_SIZE - 1)) == 0);
#else
         STORE_ASSERT(((m_cur + BLOCK_POINTER_SIZE) & (BLOCK_SIZE - 1)) == 0);
#endif
         if (fread((char *)&newPos, BLOCK_POINTER_SIZE, 1, m_file) != 1) {
            fprintf(stderr, "Error reading from store: %s\n", strerror(errno));
            exit(1);
         }
         //printf("%x: Store::read: continue in next block, %d bytes to go\n",(int)newPos,bytesLeft);
         //printf("  Store::read: next block=%x\n",(int)newPos);
         STORE_ASSERT(newPos != 0);
         STORE_ASSERT((newPos & (BLOCK_SIZE - 1)) == 0);
         curPos = newPos;
         // move to next block
         if (portable_fseek(m_file, curPos, SEEK_SET) == -1) {
            fprintf(stderr, "Store::read: Error seeking to position %d: %s\n",
                    (int)curPos, strerror(errno));
            exit(1);
         }
         m_cur = curPos;
      }

      size -= numBytes;
      buf += numBytes;
   } while (size > 0);
   return size;
}
Пример #2
0
portable_off_t Store::alloc()
{
  STORE_ASSERT(m_state==Reading);
  m_state=Writing;
  portable_off_t pos;
  if (m_head==0) // allocate new block
  {
    //printf("alloc: new block, pos=%lld\n",(long long)m_front);
    if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
    {
      fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
      exit(1);
    }
#if USE_FTELL
    pos = portable_ftell(m_file);
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
    m_front = pos + BLOCK_SIZE; // move front to end of this block
#else
    m_cur = m_front;
    pos   = m_cur;
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
    m_front = pos + BLOCK_SIZE;
#endif
  }
  else // reuse freed block
  {
    //printf("alloc: reuse block: pos=%lld\n",(long long)m_head->pos);
    Node *node = m_head;
    pos = node->pos;
    // point head to next free item
    m_head = node->next;
    delete node;
    // move to start of the block
    if (portable_fseek(m_file,pos,SEEK_SET)==-1)
    {
      fprintf(stderr,"Store::alloc: Error seeking to position %d: %s\n",
          (int)pos,strerror(errno));
      exit(1);
    }
    m_cur = pos;
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
  }
  //printf("%x: Store::alloc\n",(int)pos);
  return pos;
}
Пример #3
0
void Store::end()
{
   STORE_ASSERT(m_state == Writing);
#if USE_FTELL
   portable_off_t curPos = portable_ftell(m_file);
#else
   portable_off_t curPos = m_cur;
#endif
   int bytesInBlock = (int)(BLOCK_SIZE - (curPos & (BLOCK_SIZE - 1)));
   //printf("%x: Store::end erasing %x bytes\n",(int)curPos&~(BLOCK_SIZE-1),bytesInBlock);
   //printf("end: bytesInBlock=%x\n",bytesInBlock);
   // zero out rest of the block
   int i;
   for (i = 0; i < bytesInBlock; i++) {
      fputc(0, m_file);
   }
   m_state = Reading;
}
Пример #4
0
bool BufferedFile::seek(
    const int64         offset,
    const SeekOrigin    origin)
{
    assert(m_file);
    assert(m_buffer);

    // Seeking from the end is handled separately, since we don't know the size of the file.
    if (origin == SeekFromEnd)
    {
        if (m_file_mode == ReadMode)
            invalidate_buffer();
        else flush_buffer();

        if (portable_fseek(m_file, offset, SEEK_END))
            return false;

        m_file_index = portable_ftell(m_file);
    }
    else
    {
        int64 target_index;

        if (origin == SeekFromBeginning)
            target_index = offset;
        else
        {
            assert(origin == SeekFromCurrent);
            const int64 current_index = m_file_index + static_cast<int64>(m_buffer_index);
            target_index = max<int64>(current_index + offset, 0);
        }

        if (target_index >= m_file_index &&
            target_index <  m_file_index + static_cast<int64>(m_buffer_end))
        {
            // Seek within the I/O buffer.
            m_buffer_index = static_cast<size_t>(target_index - m_file_index);
        }
        else
        {
            int64 current_file_index;

            if (m_file_mode == ReadMode)
            {
                current_file_index = m_file_index + static_cast<int64>(m_buffer_end);
                invalidate_buffer();
            }
            else
            {
                current_file_index = m_file_index;
                flush_buffer();
            }

            if (portable_fseek(m_file, target_index - current_file_index, SEEK_CUR))
                return false;

            m_file_index = portable_ftell(m_file);
        }
    }

    return true;
}
Пример #5
0
int Store::write(const char *buf,uint size)
{
  STORE_ASSERT(m_state==Writing);
  //printf("%x: Store::write\n",(int)portable_ftell(m_file));
  do
  {
#if USE_FTELL
    portable_off_t curPos = portable_ftell(m_file);
#else
    portable_off_t curPos = m_cur;
#endif
    int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)));
    int bytesLeft    = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0;
    int numBytes     = size - bytesLeft;
    STORE_ASSERT(bytesInBlock>=0);
    STORE_ASSERT(numBytes<=(int)(BLOCK_SIZE-BLOCK_POINTER_SIZE));
    if (numBytes>0)
    {
      if ((int)fwrite(buf,1,numBytes,m_file)!=numBytes)
      {
        fprintf(stderr,"Error writing: %s\n",strerror(errno));
        exit(1);
      }
      m_cur+=numBytes;
      m_writes++;
    }
    if (bytesLeft>0) // still more bytes to write
    {
#if USE_FTELL
      STORE_ASSERT(((portable_ftell(m_file)+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
#else
      STORE_ASSERT(((m_cur+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
#endif
      // allocate new block
      if (m_head==0) // no free blocks to reuse
      {
        //printf("%x: Store::write: new: pos=%x\n",(int)m_front,(int)portable_ftell(m_file));
        // write pointer to next block
        if (fwrite(&m_front,BLOCK_POINTER_SIZE,1,m_file)!=1)
        {
          fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
          exit(1);
        }
        m_cur+=BLOCK_POINTER_SIZE;
#if USE_FTELL
        STORE_ASSERT(portable_ftell(m_file)==(curPos&~(BLOCK_SIZE-1))+BLOCK_SIZE);
#else
        STORE_ASSERT(m_cur==(curPos&~(BLOCK_SIZE-1))+BLOCK_SIZE);
#endif
        // move to next block
        if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
        {
          fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
          exit(1);
        }
        m_cur=m_front;
#if USE_FTELL
        STORE_ASSERT(portable_ftell(m_file)==m_front);
#else
        STORE_ASSERT(m_cur==m_front);
#endif
        // move front to the next of the block
        m_front+=BLOCK_SIZE;
      }
      else // reuse block from the free list
      {
        // write pointer to next block
        if (fwrite(&m_head->pos,BLOCK_POINTER_SIZE,1,m_file)!=1)
        {
          fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
          exit(1);
        }
        Node *node = m_head;
        portable_off_t pos = node->pos;
        // point head to next free item
        m_head = node->next;
        delete node;
        // move to start of the block
        if (portable_fseek(m_file,pos,SEEK_SET)==-1)
        {
          fprintf(stderr,"Store::write: Error seeking to position %d: %s\n",
              (int)pos,strerror(errno));
          exit(1);
        }
        m_cur = pos;
        //printf("%x: Store::write: reuse\n",(int)pos);
      }
    }
    size-=numBytes;
    buf+=numBytes;
  }
  while (size>0);
  return size;
}