summaryrefslogtreecommitdiffstats
path: root/src/store.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/store.cpp')
-rw-r--r--src/store.cpp61
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;