diff options
Diffstat (limited to 'src/store.cpp')
-rw-r--r-- | src/store.cpp | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/src/store.cpp b/src/store.cpp index aafb4a4..4b66b6b 100644 --- a/src/store.cpp +++ b/src/store.cpp @@ -26,7 +26,7 @@ #include <string.h> #include <assert.h> -#define BLOCK_SIZE 512 // should be >8 and a multiple of 8 +#define BLOCK_SIZE 512 // should be >8 and a power of 2 #define BLOCK_POINTER_SIZE sizeof(portable_off_t) @@ -38,12 +38,19 @@ #define STORE_ASSERT(x) #endif +// Decide to use ftell or keep track of the current file pointer ourselves. +// Since valgrind shows that calling ftell has the unwanted side-effect of +// writing some uninitialized bytes (!) it might be better (and faster) to keep track +// of the current pointer ourselves. +#define USE_FTELL 0 + //------------------------------------------------------------------------------------ Store::Store() { m_file = 0; m_front = 0; + m_cur = 0; m_head = 0; m_state = Init; m_reads = 0; @@ -84,6 +91,7 @@ int Store::open(const char *name) fputc(0,m_file); } m_front = BLOCK_SIZE; + m_cur = BLOCK_SIZE; m_head = 0; m_state = Reading; return 0; @@ -109,9 +117,16 @@ portable_off_t Store::alloc() 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 { @@ -128,6 +143,7 @@ portable_off_t Store::alloc() (int)pos,strerror(errno)); exit(1); } + m_cur = pos; STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 ); } //printf("%x: Store::alloc\n",(int)pos); @@ -140,7 +156,11 @@ int Store::write(const char *buf,uint size) //printf("%x: Store::write\n",(int)portable_ftell(m_file)); do { - portable_off_t curPos = portable_ftell(m_file); +#if USE_FTELL + portable_off_t curPos = portable_ftell(m_file); +#else + portable_off_t curPos = m_cur; +#endif int bytesInBlock = BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)); int bytesLeft = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0; int numBytes = size - bytesLeft; @@ -153,11 +173,16 @@ int Store::write(const char *buf,uint size) 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 { @@ -168,15 +193,24 @@ int Store::write(const char *buf,uint size) 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; } @@ -200,6 +234,7 @@ int Store::write(const char *buf,uint size) (int)pos,strerror(errno)); exit(1); } + m_cur = pos; //printf("%x: Store::write: reuse\n",(int)pos); } } @@ -213,7 +248,11 @@ int Store::write(const char *buf,uint size) void Store::end() { STORE_ASSERT(m_state==Writing); - portable_off_t curPos = portable_ftell(m_file); +#if USE_FTELL + portable_off_t curPos = portable_ftell(m_file); +#else + portable_off_t curPos = m_cur; +#endif int bytesInBlock = 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); @@ -254,6 +293,7 @@ void Store::release(portable_off_t pos) fprintf(stderr,"Store::release: Error reading from store: %s\n",strerror(errno)); exit(1); } + m_cur = cur+BLOCK_SIZE; if (next==0) break; // found end of list -> cur is last element STORE_ASSERT((next & (BLOCK_SIZE-1))==0); cur = next; @@ -271,6 +311,7 @@ void Store::seek(portable_off_t pos) (int)pos,strerror(errno)); exit(1); } + m_cur = pos; STORE_ASSERT((pos&(BLOCK_SIZE-1))==0); } @@ -280,7 +321,11 @@ int Store::read(char *buf,uint size) //printf("%x: Store::read total=%d\n",(int)portable_ftell(m_file),size); do { - portable_off_t curPos = portable_ftell(m_file); +#if USE_FTELL + portable_off_t curPos = portable_ftell(m_file); +#else + portable_off_t curPos = m_cur; +#endif int bytesInBlock = BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)); int bytesLeft = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0; int numBytes = size - bytesLeft; @@ -294,13 +339,18 @@ int Store::read(char *buf,uint size) 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)); @@ -318,6 +368,7 @@ int Store::read(char *buf,uint size) (int)curPos,strerror(errno)); exit(1); } + m_cur = curPos; } size-=numBytes; |