Classes | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
Store Class Reference

The Store is a file based memory manager. More...

#include <store.h>

Inheritance diagram for Store:
StorageIntf

Classes

struct  Node
 

Public Member Functions

 Store ()
 
 ~Store ()
 
int open (const char *name)
 
portable_off_t alloc ()
 
int write (const char *buf, uint size)
 
void end ()
 
void release (portable_off_t handle)
 
void close ()
 
void seek (portable_off_t handle)
 
int read (char *buf, uint size)
 
void printStats ()
 
portable_off_t pos () const
 
void dumpBlock (portable_off_t start, portable_off_t end)
 
- Public Member Functions inherited from StorageIntf
virtual ~StorageIntf ()
 

Private Types

enum  State { Init, Reading, Writing }
 

Private Member Functions

void printFreeList ()
 

Private Attributes

FILE * m_file
 
portable_off_t m_front
 
portable_off_t m_cur
 
Nodem_head
 
State m_state
 
int m_reads
 
int m_writes
 

Detailed Description

The Store is a file based memory manager.

You can open the store using open(). Then obtain a handle via alloc() followed by a sequence of write() commands to store information, and finalize it using end().

Later on you locate the information with seek() using the handle obtained with alloc(), and then use a sequence of read() calls to read the information back.

If no longer needed the storage space can be freed using release().

The store will dynamically grow the file on disk if needed.

Definition at line 52 of file store.h.

Member Enumeration Documentation

enum Store::State
private
Enumerator
Init 
Reading 
Writing 

Definition at line 102 of file store.h.

103  {
104  Init,
105  Reading,
106  Writing
107  };

Constructor & Destructor Documentation

Store::Store ( )

Creates a store.

Definition at line 50 of file store.cpp.

51 {
52  m_file = 0;
53  m_front = 0;
54  m_cur = 0;
55  m_head = 0;
56  m_state = Init;
57  m_reads = 0;
58  m_writes = 0;
59 }
State m_state
Definition: store.h:118
portable_off_t m_cur
Definition: store.h:116
int m_reads
Definition: store.h:119
Node * m_head
Definition: store.h:117
portable_off_t m_front
Definition: store.h:115
FILE * m_file
Definition: store.h:114
int m_writes
Definition: store.h:120
Store::~Store ( )

Releases the store object. Will close the underlying file if opened.

Definition at line 61 of file store.cpp.

62 {
63  if (m_file) fclose(m_file);
64 
65  // clean up free list
66  while (m_head)
67  {
68  Node *node = m_head;
69  m_head = node->next;
70  delete node;
71  }
72 }
Node * m_head
Definition: store.h:117
FILE * m_file
Definition: store.h:114

Member Function Documentation

portable_off_t Store::alloc ( )

Allocates a handle to write to and read from.

Definition at line 108 of file store.cpp.

109 {
113  if (m_head==0) // allocate new block
114  {
115  //printf("alloc: new block, pos=%lld\n",(long long)m_front);
116  if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
117  {
118  fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
119  exit(1);
120  }
121 #if USE_FTELL
122  pos = portable_ftell(m_file);
123  STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
124  m_front = pos + BLOCK_SIZE; // move front to end of this block
125 #else
126  m_cur = m_front;
127  pos = m_cur;
128  STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
129  m_front = pos + BLOCK_SIZE;
130 #endif
131  }
132  else // reuse freed block
133  {
134  //printf("alloc: reuse block: pos=%lld\n",(long long)m_head->pos);
135  Node *node = m_head;
136  pos = node->pos;
137  // point head to next free item
138  m_head = node->next;
139  delete node;
140  // move to start of the block
141  if (portable_fseek(m_file,pos,SEEK_SET)==-1)
142  {
143  fprintf(stderr,"Store::alloc: Error seeking to position %d: %s\n",
144  (int)pos,strerror(errno));
145  exit(1);
146  }
147  m_cur = pos;
148  STORE_ASSERT( (pos & (BLOCK_SIZE-1))==0 );
149  }
150  //printf("%x: Store::alloc\n",(int)pos);
151  return pos;
152 }
State m_state
Definition: store.h:118
off_t portable_off_t
Definition: portable.h:11
int errno
Contains the last error code.
Definition: structcmd.h:53
portable_off_t pos() const
Definition: store.h:97
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
portable_off_t portable_ftell(FILE *f)
Definition: portable.cpp:333
Node * m_head
Definition: store.h:117
portable_off_t m_front
Definition: store.h:115
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
#define BLOCK_SIZE
Definition: store.cpp:30
void Store::close ( )

Closes the store

Definition at line 101 of file store.cpp.

102 {
103  if (m_file) fclose(m_file);
104  m_file=0;
105  m_state = Init;
106 }
State m_state
Definition: store.h:118
FILE * m_file
Definition: store.h:114
void Store::dumpBlock ( portable_off_t  start,
portable_off_t  end 
)

Definition at line 400 of file store.cpp.

401 {
402  portable_fseek(m_file,s,SEEK_SET);
403  int size = (int)(e-s);
404  uchar *buf = new uchar[size];
405  if (fread(buf,size,1,m_file)==(size_t)size)
406  {
407  int i,j;
408  for (i=0;i<size;i+=16)
409  {
410  printf("%08x: ",(int)s+i);
411  for (j=i;j<QMIN(size,i+16);j++)
412  {
413  printf("%02x ",buf[i+j]);
414  }
415  printf(" ");
416  for (j=i;j<QMIN(size,i+16);j++)
417  {
418  printf("%c",(buf[i+j]>=32 && buf[i+j]<128)?buf[i+j]:'.');
419  }
420  printf("\n");
421  }
422  }
423  delete[] buf;
424  portable_fseek(m_file,m_cur,SEEK_SET);
425 }
unsigned char uchar
Definition: nybbler.cc:11
#define QMIN(a, b)
Definition: qglobal.h:391
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
const double e
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
FILE * m_file
Definition: store.h:114
static QCString * s
Definition: config.cpp:1042
void Store::end ( )

Ends the sequence of writes.

Note
After this call, first alloc() has to be called before new writes can be done.

Definition at line 249 of file store.cpp.

250 {
252 #if USE_FTELL
254 #else
255  portable_off_t curPos = m_cur;
256 #endif
257  int bytesInBlock = (int)(BLOCK_SIZE - (curPos & (BLOCK_SIZE-1)));
258  //printf("%x: Store::end erasing %x bytes\n",(int)curPos&~(BLOCK_SIZE-1),bytesInBlock);
259  //printf("end: bytesInBlock=%x\n",bytesInBlock);
260  // zero out rest of the block
261  int i;
262  for (i=0;i<bytesInBlock;i++)
263  {
264  fputc(0,m_file);
265  }
267 }
State m_state
Definition: store.h:118
off_t portable_off_t
Definition: portable.h:11
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_ftell(FILE *f)
Definition: portable.cpp:333
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
#define BLOCK_SIZE
Definition: store.cpp:30
int Store::open ( const char *  name)

Opens the file underlying the store using name as the file name. Returns 0 upon success, or -1 otherwise.

Definition at line 74 of file store.cpp.

75 {
76  int i;
78  if (m_file) return 0; // already open
79  m_file = portable_fopen(name,"w+b");
80  if (m_file==0) return -1;
81 
82  // first block serves as header, so offset=0 can be used as the end of the list.
83  for (i=0;i<BLOCK_SIZE/8;i++)
84  {
85  fputc('D',m_file);
86  fputc('O',m_file);
87  fputc('X',m_file);
88  fputc('Y',m_file);
89  fputc('G',m_file);
90  fputc('E',m_file);
91  fputc('N',m_file);
92  fputc(0,m_file);
93  }
95  m_cur = BLOCK_SIZE;
96  m_head = 0;
97  m_state = Reading;
98  return 0;
99 }
static QCString name
Definition: declinfo.cpp:673
State m_state
Definition: store.h:118
portable_off_t m_cur
Definition: store.h:116
Node * m_head
Definition: store.h:117
portable_off_t m_front
Definition: store.h:115
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
FILE * portable_fopen(const char *fileName, const char *mode)
Definition: portable.cpp:344
#define BLOCK_SIZE
Definition: store.cpp:30
portable_off_t Store::pos ( ) const
inline

Definition at line 97 of file store.h.

97 { return m_cur; }
portable_off_t m_cur
Definition: store.h:116
void Store::printFreeList ( )
private

Definition at line 382 of file store.cpp.

383 {
384  printf("FreeList: ");
385  while (m_head)
386  {
388  printf("%x ",(int)pos);
389  m_head = m_head->next;
390  }
391  printf("\n");
392 }
off_t portable_off_t
Definition: portable.h:11
portable_off_t pos
Definition: store.h:110
portable_off_t pos() const
Definition: store.h:97
struct Node * next
Definition: store.h:111
Node * m_head
Definition: store.h:117
void Store::printStats ( )

Definition at line 394 of file store.cpp.

395 {
396  printf("ObjStore: block size %d bytes, total size %ld blocks, wrote %d blocks, read %d blocks\n",
398 }
int m_reads
Definition: store.h:119
portable_off_t m_front
Definition: store.h:115
int m_writes
Definition: store.h:120
#define BLOCK_SIZE
Definition: store.cpp:30
int Store::read ( char *  buf,
uint  size 
)
virtual

Reads size bytes from the store into the array pointed to be buf.

Note
Before reading seek() has to be called to set the right start of the store.

Implements StorageIntf.

Definition at line 319 of file store.cpp.

320 {
322  //printf("%x: Store::read total=%d\n",(int)portable_ftell(m_file),size);
323  do
324  {
325 #if USE_FTELL
327 #else
328  portable_off_t curPos = m_cur;
329 #endif
330  int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)));
331  int bytesLeft = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0;
332  int numBytes = size - bytesLeft;
333  //printf(" Store::read: pos=%x num=%d left=%d\n",(int)curPos,numBytes,bytesLeft);
334 
335  if (numBytes>0)
336  {
337  //printf("%x: Store::read: %d out of %d bytes\n",(int)portable_ftell(m_file),numBytes,size);
338  if ((int)fread(buf,1,numBytes,m_file)!=numBytes)
339  {
340  fprintf(stderr,"Error reading from store: %s\n",strerror(errno));
341  exit(1);
342  }
343  m_cur+=numBytes;
344  m_reads++;
345  }
346  if (bytesLeft>0)
347  {
348  portable_off_t newPos;
349  // read offset of the next block
350 #if USE_FTELL
352 #else
354 #endif
355  if (fread((char *)&newPos,BLOCK_POINTER_SIZE,1,m_file)!=1)
356  {
357  fprintf(stderr,"Error reading from store: %s\n",strerror(errno));
358  exit(1);
359  }
360  //printf("%x: Store::read: continue in next block, %d bytes to go\n",(int)newPos,bytesLeft);
361  //printf(" Store::read: next block=%x\n",(int)newPos);
362  STORE_ASSERT(newPos!=0);
363  STORE_ASSERT((newPos&(BLOCK_SIZE-1))==0);
364  curPos = newPos;
365  // move to next block
366  if (portable_fseek(m_file,curPos,SEEK_SET)==-1)
367  {
368  fprintf(stderr,"Store::read: Error seeking to position %d: %s\n",
369  (int)curPos,strerror(errno));
370  exit(1);
371  }
372  m_cur = curPos;
373  }
374 
375  size-=numBytes;
376  buf+=numBytes;
377  }
378  while (size>0);
379  return size;
380 }
State m_state
Definition: store.h:118
#define BLOCK_POINTER_SIZE
Definition: store.cpp:31
off_t portable_off_t
Definition: portable.h:11
int errno
Contains the last error code.
Definition: structcmd.h:53
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
portable_off_t portable_ftell(FILE *f)
Definition: portable.cpp:333
int m_reads
Definition: store.h:119
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
if(!yymsg) yymsg
#define BLOCK_SIZE
Definition: store.cpp:30
void Store::release ( portable_off_t  handle)

Releases the memory corresponding to the handle returned with alloc()

Definition at line 269 of file store.cpp.

270 {
272  //printf("release: block pos=%lld\n",(long long)pos);
273  STORE_ASSERT(pos>0 && (pos & (BLOCK_SIZE-1))==0);
274  // goto end of the block
275  portable_off_t cur = pos, next;
276  while (1)
277  {
278  // add new node to the free list
279  Node *node = new Node;
280  node->next = m_head;
281  node->pos = cur;
282 
283  m_head = node;
284  // goto the end of cur block
285  if (portable_fseek(m_file,cur+BLOCK_SIZE-BLOCK_POINTER_SIZE,SEEK_SET)==-1)
286  {
287  fprintf(stderr,"Store::release: Error seeking to position %d: %s\n",
288  (int)(cur+BLOCK_SIZE-BLOCK_POINTER_SIZE),strerror(errno));
289  exit(1);
290  }
291  // read pointer to next block
292  if (fread(&next,BLOCK_POINTER_SIZE,1,m_file)!=1)
293  {
294  fprintf(stderr,"Store::release: Error reading from store: %s\n",strerror(errno));
295  exit(1);
296  }
297  m_cur = cur+BLOCK_SIZE;
298  if (next==0) break; // found end of list -> cur is last element
299  STORE_ASSERT((next & (BLOCK_SIZE-1))==0);
300  cur = next;
301  //printf("%x: Store::release\n",(int)cur);
302  }
303 }
State m_state
Definition: store.h:118
#define BLOCK_POINTER_SIZE
Definition: store.cpp:31
QMapNodeBase Node
Definition: qmap.cpp:41
off_t portable_off_t
Definition: portable.h:11
int errno
Contains the last error code.
Definition: structcmd.h:53
portable_off_t pos() const
Definition: store.h:97
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
Node * m_head
Definition: store.h:117
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
#define BLOCK_SIZE
Definition: store.cpp:30
void Store::seek ( portable_off_t  handle)

Goes to the start of information corresponding to handle pos

Definition at line 305 of file store.cpp.

306 {
308  //printf("%x: Store::seek\n",(int)pos);
309  if (portable_fseek(m_file,pos,SEEK_SET)==-1)
310  {
311  fprintf(stderr,"Store::seek: Error seeking to position %d: %s\n",
312  (int)pos,strerror(errno));
313  exit(1);
314  }
315  m_cur = pos;
316  STORE_ASSERT((pos&(BLOCK_SIZE-1))==0);
317 }
State m_state
Definition: store.h:118
int errno
Contains the last error code.
Definition: structcmd.h:53
portable_off_t pos() const
Definition: store.h:97
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
#define BLOCK_SIZE
Definition: store.cpp:30
int Store::write ( const char *  buf,
uint  size 
)
virtual

Writes size bytes in array buf to the store. First alloc() has to be called.

Note
The information can only be read after end() has been called.

Implements StorageIntf.

Definition at line 154 of file store.cpp.

155 {
157  //printf("%x: Store::write\n",(int)portable_ftell(m_file));
158  do
159  {
160 #if USE_FTELL
162 #else
163  portable_off_t curPos = m_cur;
164 #endif
165  int bytesInBlock = (int)(BLOCK_SIZE - BLOCK_POINTER_SIZE - (curPos & (BLOCK_SIZE-1)));
166  int bytesLeft = bytesInBlock<(int)size ? (int)size-bytesInBlock : 0;
167  int numBytes = size - bytesLeft;
168  STORE_ASSERT(bytesInBlock>=0);
169  STORE_ASSERT(numBytes<=(int)(BLOCK_SIZE-BLOCK_POINTER_SIZE));
170  if (numBytes>0)
171  {
172  if ((int)fwrite(buf,1,numBytes,m_file)!=numBytes)
173  {
174  fprintf(stderr,"Error writing: %s\n",strerror(errno));
175  exit(1);
176  }
177  m_cur+=numBytes;
178  m_writes++;
179  }
180  if (bytesLeft>0) // still more bytes to write
181  {
182 #if USE_FTELL
183  STORE_ASSERT(((portable_ftell(m_file)+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
184 #else
185  STORE_ASSERT(((m_cur+BLOCK_POINTER_SIZE)&(BLOCK_SIZE-1))==0);
186 #endif
187  // allocate new block
188  if (m_head==0) // no free blocks to reuse
189  {
190  //printf("%x: Store::write: new: pos=%x\n",(int)m_front,(int)portable_ftell(m_file));
191  // write pointer to next block
192  if (fwrite(&m_front,BLOCK_POINTER_SIZE,1,m_file)!=1)
193  {
194  fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
195  exit(1);
196  }
198 #if USE_FTELL
200 #else
201  STORE_ASSERT(m_cur==(curPos&~(BLOCK_SIZE-1))+BLOCK_SIZE);
202 #endif
203  // move to next block
204  if (portable_fseek(m_file,0,SEEK_END)==-1) // go to end of the file
205  {
206  fprintf(stderr,"Store::alloc: Error seeking to end of file: %s\n",strerror(errno));
207  exit(1);
208  }
209  m_cur=m_front;
210 #if USE_FTELL
212 #else
214 #endif
215  // move front to the next of the block
217  }
218  else // reuse block from the free list
219  {
220  // write pointer to next block
221  if (fwrite(&m_head->pos,BLOCK_POINTER_SIZE,1,m_file)!=1)
222  {
223  fprintf(stderr,"Error writing to store: %s\n",strerror(errno));
224  exit(1);
225  }
226  Node *node = m_head;
227  portable_off_t pos = node->pos;
228  // point head to next free item
229  m_head = node->next;
230  delete node;
231  // move to start of the block
232  if (portable_fseek(m_file,pos,SEEK_SET)==-1)
233  {
234  fprintf(stderr,"Store::write: Error seeking to position %d: %s\n",
235  (int)pos,strerror(errno));
236  exit(1);
237  }
238  m_cur = pos;
239  //printf("%x: Store::write: reuse\n",(int)pos);
240  }
241  }
242  size-=numBytes;
243  buf+=numBytes;
244  }
245  while (size>0);
246  return size;
247 }
State m_state
Definition: store.h:118
#define BLOCK_POINTER_SIZE
Definition: store.cpp:31
off_t portable_off_t
Definition: portable.h:11
portable_off_t pos
Definition: store.h:110
int errno
Contains the last error code.
Definition: structcmd.h:53
portable_off_t pos() const
Definition: store.h:97
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
portable_off_t m_cur
Definition: store.h:116
portable_off_t portable_fseek(FILE *f, portable_off_t offset, int whence)
Definition: portable.cpp:322
portable_off_t portable_ftell(FILE *f)
Definition: portable.cpp:333
Node * m_head
Definition: store.h:117
portable_off_t m_front
Definition: store.h:115
#define STORE_ASSERT(x)
Definition: store.cpp:37
FILE * m_file
Definition: store.h:114
int m_writes
Definition: store.h:120
if(!yymsg) yymsg
#define BLOCK_SIZE
Definition: store.cpp:30

Member Data Documentation

portable_off_t Store::m_cur
private

Definition at line 116 of file store.h.

FILE* Store::m_file
private

Definition at line 114 of file store.h.

portable_off_t Store::m_front
private

Definition at line 115 of file store.h.

Node* Store::m_head
private

Definition at line 117 of file store.h.

int Store::m_reads
private

Definition at line 119 of file store.h.

State Store::m_state
private

Definition at line 118 of file store.h.

int Store::m_writes
private

Definition at line 120 of file store.h.


The documentation for this class was generated from the following files: