Blame src/store.cpp

Packit Service 50c9f2
/******************************************************************************
Packit Service 50c9f2
 *
Packit Service 50c9f2
 * 
Packit Service 50c9f2
 *
Packit Service 50c9f2
 *
Packit Service 50c9f2
 * Copyright (C) 1997-2015 by Dimitri van Heesch.
Packit Service 50c9f2
 *
Packit Service 50c9f2
 * Permission to use, copy, modify, and distribute this software and its
Packit Service 50c9f2
 * documentation under the terms of the GNU General Public License is hereby 
Packit Service 50c9f2
 * granted. No representations are made about the suitability of this software 
Packit Service 50c9f2
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit Service 50c9f2
 * See the GNU General Public License for more details.
Packit Service 50c9f2
 *
Packit Service 50c9f2
 * Documents produced by Doxygen are derivative works derived from the
Packit Service 50c9f2
 * input used in their production; they are not affected by this license.
Packit Service 50c9f2
 *
Packit Service 50c9f2
 */
Packit Service 50c9f2
Packit Service 50c9f2
#include "store.h"
Packit Service 50c9f2
#include "portable.h"
Packit Service 50c9f2
Packit Service 50c9f2
Packit Service 50c9f2
#include <stdio.h>
Packit Service 50c9f2
#include <stdlib.h>
Packit Service 50c9f2
#include <errno.h>
Packit Service 50c9f2
#include <string.h>
Packit Service 50c9f2
#include <assert.h>
Packit Service 50c9f2
#include <ctype.h>
Packit Service 50c9f2
Packit Service 50c9f2
#define BLOCK_SIZE         512 // should be >8 and a power of 2
Packit Service 50c9f2
#define BLOCK_POINTER_SIZE sizeof(portable_off_t)
Packit Service 50c9f2
Packit Service 50c9f2
Packit Service 50c9f2
#define ASSERTS_ENABLED
Packit Service 50c9f2
Packit Service 50c9f2
#ifdef ASSERTS_ENABLED
Packit Service 50c9f2
#define STORE_ASSERT(x) assert(x)
Packit Service 50c9f2
#else
Packit Service 50c9f2
#define STORE_ASSERT(x)
Packit Service 50c9f2
#endif
Packit Service 50c9f2
Packit Service 50c9f2
// Decide to use ftell or keep track of the current file pointer ourselves.
Packit Service 50c9f2
// Since valgrind shows that calling ftell has the unwanted side-effect of
Packit Service 50c9f2
// writing some uninitialized bytes (!) it might be better (and faster) to keep track
Packit Service 50c9f2
// of the current pointer ourselves.
Packit Service 50c9f2
#define USE_FTELL 0
Packit Service 50c9f2
Packit Service 50c9f2
//------------------------------------------------------------------------------------
Packit Service 50c9f2
Packit Service 50c9f2
Store::Store() 
Packit Service 50c9f2
{
Packit Service 50c9f2
  m_file       = 0;
Packit Service 50c9f2
  m_front      = 0;
Packit Service 50c9f2
  m_cur        = 0;
Packit Service 50c9f2
  m_head       = 0;
Packit Service 50c9f2
  m_state      = Init;
Packit Service 50c9f2
  m_reads      = 0;
Packit Service 50c9f2
  m_writes     = 0;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
Store::~Store()
Packit Service 50c9f2
{
Packit Service 50c9f2
  if (m_file)   fclose(m_file);
Packit Service 50c9f2
Packit Service 50c9f2
  // clean up free list
Packit Service 50c9f2
  while (m_head)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    Node *node = m_head;
Packit Service 50c9f2
    m_head = node->next;
Packit Service 50c9f2
    delete node;
Packit Service 50c9f2
  }
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
int Store::open(const char *name)
Packit Service 50c9f2
{
Packit Service 50c9f2
  int i;
Packit Service 50c9f2
  STORE_ASSERT(m_state==Init);
Packit Service 50c9f2
  if (m_file) return 0; // already open
Packit Service 50c9f2
  m_file = portable_fopen(name,"w+b");
Packit Service 50c9f2
  if (m_file==0) return -1;
Packit Service 50c9f2
Packit Service 50c9f2
  // first block serves as header, so offset=0 can be used as the end of the list.
Packit Service 50c9f2
  for (i=0;i
Packit Service 50c9f2
  {
Packit Service 50c9f2
    fputc('D',m_file);
Packit Service 50c9f2
    fputc('O',m_file);
Packit Service 50c9f2
    fputc('X',m_file);
Packit Service 50c9f2
    fputc('Y',m_file);
Packit Service 50c9f2
    fputc('G',m_file);
Packit Service 50c9f2
    fputc('E',m_file);
Packit Service 50c9f2
    fputc('N',m_file);
Packit Service 50c9f2
    fputc(0,m_file);
Packit Service 50c9f2
  }
Packit Service 50c9f2
  m_front  = BLOCK_SIZE;
Packit Service 50c9f2
  m_cur    = BLOCK_SIZE;
Packit Service 50c9f2
  m_head   = 0;
Packit Service 50c9f2
  m_state  = Reading;
Packit Service 50c9f2
  return 0;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::close()
Packit Service 50c9f2
{
Packit Service 50c9f2
  if (m_file) fclose(m_file);
Packit Service 50c9f2
  m_file=0;
Packit Service 50c9f2
  m_state  = Init;
Packit Service 50c9f2
}
Packit Service 50c9f2
     
Packit Service 50c9f2
portable_off_t Store::alloc()
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Reading);
Packit Service 50c9f2
  m_state=Writing;
Packit Service 50c9f2
  portable_off_t pos;
Packit Service 50c9f2
  if (m_head==0) // allocate new block
Packit Service 50c9f2
  {
Packit Service 50c9f2
    //printf("alloc: new block, pos=%lld\n",(long long)m_front);
Packit Service 50c9f2
    if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
Packit Service 50c9f2
    {
Packit Service 50c9f2
      fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
Packit Service 50c9f2
      exit(1);
Packit Service 50c9f2
    }
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
    pos = portable_ftell(m_file);
Packit Service 50c9f2
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
Packit Service 50c9f2
    m_front = pos + BLOCK_SIZE; // move front to end of this block
Packit Service 50c9f2
#else
Packit Service 50c9f2
    m_cur = m_front;
Packit Service 50c9f2
    pos   = m_cur;
Packit Service 50c9f2
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
Packit Service 50c9f2
    m_front = pos + BLOCK_SIZE;
Packit Service 50c9f2
#endif
Packit Service 50c9f2
  }
Packit Service 50c9f2
  else // reuse freed block
Packit Service 50c9f2
  {
Packit Service 50c9f2
    //printf("alloc: reuse block: pos=%lld\n",(long long)m_head->pos);
Packit Service 50c9f2
    Node *node = m_head;
Packit Service 50c9f2
    pos = node->pos;
Packit Service 50c9f2
    // point head to next free item
Packit Service 50c9f2
    m_head = node->next;
Packit Service 50c9f2
    delete node;
Packit Service 50c9f2
    // move to start of the block
Packit Service 50c9f2
    if (portable_fseek(m_file,pos,SEEK_SET)==-1)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      fprintf(stderr,"Store::alloc: Error seeking to position %d: %s\n",
Packit Service 50c9f2
          (int)pos,strerror(errno));
Packit Service 50c9f2
      exit(1);
Packit Service 50c9f2
    }
Packit Service 50c9f2
    m_cur = pos;
Packit Service 50c9f2
    STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
Packit Service 50c9f2
  }
Packit Service 50c9f2
  //printf("%x: Store::alloc\n",(int)pos);
Packit Service 50c9f2
  return pos;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
int Store::write(const char *buf,uint size)
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Writing);
Packit Service 50c9f2
  //printf("%x: Store::write\n",(int)portable_ftell(m_file));
Packit Service 50c9f2
  do
Packit Service 50c9f2
  {
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
    portable_off_t curPos = portable_ftell(m_file);
Packit Service 50c9f2
#else
Packit Service 50c9f2
    portable_off_t curPos = m_cur;
Packit Service 50c9f2
#endif
Packit Service 50c9f2
    int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)));
Packit Service 50c9f2
    int bytesLeft    = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0;
Packit Service 50c9f2
    int numBytes     = size - bytesLeft;
Packit Service 50c9f2
    STORE_ASSERT(bytesInBlock>=0);
Packit Service 50c9f2
    STORE_ASSERT(numBytes<=(int)(BLOCK_SIZE-BLOCK_POINTER_SIZE));
Packit Service 50c9f2
    if (numBytes>0)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      if ((int)fwrite(buf,1,numBytes,m_file)!=numBytes)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        fprintf(stderr,"Error writing: %s\n",strerror(errno));
Packit Service 50c9f2
        exit(1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      m_cur+=numBytes;
Packit Service 50c9f2
      m_writes++;
Packit Service 50c9f2
    }
Packit Service 50c9f2
    if (bytesLeft>0) // still more bytes to write
Packit Service 50c9f2
    {
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
      STORE_ASSERT(((portable_ftell(m_file)+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
#else
Packit Service 50c9f2
      STORE_ASSERT(((m_cur+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
#endif
Packit Service 50c9f2
      // allocate new block
Packit Service 50c9f2
      if (m_head==0) // no free blocks to reuse
Packit Service 50c9f2
      {
Packit Service 50c9f2
        //printf("%x: Store::write: new: pos=%x\n",(int)m_front,(int)portable_ftell(m_file));
Packit Service 50c9f2
        // write pointer to next block
Packit Service 50c9f2
        if (fwrite(&m_front,BLOCK_POINTER_SIZE,1,m_file)!=1)
Packit Service 50c9f2
        {
Packit Service 50c9f2
          fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
Packit Service 50c9f2
          exit(1);
Packit Service 50c9f2
        }
Packit Service 50c9f2
        m_cur+=BLOCK_POINTER_SIZE;
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
        STORE_ASSERT(portable_ftell(m_file)==(curPos&~(BLOCK_SIZE-1))+BLOCK_SIZE);
Packit Service 50c9f2
#else
Packit Service 50c9f2
        STORE_ASSERT(m_cur==(curPos&~(BLOCK_SIZE-1))+BLOCK_SIZE);
Packit Service 50c9f2
#endif
Packit Service 50c9f2
        // move to next block
Packit Service 50c9f2
        if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
Packit Service 50c9f2
        {
Packit Service 50c9f2
          fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
Packit Service 50c9f2
          exit(1);
Packit Service 50c9f2
        }
Packit Service 50c9f2
        m_cur=m_front;
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
        STORE_ASSERT(portable_ftell(m_file)==m_front);
Packit Service 50c9f2
#else
Packit Service 50c9f2
        STORE_ASSERT(m_cur==m_front);
Packit Service 50c9f2
#endif
Packit Service 50c9f2
        // move front to the next of the block
Packit Service 50c9f2
        m_front+=BLOCK_SIZE;
Packit Service 50c9f2
      }
Packit Service 50c9f2
      else // reuse block from the free list
Packit Service 50c9f2
      {
Packit Service 50c9f2
        // write pointer to next block
Packit Service 50c9f2
        if (fwrite(&m_head->pos,BLOCK_POINTER_SIZE,1,m_file)!=1)
Packit Service 50c9f2
        {
Packit Service 50c9f2
          fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
Packit Service 50c9f2
          exit(1);
Packit Service 50c9f2
        }
Packit Service 50c9f2
        Node *node = m_head;
Packit Service 50c9f2
        portable_off_t pos = node->pos;
Packit Service 50c9f2
        // point head to next free item
Packit Service 50c9f2
        m_head = node->next;
Packit Service 50c9f2
        delete node;
Packit Service 50c9f2
        // move to start of the block
Packit Service 50c9f2
        if (portable_fseek(m_file,pos,SEEK_SET)==-1)
Packit Service 50c9f2
        {
Packit Service 50c9f2
          fprintf(stderr,"Store::write: Error seeking to position %d: %s\n",
Packit Service 50c9f2
              (int)pos,strerror(errno));
Packit Service 50c9f2
          exit(1);
Packit Service 50c9f2
        }
Packit Service 50c9f2
        m_cur = pos;
Packit Service 50c9f2
        //printf("%x: Store::write: reuse\n",(int)pos);
Packit Service 50c9f2
      }
Packit Service 50c9f2
    }
Packit Service 50c9f2
    size-=numBytes;
Packit Service 50c9f2
    buf+=numBytes;
Packit Service 50c9f2
  }
Packit Service 50c9f2
  while (size>0);
Packit Service 50c9f2
  return size;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::end()
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Writing);
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
  portable_off_t curPos = portable_ftell(m_file);
Packit Service 50c9f2
#else
Packit Service 50c9f2
  portable_off_t curPos = m_cur;
Packit Service 50c9f2
#endif
Packit Service 50c9f2
  int bytesInBlock = (int)(BLOCK_SIZE - (curPos & (BLOCK_SIZE-1)));
Packit Service 50c9f2
  //printf("%x: Store::end erasing %x bytes\n",(int)curPos&~(BLOCK_SIZE-1),bytesInBlock);
Packit Service 50c9f2
  //printf("end: bytesInBlock=%x\n",bytesInBlock);
Packit Service 50c9f2
  // zero out rest of the block
Packit Service 50c9f2
  int i;
Packit Service 50c9f2
  for (i=0;i
Packit Service 50c9f2
  {
Packit Service 50c9f2
    fputc(0,m_file);
Packit Service 50c9f2
  }
Packit Service 50c9f2
  m_state=Reading;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::release(portable_off_t pos)
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Reading);
Packit Service 50c9f2
  //printf("release: block pos=%lld\n",(long long)pos);
Packit Service 50c9f2
  STORE_ASSERT(pos>0 && (pos & (BLOCK_SIZE-1))==0);
Packit Service 50c9f2
  // goto end of the block
Packit Service 50c9f2
  portable_off_t cur = pos, next;
Packit Service 50c9f2
  while (1)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    // add new node to the free list
Packit Service 50c9f2
    Node *node = new Node;
Packit Service 50c9f2
    node->next = m_head;
Packit Service 50c9f2
    node->pos = cur;
Packit Service 50c9f2
Packit Service 50c9f2
    m_head = node;
Packit Service 50c9f2
    // goto the end of cur block
Packit Service 50c9f2
    if (portable_fseek(m_file,cur+BLOCK_SIZE-BLOCK_POINTER_SIZE,SEEK_SET)==-1)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      fprintf(stderr,"Store::release: Error seeking to position %d: %s\n",
Packit Service 50c9f2
          (int)(cur+BLOCK_SIZE-BLOCK_POINTER_SIZE),strerror(errno));
Packit Service 50c9f2
      exit(1);
Packit Service 50c9f2
    }
Packit Service 50c9f2
    // read pointer to next block
Packit Service 50c9f2
    if (fread(&next,BLOCK_POINTER_SIZE,1,m_file)!=1)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      fprintf(stderr,"Store::release: Error reading from store: %s\n",strerror(errno));
Packit Service 50c9f2
      exit(1);
Packit Service 50c9f2
    }
Packit Service 50c9f2
    m_cur = cur+BLOCK_SIZE;
Packit Service 50c9f2
    if (next==0) break; // found end of list -> cur is last element
Packit Service 50c9f2
    STORE_ASSERT((next & (BLOCK_SIZE-1))==0);
Packit Service 50c9f2
    cur = next;
Packit Service 50c9f2
    //printf("%x: Store::release\n",(int)cur);
Packit Service 50c9f2
  }
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::seek(portable_off_t pos)
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Reading);
Packit Service 50c9f2
  //printf("%x: Store::seek\n",(int)pos);
Packit Service 50c9f2
  if (portable_fseek(m_file,pos,SEEK_SET)==-1)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    fprintf(stderr,"Store::seek: Error seeking to position %d: %s\n",
Packit Service 50c9f2
        (int)pos,strerror(errno));
Packit Service 50c9f2
    exit(1);
Packit Service 50c9f2
  }
Packit Service 50c9f2
  m_cur = pos;
Packit Service 50c9f2
  STORE_ASSERT((pos&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
int Store::read(char *buf,uint size)
Packit Service 50c9f2
{
Packit Service 50c9f2
  STORE_ASSERT(m_state==Reading);
Packit Service 50c9f2
  //printf("%x: Store::read total=%d\n",(int)portable_ftell(m_file),size);
Packit Service 50c9f2
  do
Packit Service 50c9f2
  {
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
    portable_off_t curPos = portable_ftell(m_file);
Packit Service 50c9f2
#else
Packit Service 50c9f2
    portable_off_t curPos = m_cur;
Packit Service 50c9f2
#endif
Packit Service 50c9f2
    int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)));
Packit Service 50c9f2
    int bytesLeft    = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0;
Packit Service 50c9f2
    int numBytes     = size - bytesLeft;
Packit Service 50c9f2
    //printf("  Store::read: pos=%x num=%d left=%d\n",(int)curPos,numBytes,bytesLeft);
Packit Service 50c9f2
Packit Service 50c9f2
    if (numBytes>0)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      //printf("%x: Store::read: %d out of %d bytes\n",(int)portable_ftell(m_file),numBytes,size);
Packit Service 50c9f2
      if ((int)fread(buf,1,numBytes,m_file)!=numBytes)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        fprintf(stderr,"Error reading from store: %s\n",strerror(errno));
Packit Service 50c9f2
        exit(1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      m_cur+=numBytes;
Packit Service 50c9f2
      m_reads++;
Packit Service 50c9f2
    }
Packit Service 50c9f2
    if (bytesLeft>0)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      portable_off_t newPos;
Packit Service 50c9f2
      // read offset of the next block
Packit Service 50c9f2
#if USE_FTELL
Packit Service 50c9f2
      STORE_ASSERT(((portable_ftell(m_file)+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
#else
Packit Service 50c9f2
      STORE_ASSERT(((m_cur+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
#endif
Packit Service 50c9f2
      if (fread((char *)&newPos,BLOCK_POINTER_SIZE,1,m_file)!=1)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        fprintf(stderr,"Error reading from store: %s\n",strerror(errno));
Packit Service 50c9f2
        exit(1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      //printf("%x: Store::read: continue in next block, %d bytes to go\n",(int)newPos,bytesLeft);
Packit Service 50c9f2
      //printf("  Store::read: next block=%x\n",(int)newPos);
Packit Service 50c9f2
      STORE_ASSERT(newPos!=0);
Packit Service 50c9f2
      STORE_ASSERT((newPos&(BLOCK_SIZE-1))==0);
Packit Service 50c9f2
      curPos = newPos;
Packit Service 50c9f2
      // move to next block
Packit Service 50c9f2
      if (portable_fseek(m_file,curPos,SEEK_SET)==-1)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        fprintf(stderr,"Store::read: Error seeking to position %d: %s\n",
Packit Service 50c9f2
            (int)curPos,strerror(errno));
Packit Service 50c9f2
        exit(1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      m_cur = curPos;
Packit Service 50c9f2
    }
Packit Service 50c9f2
Packit Service 50c9f2
    size-=numBytes;
Packit Service 50c9f2
    buf+=numBytes;
Packit Service 50c9f2
  }
Packit Service 50c9f2
  while (size>0);
Packit Service 50c9f2
  return size;
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::printFreeList()
Packit Service 50c9f2
{
Packit Service 50c9f2
  printf("FreeList: ");
Packit Service 50c9f2
  while (m_head)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    portable_off_t pos = m_head->pos;
Packit Service 50c9f2
    printf("%x ",(int)pos);
Packit Service 50c9f2
    m_head = m_head->next;
Packit Service 50c9f2
  }
Packit Service 50c9f2
  printf("\n");
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::printStats()
Packit Service 50c9f2
{
Packit Service 50c9f2
  printf("ObjStore: block size %d bytes, total size %ld blocks, wrote %d blocks, read %d blocks\n",
Packit Service 50c9f2
      BLOCK_SIZE,(long)(m_front/BLOCK_SIZE),m_reads,m_writes);
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
void Store::dumpBlock(portable_off_t s,portable_off_t e)
Packit Service 50c9f2
{
Packit Service 50c9f2
  portable_fseek(m_file,s,SEEK_SET);
Packit Service 50c9f2
  int size = (int)(e-s);
Packit Service 50c9f2
  uchar *buf = new uchar[size];
Packit Service 50c9f2
  if (fread(buf,size,1,m_file)==(size_t)size)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    int i,j;
Packit Service 50c9f2
    for (i=0;i
Packit Service 50c9f2
    {
Packit Service 50c9f2
      printf("%08x: ",(int)s+i);
Packit Service 50c9f2
      for (j=i;j
Packit Service 50c9f2
      {
Packit Service 50c9f2
        printf("%02x ",buf[i+j]);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      printf("  ");
Packit Service 50c9f2
      for (j=i;j
Packit Service 50c9f2
      {
Packit Service 50c9f2
        printf("%c",(buf[i+j]>=32 && buf[i+j]<128)?buf[i+j]:'.');
Packit Service 50c9f2
      }
Packit Service 50c9f2
      printf("\n");
Packit Service 50c9f2
    }
Packit Service 50c9f2
  }
Packit Service 50c9f2
  delete[] buf;
Packit Service 50c9f2
  portable_fseek(m_file,m_cur,SEEK_SET);
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
#ifdef  STORE_TEST
Packit Service 50c9f2
Packit Service 50c9f2
int main()
Packit Service 50c9f2
{
Packit Service 50c9f2
  printf("sizeof(portable_off_t)=%d\n",(int)sizeof(portable_off_t));
Packit Service 50c9f2
  Store s;
Packit Service 50c9f2
  if (s.open("test.db")==0)
Packit Service 50c9f2
  {
Packit Service 50c9f2
    const char *str1 = "This is a test message... ";
Packit Service 50c9f2
    const char *str2 = "Another message. ";
Packit Service 50c9f2
Packit Service 50c9f2
    int i,j;
Packit Service 50c9f2
    for (j=0;j<5;j++)
Packit Service 50c9f2
    {
Packit Service 50c9f2
      char buf[100];
Packit Service 50c9f2
Packit Service 50c9f2
      portable_off_t handle = s.alloc();
Packit Service 50c9f2
      for (i=0;i<1000000000;i++)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        s.write(str1,strlen(str1)+1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      s.end();
Packit Service 50c9f2
      portable_off_t handle2 = s.alloc();
Packit Service 50c9f2
      for (i=0;i<10;i++)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        s.write(str2,strlen(str2)+1);
Packit Service 50c9f2
      }
Packit Service 50c9f2
      s.end();
Packit Service 50c9f2
Packit Service 50c9f2
      s.seek(handle);
Packit Service 50c9f2
      for (i=0;i<3;i++)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        s.read(buf,strlen(str1)+1);
Packit Service 50c9f2
        printf("i=%d Read: %s\n",i,buf);
Packit Service 50c9f2
      }
Packit Service 50c9f2
Packit Service 50c9f2
      s.release(handle);
Packit Service 50c9f2
Packit Service 50c9f2
      s.seek(handle2);
Packit Service 50c9f2
      for (i=0;i<3;i++)
Packit Service 50c9f2
      {
Packit Service 50c9f2
        s.read(buf,strlen(str2)+1);
Packit Service 50c9f2
        printf("i=%d Read: %s\n",i,buf);
Packit Service 50c9f2
      }
Packit Service 50c9f2
Packit Service 50c9f2
      s.release(handle2);
Packit Service 50c9f2
    }
Packit Service 50c9f2
Packit Service 50c9f2
    s.close();
Packit Service 50c9f2
  }
Packit Service 50c9f2
  else
Packit Service 50c9f2
  {
Packit Service 50c9f2
    printf("Open failed! %s\n",strerror(errno));
Packit Service 50c9f2
  }
Packit Service 50c9f2
}
Packit Service 50c9f2
Packit Service 50c9f2
#endif
Packit Service 50c9f2