Replacement for mdb_ole_read_full

dw <[email protected]> Sat, 26 Feb 2011 15:07:46 -0800
Newsgroups gmane.comp.db.mdb-tools.devel
Message-ID <[email protected]>
So, my first proposed modification is to replace the mdb_ole_read_full 
routine in data.c.  While the current routine does work, it has a number 
of inefficiencies:

- Performs unnecessary memory allocation/memcpy of the Memo Field Definition
- Performs (repeated) unnecessary memcpys
- Performs (repeated) unnecessary reallocs (which also do memcpys)
- Allocates more memory than is needed to hold the data
- Uses an inconsistent memory allocator (malloc vs g_malloc)
- Leaves the col->bind_ptr in an unusable state

My replacement (below) does:

- Zero memcpys
- Zero reallocs
- A single, correctly-sized allocation using g_malloc
- Preserves the Memo Field Definition in col->bind_ptr
- Fully commented

My next proposed modification is more substantive, but this seemed like 
a good place to start.

dw

/*
  * mdb_ole_read_full - reads the entire OLE field
  *
  * mdb - the database pointer
  * col - the column to read
  * size - outputs the size of the buffer returned (may be NULL)
  *
  * returns - the result in a big buffer.  The number of data bytes is
  * returned in the size parameter.  The returned buffer must freed
  * using g_free().
  *
  * On return, col->bind_ptr still points to the 12 byte Memo Field
  * Definition, NOT the data.  This means the OLE field can be
  * re-read if necessary.
  *
  */
void*
mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size)
{
	void *pOldBind;
	unsigned char *result;
	size_t pos, iTotSize;

	// What's the total length of the field?  Drop off flags
	iTotSize = mdb_get_int32(col->bind_ptr, 0)&  0x3fffffff;

	// Allocate room for the entire field.
	result = (unsigned char *)g_malloc(iTotSize);

	// Save the old pointer which points to the 12 byte Memo Field Definition
	pOldBind = col->bind_ptr;

	// mdb_ole_read&  mdb_ole_read_next always write to col->bind_ptr.
	// So we adjust it to point to our full sized buffer
	col->bind_ptr = result;

	// Reads at most 1 data page
	pos = mdb_ole_read(mdb, col, pOldBind, iTotSize);

	// Is there more to read?
	while (pos<  iTotSize)
	{
		// Adjust col->bind_ptr so the next call will write to
		// the appropriate offset in the buffer
		col->bind_ptr = result + pos;

		// Read the next chunk (at most 1 data page).  Passing NULL
		// for the 3rd parameter avoids redundant error checking
		pos += mdb_ole_read_next(mdb, col, NULL);
	}

	// assert pos == iTotSize

	if (size)
		*size = pos;

	// restore the 12 byte Memo Field Definition
	col->bind_ptr = pOldBind;

	return result;
}



------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in 
Real-Time with Splunk. Collect, index and harness all the fast moving IT data 
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business 
insights. http://p.sf.net/sfu/splunk-dev2dev